//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需要不断的改变位置。
那么这个基于桢的游戏应该定在多少桢合适呢?
这需要在手机中测试,在模