Java来做马里奥[3]—杂兵登场

效果图如下:


在ACT类游戏中,你所扮演的角色时常会与各种杂兵发生这样或者那样的冲突,以此来增强游戏性。本回将例举一种Java游戏的杂兵制造方式。

在此例中将原来的 getTileHit改为注入Sprite,以此统一处理角色及杂兵的碰撞。

public PointgetTileHit(Spritesprite, double newX, double newY)

Food.java(扮演食物的角色)
package org.test.mario;

/***/ /**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:食物用类
*</p>
*<p>
*Copyright:Copyright(c)2008
*</p>
*<p>
*Company:LoonFramework
*</p>
*<p>
*License:
http://www.apache.org/licenses/LICENSE-2.0
*</p>
*
*
@authorchenpeng
*@email:ceponline@yahoo.com.cn
*
@version0.1
*/

public class Food extends Sprite ... {

publicFood(StringfileName,doublex,doubley,Mapmap)...{
super(fileName,x,y,map);
}


publicvoidupdate()...{

}


}


Sandaime.java(扮演杂兵的角色)
package org.test.mario;

import java.awt.Point;

/***/ /**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:
*</p>
*<p>
*Copyright:Copyright(c)2008
*</p>
*<p>
*Company:LoonFramework
*</p>
*<p>
*License:
http://www.apache.org/licenses/LICENSE-2.0
*</p>
*
*
@authorchenpeng
*@email:ceponline@yahoo.com.cn
*
@version0.1
*/

public class Sandaime extends Sprite ... {

privatestaticfinaldoubleSPEED=1;

privatedouble_vx;

privatedouble_vy;

publicSandaime(Stringfilename,doublex,doubley,Mapmap)...{

super(filename,x,y,map);
width
=80;
height
=75;
_vx
=-SPEED;
_vy
=0;
}


publicvoidupdate()...{
_vy
+=0.1;

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
=-_vx;
}


doublenewY=_y+_vy;
tile
=_map.getTileHit(this,_x,newY);
if(tile==null)...{
_y
=newY;
}
else...{
if(_vy>0)...{
_y
=Map.tilesToPixels(tile.y)-height;
_vy
=0;
}
elseif(_vy<0)...{
_y
=Map.tilesToPixels(tile.y+1);
_vy
=0;
}

}

}


}


Role.java(扮演主角)
package org.test.mario;

import java.awt.Graphics;
import java.awt.Point;

/***/ /**
*<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
*/

