《J2me小白转正记》

--------------浅谈J2me游戏如何快速移植到Android


(关于这篇文章~非常的尴尬~骨头就不细说了~当然了咱没理由怪别人~还得修炼哈哈)

前言

小白:“老大,你让做的三个J2me游戏搞定了,请看DEMO。”

老大:“恩,不错,小白,你知道Android这个平台吧?”

小白:“恩,听过。听说和J2ME有很多共同点。”

老大:“(一阵奸笑)很多共同点是吧?”

小白:“恩。”

老大:“那好,你把这几个J2ME游戏给我移植到Android上去。”

小白:“……

很多J2ME开发者可能都会遇到这样的临时性需求。其实J2ME程序往Android移植,并不是特别麻烦。

经过一番认真学习,小白开始整理起了笔记……

高级UI界面

J2ME的高级用户界面比较鸡肋,在现在大多数的应用里都看不到,多数稍微复杂点的界面都是手工画,或是用一些开源的高级UI库,但Android则不同,它的UI实用、方便,而且很美观,基本无需改动且定制方便。

设备差异

虽说普通的手机性能越来越高,屏幕也越来越大,但平均而言,运行J2ME的手机从性能和屏幕分辨率及附属功能来说不及Android手机。拿入门的HTC G1来说,CPU528MHz,屏幕为3.17英寸触摸屏、HVGA480×320像素,192MB RAM256MBROM。所以从J2ME移植到Android的程序可以暂时不考虑性能问题。

但要充分发挥Android手机的特点。要注意一下几点:

比如应用UI的布局可以更加自由,输入更加灵活,网络应用注意发挥3GWIFI的速度优势。

游戏要注意可适当的用效率换效果,可增加动画、音效、背景音乐的质量,图片元素的大小,发挥高分辨率手机的优势,强大的运算能力可以让开发人员编写基于OpenGL3D游戏,可以用一些吃CPU但效果不错的开发包,如Box2D仿真物理引擎开发包。

可以结合GPS定位、重力感应、话筒、指南针、触笔的压力感应等等让游戏的效果更加逼真。

J2MEAndroid系统的常用类、方法对比

J2MEAndroid系统的常用类、方法对比

J2ME系统

Android系统

入口程序

MIDlet

Activity

图片类

Image

Image.createImage(path);

BitMap

BitmapFactory.decodeResource(getResources(),R.drawable.map0);

画笔

Graphics

Canvas

绘画

Displayable

View

按键

keyPressed()

keyRepeated()

keyReleased()

onKeyDown()

onKeyUp()

onTracKballEvent()

触笔

pointerPressed(),

pointerReleased(),

pointerDragged()

onTouchEvent()

打印信息

System.out.printlt()

Log

生命周期-开始

startApp(),活动状态,启动时调用,初始化。

onCreate(),返回时也会调用此方法。

onCreate()后调用onStart()

onStart()后调用onResume()

生命周期-暂停

PauseApp(),暂停状态,如来电时,调用该接口。

onPause()

生命周期-销毁

destroyApp(),销毁状态,退出时调用。

onStop(),程序不可见时调用onDestroy(),程序销毁时调用

刷新

高级UI组件由内部刷新实现。

低级UI,canvas中通过调用线程结合repaint()来刷新,让线程不断循环

高级UIHandler类通过消息的机制刷新

onDraw()刷新接口

低级UI开发者用线程控制更新,在lockCanvas()unlockCanvasAndPost()方法之间绘制

数据存储

Record Management System (RMS)

SQLite数据库

SharedPreferences

可绘区域

int clipX = g.getClipX();

int clipY = g.getClipY();

int clipW = g.getClipWidth();

int clipH = g.getClipHeight();

g.clipRect(x, y, width, height);

g.setClip(clipX, clipY, clipW, clipH);

canvas.save();

canvas.clipRect(x,y,x+width, y+height);

cavnas.resave();

游戏中清屏

paint.setStyle(Style.FILL);

canvas.drawRect(new Rect(0, 0, getWidth(), getHeight()), paint);

canvas.drawColor(Color.BLACK);

游戏开发包

javax.microedition.lcdui.game

GameCanvas

Layer

LayerManager

Sprite

TiledLayer

无专门针对游戏的开发包,可以直接拿来主义,将J2ME的开发包稍作修改

音效

Players=Manager.createPlayer(InputStream);

s.prepare();//创建

s.start();//播放

