博文《java小游戏实现》:坦克大战(续二)中已经实现到了坦克可以发射子弹了并可以击中敌方的坦克了。这篇博文在此基础上继续实现更多的功能。
完成功能:添加爆炸效果
在上一个版本中,我们击中敌方的坦克,敌方的坦克只是消失了,没有产生类似于我们熟悉的爆炸的效果。下面我们添加这一爆炸的效果。
vcsjxolv4tk7uabe3kgjpgjyic8+dqo8aw1nigfsdd0= src=/uploadfile/collfiles/20160623/20160623091322277.png title=\ />
首先,我们创建一个爆炸类explode.
爆炸类中,会有如下属性和方法
1、位置信息x,y;
2、标识是否存活的属性
3、产生爆炸的图片数组(这里用直径画图来来代替)
4、draw方法
代码如下:
<code class="hljs java"> public class explode {
//爆炸所在的位置
private int x;
private int y;
//爆炸图片的直径
private int[] diameter={6,20,40,60,20,7};
//标识爆炸对象是否存活的属性
private boolean live =true;
public boolean islive() {
return live;
}
//标识爆炸显示到第几步了
private int step = 0;
private tankclient tc;
public explode(int x ,int y , tankclient tc){
this.x = x;
this.y = y;
this.tc = tc;
}
/*
* 让爆炸显示出来
* */
public void draw(graphics g){
if(!live) return;
//判断显示到第几步了,如果全部显示完了,则此对象已死,返回
if(step>=diameter.length){
live = false;
step = 0;
return;
}
color c = g.getcolor();
g.setcolor(color.yellow);
g.filloval(x, y, diameter[step], diameter[step]);
g.setcolor(c);
step++;
}
}</code>
在我们写好这个爆炸类之后,我们可以在tankclient类中测试下,测试需要添加的代码如下:
<code class="hljs java"> private explode explode = new explode(200,200,this);
@override
public void paint(graphics g) {
//炸弹对象
explode.draw(g);
}
</code>
测试发现,确实看到了类似于爆炸的效果。
完成功能:当子弹击中坦克时添加爆炸效果
当子弹击中坦克时添加爆炸效果;从这句话可以看出,我们在击中一个坦克时,需要添加一个爆炸对象。因此按照下面两步来完成这一功能。
1、爆炸应该存在于集合类中。
<code>与子弹类似,在tankclient类中加入集合
将集合中的爆炸逐一画出(如果死去就去除)
</code>
在tankclient类中添加代码如下:
<code class="hljs cs"> /*
* 为每个被击中的坦克添加一个爆炸对象
* */
private list<explode> explodes = new arraylist<explode>();
@override
public void paint(graphics g) {
//炸弹对象
for(int i=0;i<explodes.size();i++){ code="" e="explodes.get(i);" explode=""></explodes.size();i++){></explode></explode></code>
2、子弹击中一个坦克后应产生爆炸对象,添加到tankclient的爆炸集合中。
<code class="hljs cs"><code>在missile类中hittank方法中添加相关代码
</code></code>
missile类中hittank方法的代码如下:
<code class="hljs cs"><code class="hljs java"> public boolean hittank(tank t){
//先判断该坦克是否还是存活,如果已经死了,子弹就不打他了
if(!t.islive()){
return false;
}
if(this.getrect().intersects(t.getrect())){//判断是否有碰撞
//碰撞之后,子弹和该坦克就应该都死了
this.live = false;//子弹死了
t.setlive(false);//坦克死了
explode e = new explode(x,y,tc);
tc.getexplodes().add(e);
return true;
}
else{
return false;
}
}
</code></code>
以上就实现了当一颗子弹击中坦克时会产生爆炸效果。
完成的功能:添加多辆敌方的坦克
上一个版本中有一个我方的坦克,有一个不会动且不会发子弹的敌方的坦克,我们一打就死了,没意思,因此,我们可以通过按键a我们来在界面中添加多辆敌方坦克,也可以随机产生坦克。
在我们实际的游戏中,坦克一般是随机产生,当我们消灭掉后又会产生一批,就是这样一个过程。
实现过程如下:
1、在tankclient.java中声明一个list enemytanks对象,用来存放一定数量的敌方坦克对象。
2、写如下一个函数,用来随机产生一定数量的随机位置的坦克。
<code class="hljs cs"><code class="hljs cs"> /*
* 函数功能:产生敌方坦克
* */
public void producetank(){
int totalnum =r.nextint(4)+3 ;
for(int i=0;i<totalnum;i++){ code="" enemy="new" int="" tank="" x="(r.nextint(10)+1)*40;"
y="(r.nextint(10)+1)*30;"></totalnum;i++){></code></code>
3、在tankclient.java中的draw函数中画出来即可。
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"> @override
public void paint(graphics g) {
//直接调用坦克类的draw方法
tk.draw(g);
/*
* 将敌方坦克也画出来,如果没有了敌方坦克,则产生一定数量的地方坦克
* */
if(enemytanks.size()==0){
this.producetank();
}
for(int i=0;i<enemytanks.size();i++){ code="" e="explodes.get(i);" enemy="enemytanks.get(i);" explode="" i="0;i<explodes.size();i++)
{" int="" missile="" ms="missiles.get(i);" tank=""></enemytanks.size();i++){></code></code></code>
4、由于此时敌方的坦克有多个,因此在missile中,添加了一个hittanks(list tanks)方法,用来打一系列的坦克。在tankclient里面每发子弹都打tanks。
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"><code class="hljs java"> public boolean hittank(tank t){
//先判断该坦克是否还是存活,如果已经死了,子弹就不打他了
if(!t.islive()){
return false;
}
if(this.getrect().intersects(t.getrect())){//判断是否有碰撞
//碰撞之后,子弹和该坦克就应该都死了
this.live = false;//子弹死了
t.setlive(false);//坦克死了
explode e = new explode(x,y,tc);
tc.getexplodes().add(e);
return true;
}
else{
return false;
}
}
/*
* 一颗子弹打list中的坦克
* */
public boolean hittanks(list<tank> tanks){
for(int i=0;i<tanks.size();i++){ code="" return=""></tanks.size();i++){></tank></code></code></code></code>
完成功能:让敌方的坦克智能化一点(动起来)
上一个版本只能产生一定随机数量的坦克,但是不能动,这个版本就让其随机动起来。
改动如下:
1、在tank类中,添加一个如下的构造函数
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"><code class="hljs java"><code class="hljs java">
public tank(int x, int y,boolean good,direction dir, tankclient tc) {
this(x,y,good);
this.dir = dir;
this.tc = tc;
}</code></code></code></code></code>
2、然后在tankclient类中的producetank方法中使用上面的构造函数来new 每一个敌方坦克对象
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"><code class="hljs java"><code class="hljs cs"> /*
* 函数功能:产生敌方坦克
* */
public void producetank(){
int totalnum =r.nextint(4)+3 ;
for(int i=0;i<totalnum;i++){ code="" dir="dirs[rn];" direction="" dirs="direction.values();" enemy="new" int=""
rn="r.nextint(dirs.length);" tank="" x="(r.nextint(10)+1)*40;" y="(r.nextint(10)+1)*30;"></totalnum;i++){></code></code></code></code></code>
通过1、2两步敌方坦克就可以动起来了,但是这还不够好,因为他会一直朝着他刚初始化的方向一直运动下去。
为了解决这个问题。在tank类中的draw方法中,我们设置一个运动次数step,当一个敌方坦克运动次数达到step之后,我们就随机给他换一个方向运动。
基于上面的思想,tank类中的draw方法的代码如下:
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs">
<code class="hljs java"><code class="hljs cs"><code class="hljs cs"> //坦克没走step步,随机换一个方向
private random r = new random();
private int step = r.nextint(7)+3;
public void draw(graphics g){
if(!live){ //判断坦克是否存活,如果死了,则不绘画出来,直接返回
return ;
}
if(!this.good){
if(step==0){
direction[] dirs =direction.values();
int rn = r.nextint(dirs.length);
this.dir = dirs[rn];
step = r.nextint(7)+3;
}
}
color c = g.getcolor();
if(good){
g.setcolor(color.red);
}
else{
g.setcolor(color.blue);
}
g.filloval(x, y, width, height);
g.setcolor(c);
//画一个炮筒
drawgunbarrel(g);
move();//根据键盘按键的结果改变坦克所在的位置
step--;
}</code></code></code></code></code></code>
以上就实现了多个敌方坦克的随机运动。
完成功能:敌方坦克发射子弹
这个版本就为敌方坦克添加发射子弹的功能。
既然我方坦克也要发射子弹,敌方坦克也要发射子弹,子弹与子弹之间就要有所区分。因此,为子弹添加一个good属性来标识子弹的好与坏。
具体步骤如下:
1、在missile类中添加good属性,并添加一个如下的构造方法
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"><code class="hljs java">
<code class="hljs cs"><code class="hljs java"> private boolean good =true;
public missile(int x,int y,direction dir,boolean good,tankclient tc){
this(x,y,dir);
this.good = good;
this.tc = tc;
}</code></code></code></code></code></code>
2、在tank类中产生子弹的fire()方法中,使用上面的构造函数来进行构造子弹missile ms = new missile(x,y,this.ptdir,this.good,this.tc);this.good指的是坦克的好坏,就坦克是好的,子弹对象就是好的,否则子弹对象就是坏的,即根据坦克的好坏来产生子弹的好坏对象
tank类中fire方法的具体代码如下:
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"><code class="hljs java"><code class="hljs cs">
<code class="hljs cs"> public missile fire(){
//计算子弹的位置,并利用炮筒的方向来new一个子弹对象
int x = this.x +(this.width)/2 - (missile.width)/2;
int y = this.y + (this.height)/2 -(missile.height)/2;
//根据坦克的类型(good)来new与之对应的子弹类型
missile ms = new missile(x,y,this.ptdir,this.good,this.tc);
return ms;
}
</code></code></code></code></code></code>
3、更改以上两点,则在tank类中draw方法中为坏坦克添加发射子弹这一功能。
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"><code class="hljs java">
<code class="hljs cs"><code class="hljs cs"> public void draw(graphics g){
if(!live){ //判断坦克是否存活,如果死了,则不绘画出来,直接返回
return ;
}
//为坏坦克添加随机的方向
if(!this.good){
if(step==0){
direction[] dirs =direction.values();
int rn = r.nextint(dirs.length);
this.dir = dirs[rn];
step = r.nextint(7)+3;
}
}
//根据坦克的好坏来设置不同的颜色
color c = g.getcolor();
if(good){
g.setcolor(color.red);
}
else{
g.setcolor(color.blue);
}
g.filloval(x, y, width, height);
g.setcolor(c);
//画一个炮筒
drawgunbarrel(g);
move();//根据键盘按键的结果改变坦克所在的位置
step--;
//敌方子弹开火
if(!this.good&&r.nextint(40)>38){
this.tc.getmissiles().add(fire());
}
}
</code></code></code></code></code></code>
4、此时,经过上面的三步之后,我方和敌方都能够发射子弹了,但是敌方能够打死敌方的坦克。因此,还需要对missile的hittank(tank t)方法进行修正。
即在碰撞检测条件中添加这一条:this.good!=t.isgood(),即只有子弹和坦克不是同一类型的,才能打死对方。
具体完整代码如下:
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"><code class="hljs java">
<code class="hljs cs"><code class="hljs java"> public boolean hittank(tank t){
//先判断该坦克是否还是存活,如果已经死了,子弹就不打他了
if(!t.islive()){
return false;
}
if(this.live&&this.good!=t.isgood()&&this.getrect().intersects(t.getrect())){//判断是否有碰撞
//碰撞之后,子弹和该坦克就应该都死了
this.live = false;//子弹死了
t.setlive(false);//坦克死了
explode e = new explode(x,y,tc);
tc.getexplodes().add(e);
return true;
}
else{
return false;
}
}
</code></code></code></code></code></code>
5、在missile的draw方法中,根据子弹的好坏给出不同的颜色。这里采用好子弹采用红色,坏子弹采用蓝色进行区分。
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"><code class="hljs java">
<code class="hljs cs"><code class="hljs cs"> public void draw(graphics g){
//如果该子弹不是存活的,则不进行绘图
if(!live){
return ;
}
color c = g.getcolor();
//根据子弹的好坏来设置不同的颜色
if(this.good){
g.setcolor(color.red);
}
else{
g.setcolor(color.blue);
}
g.filloval(x, y, width, height);
g.setcolor(c);
move();
}
</code></code></code></code></code></code>
6、现在差不多就算完成了,但是,我们还需要在tankclient类中的draw方法中做一些改善,例如:1)将我方的坦克置于被敌方子弹攻击的范围内,2)我方坦克被打死之后,应该如何处理。
本项目中,处理的方法为,在我方坦克死亡之后,提示“game over,按键a可以复活!!!”字样,并按下键盘a产生一个新的我方坦克。
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"><code class="hljs java"><code class="hljs cs"><code class="hljs cs"> @override
public void paint(graphics g) {
/*
* 画出我们自己的坦克,首先判断自己的坦克是否是活的,如果是,则画出来
* 否则,则提示 game over ,并休眠100000毫秒
* */
if(tk.islive()){
tk.draw(g);
}
else{
g.drawstring("game over,按键a可以复活!!!",game_width/2 , game_height/2);
}
/*
* 将敌方坦克也画出来,如果没有了敌方坦克,则产生一定数量的地方坦克
* */
if(enemytanks.size()==0){
this.producetank();
}
for(int i=0;i<enemytanks.size();i++){ code="" e="explodes.get(i);" enemy="enemytanks.get(i);" explode="" i="0;i<explodes.size();i++){"
int="" missile="" ms="missiles.get(i);" tank=""></enemytanks.size();i++){></code></code></code></code></code></code>
在tank类中的keyreleased方法中添加键盘a的事件。具体代码如下:
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"><code class="hljs java">
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"> //键盘按键松下时,也要进行记录
public void keyreleased(keyevent e) {
int key=e.getkeycode();
switch(key){
case keyevent.vk_a:
producemaintank();
break;
//.....一些其它的case
}
}
private void producemaintank() {
tank t=this.tc.gettk();
if(!t.islive()){
int x = r.nextint(100)+200;
int y = r.nextint(150)+300;
tank newtank =new tank(x,y,true,direction.stop,this.tc);
this.tc.settk(newtank);
}
}
</code></code></code></code></code></code></code>
以上就基本上实现了坦克大战的敌我双方的游戏了。但是,还有一些需要我们完善的功能,例如,加入一些墙等等。在后面,将会慢慢实现。也会在博文中进行记录。
以上就是《java小游戏实现》:坦克大战(续三)的内容。