MSCBSC 移动通信论坛
搜索
登录注册
网络优化工程师招聘专栏 4G/LTE通信工程师最新职位列表 通信实习生/应届生招聘职位

  • 阅读:3116
  • 回复:1
OPhone上开发符合MobileMarket界面规范的手机游戏
3G123




 发短消息    关注Ta 

积分 130
帖子 26
威望 4738 个
礼品券 0 个
专家指数 0
注册 2010-9-10
回答问题数 0
回答被采纳数 0
回答采纳率 0%
 
发表于 2010-09-27 09:34:34  只看楼主 
作者介绍
张久军,乐成数字通信学院高级讲师。6年手机软件开发经验,曾开发多款手机游戏和多款手机应用软件。擅长短信、wap、手机游戏、手机应用软件开发。二年多手机软件培训经验,所带班级毕业后一个月内实现100%就业。

在手机软件开发当中,游戏的收入近几年收入可观,据统计在2009年,中国的手机游戏市场收入大概在12亿左右。Mobile Market将会成为中国手机游戏的主要销售渠道。OPhone是中国移动推出的手机操作系统,每部OPhone的手机都内置了Mobile Market。有中国移动的大力支持,使用OPhone手机的用户会越来越多。以后会有很多OPhone用户从Mobile Market上下载手机游戏。市场也需要大量的OPhone手机游戏。本人曾有Mobile Market手机游戏开发经验,对Mobile Market开发规范有一定的了解。用OPhone写出了一个符合Mobile Market开发的手机游戏框架,供大家参考。


运行效果如下:




Mobile Market开发规范说明


在《中国移动Mobile Market应用开发要求v1.2.2(517版本).doc》中对手机软件和手机游戏的开发规范做了详细的要求,主要有界面,安装卸载,联网,程序进程,数据读写,计费功能等要求。本篇文章主要讲述如何让游戏的界面符合Mobile Market的界面规范,下面将规范中与界面有关的要求摘录出来。


  •  启动画面(适用于游戏、软件)

 应用(游戏、软件)的启动画面使用统一的中国移动Mobile Market标识图片


文字内容:中国移动Mobile Market让你的手机更加精彩,感谢你的支持!


  •  “关于”项说明

 “关于”项中,增加说明:“本应用经过中国移动测试认证中心安全测试,感谢您的支持!”
 “关于”可合并到帮助中。


  •  “帮助”项说明

应用必须提供“帮助”(主题除外)功能,包括开发者信息、软件名称、版本信息、基本的使用说明。


  •  “退出”项说明

应用必须提供“退出”(主题除外)功能,退出时不能产生新的链接或界面。


代码的整体思路
在单机手机游戏开发当中,游戏的框架主要有MVC,state。state中文意思是指状态,将一个单机游戏分成多个状态,程序员分别对每一个状态的界面,按键,业务逻辑进行编程。以一个RPG游戏为例来说,可以分成Mobile Market Logo,公司Logo,标题,主菜单,游戏介绍,游戏场景,对话,战斗,物品,任务,游戏结束,帮助,关于,设置等状态。本篇文章按照Mobile Market规范要求实现了4个状态分别是Mobile Market Logo,公司Logo,主菜单,关于四个状态。读者可以参考本文章的代码把其它状态也实现了。在单机手机游戏开发中,使用state框架非常成熟,国内有很多单机手机游戏就是使用state 框架开发的。State框架的优点是简单,易学,易用,减少对象个数,占内存少。


代码详细介绍

  •  程序的入口

程序的入口是MobileMarketGame类中的onCreate方法,在onCreate方法中创建一个Main对象,Main是View的子类,Main对像能放在手机屏幕上。代码如下


    main = new Main(this);
  • setContentView(main);
  •  显示Mobile Market Logo图片
在Main的构造方法中,通过this.updateState(stateMobileMarket, (byte) -1);使程序进入stateMobileMarket状态. 代码如下
  • this.updateState(stateMobileMarket, (byte) -1);
在onDraw方法中,判断当前状态如果是stateMobileMarket就把Mobile Market Logo显示在手机屏幕上。代码如下
    switch (this.currentState) {
  • case stateMobileMarket:drawMobileMarketLogo(g, paint);
  • break;
  • }
  •  显示公司Logo状态
