站内搜索: 请输入搜索关键词

当前页面: 开发资料首页J2ME 专题Java活动图像程序和游戏编写(3)

Java活动图像程序和游戏编写(3)

摘要: Java活动图像程序和游戏编写(3)
<tr><td>
http:///tech/article811.html
五 加入会追逐格格的小坏蛋让格格和他们对抗.
让我们给小坏蛋起名字叫坏猫猫和小螃蟹.这两个小坏蛋会追逐格格.当然,坏猫猫跑的快,小螃蟹跑得慢.他们通过判断自己和格格的相对位置决定自己向哪里移动.
坏猫猫和小螃蟹是小坏蛋类的两个实例.跑的速度不同只是因为实例被初始化时设定的线程休眠时间不同.读者可以改造笔者给出的程序码,再加入一个小坏蛋实例看看,这样会有三个小坏蛋追逐格格.现在读者看出面向对象的优越性了吗?比如类库中定义了按钮类,你可以在程序中声明无数个实例,多么方便.
[] 格格的子弹击中两个小坏蛋后他们会叫一声,并短暂停止追逐(读者不妨改改程序让坏猫猫和小螃蟹中弹后停止的时间不一样).格格击中了会动的小坏蛋能得分(击中了不会动的不得分),被抓住了要扣分.
判断这些事件很简单.生成包含格格,子弹,小坏蛋图片的边框,他们边框相交,就有事了.
可以这样生成两个边框并判断是否相交:
Rectangle rectangle_1=null, rectangle_2=null;
rectangle_1=new Rectangle(10,15,20,25);//生成一个左上角坐标为(10,15),宽为20,高为25的边框.
rectangle_1=new Rectangle(20,25,30,35);//生成一个左上角坐标为(20,25),宽为30,高为35的边框.
if(rectangle_1.intersects(rectangle_2))//两个边框相交吗?
{;
//相应程序码
};
小坏蛋被击中后,表示他停止追逐的布尔量置为true,同时停止时间计数开始递减.一旦计数小于0,表示暂停时间到,表示停止追逐的布尔量置为false,小坏蛋又开始追逐.
下面是两个小坏蛋的图像.幅面是40 X 40点.他们各有两幅图像交替显示以形成动画效果.
|||||||| ||||||| ||||||| ||||||| ||||||| ||||||| ||||||| |||||||
|||||||| ||||||| ||||||| ||||||| ||||||| ||||||| ||||||| |||||||
|||||||| ||||||| ||||||| ||||||| ||||||| ||||||| ||||||| |||||||
坏猫猫图片1 Alpha通道 坏猫猫图片2 Alpha通道 小螃蟹图片1 Alpha通道 小螃蟹图片2 Alpha通道
xia_1.gif xia_2.gif hu_1.gif hu_2.gif

