继续前两天的博客内容,接着写Java中的ACT游戏实现,本来记得手里有C++版马里奥的角色和地图的,突然找不到丢那里了,凑活ps个GBA火影的图代替下……
运行效果如下:

此次重点演示了角色和地图的绘制……其实看过我以前写JAVA的RPG开发blog文章的早知道怎么弄的了……所以此次只帖代码……
Role.java:
packageorg.test.mario;

importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.Point;

importorg.loon.framework.game.image.Bitmap;


/***//**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:角色描述及绘制用类
*</p>
*<p>
*Copyright:Copyright(c)2008
*</p>
*<p>
*Company:LoonFramework
*</p>
*
*@authorchenpeng
*@email:ceponline@yahoo.com.cn
*@version0.1
*/

publicclassRole...{

privatedouble_x;

privatedouble_y;

privatedouble_vx;

privatedouble_vy;

privatebooleanisFlat;

privateint_dir;

privateint_count;

finalstaticprivateImagerole=newBitmap("./role.gif").getImage();

privateMap_map;

finalstaticpublicintWIDTH=40;

finalstaticpublicintHEIGHT=40;

finalstaticprivateintSPEED=6;

finalstaticprivateintJUMP_SPEED=16;

finalstaticprivateintRIGHT=0;

finalstaticprivateintLEFT=1;


publicRole(double_x,double_y,Map_map)...{
this._x=_x;
this._y=_y;
this._map=_map;
_vx=0;
_vy=0;
isFlat=false;
_dir=RIGHT;
_count=0;

AnimationThreadthread=newAnimationThread();
thread.start();
}


publicvoidstop()...{
_vx=0;
}


publicvoidleft()...{
_vx=-SPEED;
_dir=LEFT;
}


publicvoidright()...{
_vx=SPEED;
_dir=RIGHT;
}


publicvoidjump()...{

if(isFlat)...{
_vy=-JUMP_SPEED;
isFlat=false;
}
}


publicvoidupdate()...{
//0.6为允许跳跃的高度限制,反值效果
_vy+=0.6;

doublenewX=_x+_vx;

Pointtile=_map.getTileHit(this,newX,_y);

if(tile==null)...{
_x=newX;

}else...{

if(_vx>0)...{

_x=Map.tilesToPixels(tile.x)-WIDTH;

}elseif(_vx<0)...{
_x=Map.tilesToPixels(tile.x+1);
}
_vx=0;
}

doublenewY=_y+_vy;
tile=_map.getTileHit(this,_x,newY);

if(tile==null)...{
_y=newY;
isFlat=false;

}else...{

if(_vy>0)...{
_y=Map.tilesToPixels(tile.y)-HEIGHT;
_vy=0;
isFlat=true;

}elseif(_vy<0)...{
_y=Map.tilesToPixels(tile.y+1);
_vy=0;
}
}
}


publicvoiddraw(Graphicsg,intoffsetX,intoffsetY)...{
g.drawImage(role,(int)_x+offsetX,(int)_y+offsetY,(int)_x
+offsetX+WIDTH,(int)_y+offsetY+HEIGHT,_count*WIDTH,
_dir*HEIGHT,_count*WIDTH+WIDTH,_dir*HEIGHT+HEIGHT,
null);
}


publicdoublegetX()...{
return_x;
}


publicdoublegetY()...{
return_y;
}


privateclassAnimationThreadextendsThread...{

publicvoidrun()...{

while(true)...{

if(_count==0)...{
_count=1;

}elseif(_count==1)...{
_count=0;
}


try...{
Thread.sleep(300);

}catch(InterruptedExceptione)...{
e.printStackTrace();
}
}
}
}

}
Map.java:
packageorg.test.mario;

importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.Point;

importorg.loon.framework.game.image.Bitmap;


/***//**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:地图绘制及描述用类
*</p>
*<p>
*Copyright:Copyright(c)2008
*</p>
*<p>
*Company:LoonFramework
*</p>
*
*@authorchenpeng
*@email:ceponline@yahoo.com.cn
*@version0.1
*/