s.stop();//暂停

s.stop();//关闭

s.release();//释放

MediaPlayer类处理背景音乐

SoundPool类处理一些简单的音效

全屏

CanvasSetFullScreenMode()

getWindow().setFlags(

WindowManager.LayoutParams.FLAG_FULLSCREEN,

WindowManager.LayoutParams.FLAG_FULLSCREEN);

requestWindowFeature(Window.FEATURE_NO_TITLE);

获得屏幕尺寸

Canvas类的getHeight()getWidth()

Display d = getWindowManager().getDefaultDisplay();

screenWidth = d.getWidth();

screenHeight = d.getHeight();

双缓冲

ImagebufImage=Image.createImage(bufWidth,bufHeight);

GraphicsbufGraphics=bufImage.getGraphics();

Bitmap carBuffer = Bitmap.createBitmap(bufWidth, bufHeight, Bitmap.Config.ARGB_4444);

Canvas carGp = new Canvas(carBuffer);

开始移植

小白找到Android中对应的J2ME相关的替代类和替代方法后,开始噼里啪啦的改代码了。没过多久,首个俄罗斯方块算是移植成功。当他开始移植下一款游戏时,发现又要重复的改那些代码……

“可不可以减少代码的改动呢?”小白问自己。“可否用Android的相关代码构造一些和J2me里功能类似的代码呢?”

原则:尽量少改动J2ME项目的代码。用Android中对应的类改写成J2ME中的方法和类,减少以后移植的工作量,甚至实现无缝移植。

“或许我可以构造一个名为MIDlet实为Activity的类,这样J2me中的入口类就不用改动了”

Activity类改装的MIDlet类:

public abstract class MIDlet extends Activity{

public void onCreate(BundlesavedInstanceState) {

super.onCreate(savedInstanceState);

startApp();

}

public abstract void destroyApp(booleanunconditional);

public StringgetAppProperty(String key) {

returnnull;

}

public abstract void startApp();

public voidnotifyDestroyed() {

}

public void notifyPaused() {}

public void pauseApp() {}

public void platformRequest(String URL){}

public void resumeRequest() {}

}

MIDlet类我们解决了,接下来就是非常重要的Canvas类了

J2me里的Canvas类相当于Android体系中的SurfaceView类,都是负责绘制显示界面的,游戏的大循环一半也在这两个类里实现,也就是都会实现Runnable类,更新逻辑和更新界面都在此类的大循环中处理。

Graphics类在J2me里负责绘图和排版样式等。

我们可以用Android里的Canvas类和Paint类共同组合一个Android里的Graphics类,如Graphics类的构造函数可这样定义:

public Graphics(Bitmap bitmap) {

this.bitmap = bitmap;

this.canvas = new Canvas(bitmap);

this.canvas.clipRect(0, 0, bitmap.getWidth(), bitmap.getHeight());

this.canvas.save(Canvas.CLIP_SAVE_FLAG);

this.paint = new Paint();

this.clip = canvas.getClipBounds();

}

Graphics里可以设置居中方式,在Android体系里我们用Paint类来实现相同的效果,例如:

public voidsetAlign(int align)

{

if(LEFT == align

||(Graphics.LEFT |Graphics.TOP) == align

||(Graphics.LEFT |Graphics.BOTTOM) == align)

{

paint.setTextAlign(Align.LEFT);

}else if(HCENTER == align

||(Graphics.HCENTER|Graphics.TOP) == align)

{

paint.setTextAlign(Align.CENTER);

}else if(RIGHT == align

||(Graphics.RIGHT |Graphics.TOP) == align)

{

paint.setTextAlign(Align.RIGHT);

}

}

所有的绘制方法也同样沿用J2me中的方法名,用Android体系的代码完成方法体,达到无缝移植。以绘制、填充矩形为例:

public void fillArc(int x,int y,intwidth,int height, int startAngle,int arcAngle) {

paint.setStyle(Style.FILL);

canvas.drawArc(new RectF(x,y,width,height), startAngle, arcAngle, true,paint);

}

public void drawArc(int x,int y,intwidth,int height, int startAngle,int arcAngle) {

paint.setStyle(Style.STROKE);

canvas.drawArc(new RectF(x,y,width,height), startAngle, arcAngle, true,paint);

}

再来说说按键处理:

大体思路就是获取Android中的按键消息后,修改封装一下,转换成J2me的键值和事件,然后传递给显示层。