在run方法中调用logic,在logic中让线程睡眠1秒,然后切换到stateLdci,代码如下
    private void logic() throws InterruptedException {
  • switch (this.currentState) { case stateMobileMarket:
  • thread.sleep(1000);this.updateState(stateLdci, stateMobileMarket);
  • break; }
  • }
在onDraw方法中,判断当前状态如果是stateLdci就把公司Logo显示在手机屏幕上。
  •  进入主菜单
在stateLdci状态下,让线程执行10次,然后切换到主菜单,代码如下
    private void logic() throws InterruptedException {
  • switch (this.currentState) { case stateLdci:
  • this.count++;if (this.count > 10) {
  • this.updateState(stateMainMenu, stateLdci);}
  • break; }
  • }
  •  按键处理
按下键后,执行onKeyDown方法,在onKeyDown方法中根据键值做相应的处理。代码如下
    public boolean onKeyDown(int keyCode, KeyEvent event) {
  • switch (this.currentState) {case stateMainMenu:
  • keyMainMenu(keyCode);break;
  • case stateAbout:this.updateState(this.stateMainMenu, this.stateAbout);
  • break;}
  • }
  •  显示关于信息
在主菜单状态下,选中关于,按下中间键后,程序切换到关于状态。代码如下
    private void keyMainMenu(int keyCode) {
  • switch (keyCode) { case KeyEvent.KEYCODE_ENTER:// 中间键
  • switch (this.menuIndex) {case 3:
  • this.updateState(stateAbout, stateMainMenu);break;
  • }break;
  • }
  • }
在onDraw调用drawAbout,在drawAbout方法中将关于信息画出来,代码如下
    private void drawAbout(Canvas g, Paint paint) {
  • g.drawText("本应用经过中国移动测试认证中心安全测试,感谢您的支持", 0, 50, paint); g.drawText("电子邮件:zhangjiujun@ldci.com.cn", 0, 100, paint);
  • g.drawText("公司主页:www.ldci.com.cn", 0, 150, paint); g.drawText("乐成", 0, 200, paint);
  • }
  •  从关于返回到主菜单
在关于状态下,用户按下任意键后调用onKeyDown,在onKeyDown通过调用updateState返回到主菜单
    public boolean onKeyDown(int keyCode, KeyEvent event) {
  • switch (this.currentState) { case stateAbout:
  • this.updateState(this.stateMainMenu, this.stateAbout);break;
  • }
OPhone实现的完整代码
本项目由两个程序实现。 Mobile MarketGame.java是程序的入口。Main.java负责实现界面绘制,按键处理,业务逻辑。Mobile MarketGame的代码如下:
    package com.ldci;

  • import android.app.Activity;
  • import android.os.Bundle;import android.view.KeyEvent;
  • import android.view.Window;
  • /*** 程序入口
  • * * @author 乐成 张久军
  • * */
  • public class Mobile MarketGame extends Activity {Main main = null;

  • public void onCreate(Bundle savedInstanceState) {
  • super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);

  • main = new Main(this); setContentView(main);
  • }
  • public boolean onKeyDown(int keyCode, KeyEvent event) { main.onKeyDown(keyCode, event);
  • return super.onKeyDown(keyCode, event);}

  • public boolean onKeyUp(int keyCode, KeyEvent event) {
  • main.onKeyUp(keyCode, event); return super.onKeyUp(keyCode, event);
  • }
  • }