publicclassMap...{

//在以前的blog文章中我介绍过,游戏开发中通常以数组描述地图
//此处1描绘为一个障碍物,0描绘为一个可通行空间
finalstaticpublicintTILE_SIZE=32;

finalstaticpublicintROW=20;

finalstaticpublicintCOL=30;

finalstaticpublicintWIDTH=TILE_SIZE*COL;

finalstaticpublicintHEIGHT=TILE_SIZE*ROW;

finalstaticpublicdoubleGRAVITY=0.6;

//地图描述

finalstaticprivateint[][]map=...{

...{2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,2},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,
2,2,2,2,2,2,2,1},

...{1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,2,2,2,2,2,2,2,2,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1},

...{1,2,2,2,2,2,0,0,0,0,0,0,0,0,2,2,2,2,2,1,0,0,
0,0,0,0,0,0,2,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1},

...{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,1},

...{1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,2,2,2,2,2,2,1}};

finalstaticprivateImagetile=newBitmap("./tile_0.gif").getImage();

finalstaticprivateImagetile2=newBitmap("./tile_1.gif").getImage();


/***//**
*构造函数
*
*/

publicMap()...{
}


publicvoiddraw(Graphicsg,intoffsetX,intoffsetY)...{
intfirstTileX=pixelsToTiles(-offsetX);
intlastTileX=firstTileX+pixelsToTiles(Main._WIDTH)+1;
lastTileX=Math.min(lastTileX,COL);
intfirstTileY=pixelsToTiles(-offsetY);
intlastTileY=firstTileY+pixelsToTiles(Main._HEIGHT)+1;
lastTileY=Math.min(lastTileY,ROW);


for(inti=firstTileY;i<lastTileY;i++)...{

for(intj=firstTileX;j<lastTileX;j++)...{
//转换map标识

switch(map[i][j])...{
case1://绘制砖地

g.drawImage(tile,tilesToPixels(j)+offsetX,
tilesToPixels(i)+offsetY,null);
break;
case2:
g.drawImage(tile2,tilesToPixels(j)+offsetX,
tilesToPixels(i)+offsetY,null);
break;
}
}
}
}


/***//**
*换算角色与地板的撞击,并返回Point用以描述新的x,y
*
*@paramplayer
*@paramnewX
*@paramnewY
*@return
*/

publicPointgetTileHit(Roleplayer,doublenewX,doublenewY)...{

newX=Math.ceil(newX);
newY=Math.ceil(newY);

doublefromX=Math.min(player.getX(),newX);
doublefromY=Math.min(player.getY(),newY);
doubletoX=Math.max(player.getX(),newX);
doubletoY=Math.max(player.getY(),newY);

intfromTileX=pixelsToTiles(fromX);
intfromTileY=pixelsToTiles(fromY);
inttoTileX=pixelsToTiles(toX+Role.WIDTH-1);
inttoTileY=pixelsToTiles(toY+Role.HEIGHT-1);


for(intx=fromTileX;x<=toTileX;x++)...{

for(inty=fromTileY;y<=toTileY;y++)...{


if(x<0||x>=COL)...{
returnnewPoint(x,y);
}

if(y<0||y>=ROW)...{
returnnewPoint(x,y);
}

if(map[y][x]==1||map[y][x]==2)...{
returnnewPoint(x,y);
}
}
}

returnnull;
}


/***//**
*将Tiles转为Pixels
*
*@parampixels
*@return
*/

publicstaticintpixelsToTiles(doublepixels)...{
return(int)Math.floor(pixels/TILE_SIZE);
}


/***//**
*将Pixels转为Tiles
*
*@parampixels
*@return
*/

publicstaticinttilesToPixels(inttiles)...{
returntiles*TILE_SIZE;
}
}
Main.java
packageorg.test.mario;

importjava.awt.Color;
importjava.awt.Frame;
importjava.awt.Graphics;
importjava.awt.Image;
importjava.awt.Panel;
importjava.awt.event.KeyEvent;
importjava.awt.event.KeyListener;
importjava.awt.event.WindowAdapter;
importjava.awt.event.WindowEvent;

