J2ME_2D小游戏入门之旅

上传人:xins****2008 文档编号:74662947 上传时间:2022-04-14 格式:DOC 页数:26 大小:134KB
收藏 版权申诉 举报 下载
J2ME_2D小游戏入门之旅_第1页
第1页 / 共26页
J2ME_2D小游戏入门之旅_第2页
第2页 / 共26页
J2ME_2D小游戏入门之旅_第3页
第3页 / 共26页
资源描述:

《J2ME_2D小游戏入门之旅》由会员分享,可在线阅读,更多相关《J2ME_2D小游戏入门之旅(26页珍藏版)》请在装配图网上搜索。

1、J2ME2D小游戏入门之旅(一)游戏的框架 录入者:admin |时间:2006-05-19 17:36:25 | 作者: | 来源: | 点击数:213 上一篇 下一篇favoyang 转载请联系作者响应站长mingjava的号召,我也和大家一起分享一下我的经验,希望大家指教。同时 欢迎各位高手的原创文章。前几天看到tony在csdn上发布自己的学习作品“是男人就坚持60s”,觉得创意虽然简单但是却很耐玩,是学习手机游戏制作的入门经典,于是一时兴起,clone了一下,图片依然使用的是tony的图片,纯粹学习之用。如果大家对这个游戏感兴趣可以与tony联系或访问他的blog。从发展趋势上说mi

2、dp2.0是趋势,最便宜的midp2.0手机如ot735i,已经1700元左右;而西门子一年前的高端机cx65,现在也只有2500左右;并且2500-3000这个价位的midp2.0手机有多种选择,西门子、se、N机都有。我个人挺喜欢cx65,如果将来手机制造商成本不断降低,相信1500元的midp将不是梦当然还要看应用是否丰富了。 言归正传,我们将使用midp 2.0 来开发我们的游戏,代号fly。开发工具jbulider。等文章全写完了,会提供src下载。目录:一、游戏的框架二、完善周边工具类(图象、GameObject、Font)三、控制飞机的移动四、加入子弹群,实现碰撞运算五、实现爆炸

3、效果、并加入道具导弹六、不足多多,你认为呢?七、源码一、游戏的框架我们的游戏需要一个通用的游戏框架,也方便以后的开发,但实现一个引擎是复杂的。作为初学者如果要你考虑太多的问题,恐怕会让你偏离主线,这里只给出canvas的代码,不理解可以参看本站的另外一篇系列文章使用MIDP2.0开发游戏。public class MyGameCanvas extends GameCanvasimplements Runnable, CommandListener private static MyGameCanvas instance; Graphics g; boolean running; Thread

4、t; Command startcmd,exitcmd,restartcmd; int keystate; boolean keyevent; boolean key_up,key_down,key_left,key_right,key_fire; private boolean allowinput; public int screenwidth; public int screenheight; boolean gameover; /define your variable here /define your variable end protected MyGameCanvas() su