public class Role extends Sprite ... {

privatedouble_vx;

privatedouble_vy;

privateboolean_isFlat;

privateint_dir;

//强制跳跃
privateboolean_forceJump;

finalstaticprivateintSPEED=6;

finalstaticprivateintJUMP_SPEED=16;

finalstaticprivateintRIGHT=0;

finalstaticprivateintLEFT=1;

/***//**
*构造函数,以角色图位置,初始的x、y坐标,地图四项参数创建一个可用的角色
*
*
@paramfilename
*
@paramx
*
@paramy
*
@parammap
*/

publicRole(Stringfilename,doublex,doubley,Mapmap)...{
super(filename,x,y,map);
width
=40;
height
=40;
_vx
=0;
_vy
=0;
_isFlat
=false;
_forceJump
=false;
_dir
=RIGHT;
}


publicvoidsetJump(booleanforceJump)...{
_forceJump
=forceJump;
}


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


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


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


publicvoidjump()...{
if(_isFlat||_forceJump)...{
_vy
=-JUMP_SPEED;
_isFlat
=false;
_forceJump
=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(_image,(
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);
}

}


Sprite.java(抽象的精灵类)
package org.test.mario;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;

import org.loon.framework.game.image.Bitmap;

/***/ /**
*<p>
*Title:LoonFramework
*</p>
*<p>
*Description:精灵类(为了批量制造角色,将Role中通用设定抽象成此类)
*</p>
*<p>
*Copyright:Copyright(c)2008
*</p>
*<p>
*Company:LoonFramework
*</p>
*<p>
*License:
http://www.apache.org/licenses/LICENSE-2.0
*</p>
*
*
@authorchenpeng
*@email:ceponline@yahoo.com.cn
*
@version0.1
*/

public abstract class Sprite ... {
//坐标
protecteddouble_x;

protecteddouble_y;

//
protectedintwidth;

//
protectedintheight;

//图像
protectedImage_image;

//步数
protectedint_count;

//地图
protectedMap_map;

/***//**
*构造函数,以角色图位置,初始的x、y坐标,地图四项参数创建一个可用的角色
*
*
@paramfileName
*
@param_x
*
@param_y
*
@parammap
*/

publicSprite(StringfileName,double_x,double_y,Mapmap)...{
this._x=_x;
this._y=_y;
this._map=map;

width
=32;
height
=32;

loadImage(fileName);

_count
=0;

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


publicabstractvoidupdate();

publicvoiddraw(Graphicsg,intoffsetX,intoffsetY)...{
g.drawImage(_image,(
int)_x+offsetX,(int)_y+offsetY,(int)_x
+offsetX+width,(int)_y+offsetY+height,_count*width,
0,_count*width+width,height,null);
}


publicbooleanisHit(Spritesprite)...{
RectangleplayerRect
=newRectangle((int)_x,(int)_y,width,height);
RectanglespriteRect
=newRectangle((int)sprite.getX(),(int)sprite
.getY(),sprite.getWidth(),sprite.getHeight());
//判定两者边框是否相交
if(playerRect.intersects(spriteRect))...{
returntrue;
}


returnfalse;
}


publicdoublegetX()...{
return_x;
}


publicdoublegetY()...{
return_y;
}


publicintgetWidth()...{
returnwidth;
}


publicintgetHeight()...{
returnheight;
}


privatevoidloadImage(Stringfilename)...{
_image
=newBitmap(filename).getImage();
}


privateclassAnimationThreadextendsThread...{
publicvoidrun()...{
while(true)...{
//换算步数
if(_count==0)...{
_count
=1;
}
elseif(_count==1)...{
_count
=0;
}

//动作更替延迟
try...{
Thread.sleep(
300);
}
catch(InterruptedExceptione)...{
e.printStackTrace();
}

}

}

}


publicvoidsetHeight(intheight)...{
this.height=height;
}


publicvoidsetWidth(intwidth)...{
this.width=width;
}


}


Map.java(地图描述)
package org.test.mario;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.util.LinkedList;

import org.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
*/

public class Map ... {

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

finalstaticpublicintROW=20;

finalstaticpublicintCOL=30;

finalstaticpublicintWIDTH=TILE_SIZE*COL;

finalstaticpublicintHEIGHT=TILE_SIZE*ROW;

finalstaticpublicdoubleGRAVITY=0.6;

//缓存精灵的list
privateLinkedListsprites;

//地图描述
finalstaticprivateint[][]map=...{
...{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,0,2}
,
...{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,0,1}
,
...{2,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,3,3,3,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,2,2,2,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,3,0,
0,0,0,0,0,0,0,1}
,
...{1,0,0,0,0,0,0,0,0,4,4,4,4,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,3,3,3,3,3,0,0,0,0,0,0,0,0,3,3,4,3,3,1,2,2,
0,0,0,0,0,0,3,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()...{
//精灵list
sprites=newLinkedList();
//注入兵粮丸
for(inti=0;i<ROW;i++)...{
for(intj=0;j<COL;j++)...{
switch(map[i][j])...{
case3:
sprites.add(
newFood("./food.gif",tilesToPixels(j),tilesToPixels(i),this));
break;
case4:
sprites.add(
newSandaime("./sdm.gif",tilesToPixels(j),tilesToPixels(i),this));
break;
}

}

}

}


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
*
*
@paramsprite
*
@paramnewX
*
@paramnewY
*
@return
*/

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

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

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

intfromTileX=pixelsToTiles(fromX);
intfromTileY=pixelsToTiles(fromY);
inttoTileX=pixelsToTiles(toX+sprite.getWidth()-1);
inttoTileY=pixelsToTiles(toY+sprite.getHeight()-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;
}


/***//**
*返回Spritelist
*
@return
*/

publicLinkedListgetSprites()...{
returnsprites;
}


publicvoidsetSprites(LinkedListsprites)...{
this.sprites=sprites;
}

}


Main.java(部署及运行)
package org.test.mario;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Panel;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Iterator;
import java.util.LinkedList;

import org.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
*/

public class Main extends Panel implements Runnable,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;

//底层背景
finalstaticprivateImageback=newBitmap("./雕像.png").getImage();

publicMain()...{
setSize(_WIDTH,_HEIGHT);
setFocusable(
true);
_screen
=newBitmap(_WIDTH,_HEIGHT).getImage();
_graphics
=_screen.getGraphics();
_map
=newMap();
//设置扮演的角色
_role=newRole("role.gif",190,40,_map);

//监听窗体
addKeyListener(this);

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


publicvoidgameOver()...{

_map
=newMap();

_role
=newRole("role.gif",190,40,_map);
}


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

publicvoidrun()...{
while(true)...{
//改变方向
if(LEFT)...{
_role.left();
}
elseif(RIGHT)...{
_role.right();
}
else...{
_role.stop();
}

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

_role.update();

LinkedListsprites
=_map.getSprites();

for(Iteratorit=sprites.iterator();it.hasNext();)...{
//还原为sprite
Spritesprite=(Sprite)it.next();
//变更精灵状态
sprite.update();

//碰撞检测
if(_role.isHit(sprite))...{
//对象检测,为兵粮丸时
if(spriteinstanceofFood)...{
Foodcoin
=(Food)sprite;
//删除对象
//it.remove();
sprites.remove(coin);
break;
//为三代目时
}
elseif(spriteinstanceofSandaime)...{
Sandaimesdm
=(Sandaime)sprite;
if((int)_role.getY()<(int)sdm.getY())...{
sprites.remove(sdm);
_role.setJump(
true);
_role.jump();
break;
}
else...{
gameOver();
}

}

}

}

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);
_graphics.drawImage(back,
0,0,this);
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);
//遍历精灵对象并绘制
LinkedListsprites=_map.getSprites();

for(Iteratorit=sprites.iterator();it.hasNext();)...{
Spritesprite
=(Sprite)it.next();
sprite.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来做马里奥(4)—杂兵登场");
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);
}

}
);
}


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值