下面是最终的程序码.
import java.awt.*;
import java.applet.*;
public class wumin1 extends Applet
[]{;
carton carton_1=null;//声明一个carton类的实例.
[] AudioClip back_ground_music;//声明一个声音实例.这是背景音乐
bad_egg bad_egg_1=null,bad_egg_2=null;
public void init()
{;
back_ground_music=getAudioClip(getCodeBase(),"spacemusic.au");
back_ground_music.loop();//背景音乐循环播放
};
public void start()
{;
if (carton_1==null)//假如格格未初始化
{;
[] carton_1=new carton(getGraphics(),this);//初始化
carton_1.start();//格格启动
[] };
if (bad_egg_1==null)
{;
[] //小坏蛋的构造函数参数从前向后,依次为:当前实例,当前图形设备环境,小
[] //坏蛋的sleep()暂停方法的暂停时间,小坏蛋的图片名,
//小坏蛋的初始位置的X和Y坐标,格格,小坏蛋编号.
bad_egg_1=new bad_egg(this,getGraphics(),30,"hu",350,300,carton_1,1);
bad_egg_1.start();
};
if (bad_egg_2==null)
{;
bad_egg_2=new bad_egg(this,getGraphics(),50,"xia",350,30,carton_1,2);
bad_egg_2.start();
};
};
public void stop()
{;
carton_1.stop();//停止
carton_1=null;//释放资源
bad_egg_1.stop();//小坏蛋1停止
bad_egg_1=null; //释放资源
bad_egg_2.stop();//小坏蛋2停止
bad_egg_2=null; //释放资源
back_ground_music.stop();//背景音乐停止
};
//键被按下事件的处理.
public boolean keyDown(Event e,int key)
{;
if (key==Event.UP)//假如是向上键被按下
carton_1.set_direction(0);//向上的布尔变量置true
if (key==Event.DOWN)//假如是向下键被按下
carton_1.set_direction(1);//向下的布尔变量置true
if (key==Event.LEFT)//假如是向左键被按下
carton_1.set_direction(2);//向左的布尔变量置true
if (key==Event.RIGHT)//假如是向右键被按下
carton_1.set_direction(3);//向右的布尔变量置true
[]/*
去掉这两条指令上下的注释标记,格格就会拿机关枪开火
[] if (key==32)
carton_1.fire_wanna_switch(true);//Blank to fire.
*/
return true;
};
//键被松开事件的处理.
public boolean keyUp(Event e,int key)
{;
if (key==Event.UP)//假如是向上键被松开
carton_1.clear_direction(0);//向上的布尔变量置false
if (key==Event.DOWN)//假如是向下键被松开
carton_1.clear_direction(1);//向下的布尔变量清置false
if (key==Event.LEFT)//假如是向左键被松开
carton_1.clear_direction(2);//向左的布尔变量清置false
if (key==Event.RIGHT)//假如是向右键被松开
carton_1.clear_direction(3);//向右的布尔变量清置false
if (key==32)//假如是空格键被松开要求开枪
carton_1.fire_wanna_switch(true);//请求开枪.
return true;
};
};
//格格所属类的描述
class carton extends Thread//从Thread类派生
[]{;
Graphics g,off_screen=null;//g是当前的图形设备环境,off_screen是后台缓冲区图形设备环境
boolean up=false,down=false,left=false,right=false;//四个方向布尔变量
boolean img_now_switch=true;//图片切换开关.
boolean fire_wanna=false,fire_proposal=false;//fire_wanna是要求开枪,用户每次松开空格键就置位,fire_proposal是准许开枪,格格正在移动时置位
int position_x=200,position_y=150,pos_x,pos_y;//(position_x,position_y)是格格当前位置,(pos_x,pos_y)是刚才的位址
[] int img_now_switch_count=0;//格格图片切换计数.到一定值就切换
int img_now_switch_count_top=30;//切换值.图片切换计数到此值,就切换
[] int i=0,j=0,k=0;//这些是程序中计算时的临时变量
int fire_direction=0;//子弹方向.1=上,2=右上,3=右,4=右下,5=下,6=左下,7=左,8=左上
int bullet_amount=0;//子弹总数量
int bullet_position[][]=new int[31][3];//全部子弹信息纪录.每个子弹占横向三个元素.第一个是横坐标,第二个是纵坐标,第三个是方向
Image img_center_close,img_center_open,img_up,img_down,img_left;
Image img_right,img_up_left,img_up_right,img_down_left,img_down_right;//格格全部的图片
Image img_now,bullet_now;//现在要显示的格格图片(当前图片).它会改变的
Image bullet_up,bullet_up_left,bullet_up_right,bullet_right;
Image bullet_left,bullet_down,bullet_down_left,bullet_down_right;//子弹的全部图片
Image off_screen_buffer=null;//后台图形缓冲
[] AudioClip fire_sound;//开枪的声音
AudioClip cought_by_hu,cought_by_xia,hit_hu,hit_xia;//格格被小坏蛋抓住的声音和子弹击中小坏蛋的声音
Applet applet;//运行环境
[] int sleep_time=5;//格格休眠时间
int score=0;//积分
String score_s;
[] Image bad_egg[]= new Image[2];//小坏蛋的图片
int bad_egg_position_x[]=new int[2];//小坏蛋的坐标
int bad_egg_position_y[]=new int[2];
boolean bad_egg_stop[]=new boolean[2];//小坏蛋被子弹击中后次变量为true
int bad_egg_freeze[]=new int[2];//小坏蛋被子弹击中后的暂停时间计数
[] Rectangle bad_egg_1=null,bad_egg_2=null,bad_egg_bullet=null;//用来判断小坏蛋位置及小坏蛋是否被子弹击中的方框

Color my_color;//临时颜色
//初始化时要将各种环境准备好
public carton(Graphics a,Applet app)
{;
g=a;//获得当前图形设备环境
applet=app;//获得当前运行环境
//下面把所有要用的图片调入
img_center_close=applet.getImage(applet.getCodeBase(),"center_close.gif");
img_center_open=applet.getImage(applet.getCodeBase(),"center_open.gif");
img_up=applet.getImage(applet.getCodeBase(),"up.gif");
img_down=applet.getImage(applet.getCodeBase(),"down.gif");
[] img_left=applet.getImage(applet.getCodeBase(),"left.gif");
[] img_right=applet.getImage(applet.getCodeBase(),"right.gif");
img_up_left=applet.getImage(applet.getCodeBase(),"up_left.gif");
img_up_right=applet.getImage(applet.getCodeBase(),"up_right.gif");
img_down_left=applet.getImage(applet.getCodeBase(),"down_left.gif");
img_down_right=applet.getImage(applet.getCodeBase(),"down_right.gif");
bullet_up=applet.getImage(applet.getCodeBase(),"bullet_up.gif");
bullet_down=applet.getImage(applet.getCodeBase(),"bullet_down.gif");
bullet_left=applet.getImage(applet.getCodeBase(),"bullet_left.gif");
bullet_right=applet.getImage(applet.getCodeBase(),"bullet_right.gif");
bullet_up_left=applet.getImage(applet.getCodeBase(),"bullet_up_left.gif");
bullet_up_right=applet.getImage(applet.getCodeBase(),"bullet_up_right.gif");
[] bullet_down_left=applet.getImage(applet.getCodeBase(),"bullet_down_left.gif");
bullet_down_right=applet.getImage(applet.getCodeBase(),"bullet_down_right.gif");
fire_sound=applet.getAudioClip(applet.getCodeBase(),"monkey.au");//把开枪的声音调入
cought_by_hu=applet.getAudioClip(applet.getCodeBase(),"bong.au");
cought_by_xia=applet.getAudioClip(applet.getCodeBase(),"bubble1.au");
hit_hu=applet.getAudioClip(applet.getCodeBase(),"ah.au");
[] hit_xia=applet.getAudioClip(applet.getCodeBase(),"ooh.au");
//设置当前图片
img_now=img_center_open;
//创建后台缓冲区,并取其图形设备环境
[] off_screen_buffer=applet.createImage(400,350);
off_screen=off_screen_buffer.getGraphics();
//初始化小坏蛋的各种参数
bad_egg[0]=null;
bad_egg[1]=null;
bad_egg_position_x[0]=0;
[] bad_egg_position_x[1]=0;
bad_egg_position_y[0]=0;
bad_egg_position_y[1]=0;
bad_egg_stop[0]=false;
[] bad_egg_stop[1]=false;
bad_egg_freeze[0]=80;
bad_egg_freeze[1]=80;
};
//这是主运行函数.
public void run()
{;
while(true)//此函数一直运行
{;
set_position();//计算格格的坐标

select_image();//选择当前图片同时设定子弹的飞行方向
bullet_processing();//处理子弹
draw_image();//画图
bad_egg_sleep();//小坏蛋停止追逐格格的处理
draw_score();//显示积分
try//标准的暂停方式
{;
sleep(sleep_time);
};
catch(InterruptedException e)
{;
[] };
};
};
//小坏蛋停止追逐格格的处理
public void bad_egg_sleep()
{;
//下面的循环处理小坏中弹后停止追逐.读者可以把它分解为两个单独的判断,这样两个小坏蛋中弹后可以停止不同的时间.
for (i=0;i<2;i++)//两个小坏蛋都要处理
{;
if(bad_egg_freeze[i]>0 && bad_egg_stop[i])//假如小坏蛋现在已停止追逐并且停止时间计数大于0
bad_egg_freeze[i]--;//计数减1
if(bad_egg_freeze[i]<1)//停止追逐时间计数小于1
{;
bad_egg_stop[i]=false;//小坏蛋停止追逐标志为false,又开始追逐
bad_egg_freeze[i]=80;//停止计数恢复初值
};
};
};
//显示积分的方法
public void draw_score()
{;
my_color=new Color(192,192,192);
g.setColor(my_color);
g.fillRect(150,350,100,10);//把显示分数的地方用填充矩形的方法清空
my_color=new Color(0,0,0);
g.setColor(my_color);
if (score>100000)
score=100000;//设一个积分上限
score_s=String.valueOf(score);//将整数型的积分转换为字符串
[] g.drawString("Your year end bonus is: $ "+score_s,0,360);//显示
};

//计算格格的坐标
public void set_position()
{;
//首先保留当前位置坐标值
pos_x=position_x;
[] pos_y=position_y;
if(up==true && position_y>1)//假如向上的键被按下并且小方块的纵坐标大于1
position_y--;//小方块向上移
if(down==true && position_y<330)//假如向下的键被按下并且小方块的纵坐标小于330
position_y++;//小方块向下移动
if(left==true && position_x>1)//假如向左的键被按下并且小方块的横坐标大于1
position_x--;//小方块向左移动
if(right==true && position_x<380)//假如向右的键被按下并且小方块的横坐标小于380
position_x++;//小方块向右移
bad_egg_bullet=new Rectangle(position_x,position_y,15,15);//这个矩形是格格的边框
//下面是两个小坏蛋的边框
bad_egg_1=new Rectangle(bad_egg_position_x[0],bad_egg_position_y[0],30,30);
bad_egg_2=new Rectangle(bad_egg_position_x[1],bad_egg_position_y[1],30,30);
if(bad_egg_1.intersects(bad_egg_bullet))//假如格格的边框和小坏蛋1的边框相交
{;
score=score-20;//格格被小坏蛋1抓住了.积分减 20
cought_by_hu.play();//发出格格被小坏蛋1抓住的声音
};
if(bad_egg_2.intersects(bad_egg_bullet))
{;
score=score-50;//格格被小坏蛋2抓住了.积分减 50
cought_by_xia.play();//发出格格被小坏蛋2抓住的声音
};
};
//画屏幕
public void draw_image()
{;
my_color=new Color(179,179,179);
off_screen.setColor(my_color);
off_screen.fillRect(0,0,400,350);//在后台画背景
off_screen.drawImage(img_now,position_x,position_y,applet);//在后台画格格的图像
draw_bullet();//画子弹
//在后台画两个小坏蛋
off_screen.drawImage(bad_egg[0],bad_egg_position_x[0],bad_egg_position_y[0],applet);
off_screen.drawImage(bad_egg[1],bad_egg_position_x[1],bad_egg_position_y[1],applet);
g.drawImage(off_screen_buffer,0,0,applet);//送到前景显示
};
//根据格格移动方向选择要显示的图片并决定子弹飞行方向的方法
[] public void select_image()
{;
fire_proposal=true;//默认状态是准许开枪
if(position_x==pos_x && position_y==pos_y)//假如格格没有动
{;
fire_proposal=false;//不准开枪
fire_direction=0;//方向为0是无效值
img_now_switch_count++;//格格图像切换计数加1
if (img_now_switch_count==img_now_switch_count_top)//切换计数到了切换值
{;
img_now_switch=!img_now_switch;//切换标志取反
img_now_switch_count=0;//切换计数清零
};
//切换标志为true,选择img_center_open去显示;为false,选择img_center_close去显示
img_now=(img_now_switch)?img_center_open:img_center_close;
};
if(position_x==pos_x && position_y {;
fire_direction=1;//现在格格是在向上移动,如果开枪,子弹方向向上
[] img_now=img_up;//选择img_up去显示
};
if(position_x>pos_x && position_y {;
fire_direction=2;//现在格格是在向右上移动,如果开枪,子弹方向向右上
[] img_now=img_up_right;//选择img_up_right去显示
};
[] if(position_x>pos_x && position_y==pos_y)//格格现在的位置在刚才位置的右方
{;
fire_direction=3;//现在格格是在向右移动,如果开枪,子弹方向向右
img_now=img_right;//选择img_right去显示
};
[] if(position_x>pos_x && position_y>pos_y)//格格现在的位置在刚才位置的右下方
{;
fire_direction=4;//现在格格是在向右下移动,如果开枪,子弹方向向右下
[] img_now=img_down_right;//选择img_down_right去显示
};
if(position_x==pos_x && position_y>pos_y)//格格现在的位置在刚才位置的下方
{;
[] fire_direction=5;//现在格格是在向下移动,如果开枪,子弹方向向下
[] img_now=img_down;//选择img_down去显示
};
if(position_xpos_y)//格格现在的位置在刚才位置的左下方
[] {;
fire_direction=6;//现在格格是在向左下移动,如果开枪,子弹方向向左下
img_now=img_down_left;//选择img_down_left去显示
};
[] if(position_x {;
fire_direction=7;//现在格格是在向左移动,如果开枪,子弹方向向左
img_now=img_left;//选择img_left显示
};
if(position_x {;
fire_direction=8;//现在格格是在向左上移动,如果开枪,子弹方向向左上
img_now=img_up_left;//选择img_up_left去显示
};
};
//在后台画子弹的方法
public void draw_bullet()
{;
for (i=1;i<=bullet_amount;i++)//一个个子弹去画
{;
//先根据子弹飞行的方向决定应该选哪个图片画
switch(bullet_position[i][2])//第三个元素(下标2)是方向
{;
case 1://向上
bullet_now=bullet_up;//选向上的图片
break;
case 2://向右上
bullet_now=bullet_up_right;//选向右上的图片
break;
case 3://向右
bullet_now=bullet_right;//选向右的图片
break;
case 4://向右下
bullet_now=bullet_down_right;//选向右下的图片
break;
case 5://向下
bullet_now=bullet_down;//选向下的图片
break;
case 6://向左下
bullet_now=bullet_down_left;//选向左下的图片
break;
case 7://向左
bullet_now=bullet_left;//选向左的图片
break;
case 8://向左上
bullet_now=bullet_up_left;//选向左上的图片
break;
default://无效方向不画
bullet_now=null;
break;
};
//在后台缓冲区上画一个子弹
off_screen.drawImage(bullet_now,bullet_position[i][0],bullet_position[i][1],applet);
};
};
//这个方法供小坏蛋类的实例调用,来设置要显示的小坏蛋的图像,告知小坏蛋当前的坐标.aa指出是哪一个小坏蛋
public void ready_bad_egg(int aa,Image a,int b,int c)
{;
[] bad_egg[aa-1]=a;
bad_egg_position_x[aa-1]=b;
bad_egg_position_y[aa-1]=c;
};
//申请开枪的方法
public void fire_wanna_switch(boolean a)
{;
fire_wanna=a;
};
//处理子弹的方法
public void bullet_processing()
[] {;
//增加一颗子弹
if (fire_wanna && fire_proposal && bullet_amount<30)//假如用户要求开枪,并且格格现在在移动可以开枪,并且现行子弹总数小于30颗
{;
bullet_amount++;//子弹总数加1
bullet_position[bullet_amount][2]=fire_direction;//保存子弹飞行方向.fire_direction是在select_image()方法中算出的
fire_wanna=false;//开枪后将开枪要求置为false
fire_sound.play();//发声
//下面根据格格的位置设置子弹的初始坐标.有加减的情况是因为子弹要从格格图片的中心飞出,但格格的坐标是格格图片左上角的坐标,因此要加以调整.根据子弹飞行方向的不同,调整的值不同
switch (fire_direction)
{;
case 1:
bullet_position[bullet_amount][0]=position_x+5;
[] bullet_position[bullet_amount][1]=position_y;
break;
case 2:
bullet_position[bullet_amount][0]=position_x+10;
bullet_position[bullet_amount][1]=position_y;
break;
case 3:
bullet_position[bullet_amount][0]=position_x+10;
bullet_position[bullet_amount][1]=position_y+5;
break;
case 4:
bullet_position[bullet_amount][0]=position_x+10;
bullet_position[bullet_amount][1]=position_y+10;
break;
case 5:
bullet_position[bullet_amount][0]=position_x+5;
bullet_position[bullet_amount][1]=position_y+10;
break;
case 6:
bullet_position[bullet_amount][0]=position_x;
bullet_position[bullet_amount][1]=position_y+10;
break;
case 7:
bullet_position[bullet_amount][0]=position_x;
bullet_position[bullet_amount][1]=position_y+5;
break;
case 8:
[] bullet_position[bullet_amount][0]=position_x;
bullet_position[bullet_amount][1]=position_y;
break;
default:
break;
};
};
//下面计算子弹的位置,一颗一颗处理
for (i=1;i<=bullet_amount;i++)
{;
switch(bullet_position[i][2])
{;
case 1://向上移动
bullet_position[i][0]=bullet_position[i][0];//横坐标不变
bullet_position[i][1]=bullet_position[i][1]-6;//纵坐标减 6
break;
case 2://向右上移动
bullet_position[i][0]=bullet_position[i][0]+6;//横坐标加 6
[] bullet_position[i][1]=bullet_position[i][1]-6;//纵坐标减 6
break;
case 3:
bullet_position[i][0]=bullet_position[i][0]+6;
bullet_position[i][1]=bullet_position[i][1];
break;
case 4:
bullet_position[i][0]=bullet_position[i][0]+6;
bullet_position[i][1]=bullet_position[i][1]+6;
break;
case 5:
bullet_position[i][0]=bullet_position[i][0];
bullet_position[i][1]=bullet_position[i][1]+6;
break;
case 6:
bullet_position[i][0]=bullet_position[i][0]-6;
[] bullet_position[i][1]=bullet_position[i][1]+6;
break;
case 7:
bullet_position[i][0]=bullet_position[i][0]-6;
[] bullet_position[i][1]=bullet_position[i][1];
break;
case 8:
bullet_position[i][0]=bullet_position[i][0]-6;
bullet_position[i][1]=bullet_position[i][1]-6;
break;
[] default:
break;
};
};
//下面判断是否有某颗子弹飞出了屏幕边界,有的话,去掉它,并将它后面得数组元素前移
k=0;// k 用来纪录有机颗子弹飞出了屏幕边界
[] //生成两个小坏蛋的边框
[] bad_egg_1=new Rectangle(bad_egg_position_x[0],bad_egg_position_y[0],20,20);
bad_egg_2=new Rectangle(bad_egg_position_x[1],bad_egg_position_y[1],20,20);

for (i=1;i<=bullet_amount;i++)//一颗一颗子弹去处理
{;
//生成这颗子弹的边框.边框的大小和子弹每次移动的坐标点数量有关.是经验值
bad_egg_bullet=new Rectangle(bullet_position[i][0],bullet_position[i][1],5,5);
//假如子弹飞出了屏幕边界或者它的边框和某个小坏蛋的边框相交
if (bullet_position[i][0]<-10 || bullet_position[i][0]>400 || bullet_position[i][1]<-10 || bullet_position[i][1]>350||bad_egg_1.intersects(bad_egg_bullet)||bad_egg_2.intersects(bad_egg_bullet))
{;
//击中了小坏蛋1
if(bad_egg_1.intersects(bad_egg_bullet))
{;
hit_hu.play();//发出小坏蛋1被击中的声音
if(!bad_egg_stop[0])//假如小坏蛋1目前处于追逐状态
{;
score=score+50;//积分加 50
bad_egg_stop[0]=true;//小坏蛋停止追逐
};
};
//击中了小坏蛋2
if(bad_egg_2.intersects(bad_egg_bullet))
{;
hit_xia.play();
if(!bad_egg_stop[1])
{;
score=score+20;//积分加 20
bad_egg_stop[1]=true;
};
[] };
for (j=i+1;j<=bullet_amount;j++)//它后面所有的元素向前移占据它栽数组中的位置
{;
bullet_position[j-1][0]=bullet_position[j][0];
bullet_position[j-1][1]=bullet_position[j][1];
bullet_position[j-1][2]=bullet_position[j][2];
};
k++;//飞出屏幕边界的子弹或是击中了小坏蛋的子弹数量加1
};
};
bullet_amount=bullet_amount-k;//现在子弹的总数量是刚才的数量减去飞出屏幕边界的和击中小坏蛋的子弹的数量
};
//这个方法给小坏蛋类使用告知格格的位置
public int get_position(char c)
[] {;
if (c=='x')
return position_x;
if (c=='y')
return position_y;
return -100;
[] };
//这个方法给小坏蛋类使用告知小坏蛋是否处于停止追逐状态
public boolean get_bad_egg_stop(int a)
{;
return bad_egg_stop[a];
[]};
http:///tech/article811.html
</td></tr></table></td> </tr> <tr> <td background="/pic/split.gif" height=1></td> </tr> <tr> <td class="tdMargin1">
↑返回目录
前一篇: Java活动图像程序和游戏编写(4)
后一篇: Java活动图像程序和游戏编写(2)