J2ME 2D小游戏入门之旅.docx

上传人:b****5 文档编号:3408859 上传时间:2022-11-22 格式:DOCX 页数:30 大小:56.12KB
下载 相关 举报
J2ME 2D小游戏入门之旅.docx_第1页
第1页 / 共30页
J2ME 2D小游戏入门之旅.docx_第2页
第2页 / 共30页
J2ME 2D小游戏入门之旅.docx_第3页
第3页 / 共30页
J2ME 2D小游戏入门之旅.docx_第4页
第4页 / 共30页
J2ME 2D小游戏入门之旅.docx_第5页
第5页 / 共30页
点击查看更多>>
下载资源
资源描述

J2ME 2D小游戏入门之旅.docx

《J2ME 2D小游戏入门之旅.docx》由会员分享,可在线阅读,更多相关《J2ME 2D小游戏入门之旅.docx(30页珍藏版)》请在冰豆网上搜索。

J2ME 2D小游戏入门之旅.docx

J2ME2D小游戏入门之旅

J2ME 2D小游戏入门之旅

(一)游戏的框架

[录入者:

admin| 时间:

2006-05-1917:

36:

25|作者:

| 来源:

|点击数:

213]

[上一篇][下一篇]

 

favoyang

转载请联系作者

响应站长mingjava的号召,我也和大家一起分享一下我的经验,希望大家指教。

同时欢迎各位高手的原创文章。

     前几天看到tony在csdn上发布自己的学习作品“是男人就坚持60s”,觉得创意虽然简单但是却很耐玩,是学习手机游戏制作的入门经典,于是一时兴起,clone了一下,图片依然使用的是tony的图片,纯粹学习之用。

如果大家对这个游戏感兴趣可以与tony联系或访问他的blog。

     从发展趋势上说midp2.0是趋势,最便宜的midp2.0手机如ot735i,已经1700元左右;而西门子一年前的高端机cx65,现在也只有2500左右;并且2500-3000这个价位的midp2.0手机有多种选择,西门子、se、N机都有。

我个人挺喜欢cx65,如果将来手机制造商成本不断降低,相信1500元的midp将不是梦…当然还要看应用是否丰富了。

      言归正传,我们将使用midp2.0来开发我们的游戏,代号fly。

开发工具jbulider。

等文章全写完了,会提供src下载。

目录:

一、游戏的框架

二、完善周边工具类(图象、GameObject、Font)

三、控制飞机的移动

四、加入子弹群,实现碰撞运算

五、实现爆炸效果、并加入道具导弹

六、不足多多,你认为呢?

七、源码

  一、游戏的框架

我们的游戏需要一个通用的游戏框架,也方便以后的开发,但实现一个引擎是复杂的。

作为初学者如果要你考虑太多的问题,恐怕会让你偏离主线,这里只给出canvas的代码,不理解可以参看本站的另外一篇系列文章《使用MIDP2.0开发游戏》。

 publicclassMyGameCanvasextendsGameCanvas

