博文《Java小遊戲實現》:坦克大戰(續二)中已經實現到了坦克可以發射子彈了並可以擊中敵方的坦克了。這篇文章在此基礎上繼續實現更多的功能。
完成功能:添加爆炸效果
在上一個版本中,我們擊中敵方的坦克,敵方的坦克只是消失了,沒有產生類似於我們熟悉的爆炸的效果。下面我們來加入這爆炸的效果。
vcSjxOLV4tK7uabE3KGjPGJyIC8+DQo8aW1nIGFsdD0="" src="/uploadfile/Collfiles/20160623/2016062309135" 建立一個爆炸類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>
<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>
<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>通過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"> 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>以上就實現了多個敵方坦克的隨機運動。 完成功能:敵方坦克發射子彈這個版本就為敵方坦克添加發射子彈的功能。 既然我方坦克也要發射子彈,敵方坦克也要發射子彈,子彈與子彈之間就要有所區分。因此,為子彈添加一個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 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>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小游戏实现》:坦克大战(续三)的内容,更多相关内容请关注PHP中文网(www.php.cn)!