Main.java的代码如下:
    package com.ldci;

  • import android.content.Context;
  • import android.graphics.*;import android.graphics.Paint.Style;
  • import android.util.AttributeSet;import android.view.*;

  • import java.io.*;

  • /**
  • * 主类,实现界面绘制,按键处理,业务逻辑*
  • * @author 乐成 张久军*
  • */public class Main extends View implements Runnable {

  • /**
  • * Mobile Market Logo */
  • Bitmap bmMobileMarketLogo = null;/**
  • * 公司Logo */
  • Bitmap bmLdciLogo = null;
  • /** * MobileMarket要求的主菜单
  • */private final static String[] menuStr = { "开始", "帮助", "设置", "关于", "退出" };
  • /** * 当前状态
  • */byte currentState = -1;
  • /** * MobileMarket Logo状态
  • */final static byte stateMobileMarket = 1;
  • /** * 公司Logo状态
  • */final static byte stateLdci = 2;
  • /** * 主菜单状态
  • */final static byte stateMainMenu = 3;
  • /** * 关于状态
  • */final static byte stateAbout = 4;

  • public Main(Context context) {
  • super(context);
    this.context = context;
  • this.updateState(stateMobileMarket, (byte) -1);
    thread = new Thread(this);
  • thread.start();}

  • /**
  • * 画图 */
  • protected void onDraw(Canvas g) { try {
  • Paint paint = new Paint();paint.setColor(0xFFff0000);
  • switch (this.currentState) {case stateMobileMarket:
  • drawMobileMarketLogo(g, paint);break;
  • case stateLdci:drawLdciLogo(g, paint);
  • break;case stateMainMenu:
  • drawMainMenu(g, paint);break;
  • case stateAbout:drawAbout(g, paint);
  • break;}
  • } catch (Exception e) {e.printStackTrace();
  • }}

  • /**
  • * 业务逻辑 */
  • public void run() { long beginTime = 0, endTime = 0, useTime = 0;
  • while (true) {try {

  • beginTime = System.currentTimeMillis();logic();

  • endTime = System.currentTimeMillis();
    useTime = endTime - beginTime;
  • if (useTime > 100) {
    useTime = 100;
  • }thread.sleep(100 - useTime);// 线程每秒运行10次
  • this.postInvalidate();
  • } catch (Exception e) {e.printStackTrace();
  • } }

  • }

  • /**
  • * 按键处理 */
  • public boolean onKeyDown(int keyCode, KeyEvent event) { try {
  • switch (this.currentState) {case stateMainMenu:
  • keyMainMenu(keyCode);break;
  • case stateAbout:this.updateState(this.stateMainMenu, this.stateAbout);
  • break;}
  • } catch (Exception e) {e.printStackTrace();
  • } return super.onKeyDown(keyCode, event);
  • }
  • private void keyMainMenu(int keyCode) { switch (keyCode) {
  • case KeyEvent.KEYCODE_DPAD_UP:// 上键this.menuIndex--;
  • if (this.menuIndex <
    0) {
    thisthis.menuIndex = this.menuStr.length - 1;
  • }break;
  • case KeyEvent.KEYCODE_DPAD_DOWN:// 下键this.menuIndex++;
  • if (this.menuIndex > this.menuStr.length - 1) {
    this.menuIndex = 0;
  • }break;
  • case KeyEvent.KEYCODE_ENTER:// 中间键switch (this.menuIndex) {
  • case 3:this.updateState(stateAbout, stateMainMenu);
  • break;}
  • break; }
  • }
  • /** * 逻辑
  • ** @throws InterruptedException
  • */private void logic() throws InterruptedException {
  • switch (this.currentState) { case stateMobileMarket:
  • thread.sleep(1000);this.updateState(stateLdci, stateMobileMarket);
  • break; case stateLdci:
  • this.count++;if (this.count > 10) {
  • this.updateState(stateMainMenu, stateLdci);}
  • break; }
  • }
  • /** * 状态转换负责加载下一个状态的资源,释放前一个状态资源
  • ** @param nextState
  • * @param preState */
  • private void updateState(byte nextState, byte preState) { try {

  • this.currentState = nextState;// 加载资源
  • switch (nextState) {case stateMobileMarket:
  • InputStream is = context.getResources().openRawResource(R.drawable.mobilemarketlogo);

  • bmMobileMarketLogo = BitmapFactory.decodeStream(is);is.close();

  • is = null;break;
  • case stateLdci:InputStream is2 = context.getResources().openRawResource(
  • R.drawable.ldcilogo);
    bmLdciLogo = BitmapFactory.decodeStream(is2);
  • is2.close();
    is2 = null;
  • break;}

  • // 释放资源
  • switch (preState) {case stateMobileMarket:

  • this.bmMobileMarketLogo = null;break;
  • }System.gc();// 调用垃圾回收器,
  • } catch (Exception e) {e.printStackTrace();
  • }}

  • private void drawAbout(Canvas g, Paint paint) {
  • g.drawText("本应用经过中国移动测试认证中心安全测试,感谢您的支持", 0, 50, paint); g.drawText("电子邮件:zhangjiujun@ldci.com.cn", 0, 100, paint);
  • g.drawText("公司主页:www.ldci.com.cn", 0, 150, paint); g.drawText("乐成", 0, 200, paint);
  • }
  • private void drawMainMenu(Canvas g, Paint paint) { int rectLeft = 110;
  • int rectTop = 30 + menuIndex * 50; int rectRight = 220;
  • int rectBottom = 30 + menuIndex * 50 + 30;
  • paint.setColor(0xFF0000FF); paint.setStyle(Style.STROKE);
  • RectF r = new RectF(rectLeft, rectTop, rectRight, rectBottom); g.drawRect(r, paint);

  • paint.setColor(0xFFFF0000);
  • for (int i = 0; i <
    this.menuStr.length; i++) {g.drawText(this.menuStr, 150, 50 + i * 50, paint);
  • }}

  • private void drawLdciLogo(Canvas g, Paint paint) {
  • g.drawBitmap(this.bmLdciLogo, 60, 200, paint);
  • paint.setColor(0xFFFF0000); paint.setStyle(Style.STROKE);
  • // 外边空心的矩形 float rectLeft = 60;
  • float rectTop = 400; float rectRight = 260;
  • float rectBottom = 420; RectF r = new RectF(rectLeft, rectTop, rectRight, rectBottom);
  • g.drawRect(r, paint);
  • paint.setStyle(Style.FILL); RectF fillRect = new RectF(rectLeft, rectTop, rectLeft + 20 * count,
  • rectBottom); g.drawRect(fillRect, paint);
  • }
  • private void drawMobileMarketLogo(Canvas g, Paint paint) { g.drawBitmap(bmMobileMarketLogo, 60, 81, paint);
  • }
  • /** * 触摸事件
  • */public boolean onTouchEvent(MotionEvent event) {
  • return super.onTouchEvent(event);}

  • public boolean onKeyUp(int keyCode, KeyEvent event) {
  • return super.onKeyUp(keyCode, event);}

  • int count = 0;
  • Thread thread = null;Context context = null;
  • int menuIndex = 0;/**
  • * 键值 */
  • public static int keyCode = 0;
  • }