先定义出J2me中的键值:

public class GameCanvas extends Screen{

public static final int UP = 1;

public static final int DOWN = 6;

public static final int LEFT = 2;

public static final int RIGHT = 5;

public static final int FIRE = 8;

publicstatic final int GAME_A = 9;

public static final int GAME_B = 10;

public static final int GAME_C = 11;

public static final int GAME_D = 12;

public static final int KEY_NUM0 = 48;

public static final int KEY_NUM1 = 49;

public static final int KEY_NUM2 = 50;

public static final int KEY_NUM3 = 51;

public static final int KEY_NUM4 = 52;

public static final int KEY_NUM5 = 53;

public static final int KEY_NUM6 = 54;

public static final int KEY_NUM7 = 55;

public static final int KEY_NUM8 = 56;

public static final int KEY_NUM9 = 57;

public static final int KEY_STAR = 42;

public static final int KEY_POUND = 35;

}

经过中间一个转换方法:

publicint keyCode4J2me = 0;

publicint keyAction4J2me = 0;

publicvoid changeToJ2meKey(int keyCode, KeyEvent e) {

if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {

keyCode4J2me= GameCanvas.DOWN;

keyAction4J2me= GameCanvas.DOWN;

}else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {

keyCode4J2me= GameCanvas.LEFT;

keyAction4J2me= GameCanvas.LEFT;

}else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {

keyCode4J2me= GameCanvas.RIGHT;

keyAction4J2me= GameCanvas.RIGHT;

}else if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {

keyCode4J2me= GameCanvas.FIRE;

keyAction4J2me= GameCanvas.FIRE;

}else if (keyCode == KeyEvent.KEYCODE_0) {

keyCode4J2me= GameCanvas.KEY_NUM0;

}else if (keyCode == KeyEvent.KEYCODE_1) {

keyCode4J2me= GameCanvas.KEY_NUM1;

}else if (keyCode == KeyEvent.KEYCODE_2) {

keyCode4J2me= GameCanvas.KEY_NUM2;

}

}

转换成J2me的按键处理体系,转去调用J2me原生的keyReleased方法:

public boolean onKeyUp(int keyCode,KeyEvent e) {

changeToJ2meKey(keyCode,e);

keyReleased(keyActual);

return true;

}

其他的字体类、颜色类、等等都可以按此方法无缝移植。

Font字体类用Android中的FontMetrics重写。

Graphics类中的setColor(int rgb)以及setColor(intr,int g,int b)方法,则可以修改Graphics类中Paint的颜色。如:

public voidsetColor(int r,int g,int b) {

int argb =(0xff000000)+(r<<16)+(g<<8)+b;

paint.setColor(argb);

}

小白心想: “或许我还可以用Android中的Canvas类改写一个J2me中的Graphics类,用Android中的Bitmap改装一个J2me中的Image类……然后把J2me游戏开发包javax.microedition.lcdui.game包里的GameCanvas类,Layer类,LayerManager类,Sprite类,TiledLayer类直接拿来用。嗯嗯,几乎不用改动原来的J2me代码了。第一个移植任务花费了一个周,以后一天就能移植一个小游戏啦。哈哈哈。”

后记

小白:“老大,游戏移植好了,请验收一下吧。”

老大:“恩……恩……动作很快嘛,我看看代码,恩……代码封装的不错,一会来我办公室,谈谈你转正的事。”

小白:“多谢老大。”

老大:“普通的程序员会熟练的使用轮子,优秀的程序员要学会自己造轮子!”

小白:“恩,我记住了。”

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. android上一些方法的区别和用法的注意事项
  5. android EditText设置不可写
  6. android 使用html5作布局文件: webview跟javascript交互
  7. android实现字体闪烁动画的方法
  8. android studio调试c/c++代码
  9. Android中dispatchDraw分析

随机推荐

  1. GIT远程仓库强制覆盖本地仓库代码
  2. GIT切换远程仓库地址
  3. Flutter DateTime日期转换的详细使用
  4. 如何使用Python OpenCV提取物体轮廓详解
  5. 实战-TP数据库操作(一)
  6. CSS 动画属性,太极图实列演示
  7. PHP和python/JAVA比,哪个更好学?
  8. 5分钟站点生成神器——Docusaurus
  9. Vite+React+TypeScript手撸TodoList的项
  10. 通过C#编写一个简易的Windows截屏增强工