<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Java &#38; Game &#187; 游戏</title>
	<atom:link href="http://www.javagg.com/archives/tag/%e6%b8%b8%e6%88%8f/feed" rel="self" type="application/rss+xml" />
	<link>http://www.javagg.com</link>
	<description>java&#38;j2me</description>
	<lastBuildDate>Sat, 02 Jul 2011 08:59:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>J2ME游戏移植到Android平台的方法</title>
		<link>http://www.javagg.com/archives/846</link>
		<comments>http://www.javagg.com/archives/846#comments</comments>
		<pubDate>Tue, 03 May 2011 02:52:32 +0000</pubDate>
		<dc:creator>纯净水</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">http://www.javagg.com/?p=846</guid>
		<description><![CDATA[本文主要介绍如何把J2ME游戏移植到Android平台的方法，如果你是个J2ME的游戏开发者，并且想把一些J2ME游戏快速地迁移到Android平台，那么相信本文会对你有所帮助。当然，如果您非说可以安装个JVM来实现，那您可以直接跳过本文了。
由于手比较懒，对J2ME的描述不是很详细，还望多包涵。废话不多说，请看下文：
1.    平台比较
J2me:
    开发平台
Android:
    操作系统
2.    工程结构比较（源代码，资源文件夹，图片，数据）
J2me:
    Res：资源文件
    Src：源代码
Android:
    Src：源代码
    Res\drawable：图片
    Res\raw：声音
    Res\values：字符串
    Assets：数据文件
3.    安装包比较
J2me:
    Jad,jar
Android:
   [...]]]></description>
			<content:encoded><![CDATA[<p>本文主要介绍如何把J2ME游戏移植到Android平台的方法，如果你是个J2ME的游戏开发者，并且想把一些J2ME游戏快速地迁移到Android平台，那么相信本文会对你有所帮助。当然，如果您非说可以安装个JVM来实现，那您可以直接跳过本文了。<span id="more-846"></span></p>
<p>由于手比较懒，对J2ME的描述不是很详细，还望多包涵。废话不多说，请看下文：</p>
<p>1.    平台比较</p>
<p>J2me:<br />
    开发平台</p>
<p>Android:</p>
<p>    操作系统</p>
<p>2.    工程结构比较（源代码，资源文件夹，图片，数据）</p>
<p>J2me:</p>
<p>    Res：资源文件</p>
<p>    Src：源代码</p>
<p>Android:</p>
<p>    Src：源代码</p>
<p>    Res\drawable：图片</p>
<p>    Res\raw：声音</p>
<p>    Res\values：字符串</p>
<p>    Assets：数据文件</p>
<p>3.    安装包比较</p>
<p>J2me:</p>
<p>    Jad,jar</p>
<p>Android:</p>
<p>    apk</p>
<p>4.    代码结构比较</p>
<p>J2me:</p>
<p>    MIDlet，Canvas</p>
<p>Android:</p>
<p>    Activity，View</p>
<p>都采用继承的方式，都只有一个MIDlet/Activity，一般都只有一个Canvas/View</p>
<p>5.    代码细节比较</p>
<p>l 全屏设置</p>
<p>J2me:</p>
<p>    在Canvas类中调用SetFullScreenMode(Boolean)</p>
<p>Android:</p>
<p>    在Activity类中调用</p>
<p>    //设定全屏显示   </p>
<p>    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,         </p>
<p>                         WindowManager.LayoutParams.FLAG_FULLSCREEN);</p>
<p>    requestWindowFeature(Window.FEATURE_NO_TITLE);</p>
<p>2 获得屏幕尺寸</p>
<p>J2me:</p>
<p>    Canvas类的getHeight()和getWidth()方法</p>
<p>Android:</p>
<p>    int screenWidth,screenHeight;</p>
<p>    WindowManager windowManager = getWindowManager();</p>
<p>    Display display = windowManager.getDefaultDisplay();</p>
<p>       screenWidth = display.getWidth();</p>
<p>       screenHeight = display.getHeight();</p>
<p>3 Display</p>
<p>J2me:</p>
<p>    Display dis=Display.getDisplay(MIDlet);</p>
<p>Android:</p>
<p>    Display display = windowManager.getDefaultDisplay();</p>
<p>4 画布类</p>
<p>J2me:</p>
<p>    Canvas</p>
<p>Android:</p>
<p>    继承View类，定义构造方法：</p>
<p>    public MyView(Context context)</p>
<p>    {</p>
<p>        super(context);</p>
<p>    }</p>
<p>5 屏幕绘制方法</p>
<p>J2me:</p>
<p>    Paint(Graphics)</p>
<p>Android:</p>
<p>    void onDraw(Canvas g)</p>
<p>6 Graphics</p>
<p>J2me:</p>
<p>Android:</p>
<p>7 Image的创建</p>
<p>J2me:</p>
<p>    Image.createImage(path);</p>
<p>Android:</p>
<p>    img = BitmapFactory.decodeResource(getResources(),R.drawable.map0);</p>
<p>8 Font的创建，Font使用，字体设置</p>
<p>J2me:</p>
<p>Android:</p>
<p>9 drawImage</p>
<p>J2me:</p>
<p>Android:</p>
<p>    public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint)</p>
<p>    多个重载</p>
<p>10 字符串绘制</p>
<p>J2me:</p>
<p>Android:</p>
<p>    public native void drawText(String text, float x, float y, Paint paint);</p>
<p>    多个重载</p>
<p>11 setClip</p>
<p>J2me:</p>
<p>Android:</p>
<p>    public boolean clipRect(float left, float top, float right, float bottom,Region.Op op)</p>
<p>    最后一个参数为：Region.Op.REPLACE</p>
<p>12旋转</p>
<p>J2me:</p>
<p>    drawRegion()</p>
<p>    drawImage() </p>
<p>Android:</p>
<p>    还没找到好的方法，不过可以先创建一张翻转后的图片，再使用，封装好的代码如下：</p>
<p>    //创建翻转图片</p>
<p>public Bitmap createTransImage(Bitmap img,int trans)</p>
<p>{</p>
<p>//   Bitmap img;</p>
<p>try</p>
<p>{</p>
<p>//       img = BitmapFactory.decodeResource(getResources(),sImg);</p>
<p>int width = img.getWidth();</p>
<p>int height = img.getHeight();</p>
<p>int newWidth = 200;</p>
<p>int newHeight = 200;</p>
<p>// calculate the scale &#8211; in this case = 0.4f</p>
<p>float scaleWidth = ((float) newWidth) / width;</p>
<p>float scaleHeight = ((float) newHeight) / height;</p>
<p>// createa matrix for the manipulation</p>
<p>Matrix matrix = new Matrix();</p>
<p>// resize the bit map</p>
<p>matrix.postScale(scaleWidth, scaleHeight);</p>
<p>// rotate the Bitmap</p>
<p>int degree=0;</p>
<p>Bitmap resizedBitmap=null;</p>
<p>int data[];</p>
<p>int buf;</p>
<p>switch(trans)</p>
<p>{</p>
<p>case ROTATE_HOR:</p>
<p>//创建镜像翻转</p>
<p>data=new int [img.getWidth()*img.getHeight()];</p>
<p>img.getPixels(data, 0, img.getWidth(), 0, 0, img.getWidth(),img.getHeight());</p>
<p>//交换数据</p>
<p>for(int i=0;i<img.getHeight();i++)</p>
<p>for(int j=0;j<img.getWidth()/2;j++)</p>
<p>{</p>
<p>buf=data[i*img.getWidth()+j];</p>
<p>data[i*img.getWidth()+j]=data[img.getWidth()*(i+1)-(j+1)];</p>
<p>data[img.getWidth()*(i+1)-(j+1)]=buf;</p>
<p>}</p>
<p>resizedBitmap=Bitmap.createBitmap(data, img.getWidth(),</p>
<p>img.getHeight(), Bitmap.Config.ARGB_4444);;</p>
<p>return resizedBitmap;</p>
<p>case ROTATE_VER:</p>
<p>//创建镜像翻转</p>
<p>data=new int [img.getWidth()*img.getHeight()];</p>
<p>img.getPixels(data, 0, img.getWidth(), 0, 0, img.getWidth(),img.getHeight());</p>
<p>//交换数据</p>
<p>for(int i=0;i<img.getHeight()/2;i++)</p>
<p>for(int j=0;j<img.getWidth();j++)</p>
<p>{</p>
<p>buf=data[i*img.getWidth()+j];</p>
<p>data[i*img.getWidth()+j]=data[(img.getHeight()-i-1)*img.getWidth()+j];</p>
<p>data[(img.getHeight()-i-1)*img.getWidth()+j]=buf;</p>
<p>}</p>
<p>resizedBitmap=Bitmap.createBitmap(data, img.getWidth(),</p>
<p>img.getHeight(), Bitmap.Config.ARGB_4444);;</p>
<p>return resizedBitmap;</p>
<p>case ROTATE_90:</p>
<p>matrix.postRotate(90);</p>
<p>// recreate the new Bitmap</p>
<p>resizedBitmap = Bitmap.createBitmap(img, 0, 0,</p>
<p>width, height, matrix, true);</p>
<p>return resizedBitmap;</p>
<p>case ROTATE_180:</p>
<p>matrix.postRotate(180);</p>
<p>// recreate the new Bitmap</p>
<p>resizedBitmap = Bitmap.createBitmap(img, 0, 0,</p>
<p>width, height, matrix, true);</p>
<p>return resizedBitmap;</p>
<p>case ROTATE_270:</p>
<p>matrix.postRotate(270);</p>
<p>// recreate the new Bitmap</p>
<p>resizedBitmap = Bitmap.createBitmap(img, 0, 0,</p>
<p>width, height, matrix, true);</p>
<p>return resizedBitmap;</p>
<p>}</p>
<p>return resizedBitmap;</p>
<p>}</p>
<p>catch (Exception e)</p>
<p>{</p>
<p>return null;</p>
<p>}</p>
<p>}</p>
<p>13 drawRect</p>
<p> J2me:</p>
<p> Android:</p>
<p>    public void drawRect(float left, float top, float right, float bottom,Paint paint)</p>
<p>14 声音处理</p>
<p> J2me:</p>
<p> Android:</p>
<p>    创建：</p>
<p>    MediaPlayer coverSound =MediaPlayer.create(Activity,R.raw.back);</p>
<p>    coverSound.prepare();</p>
<p>    播放：</p>
<p>    coverSound.start();</p>
<p>    暂停：</p>
<p>    coverSound.pause();</p>
<p>    声音设置：</p>
<p>    AudioManager vc = (AudioManager)Activity.getSystemService(Context.AUDIO_SERVICE);</p>
<p>    vc.adjustVolume(AudioManager.ADJUST_LOWER, 1);</p>
<p>    关闭：</p>
<p>    coverSound.stop();</p>
<p>    coverSound.release();</p>
<p>15 中断处理</p>
<p> J2me:</p>
<p> Android:</p>
<p>    public void onWindowFocusChanged(boolean visibility)</p>
<p>16 填充屏幕</p>
<p>J2me:</p>
<p>Android:</p>
<p>    CanvasInstance.drawColor(int color)</p>
<p>l7 按键处理</p>
<p> J2me:</p>
<p> Android:</p>
<p>    要使按键可以被响应，需要在构造函数中调用</p>
<p>    this.setFocusable(true);</p>
<p>    处理方法：</p>
<p>    public boolean onKeyDown(int keyCode, KeyEvent msg)</p>
<p>    public boolean onKeyUp(int keyCode, KeyEvent msg)</p>
<p>18 触摸屏处理</p>
<p> J2me:</p>
<p> Android:</p>
<p>    public boolean onTouchEvent(MotionEvent me)</p>
<p>    {</p>
<p>      if(me.getAction()==MotionEvent.ACTION_DOWN)</p>
<p>          。。。。。。</p>
<p>      else if(me.getAction()==MotionEvent.ACTION_UP)</p>
<p>          。。。。。。</p>
<p>      return true;</p>
<p>    } </p>
<p>19 资源文件的的存放位置及读取</p>
<p> J2me:</p>
<p> Android:</p>
<p>    图片：</p>
<p>        Res\drawable：</p>
<p>    声音：</p>
<p>        Res\raw</p>
<p>    数据：</p>
<p>        Asserts</p>
<p>        InputStream is=ActivityInstance.getAssets().open(path + &#8220;.dat&#8221;);</p>
<p>20 屏幕刷新，</p>
<p> J2me:</p>
<p>    repaint()</p>
<p>Android:</p>
<p>    postInvalidate();</p>
<p>21 颜色的使用</p>
<p> J2me:</p>
<p> Android:</p>
<p>      PaintInstance.setColor(0xAARRGGBB);</p>
<p>22 数据保存和读取</p>
<p>J2me:</p>
<p> Android:</p>
<p>    保存：</p>
<p>      SharedPreferences settings = ActivityInstance.getSharedPreferences(String name,int mode);</p>
<p>      SharedPreferences.Editor editor = settings.edit();</p>
<p>      editor.putBoolean(&#8220;hasRec&#8221;, true);</p>
<p>      。。。。。</p>
<p>      editor.putInt(&#8220;ex&#8221;,enemy[i].i_X_abs);</p>
<p>      editor.commit();</p>
<p>    读取：</p>
<p>      SharedPreferences settings = ActivityInstance.getSharedPreferences  (String name,int mode);</p>
<p>      this.curFaceDirection=settings.getInt(&#8220;cd&#8221;, 0);</p>
<p>23 填充方式</p>
<p>J2me:</p>
<p>Android:</p>
<p>    paint.setStyle(Style.FILL);</p>
<p>    paint.setStyle(Style.STROKE);</p>
<p>24锚点</p>
<p>J2me:</p>
<p>Android:</p>
<p>    setTextAlign(Paint.Align.LEFT);</p>
<p>25 连接处理</p>
<p>J2me:</p>
<p>    HttpConnection conn = (HttpConnection) Connector.open(&#8220;www.baidu.com&#8221;, Connector.READ, true);</p>
<p>    conn.setRequestMethod(&#8220;GET&#8221;);</p>
<p>    conn.setRequestProperty(&#8220;accept&#8221;, &#8220;**&#8221;);</p>
<p>    String location = conn.getRequestProperty(&#8220;location&#8221;);</p>
<p>    int resCode = conn.getResponseCode();</p>
<p>    InputStream stream = conn.getInputStream();</p>
<p>    conn.disconnect();</p>
<p>总结了一下，有以下几点不同之处：</p>
<p>J2ME中的连接从Connector打开，Android中从URL对象打开</p>
<p>要设置连接是否可读写，J2ME中可以直接在Connector.Open时设置，而在Android中必须使用setDoInput(boolean)和setDoOutput(boolean)方法设置</p>
<p>在J2ME中可以在Connector.Open中对连接进行超时设置，在Android中使用setConnectTimeout(int)不仅可以对连接超时进行设置，还能设置超时时间，参数为0时忽略连接超时</p>
<p>在使用这些Api时，一定要注意每个参数的意义，比如j2me中drawRect的后两个参数为宽度和高度，而在Android中则变成了结束点的坐标，使用时千万不能想当然的随意传参。</p>
<p>对于Override方法的定义，一定别忘了super.的方式来进行回调。</p>
<p>上面基本上把J2ME和Android在2D游戏游戏开发中常用的API做了一个比较，了解这些内容后，基本上是可以比较容易地把ME的游戏游戏平顺地迁 移到Android平台。当然，此处只限制为游戏，如果你想把一款J2ME的软件迁移到Android平台，此方法并不适用，你需要学习android的 控件的使用。</p>
<p>出自：http://blog.sina.com.cn/shilverfox</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javagg.com/archives/846/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>手机游戏动作编辑器MotionWelder&#8211;编写程序</title>
		<link>http://www.javagg.com/archives/800</link>
		<comments>http://www.javagg.com/archives/800#comments</comments>
		<pubDate>Thu, 08 Jul 2010 06:49:01 +0000</pubDate>
		<dc:creator>纯净水</dc:creator>
				<category><![CDATA[j2me]]></category>
		<category><![CDATA[游戏]]></category>
		<category><![CDATA[动作编辑器]]></category>

		<guid isPermaLink="false">http://www.javagg.com/?p=800</guid>
		<description><![CDATA[开发环境：Eclipse+EclipseMe （Eclipse3.4版本以上使用EclipseMe时在添加第三方库常常会出现classnotfound异常，可使用mtj代替EclipseME，或使用低一些的Eclipse版本）
1、新建J2ME工程，导入MotionWelder的J2ME库（在该程序下载包里J2ME 的lib目录里的motionwelder.jar）
       右键工程&#8211;&#62;Build Path &#8211;&#62;Add external archives&#8230; &#8212;&#62;选择motionwelder.jar打开，即可导入完毕。
2、把导出的动作数据文件拷到工程的资源目录，导入动作数据文件
/*
spriteName 动作数据文件
splitImageClips 内存加载图片的方式，如果为false则加载完整的图片（图片没有切片），true则加载切片的图片
imageloader  加载动作所需图片的类
*/
MSpriteData animationData = MSpriteLoader.loadMSprite(java.lang.String spriteName, boolean splitImageClips, MSpriteImageLoader imageloader)
3、加载动作图片
interface MSpriteImageLoader：
splitImageClips = false  - 加载完整的图片
           Image[]  loadImage(spriteName,imageId,orientationUsedInStudio);
splitImageClips = true &#8211; 加载图片切片
          Image[] loadImageClip(String spriteName,int imageId,int x,int y,int w,int h,int orientationUsedInStudio);
-spriteName
         &#8211; 动作数据文件的名字
-orientationUsedInStudio
        -使用了的翻转类型,
               MSprite.ORIENTATION_NONE                         &#8211; 无翻转
               MSprite.ORIENTATION_FLIP_H                      - 水平翻转
               MSprite.ORIENTATION_FLIP_V                      - 垂直翻转
               MSprite.ORIENTATION_FLIP_BOTH_H_V   &#8211; 水平和垂直翻转
- imageId
         &#8211; 图片id，即动作所使用到的图片
-x,y,w,h      
       -切片在图片中的坐标（x，y，宽，高）.
Image[3]
       Image[0] =无翻转图片
       Image[1] [...]]]></description>
			<content:encoded><![CDATA[<p>开发环境：Eclipse+EclipseMe （Eclipse3.4版本以上使用EclipseMe时在添加第三方库常常会出现classnotfound异常，可使用mtj代替EclipseME，或使用低一些的Eclipse版本）<br />
1、新建J2ME工程，导入MotionWelder的J2ME库（在该程序下载包里J2ME 的lib目录里的motionwelder.jar）<br />
       右键工程&#8211;&gt;Build Path &#8211;&gt;Add external archives&#8230; &#8212;&gt;选择motionwelder.jar打开，即可导入完毕。<br />
2、把导出的动作数据文件拷到工程的资源目录，导入动作数据文件<br />
/*<br />
spriteName 动作数据文件<br />
splitImageClips 内存加载图片的方式，如果为false则加载完整的图片（图片没有切片），true则加载切片的图片<br />
imageloader  加载动作所需图片的类<br />
*/<br />
MSpriteData animationData = MSpriteLoader.loadMSprite(java.lang.String spriteName, boolean splitImageClips, MSpriteImageLoader imageloader)<br />
3、加载动作图片<br />
interface MSpriteImageLoader：<br />
splitImageClips = false  - 加载完整的图片<br />
           Image[]  loadImage(spriteName,imageId,orientationUsedInStudio);<span id="more-800"></span></p>
<p>splitImageClips = true &#8211; 加载图片切片<br />
          Image[] loadImageClip(String spriteName,int imageId,int x,int y,int w,int h,int orientationUsedInStudio);</p>
<p>-spriteName<br />
         &#8211; 动作数据文件的名字<br />
-orientationUsedInStudio<br />
        -使用了的翻转类型,<br />
               MSprite.ORIENTATION_NONE                         &#8211; 无翻转<br />
               MSprite.ORIENTATION_FLIP_H                      - 水平翻转<br />
               MSprite.ORIENTATION_FLIP_V                      - 垂直翻转<br />
               MSprite.ORIENTATION_FLIP_BOTH_H_V   &#8211; 水平和垂直翻转<br />
- imageId<br />
         &#8211; 图片id，即动作所使用到的图片<br />
-x,y,w,h      <br />
       -切片在图片中的坐标（x，y，宽，高）.<br />
Image[3]<br />
       Image[0] =无翻转图片<br />
       Image[1] = 水平翻转图片      // 如果没有为null<br />
       Image[2] = 垂直翻转图片         // 如果没有为null<br />
4、播放动作<br />
/*动作列表*/<br />
public static int ANIM_STAND = 0;<br />
public static int ANIM_RUN = 1;</p>
<p>/* 创建动作播放器 */<br />
MSimpleAnimationPlayer player = new MSimpleAnimationPlayer(MSpriteData spriteData, int spriteX, int spriteY);<br />
或<br />
MSpriteAnimationPlayer player = new MSpriteAnimationPlayer(MSpriteData spriteData, MSprite sprite);<br />
两个的区别在于：正如名字一样MSpriteAnimationPlayer提供的一个简单的播放器，它在处理end of animation时是仅停止播放，不能更好地拓展。如果需要灵巧地控制各个动画的切换最好使用MSpriteAnimationPlayer。</p>
<p>/*设置当前的播放动作*/<br />
player.setAnimation(ANIM_STAND);<br />
player.setLoopOffset(-1);           // 播放一次..<br />
player.setLoopOffset(0);            // 从第一帧到帧尾循环播放<br />
player.setLoopOffset(2);           // 从第二帧到帧尾循环播放</p>
<p>/* 循环调用这里，更新和绘制动作*/<br />
player.update();<br />
player.drawFrame(g);</p>
<p>例子：使用第一节的数据文件，当我们按数字键5或者中键的时候施放这个向下攻击的动作。主要代码如下：<br />
主屏幕   GameScreen.java<br />
import javax.microedition.lcdui.Canvas;<br />
import javax.microedition.lcdui.Graphics;<br />
public class GameScreen extends Canvas implements Runnable {<br />
private GameSprite gameSprite;//游戏精灵<br />
private static final int KEY_FIRE=-5;//键盘中键<br />
public static boolean isHit = false;//是否发动攻击<br />
public GameScreen() {<br />
  gameSprite = new GameSprite();//实例化游戏精灵<br />
  Thread t = new Thread(this);//创建线程<br />
  t.start();//启动线程<br />
}<br />
protected void paint(Graphics g) {<br />
  g.setColor(0xffffffff);<br />
  g.fillRect(0, 0, getWidth(), getHeight());//清屏<br />
  gameSprite.paint(g);//绘制精灵<br />
}<br />
public void run() {<br />
  try {<br />
   long time;<br />
   while (true) {<br />
    time = System.currentTimeMillis();<br />
    //重绘<br />
    repaint();<br />
    serviceRepaints();<br />
    if (isHit) {//如果发动攻击<br />
     gameSprite.update();//更新精灵<br />
    }<br />
    long timeTakenForPainting = System.currentTimeMillis() &#8211; time;<br />
    if (timeTakenForPainting &lt; 100) {<br />
     Thread.sleep(100 &#8211; timeTakenForPainting);<br />
    }<br />
   }<br />
  } catch (Exception e) {<br />
   System.out.println(&#8220;Error &#8221; + e);<br />
  }<br />
}<br />
protected void keyPressed(int key) {<br />
  if (key == Canvas.KEY_NUM5 || key == KEY_FIRE) {<br />
   isHit = true;//按数字键5或中键攻击<br />
  }<br />
}<br />
protected void keyReleased(int key) {<br />
}<br />
}</p>
<p>游戏精灵  GameSprite.java<br />
import javax.microedition.lcdui.Graphics;<br />
import com.studio.motionwelder.MPlayer;<br />
import com.studio.motionwelder.MSprite;<br />
import com.studio.motionwelder.MSpriteAnimationPlayer;<br />
import com.studio.motionwelder.MSpriteData;<br />
import com.studio.motionwelder.MSpriteLoader;<br />
public class GameSprite implements MSprite {<br />
private MSpriteData spriteData;<br />
private MPlayer player;<br />
private int animation;<br />
private static final int DOWN_HIT = 0;<br />
int spriteX = 100;//精灵坐标<br />
int spriteY = 175;<br />
public GameSprite() {<br />
  try {<br />
   loadResource();//加载资源<br />
  } catch (Exception e) {<br />
   e.printStackTrace();<br />
  }<br />
  player = new MSpriteAnimationPlayer(spriteData, this);//创建播放器<br />
  this.setAnimation(DOWN_HIT);//设置当前动画ID<br />
}<br />
private void setAnimation(int animation) {//设置动画ID<br />
  switch (animation) {<br />
  case DOWN_HIT:<br />
   player.setAnimation(DOWN_HIT);<br />
   break;<br />
  }<br />
  this.animation = animation;<br />
}<br />
private void loadResource() throws Exception {<br />
  spriteData = MSpriteLoader.loadMSprite(&#8220;/SwordSprite.anu&#8221;, true,<br />
    ResourceLoader.getInstance());//加载数据文件<br />
}<br />
public void update() {<br />
  switch (animation) {<br />
  case DOWN_HIT:<br />
   player.setLoopOffset(-1);//设置仅播放一次<br />
   break;<br />
  }<br />
  player.update();//下一帧<br />
}<br />
public void endOfAnimation() {//处理动画播放完后的方法，可以添加切换到另外的动画等等<br />
  switch (animation) {<br />
  case DOWN_HIT:<br />
   player.setFrame(0);//如果播放完则设置帧为第0帧<br />
   break;<br />
  }<br />
  GameScreen.isHit = false;//攻击动作完成<br />
}<br />
public int getSpriteDrawX() {//设置精灵的绘制坐标X<br />
  return spriteX;<br />
}<br />
public int getSpriteDrawY() {//设置精灵的绘制坐标Y<br />
  return spriteY;<br />
}<br />
public byte getSpriteOrientation() {//设置精灵的方向<br />
  return 0;<br />
}<br />
public void updateSpritePosition(int arg0, int arg1) {<br />
  //更新精灵的位置，比如跑动是X及Y的坐标变化<br />
}<br />
public void paint(Graphics g) {<br />
  player.drawFrame(g);//绘制动作的帧<br />
}<br />
}</p>
<p>资源加载 ResourceLoader.java<br />
import java.io.IOException;<br />
import javax.microedition.lcdui.Image;<br />
import javax.microedition.lcdui.game.Sprite;<br />
import com.studio.motionwelder.MSprite;<br />
import com.studio.motionwelder.MSpriteImageLoader;<br />
public class ResourceLoader implements MSpriteImageLoader {<br />
private static ResourceLoader resLoader;// 单例<br />
private ResourceLoader() {<br />
}<br />
public static ResourceLoader getInstance() {// 获取ResourceLoader的实例<br />
  if (resLoader == null)<br />
   resLoader = new ResourceLoader();<br />
  return resLoader;<br />
}<br />
public Image[] loadImage(String spriteName, int imageId,<br />
   int orientationUsedInStudio) {// 整图形式加载图片<br />
  return null;<br />
}<br />
public Image[] loadImageClip(String spriteName, int imageId, int x, int y,<br />
   int w, int h, int orientationUsedInStudio) {// 切片形式加载图片<br />
  boolean doYouNeedHFlippedSpriteInYourgame = false;<br />
  boolean doYouNeedVFlippedSpriteInYourgame = false; // 是否有旋转操作<br />
  Image baseImage = null;<br />
  if (imageId == 0) {<br />
   baseImage = loadImage(&#8220;/hero.png&#8221;);<br />
   doYouNeedHFlippedSpriteInYourgame = false;<br />
   doYouNeedVFlippedSpriteInYourgame = false;<br />
  }<br />
  Image img[] = new Image[3];<br />
  img[0] = Image.createImage(baseImage, x, y, w, h, Sprite.TRANS_NONE); // 保存无旋转的切片<br />
  /** 如果使用了Nokia的图像操作就不要这样用，关于Nokia的操作作者在库代码里把它注释掉了 */<br />
  if (orientationUsedInStudio == MSprite.ORIENTATION_FLIP_H<br />
    || orientationUsedInStudio == MSprite.ORIENTATION_FLIP_BOTH_H_V<br />
    || doYouNeedHFlippedSpriteInYourgame)<br />
   img[1] = Image.createImage(baseImage, x, y, w, h,<br />
     Sprite.TRANS_MIRROR); // 保存水平旋转的切片<br />
  /** 如果使用了Nokia的图像操作就不要这样用，关于Nokia的操作作者在库代码里把它注释掉了 */<br />
  if (orientationUsedInStudio == MSprite.ORIENTATION_FLIP_V<br />
    || orientationUsedInStudio == MSprite.ORIENTATION_FLIP_BOTH_H_V<br />
    || doYouNeedVFlippedSpriteInYourgame)<br />
   img[2] = Image.createImage(baseImage, x, y, w, h,<br />
     Sprite.TRANS_MIRROR_ROT180); // 保存垂直旋转的切片<br />
  return img;<br />
}<br />
private Image loadImage(String imagePath) {<br />
  try {<br />
   Image img = Image.createImage(imagePath);<br />
   return img;<br />
  } catch (IOException e) {<br />
   e.printStackTrace();<br />
  }<br />
  return null;<br />
}<br />
}</p>
<p><a href="http://www.javagg.com/wp-content/uploads/2010/07/http_imgload.gif"><img class="alignnone size-full wp-image-801" title="http_imgload" src="http://www.javagg.com/wp-content/uploads/2010/07/http_imgload.gif" alt="" width="160" height="191" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.javagg.com/archives/800/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>应用双缓冲技术解决画面闪烁的问题</title>
		<link>http://www.javagg.com/archives/566</link>
		<comments>http://www.javagg.com/archives/566#comments</comments>
		<pubDate>Fri, 05 Mar 2010 15:36:01 +0000</pubDate>
		<dc:creator>纯净水</dc:creator>
				<category><![CDATA[j2me]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">eric_DIARY_105790599</guid>
		<description><![CDATA[有些时候我们可能在J2ME中遇到画面闪烁的问题，这时候我们可以应用双缓冲的技术来解决，不过由于现在越来越多的手机自身就支持双缓冲了。所以这里只做个简单的介绍。
我写了程序本来想在NOkia 6108上比较用和不用的区别，结果这个手机自己就支持双缓冲，所以根本没有比较出来。不过了解这个技术还是有必要的，所以我决定还是写出来。双缓冲本来是在开发PC应用程序的时候遇到的。在MIDP开发中同样存在，当你在屏幕上进行原始写画的时候，如果很复杂的话，用户会发现界面在闪烁。因此你可以这样做，首先在另一个图片上进行paint()得操作，当完成了以后就把它copy到屏幕上，由于通常copy得时候速度很快就不会出现闪烁了。这个技术就是双缓冲。
Canvas类提供了isDoubleBuffered()方法来判断设备是不是支持这个功能，如果返回true的话，那么我们就没有必要使用双缓冲了，如果false的话，我们可以这么做：
public DoubleCanvas(UIController uicontroller)
{
super();
this.uicontroller = uicontroller;
width = this.getWidth();
height = this.getHeight();
this.setCommandListener(this);
if(!isDoubleBuffered())
{
offImage = Image.createImage(width,height);
}
}
protected void paint(Graphics arg0)
{
arg0.drawString(isDoubleBuffered()+&#8221;",width/2,height/2,Graphics.HCENTER&#124;Graphics.TOP);
 Graphics saved = arg0;
if(offImage != null)
{
arg0 = offImage.getGraphics();
}
arg0.setColor(255,128,128);
for(int i = 2,j=2;i&#60;width/2-6&#38;&#38;j&#60;height/2-6;i=i+2,j=j+2)
{
arg0.drawRect(i,j,width-2*i,height-2*j);
}
if(arg0 != saved)
{
saved.drawImage(offImage,0,0,Graphics.LEFT&#124;Graphics.TOP);
}
 }
得到offImage得Graphics实例后，进行paint()得操作。这个部分通常比较复杂，我这里的不够复杂：）
然后把offImage直接copy到屏幕上也就是执行saved.drawImage(offImage,0,0,Graphics.LEFT&#124;Graphics.TOP);

 我写了一个应用程序来比较使用和不使用双缓冲的效果，但是由于我的手机支持双缓冲所以看不出效果，如果你有兴趣，那么可以把paint()部分的代码修改的复杂一些然后再移植到不支持的手机上也许可以看出效果，下面是我程序的代码：
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;


public class DoubleBufferMIDlet extends MIDlet
{
private UIController uicontroller;
protected void startApp() throws MIDletStateChangeException
{
uicontroller = new UIController(this);
uicontroller.init();
 }
 protected void pauseApp()
{

 }

protected void destroyApp(boolean arg0) throws MIDletStateChangeException
{
 [...]]]></description>
			<content:encoded><![CDATA[<p>有些时候我们可能在J2ME中遇到画面闪烁的问题，这时候我们可以应用双缓冲的技术来解决，不过由于现在越来越多的手机自身就支持双缓冲了。所以这里只做个简单的介绍。</p>
<p>我写了程序本来想在NOkia 6108上比较用和不用的区别，结果这个手机自己就支持双缓冲，所以根本没有比较出来。不过了解这个技术还是有必要的，所以我决定还是写出来。双缓冲本来是在开发PC应用程序的时候遇到的。在MIDP开发中同样存在，当你在屏幕上进行原始写画的时候，如果很复杂的话，用户会发现界面在闪烁。因此你可以这样做，首先在另一个图片上进行paint()得操作，当完成了以后就把它copy到屏幕上，由于通常copy得时候速度很快就不会出现闪烁了。这个技术就是双缓冲。<span id="more-566"></span></p>
<p>Canvas类提供了isDoubleBuffered()方法来判断设备是不是支持这个功能，如果返回true的话，那么我们就没有必要使用双缓冲了，如果false的话，我们可以这么做：<br />
public DoubleCanvas(UIController uicontroller)<br />
{<br />
super();<br />
this.uicontroller = uicontroller;<br />
width = this.getWidth();<br />
height = this.getHeight();<br />
this.setCommandListener(this);<br />
<span style="background-color: #ff0000;">if(!isDoubleBuffered())<br />
{<br />
offImage = Image.createImage(width,height);<br />
}</span></p>
<p>}<br />
protected void paint(Graphics arg0)<br />
{</p>
<p>arg0.drawString(isDoubleBuffered()+&#8221;",width/2,height/2,Graphics.HCENTER|Graphics.TOP);<br />
<span style="background-color: #d3d3d3;"> Graphics saved = arg0;<br />
if(offImage != null)<br />
{<br />
arg0 = offImage.getGraphics();<br />
}<br />
arg0.setColor(255,128,128);<br />
for(int i = 2,j=2;i&lt;width/2-6&amp;&amp;j&lt;height/2-6;i=i+2,j=j+2)<br />
{<br />
arg0.drawRect(i,j,width-2*i,height-2*j);<br />
}<br />
if(arg0 != saved)<br />
{<br />
saved.drawImage(offImage,0,0,Graphics.LEFT|Graphics.TOP);<br />
}</span></p>
<p><span style="background-color: #d3d3d3;"> }</span></p>
<p><span style="background-color: #ffffff;">得到offImage得Graphics实例后，进行paint()得操作。这个部分通常比较复杂，我这里的不够复杂：）<br />
然后把offImage直接copy到屏幕上也就是执行</span><span style="background-color: #d3d3d3;">saved.drawImage(offImage,0,0,Graphics.LEFT|Graphics.TOP);<br />
</span></p>
<p><span style="background-color: #d3d3d3;"> <span style="background-color: #ffffff;">我写了一个应用程序来比较使用和不使用双缓冲的效果，但是由于我的手机支持双缓冲所以看不出效果，如果你有兴趣，那么可以把paint()部分的代码修改的复杂一些然后再移植到不支持的手机上也许可以看出效果，下面是我程序的代码：</span></span></p>
<p><span style="background-color: #ffffff;">import javax.microedition.midlet.MIDlet;<br />
import javax.microedition.midlet.MIDletStateChangeException;<br />
</span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"><br />
public class <span style="background-color: #ff0000;">DoubleBufferMIDlet </span>extends MIDlet<br />
{<br />
private UIController uicontroller;</p>
<p>protected void startApp() throws MIDletStateChangeException<br />
{<br />
uicontroller = new UIController(this);<br />
uicontroller.init();</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> }</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> protected void pauseApp()<br />
{<br />
</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> }</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"><br />
protected void destroyApp(boolean arg0) throws MIDletStateChangeException<br />
{<br />
</span></span><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> }</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;">}</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;">import javax.microedition.lcdui.Command;<br />
import javax.microedition.lcdui.CommandListener;<br />
import javax.microedition.lcdui.Displayable;<br />
import javax.microedition.lcdui.List;<br />
</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"><br />
public class <span style="background-color: #ff0000;">MainListUI</span> extends List implements CommandListener<br />
{</span></span><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"><br />
private UIController uicontroller;</p>
<p>public MainListUI(UIController uicontroller)<br />
{<br />
super(&#8220;Test&#8221;,List.IMPLICIT);<br />
this.uicontroller = uicontroller;<br />
this.append(&#8220;Non-buffer&#8221;,null);<br />
this.append(&#8220;Double-buffer&#8221;,null);<br />
this.setCommandListener(this);<br />
}</p>
<p>public void commandAction(Command arg0, Displayable arg1)<br />
{</span></span></p>
<p><span style="background-color: #ffffff;"> if(arg0 == List.SELECT_COMMAND)<br />
{<br />
if(this.getSelectedIndex() == 0)<br />
{</p>
<p>uicontroller.handleEvent(UIController.EventID.DISPLAY_NON_BUFFER);<br />
}<br />
else<br />
{</p>
<p>uicontroller.handleEvent(UIController.EventID.DISPLAY_BUFFER);<br />
}<br />
}<br />
</span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> }</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;">}<br />
</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;">import javax.microedition.lcdui.Command;<br />
import javax.microedition.lcdui.CommandListener;<br />
import javax.microedition.lcdui.Display;<br />
import javax.microedition.lcdui.Displayable;</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"><br />
public class <span style="background-color: #ff0000;">UIController</span> implements CommandListener<br />
{</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> private Display display;<br />
private DoubleBufferMIDlet midlet;<br />
private MainListUI mainList;<br />
private NonDoubleCanvas noDoubleCanvas;<br />
private DoubleCanvas doubleCanvas;<br />
public static final Command backCommand = new Command(&#8220;Back&#8221;,Command.BACK,2);</p>
<p>public static class EventID<br />
{<br />
public static final int DISPLAY_NON_BUFFER = 0;<br />
public static final int DISPLAY_BUFFER = 1;<br />
}</p>
<p>public UIController(DoubleBufferMIDlet midlet)<br />
{<br />
this.midlet = midlet;<br />
}</p>
<p>public void init()<br />
{<br />
display = Display.getDisplay(midlet);<br />
mainList = new MainListUI(this);<br />
noDoubleCanvas = new NonDoubleCanvas(this);<br />
doubleCanvas = new DoubleCanvas(this);<br />
addCommand();<br />
display.setCurrent(mainList);<br />
}</p>
<p>public void addCommand()<br />
{<br />
noDoubleCanvas.addCommand(backCommand);<br />
doubleCanvas.addCommand(backCommand);<br />
}</p>
<p>public Display getDisplay()<br />
{<br />
return display;<br />
}</p>
<p>public void setCurrent(Displayable disp)<br />
{<br />
display.setCurrent(disp);<br />
}</p>
<p>public void handleEvent(int eventID)<br />
{<br />
switch(eventID)<br />
{<br />
case EventID.DISPLAY_BUFFER:<br />
{<br />
setCurrent(doubleCanvas);<br />
System.out.println(EventID.DISPLAY_BUFFER);<br />
break;<br />
}<br />
case EventID.DISPLAY_NON_BUFFER:<br />
{<br />
setCurrent(noDoubleCanvas);<br />
System.out.println(EventID.DISPLAY_NON_BUFFER);<br />
break;<br />
}<br />
}<br />
}<br />
public void commandAction(Command arg0, Displayable arg1)<br />
{</p>
<p>if(arg0 == backCommand)<br />
{<br />
display.setCurrent(mainList);<br />
}</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> }</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> </span></span></p>
<p><span style="background-color: #ffffff;">}</span></p>
<p><span style="background-color: #ffffff;">import javax.microedition.lcdui.Canvas;<br />
import javax.microedition.lcdui.Command;<br />
import javax.microedition.lcdui.CommandListener;<br />
import javax.microedition.lcdui.Displayable;<br />
import javax.microedition.lcdui.Graphics;</span></p>
<p><span style="background-color: #ffffff;">public class <span style="background-color: #ff0000;">NonDoubleCanvas</span> extends Canvas implements CommandListener<br />
{</p>
<p>private UIController uicontroller;<br />
private int width;<br />
private int height;</p>
<p>public NonDoubleCanvas(UIController uicontroller)<br />
{<br />
super();<br />
this.uicontroller = uicontroller;<br />
width = this.getWidth();<br />
height = this.getHeight();<br />
this.setCommandListener(this);<br />
}</span></p>
<p><span style="background-color: #ffffff;"><br />
protected void paint(Graphics arg0)<br />
{</p>
<p>arg0.setColor(100,100,100);<br />
arg0.drawString(isDoubleBuffered()+&#8221;",width/2,height/2,Graphics.HCENTER|Graphics.TOP);<br />
for(int i = 2,j=2;i&lt;width/2-6&amp;&amp;j&lt;height/2-6;i=i+2,j=j+2)<br />
{<br />
arg0.drawRect(i,j,width-2*i,height-2*j);<br />
}</span></p>
<p><span style="background-color: #ffffff;"> }</span></p>
<p><span style="background-color: #ffffff;"> public void commandAction(Command arg0, Displayable arg1)<br />
{</p>
<p>uicontroller.commandAction(arg0,arg1);<br />
}</span></p>
<p><span style="background-color: #ffffff;">}</span></p>
<p><span style="background-color: #ffffff;">import javax.microedition.lcdui.Canvas;<br />
import javax.microedition.lcdui.Command;<br />
import javax.microedition.lcdui.CommandListener;<br />
import javax.microedition.lcdui.Displayable;<br />
import javax.microedition.lcdui.Graphics;<br />
import javax.microedition.lcdui.Image;</span></p>
<p><span style="background-color: #ffffff;">public class <span style="background-color: #ff0000;">DoubleCanvas </span>extends Canvas implements CommandListener<br />
{</span></p>
<p><span style="background-color: #ffffff;"><br />
private UIController uicontroller;<br />
private Image offImage;<br />
private int width;<br />
private int height;</p>
<p>public DoubleCanvas(UIController uicontroller)<br />
{<br />
super();<br />
this.uicontroller = uicontroller;<br />
width = this.getWidth();<br />
height = this.getHeight();<br />
this.setCommandListener(this);<br />
if(!isDoubleBuffered())<br />
{<br />
offImage = Image.createImage(width,height);<br />
}</p>
<p>}</span></p>
<p><span style="background-color: #ffffff;"><br />
protected void paint(Graphics arg0)<br />
{</p>
<p>arg0.drawString(isDoubleBuffered()+&#8221;",width/2,height/2,Graphics.HCENTER|Graphics.TOP);<br />
Graphics saved = arg0;<br />
if(offImage != null)<br />
{<br />
arg0 = offImage.getGraphics();<br />
}<br />
arg0.setColor(255,128,128);<br />
for(int i = 2,j=2;i&lt;width/2-6&amp;&amp;j&lt;height/2-6;i=i+2,j=j+2)<br />
{<br />
arg0.drawRect(i,j,width-2*i,height-2*j);<br />
}<br />
if(arg0 != saved)<br />
{<br />
saved.drawImage(offImage,0,0,Graphics.LEFT|Graphics.TOP);<br />
}</span></p>
<p><span style="background-color: #ffffff;"> }</span></p>
<p><span style="background-color: #ffffff;"> public void commandAction(Command arg0, Displayable arg1)<br />
{<br />
uicontroller.commandAction(arg0,arg1);<br />
}</span></p>
<p><span style="background-color: #ffffff;">}</span></p>
<p><span style="background-color: #ffffff;"> </span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.javagg.com/archives/566/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

