Article de blog « Implémentation du mini-jeu Java » : Dans Tank Battle (suite 2), il a été réalisé que les chars peuvent tirer des balles et toucher les chars ennemis. Ce billet de blog continue d'implémenter davantage de fonctions sur cette base.
Fonctionnalité terminée : Ajout d'un effet d'explosion
Dans la version précédente, nous frappions le char ennemi et le char ennemi disparaissait tout simplement sans produire un effet similaire à l'explosion que nous connaissons. Ensuite, nous ajoutons cet effet d'explosion.
vcSjxOLV4tK7uabE3KGjPGJyIC8 DQo8aW1nIGFsdD0="" src="/uploadfile/Collfiles/20160623/20160623091322277.png" title="" />
Tout d'abord , nous créons une classe d'explosion Explode.
Dans la classe d'explosion, il y aura les attributs et méthodes suivants
1 Informations de position x, y;
2. qui identifient s'il est vivant
3. Le tableau d'images qui produit l'explosion (remplacé par le dessin du diamètre ici)
4 Le code de la méthode de tirage
est le suivant :
<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>
in Après avoir écrit cette classe d'explosion, nous pouvons la tester dans la classe TankClient. Le code qui doit être ajouté pour les tests est le suivant :
<code class="hljs java"> private Explode explode = new Explode(200,200,this); @Override public void paint(Graphics g) { //炸弹对象 explode.draw(g); } </code>
Le test. Nous avons constaté que nous avions observé un effet similaire à une explosion.
Fonction complète : Ajouter un effet d'explosion lorsqu'une balle touche un char
Ajouter un effet d'explosion lorsqu'une balle touche un char comme le montre cette phrase, lorsque nous touchons un char, Un objet explosion doit être ajouté. Suivez donc les deux étapes ci-dessous pour compléter cette fonction.
1. L'explosion devrait exister dans la classe de collection.
<code>与子弹类似,在TankClient类中加入集合 将集合中的爆炸逐一画出(如果死去就去除) </code>
Ajoutez le code suivant dans la classe 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 Après qu'une balle a touché un char, un objet d'explosion doit être généré et ajouté à la collection d'explosions de TankClient. .
<code class="hljs cs"><code>在Missile类中hitTank方法中添加相关代码 </code></code>
Le code de la méthode hitTank dans la classe Missile est le suivant :
<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>
Ce qui précède permet d'obtenir un effet d'explosion lorsqu'une balle touche le char.
Fonction terminée : Ajouter plusieurs chars ennemis
Dans la version précédente, il y avait un notre char et un char ennemi qui ne pouvaient pas bouger ou tirer des balles. Nous mourrons dès que nous combattons, ce qui est ennuyeux. Par conséquent, nous pouvons ajouter plusieurs chars ennemis à l'interface en appuyant sur le bouton A, ou nous pouvons générer des chars de manière aléatoire.
Dans notre jeu actuel, les chars sont généralement générés de manière aléatoire. Lorsque nous les détruisons, un autre lot sera généré.
Le processus de mise en œuvre est le suivant :
1. Déclarez un objet List ennemisTanks dans TankClient.java pour stocker un certain nombre d'objets tanks ennemis.
2. Écrivez la fonction suivante pour générer aléatoirement un certain nombre de chars à des positions aléatoires.
<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. Dessinez-le simplement dans la fonction de dessin de TankClient.java.
<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. Puisqu'il y a plusieurs chars ennemis à ce moment-là, une méthode hitTanks (Liste des chars) est ajoutée dans Missile pour frapper une série de chars. Dans TankClient, chaque balle est tirée sur des chars.
<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>
Fonction terminée : rendre les chars ennemis plus intelligents (bouger)
La version précédente ne pouvait générer qu'un certain nombre aléatoire de chars, mais ils ne pouvaient pas se déplacer de manière aléatoire. .
Les modifications sont les suivantes :
1 Dans la classe Tank, ajoutez le constructeur suivant
<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. Utilisez ensuite ce qui précède dans la méthode ProduceTank dans TankClient. classe Le constructeur de chaque nouvel objet char ennemi
<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>
peut passer par les étapes 1 et 2, mais ce n'est pas suffisant, car il sera toujours initialisé vers lui. La direction continue d'avancer.
Pour résoudre ce problème. Dans la méthode de tirage au sort de la classe Tank, nous définissons un nombre de mouvements par pas. Lorsque le nombre de mouvements d'un char ennemi atteint un pas, nous changeons aléatoirement sa direction de mouvement.
Basé sur l'idée ci-dessus, le code de la méthode de tirage au sort dans la classe Tank est le suivant :
<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>
Ce qui précède réalise le mouvement aléatoire de plusieurs chars ennemis.
Fonction terminée : les chars ennemis tirent des balles
Cette version ajoute la fonction de tirer des balles sur les chars ennemis.
Puisque nos chars tirent également des balles et que les chars ennemis tirent également des balles, il doit y avoir une distinction entre les balles et les balles. Par conséquent, ajoutez un bon attribut à la puce pour identifier si la puce est bonne ou mauvaise.
Les étapes spécifiques sont les suivantes :
1. Ajoutez le bon attribut à la classe Missile et ajoutez un constructeur comme suit
<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. Générez des balles dans le Classe Tank Dans la méthode fire(), utilisez le constructeur ci-dessus pour construire la balle Missile ms = new Missile(x,y,this.ptDir,this.good,this.tc);this.good fait référence à la qualité du char , Tant que le tank est bon, l'objet balle est bon, sinon l'objet balle est mauvais, c'est-à-dire que l'objet balle est généré en fonction de la qualité du tank
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)!