5、per(true); g=getGraphics(); running=false; t=null; addCommand(startcmd=new Command(start,Command.OK,1); addCommand(exitcmd=new Command(exit,Command.EXIT,1); setCommandListener(this); screenwidth=getWidth(); screenheight=getHeight(); /put your init once code here/put your init once code end synchroni

6、zed public static MyGameCanvas getInstance() if (instance = null) instance = new MyGameCanvas(); System.out.println(new MyGameCanvas); return instance; public void run() System.out.println(MyGameCanvas run start); long st=0,et=0,diff=0; int rate=50;/16-17 frame per second while(running) st=System.cu

7、rrentTimeMillis(); gameinput(); gameMain(); et=System.currentTimeMillis(); diff=et-st; if(diffspeed) animcount=0; sprite.nextFrame(); if(lifetime!=0 & +lifecountlifetime) alive=false; public void paint(Graphics g)/Paint if(!alive) return; sprite.paint(g); public void reset()/复位 alive=true; lifecount

8、=0; animcount=0; sprite.setFrame(0); 3.封装字体类,你需要漂亮的字体吗? 我们经常需要用图片来输出文字,一个方便的字体类是必须的。我们希望仅仅提供一个图片,一个图片所描述的字符的数组,来初始化一个字体类。字体类提供一个类似Textout的方法,方便得在一个位置输出信息。先封装一个简单的版本,只支持英文和数字,并且输出不能自动换行。可能你有一个简单的思路,就是简单的保存字符数组,当打印的时候遍历数组,来查找每个字符在sprite的frameseq中的index,但当我们打印一个字符串的时候就会发现,太多的遍历操作耽误了宝贵时间,这里我们使用一个小技巧用容量换

9、取速度,我们知道Character. hashCode()可以返回字符的ascii编码,常用字符将返回1-127;利用这一点,我们开辟一个128的数组charhash,将输入的字符c所在图片index存入charhashc. hashCode()中。以后也用这种映射方法来读取字符。charhash的元素初值为-1,以后只要数值大于0就是有效值。public class Font Sprite sprite; /Sprite int width,height; /每个char的尺寸 int charhash; /储存1-127个常见字符在sprite的frameseq中的位置 Graphics

10、g; public Font(Graphics g,Image img, int width, int height, char chars) this.g=g; sprite=new Sprite(img,width,height); this.width=width; this.height=height; charhash=new int128; for (int i = 0; i charhash.length; i+) charhash=-1;/没有代表此字符的图片 Character c; for (int i = 0; i =0) sprite.setFrame(charhash

11、hashcode); sprite.paint(g); public void drawString(String str, int x, int y) int length=str.length(); for (int i = 0; i length; i+) drawChar(str.charAt(i),x+width*i,y); 这样只要有一个实例font,就可以调用font.drawString(“hello”,0,0);在0,0位置输出漂亮的图片字符串。怎么样还挺好使的吧:)J2ME2D小游戏入门之旅(三)控制飞机移动 录入者:admin |时间:2006-05-19 17:36:3

12、2 | 作者: | 来源: | 点击数:168 上一篇 下一篇三、控制飞机的移动实在是等不及了吧?加把劲,让我们加入游戏的主角飞机吧。你可以将这个游戏定位在动作游戏,一个动作游戏需要不断的从用户端获得输入,基本上不间断,所以plane需要不断的改变位置。那么这个基于桢的游戏应该定在多少桢合适呢?这需要在手机中测试,在模拟器上,如果定在15-18桢左右,是比较合适的。听csdn的几位xd说有的游戏仅仅定在12桢,所以不同的游戏是不一定的。基本上动作游戏对机子的要求是要高一点。我们的游戏框架是线性的,即输出显示和接受输入是在同一个线程中,15桢以下的游戏处理输入会显得比较苯,高于20桢如果处理器速

13、度较慢,很容易出现输入卡在缓冲区,处理不过来的情况。现阶段尽量让桢数降下来吧,你不能和pc上用dx编程时,统一30fps的情况相提并论。在这个以控制精灵移动为主要内容的游戏中,我们不封装任何的游戏事件,我们的程序可能有些稚嫩,没关系,一步一步来吧。1. 飞机plane是一个标准的plane。由三桢画面组成,首先在ps中处理,让其透明:在构造函数中,我们加入对飞机的初始化对象语句:Image img=ImageTools.getImage(/pic/MyPlaneFrames.png);plane=new GameObject(img,24,24);在gameInit()中初始化状态,位置居中:

14、plane.reset();plane.moveto(screenwidth-plane.sprite.getWidth()/2,(screenheight-plane.sprite.getHeight()/2);在gameMain中加入:plane.paint(g);接下来,让飞机在控制下移动,主要是在gameMain中加入输入处理,如果飞机左移就更新画面到飞机左倾的画面,如果飞机右倾反之,没有输入的时候让飞机处于正常。if (gameover) elseif (keyevent) if(key_up) plane.move(0, -3); plane.sprite.setFrame(0);

15、 if(key_down) plane.move(0, 3); plane.sprite.setFrame(0); if(key_left) plane.move( -3, 0); plane.sprite.setFrame(1); if(key_right) plane.move(3, 0); plane.sprite.setFrame(2); if(key_fire) else plane.sprite.setFrame(0); 尽管很简单,但这是控制精灵移动的主要方式。可以想象一下,如果往左飞不是简单的一桢画面而是播放动画,该怎么实现呢?我们的GameObject功能有限,没有对spri

16、ite的动画序列进行增强,今后我们可以增强GameObject,使其支持多个动画序列,弥补spriite的不足。现在逐渐体会到一个好的游戏引擎是多么重要了吧2. 背景让飞机在海面飞行吧,我们用一个蓝色的背景图片代表海面,我们需要他铺满整个背景。我们使用TiledLayer来绘画背景。初始化:img=ImageTools.getImage(/pic/back_water.png);int backcolumns=screenwidth/img.getWidth()+1;/计算横向int backrows=screenheight/img.getHeight()+1;background=new

17、TiledLayer(backcolumns,backrows,img,img.getWidth(),img.getHeight();int x,y;for (int i = 0; i backcolumns*backrows; i+) x=i%backcolumns; y=i/backcolumns; System.out.println(x=+x+ y=+y); background.setCell(x,y,1);接下来在gameMain中加入绘制语句。background.paint(g);/draw background注意,要保证背景的绘制在飞机的绘画之前。如果使用Layermana

18、ger可以很方便的的控制绘制层,但是我们的接下来的子弹要求多个子弹对象共用一个sprite的图像,但是Layermanager绘画的时候以Layer为单位,由Layermanager帮助我们调用各个layer的paint,so一次只支持将一个sprite画在一个地方,所以我觉得Layermanager有些鸡肋。一般时候我们还是自己paint吧。当然,层是一个很重要的概念,利用层,屏幕校准将非常方便,震动整个屏幕等特效将很实现。也许你有个好法,可以让我不在Layermanager层与sprite状态对象组之间矛盾可喜可贺呀,我们的飞机动起来了,哈哈,让我们期待加入子弹吧,那是本游戏的“精华”。J

19、2ME2D小游戏入门之旅(四)加入子弹群,实现碰撞运算 录入者:admin |时间:2006-05-19 17:36:37 | 作者: | 来源: | 点击数:197 上一篇 下一篇飞机类游戏中子弹是必不可少的,他们数量很多且充斥着整个屏幕,这些随机或者有着一定AI的小物体,实现起来不是总那么容易,有时候你不得不考虑很多和效能有关的问题。我们之前定义了GameObject,很大程度上就是为了方便的重用Sprite,因为我们有很多的子弹,不可能没增加一个子弹都是一个Sprite,我需要共享同一个Sprite。我们通过继承GameObject来实现。下面分析一下这个子弹类:它将继承自GameObj

20、ect;记录子弹的个数;一个子弹的状态数组,记录各个子弹的类型type,位置x,y,速度vx,vy,是否存活alive等等。初始化子弹一个绘制方法,将子弹画到屏幕上。一个碰撞检测方法。好了先这样吧,以下是我们子弹类的定义,注意这种思想重用Sprite,这很重要。(这里参考了tony的很多设计)public class Bullets extends GameObject private int bullets;/子弹状态数组 private int bulletstotal;/数组的length private Random rnd;/随机数 public static final int B

21、ULLET_TYPE_LEFT=0;/子弹初始化的位置类型 public static final int BULLET_TYPE_RIGHT=1;/分为上下左右四种 public static final int BULLET_TYPE_TOP=2; public static final int BULLET_TYPE_BOTTOM=3; private int width,height;/屏幕的高和宽,用于随机子弹位置 public Bullets(Image img,int picwidth,int picheight,int bulletstotal,int width,int he

22、ight) super(img,picwidth,picheight); this.bulletstotal=bulletstotal; bullets=new intbulletstotal6; rnd=new Random(); this.width=width; this.height=height; public void initBullets()/初始化子弹状态数组 for (int i = 0; i bullets.length; i+) initBullet(i); private void initBullet(int i) /初始化index号子弹 bullets0 = (

23、rnd.nextInt() & 0x7fffffff) % 4; /type bullets5 = 1; /alive 1表示存活, 0表示死去 switch (bullets0) case BULLET_TYPE_LEFT: bullets1 = -5; bullets2 = (rnd.nextInt() & 0x7fffffff) % height; bullets3 = (rnd.nextInt() & 0x7fffffff) % 3 + 1; /vx bullets4 = (rnd.nextInt() % 3; /vy break; case BULLET_TYPE_RIGHT: bu

24、llets1 = width + 5; bullets2 = (rnd.nextInt() & 0x7fffffff) % height; bullets3 = ( (rnd.nextInt() & 0x7fffffff) % 3 + 1) * -1; /vx bullets4 = (rnd.nextInt() % 3; /vy break; case BULLET_TYPE_TOP: bullets1 = (rnd.nextInt() & 0x7fffffff) % width; bullets2 = -5; bullets3 = (rnd.nextInt() % 3; /vx bullet

25、s4 = (rnd.nextInt() & 0x7fffffff) % 3 + 1; /vy break; case BULLET_TYPE_BOTTOM: bullets1 = (rnd.nextInt() & 0x7fffffff) % width; bullets2 = height + 5; bullets3 = (rnd.nextInt() % 3; /vx bullets4 = ( (rnd.nextInt() & 0x7fffffff) % 3 + 1) * -1; /vy break; public void updata(int i)/根据速度更新i子弹下一桢的位置,碰壁反弹

26、 bullets1+=bullets3; bullets2+=bullets4; if(bullets1width+5) bullets3*=-1; if(bullets2height+5) bullets4*=-1; private void paint(Graphics g,int i)/绘画出第i个子弹 updataspritepos(i);/更新位置 sprite.paint(g);/绘画Sprtie public void paint(Graphics g) /绘画整个子弹组 for (int i = 0; i bullets.length; i+) if(bullets5=0)/死

27、去的子弹不绘画 continue; sprite.setPosition(bullets1,bullets2); /更新位置 sprite.paint(g); public void refreshBullets(Sprite planesprite, boolean needcollision)/刷新字典数组的状态,并作碰撞处理 for (int i = 0; i bullets.length; i+) if(bullets5=0) /死去的子弹不更新 continue; if(needcollision)/如果需要碰撞检测 if (isCollision(planesprite, i, 1

28、0) /如果碰撞,进行处理 /System.out.println(collision ); Navigate.mc.gameover = true; Navigate.mc.explosion.sprite.setPosition(bullets1 - 16, bullets2 - 16); bullets5 = 0;/杀死碰撞的子弹 continue; updata(i);/更新状态 private boolean isCollision(Sprite sprite,int i,int range)/判断是否碰撞 /updataspritepos(i); /return sprite.co

29、llidesWith(this.sprite,true); boolean result=false; int planeXCenter=sprite.getX()+12; int planeYCenter=sprite.getY()+12; int bulletXCenter=bullets1+3; int bulletYCenter=bullets2+3; if(Math.abs(planeXCenter-bulletXCenter) range) if (Math.abs(planeYCenter - bulletYCenter ) range) result = true; retur

30、n result; private void updataspritepos(int i)/将sprite更新到i字弹的位置 sprite.setPosition(bullets1,bullets2); public void killbullets(Sprite planesprite,int range)杀死一定区域内的子弹 for (int i = 0; i bullets.length; i+) if(bullets5!=0)/alive bullets if(isCollision(planesprite, i, range) bullets5=0; initBullet(i); 子

31、弹如何表示?首先我们用一个二维数组来记录子弹的信息:bullets0表示子弹的类型,有上、下、左、右四种,分别表示子弹飞入屏幕前的四种位置;bullets1表示子弹的x坐标;bullets2表示子弹的y坐标bullets3表示子弹的x方向速度;bullets4表示子弹的y方向速度;bullets5表示子弹的存活状态;子弹如何初始化?我们首先写了一个初始化单个子弹的方法,然后便利数组调用initBullet (i);来更新整个状态数组。子弹如何绘制?我们首先写了一个绘制单个子弹的方法,然后便利数组调用paint(g,i);来绘制整个状态数组。子弹如何碰撞?有很多种方法,其中sprite本身就提供

32、了边框碰撞检测和基于像素的碰撞检测。前者不太适合我们的游戏,我们的飞机是不规则物体,且飞行游戏对碰撞比较敏感;而后者的效率又得不到我们的信赖,所以我们是用一种半径检测,把飞机近似的看成圆,选取恰当的半径,Math.abs(planeXCenter-bulletXCenter) range则表明碰撞。碰撞看似简单,其实是很复杂的问题,值得庆幸的是,二维碰撞相比三维碰撞简单得多。一个小技巧是,宁可让膨胀检测半径变小也不要他变得大漏掉检测,总比误检测要好得多。子弹更新?我们利用refreshBullets进行更新,这是主要逻辑部分。这个方法负责便利数组检测碰撞,如果碰撞就将处于碰撞位置的子弹杀死,并

33、作相应的处理,这里是结束游戏并爆炸飞机;否则更新子弹的位置。我们只是线性的遍历整个的数组,进行碰撞检测,之后是更新位置;但是这样做有一个前提,就是碰撞检测简单而且处理部分也很简单:在这个游戏中,碰撞检测只是子弹群和飞机的检测,碰撞检测在游戏结束后就不执行了(通过控制boolean needcollision);而处理更是简单了一些直接结束了游戏。如果不是如此,比如处理后并不是简单的结束游戏,我们就不得不设计的复杂一些。可能就不是将碰撞简单的以飞机为中心了。我们需要设计好游戏事件,设计好碰撞系统。如果碰撞本身比较复杂,或者子弹数量,种类增加时,我们线性的遍历数组就不能总是对所有的子弹都检测,可能

34、屏幕需要分区,不处于一个区域的单位不检测。总之当你想想你的1934时,将不在是想象着子弹,飞机什么的,你要思考一个系统。总结一下子弹类的公共接口:n Bullets(Image img,int picwidth,int picheight,int bulletstotal,int width,int height)构造函数n public void initBullets()初始化子弹数组n public void paint(Graphics g) paint子弹数组n public void refreshBullets(Sprite planesprite, boolean needco

35、llision)更新子弹数组状态,碰撞检测、处理等逻辑工作的综合n public void killbullets(Sprite planesprite,int range)/稍后解释到此为止,我们的游戏已经初具规模了,下一步是加入效果类,嘿嘿有点意思了J2ME2D小游戏入门之旅(五)实现爆炸效果、并加入道具导弹 录入者:admin |时间:2006-05-19 17:36:47 | 作者: | 来源: | 点击数:154 上一篇 下一篇 大多数游戏都有着丰富的效果类,在精灵移动类游戏中曾一度以此为一个重要的卖点,。光光是一些丰富的特效是不能够产生一个好的游戏的,但是一个好的游戏是万万不能缺少

36、好的效果的。很多人认为游戏的效果层有时和跟游戏逻辑本身并没有太大的关系,往往就是在最终屏幕上再画上一层效果层。但是游戏逻辑和效果层之间的通信是很重要的。这种通信往往体现在延时与等待上。比如飞机爆炸时,不接受任何用户输入,并且爆炸效果还要继续跟随飞机坠落,甚至爆炸的范围会影响周围的物体,要等待爆炸结果结束了才继续进行游戏。游戏逻辑和效果层之间的通信是很复杂的问题。在这里我突然有了罪恶感,我们没有对游戏进行任何的分析就起步了,游戏完全是基于硬编码的,我想到那儿,大家跟着看到那儿。飞机类仅仅是一个sprite,没有设计成一个状态机,这也就使得我们的效果层和逻辑层的通信有些卡通了。也许本文给了你编写自

37、己第一个游戏的喜悦,也带给了你对游戏扩展性与复杂性的一丝担忧。或许这比便一个硬编码的游戏更有意义呢?谁说得好呢,现还是以为那些扩展性良好的游戏是伟大游戏构架师的杰作吧,相信你有了一两个好的想法后会重新设计这个游戏的,使之稍微有一些像个“系统”。然而好的技术不一定产生好的游戏呵呵有扯远了,会到现实吧,boys and girls!goon.描述一下我们的爆炸效果,在子弹击中飞机后,子弹要迅速消失,飞机图像保持不变,此时将爆炸效果至于飞机图像之上,然后开始显示boom动画,在此期间,飞机不接受任何移动指示,因为他lose control。在爆炸效果后飞机消失。我们的爆炸效果类:GameObject

38、 explosion;/ 初始化once:img=ImageTools.getImage(/pic/explosion.png);/ explosion=new GameObject(img,32,32);初始化:explosion.reset();explosion.lifetime=3;/生命周期定位三桢逻辑处理:if (gameover) /如果游戏结束,显示效果类 explosion.paint(g); explosion.update(); if(!explosion.alive)/当生命周期结束了 plane.alive=false;/关闭plane g.setColor(255,255,255);/输出评语,下回分解 g.drawString(StringTools.timeOpinion(gametime),5,22,g.LEFT|g.TOP); g.drawString(fly 0.1 ver by favo yang,2,100,g.LEFT|g.TOP); g.drawString(E-mail : favoyang,2,115,g.LEFT|g.TOP); g.drawString(simulate from:,2,130,g.LEFT|g.TOP); g.drawString(Mr.tony s ,2,145,g.L

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!