总结
本文介绍了如何按照MobileMarket的界面规范来开发Ophone手机游戏。并使用state框架给出一个案例。欢迎开发者沟通讨论,邮箱zhangjiujun@ldci.com.cn
扫码关注5G通信官方公众号,免费领取以下5G精品资料
  • 1、回复“YD5GAI”免费领取《中国移动:5G网络AI应用典型场景技术解决方案白皮书
  • 2、回复“5G6G”免费领取《5G_6G毫米波测试技术白皮书-2022_03-21
  • 3、回复“YD6G”免费领取《中国移动:6G至简无线接入网白皮书
  • 4、回复“LTBPS”免费领取《《中国联通5G终端白皮书》
  • 5、回复“ZGDX”免费领取《中国电信5G NTN技术白皮书
  • 6、回复“TXSB”免费领取《通信设备安装工程施工工艺图解
  • 7、回复“YDSL”免费领取《中国移动算力并网白皮书
  • 8、回复“5GX3”免费领取《 R16 23501-g60 5G的系统架构1
  • 对本帖内容的看法? 我要点评

     
    qiangshidi




     发短消息    关注Ta 

    积分 635
    帖子 127
    威望 3280 个
    礼品券 0 个
    专家指数 0
    注册 2010-9-29
    回答问题数 0
    回答被采纳数 0
    回答采纳率 0%
     
    发表于 2010-09-30 19:46:46 
    技术问题,回答得专家指数,快速升级
    很不错的资料的,谢谢!

    对本帖内容的看法? 我要点评

     

    快速回复主题    
    标题
    内容
     上传资料请点左侧【添加附件】

    当前时区 GMT+8, 现在时间是 2025-12-13 12:50:30
    渝ICP备11001752号  Copyright @ 2006-2016 mscbsc.com  本站统一服务邮箱:mscbsc@163.com

    Processed in 0.396035 second(s), 13 queries , Gzip enabled
    TOP
    清除 Cookies - 联系我们 - 移动通信网 - 移动通信论坛 - 通信招聘网 - Archiver