importorg.loon.framework.game.image.Bitmap;


/***//**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:
*</p>
*<p>
*Copyright:Copyright(c)2008
*</p>
*<p>
*Company:LoonFramework
*</p>
*
*@authorchenpeng
*@email:ceponline@yahoo.com.cn
*@version0.1
*/

publicclassMainextendsPanelimplementsRunnable,KeyListener...{


/***//**
*
*/
privatestaticfinallongserialVersionUID=1L;

publicstaticfinalint_WIDTH=640;

publicstaticfinalint_HEIGHT=480;

privateMap_map;

privateRole_role;

privateThread_sleep;

privateImage_screen=null;

privateGraphics_graphics=null;

//方向控制,由于是自然落体所以没有down
privatebooleanLEFT;

privatebooleanRIGHT;

privatebooleanUP;


publicMain()...{
setSize(_WIDTH,_HEIGHT);
setFocusable(true);
_screen=newBitmap(_WIDTH,_HEIGHT).getImage();
_graphics=_screen.getGraphics();
_map=newMap();

_role=newRole(190,40,_map);

//监听窗体
addKeyListener(this);

//启动线程
_sleep=newThread(this);
_sleep.start();
}


/***//**
*运行
*/

publicvoidrun()...{

while(true)...{
//改变方向

if(LEFT)...{
_role.left();

}elseif(RIGHT)...{
_role.right();

}else...{
_role.stop();
}

if(UP)...{
_role.jump();
}
_role.update();
repaint();

try...{
Thread.sleep(20);

}catch(InterruptedExceptione)...{
e.printStackTrace();
}
}
}


publicvoidupdate(Graphicsg)...{
paint(g);
}


publicvoidpaint(Graphicsg)...{

_graphics.setColor(Color.BLACK);
_graphics.fillRect(0,0,_WIDTH,_HEIGHT);

intoffsetX=_WIDTH/2-(int)_role.getX();

offsetX=Math.min(offsetX,0);
offsetX=Math.max(offsetX,_WIDTH-Map.WIDTH);

intoffsetY=_HEIGHT/2-(int)_role.getY();

offsetY=Math.min(offsetY,0);
offsetY=Math.max(offsetY,_HEIGHT-Map.HEIGHT);


_map.draw(_graphics,offsetX,offsetY);


_role.draw(_graphics,offsetX,offsetY);

g.drawImage(_screen,0,0,null);
}


publicvoidkeyPressed(KeyEvente)...{
intkey=e.getKeyCode();

if(key==KeyEvent.VK_LEFT)...{
LEFT=true;
}

if(key==KeyEvent.VK_RIGHT)...{
RIGHT=true;
}

if(key==KeyEvent.VK_UP)...{
UP=true;
}
}


publicvoidkeyReleased(KeyEvente)...{
intkey=e.getKeyCode();

if(key==KeyEvent.VK_LEFT)...{
LEFT=false;
}

if(key==KeyEvent.VK_RIGHT)...{
RIGHT=false;
}

if(key==KeyEvent.VK_UP)...{
UP=false;
}
}


publicvoidkeyTyped(KeyEvente)...{
}


publicstaticvoidmain(String[]args)...{
Frameframe=newFrame();
frame.setTitle("Java来做马里奥(2)—木叶传承");
frame.setSize(_WIDTH,_HEIGHT+20);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.add(newMain());
frame.setVisible(true);

frame.addWindowListener(newWindowAdapter()...{

publicvoidwindowClosing(WindowEvente)...{
System.exit(0);
}
});
}

}
以上……
突然觉得这样做也挺有意思的,准备让木叶丸踩三代玩,啊哈哈哈……(众人曰:神经病)||||
运行效果如下:

此次重点演示了角色和地图的绘制……其实看过我以前写JAVA的RPG开发blog文章的早知道怎么弄的了……所以此次只帖代码……
Role.java:































































































































































































Map.java:
































































































































































































































Main.java












































































































































































































以上……
突然觉得这样做也挺有意思的,准备让木叶丸踩三代玩,啊哈哈哈……(众人曰:神经病)||||