implementsRunnable,CommandListener{

 privatestaticMyGameCanvasinstance;

 Graphicsg;

 booleanrunning;

 Threadt;

 Commandstartcmd,exitcmd,restartcmd;

 intkeystate;

 booleankeyevent;

 booleankey_up,key_down,key_left,key_right,key_fire;

 privatebooleanallowinput;

 publicintscreenwidth;

 publicintscreenheight;

 booleangameover;

 //defineyourvariablehere

   //defineyourvariableend

   protectedMyGameCanvas(){

   super(true);

   g=getGraphics();

   running=false;

   t=null;

   addCommand(startcmd=newCommand("start",Command.OK,1));

   addCommand(exitcmd=newCommand("exit",Command.EXIT,1));

   setCommandListener(this);

   screenwidth=getWidth();

   screenheight=getHeight();

    //putyourinitoncecodehere

       //putyourinitoncecodeend

 }

   synchronizedpublicstaticMyGameCanvasgetInstance(){

   if(instance==null){

     instance=newMyGameCanvas();

     System.out.println("newMyGameCanvas");

   }

   returninstance;

 }

  publicvoidrun(){

   System.out.println("MyGameCanvasrunstart");

   longst=0,et=0,diff=0;

   intrate=50;//16-17framepersecond

   while(running){

     st=System.currentTimeMillis();

     gameinput();

     gameMain();

     et=System.currentTimeMillis();

     diff=et-st;

     if(diff

       //System.out.println("Sleep"+(rate-diff));

       try{

         Thread.sleep(rate-diff);

       }

       catch(InterruptedExceptionex){}

     }else{

       //System.out.println("rush,andtheframeusingtime:

"+diff);

     }

   }

   System.out.println("MyGameCanvasrunend");

 }

  publicvoidstart(){

     if(!

running){

       running=true;

       t=newThread(this);

       t.start();

     }

 }

  privatevoidgameMain(){

   g.setColor(0,0,0);//clearscreen

   g.fillRect(0,0,getWidth(),getHeight());

    flushGraphics();

 }

  privatevoidgameInit(){

   gameover=false;

   allowinput=true;

   key_up=key_down=key_left=key_right=key_fire=false;

 }

  publicvoidstop(){

   if(running){

     running=false;

   }

 }

  publicvoidcommandAction(Commandc,Displayabled){

   Stringcmdstr=c.getLabel();

   if(cmdstr.equals("start")){

      gameInit();

      start();

      removeCommand(startcmd);

      addCommand(restartcmd=newCommand("restart",Command.OK,1));

   }elseif(cmdstr.equals("restart")){

     stop();

     while(t.isAlive());

     gameInit();

     start();

   }elseif(cmdstr.equals("exit")){

     stop();

     Navigate.midlet.destroyApp(false);

     Navigate.midlet.notifyDestroyed();

   }

 }

  privatevoidgameinput(){

   if(allowinput){

     keystate=getKeyStates();

     keyevent=false;

     if((keystate&UP_PRESSED)!

=0){//up

       key_up=true;keyevent=true;

       //dealyourunstopjobcodehere

       //System.out.println("uppress");

       //dealyourunstopjobcodeend

     }elseif((keystate&UP_PRESSED)==0){//releasekey

       if(key_up==true){

         key_up=false;

         //dealyouronepress-onejobcodehere

         //System.out.println("uprelease");

         //dealyouronepress-onejobcodeend

       }

     }

      if((keystate&DOWN_PRESSED)!

=0){//down

       key_down=true;keyevent=true;

       //dealyourunstopjobcodehere

       //System.out.println("downpress");

       //dealyourunstopjobcodeend

     }elseif((keystate&DOWN_PRESSED)==0){//releasekey

       if(key_down==true){

         key_down=false;

         //dealyouronepress-onejobcodehere

         //System.out.println("downrelease");

         //dealyouronepress-onejobcodeend

       }

     }

      if((keystate&LEFT_PRESSED)!

=0){//left

       key_left=true;keyevent=true;

       //dealyourunstopjobcodehere

       //System.out.println("leftpress");

       //dealyourunstopjobcodeend

     }elseif((keystate&LEFT_PRESSED)==0){//releasekey

       if(key_left==true){

         key_left=false;

         //dealyouronepress-onejobcodehere

         //System.out.println("leftrelease");

         //dealyouronepress-onejobcodeend

       }

     }

      if((keystate&RIGHT_PRESSED)!

=0){//right

       key_right=true;keyevent=true;

       //dealyourunstopjobcodehere

//System.out.println("rightpress");

       //dealyourunstopjobcodeend

     }elseif((keystate&RIGHT_PRESSED)==0){//releasekey

       if(key_right==true){

         key_right=false;

         //dealyouronepress-onejobcodehere

         //System.out.println("rightrelease");

         //dealyouronepress-onejobcodeend

       }

     }

      if((keystate&FIRE_PRESSED)!

=0){//fire

       key_fire=true;keyevent=true;

       //dealyourunstopjobcodehere

       //System.out.println("firepress");

       //dealyourunstopjobcodeend

     }elseif((keystate&FIRE_PRESSED)==0){//releasekey

       if(key_fire==true){

         key_fire=false;

         //dealyouronepress-onejobcodehere

         //System.out.println("firerelease");

         //dealyouronepress-onejobcodeend

       }

     }

     if(!

keyevent){

       //nokeyeventhere

       //System.out.println("NOKEYpress");

       //nokeyeventend

     }

   }

 }

  publicstaticvoidcleanJob(){

   instance=null;

 }

}

 使用singlon实现,因为每个gamecanvas都需要很多的内存空间。

另外对我们来说,只要改写gameInit(),gameMain(),一次性初始化的代码写在构造函数中。

J2ME 2D小游戏入门之旅

(二)完善周边工具类

[录入者:

admin| 时间:

2006-05-1917:

36:

28|作者:

| 来源:

|点击数:

155]

[上一篇][下一篇]

二、完善周边工具类(图象、GameObject、Font)

    虽然我们有了midp2.0的支持,但是有时还是需要一些辅助工具,方便我们使用。

这怕是在进行真正的游戏设计之前最有趣的了。

    1,首先是一个ImageTools工具类,提供一个方法帮助调用Image

publicclassImageTools{

 protectedImageTools(){

 }

 publicstaticImagegetImage(Stringstr){

   Imageimg=null;

   try{

     img=Image.createImage(str);

   }

   catch(Exceptionex){

     System.out.println(ex);

   }

   finally{

     returnimg;

   }

 }

}

2.GameObject,提供一个通用的游戏对象。

      有了Sprite类,为什么还要GameObject呢?

其实我们一般是将Sprite,看作成一个高级的Image,往往一个Sprite要被多个游戏对象调用,GameObject其实就是Sprite的状态类。

GameObject提供简单的生命周期概念,动画更新速度;

 publicclassGameObject{

 publicSpritesprite;//内置的Sprite

 publicbooleanalive;//存活标记

 privateintlifecount=0;//生命周期计数器

 publicintlifetime=0;//生命周期,以桢为单位

 publicintspeed=0;//动画桢更新速度,(0至无穷,0代表每一桢跟新一个画面)

 privateintanimcount=0;///动画桢更新计数器

  publicGameObject(Imageimg,intwidth,intheight){

   sprite=newSprite(img,width,height);

   reset();

 }

  publicvoidmove(intdx,intdy){//相对移动

   sprite.move(dx,dy);

 }

  publicvoidmoveto(intx,inty){//绝对移动

   sprite.setPosition(x,y);

 }

  publicvoidupdate(){//更新状态,动画桢更新,生命周期更新

   if(!

alive)

     return;

   if(++animcount>speed){

     animcount=0;

     sprite.nextFrame();

     if(lifetime!

=0&&++lifecount>lifetime)

       alive=false;

   }

 }

  publicvoidpaint(Graphicsg){//Paint

   if(!

alive)

     return;

   sprite.paint(g);

 }

 publicvoidreset(){//复位

   alive=true;

   lifecount=0;

   animcount=0;

   sprite.setFrame(0);

 }

}

     3.封装字体类,你需要漂亮的字体吗?

   我们经常需要用图片来输出文字,一个方便的字体类是必须的。

我们希望仅仅提供一个图片,一个图片所描述的字符的数组,来初始化一个字体类。

字体类提供一个类似Textout的方法,方便得在一个位置输出信息。

先封装一个简单的版本,只支持英文和数字,并且输出不能自动换行。

可能你有一个简单的思路,就是简单的保存字符数组,当打印的时候遍历数组,来查找每个字符在sprite的frameseq中的index,但当我们打印一个字符串的时候就会发现,太多的遍历操作耽误了宝贵时间,这里我们使用一个小技巧用容量换取速度,我们知道Character.hashCode()可以返回字符的ascii编码,常用字符将返回1-127;利用这一点,我们开辟一个128的数组charhash,将输入的字符c所在图片index存入charhash[c.hashCode()]中。

以后也用这种映射方法来读取字符。

charhash的元素初值为-1,以后只要数值大于0就是有效值。

publicclassFont{

 Spritesprite;      //Sprite

 intwidth,height; //每个char的尺寸

 int[]charhash;   //储存1-127个常见字符在sprite的frameseq中的位置

 Graphicsg;

  publicFont(Graphicsg,Imageimg,intwidth, intheight,char[]chars){

   this.g=g;

   sprite=newSprite(img,width,height);

   this.width=width;

   this.height=height;

   charhash=newint[128];

   for(inti=0;i

     charhash=-1;//没有代表此字符的图片

   }

   Characterc;

   for(inti=0;i

     c=newCharacter(chars);

     charhash[c.hashCode()]=i;

   }

 }

  publicvoiddrawChar(charch,intx,inty){

   Characterc=newCharacter(ch);

   inthashcode=c.hashCode();

   sprite.setPosition(x,y);

   if(hashcode>=0){

     sprite.setFrame(charhash[hashcode]);

     sprite.paint(g);

   }

 }

  publicvoiddrawString(Stringstr,intx,inty){

   intlength=str.length();

   for(inti=0;i

     drawChar(str.charAt(i),x+width*i,y);

   }

 }

}

 这样只要有一个实例font,就可以调用font.drawString(“hello”,0,0);

在0,0位置输出漂亮的图片字符串。

怎么样还挺好使的吧:

J2ME 2D小游戏入门之旅(三)控制飞机移动

[录入者:

admin| 时间:

2006-05-1917:

36:

32|作者:

| 来源:

|点击数:

168]

[上一篇][下一篇]

三、控制飞机的移动

实在是等不及了吧?

加把劲,让我们加入游戏的主角飞机吧。

你可以将这个游戏定位在动作游戏,一个动作游戏需要不断的从用户端获得输入,基本上不间断,所以plane需要不断的改变位置。

那么这个基于桢的游戏应该定在多少桢合适呢?

这需要在手机中测试,在模

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 初中教育 > 政史地

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1