« Implémentation du mini-jeu Java » : Tank Battle
« Implémentation du mini-jeu Java » : Tank Battle (suite 1)
Article de blog « Implémentation du mini-jeu Java » : Tank Battle (suite 1) ) a été mis en œuvre pour que le char puisse tirer une balle. Ce billet de blog continue d'implémenter davantage de fonctions sur cette base.
Fonction complète : le char tire plusieurs balles
Avec la base d'un char tirant une balle, tirer plusieurs balles est assez simple. Il vous suffit d'ajouter un conteneur à la classe TankClien pour le stocker. . Juste plusieurs balles. Comme la capacité du conteneur est également limitée, nous ne pouvons pas continuer à le remplir. Par conséquent, dans la classe bullet, nous avons introduit un attribut live pour l'objet bullet afin de déterminer si la balle est toujours vivante. Pour déterminer si la balle est toujours vivante, il faut déterminer si la position de la balle est hors des limites.
Seul le code pertinent pour compléter cette fonction est publié ci-dessous
TankClient.java
<code class="hljs cs"> private List<missile> missiles = new ArrayList<missile> (); public List<missile> getMissiles() { return missiles; } @Override public void paint(Graphics g) { //直接调用坦克类的draw方法 tk.draw(g); //画子弹 for(int i=0;i<missiles.size();i++){ code="" missile="" ms="missiles.get(i);"></missiles.size();i++){></missile></missile></missile></code>
Classe Missile.java
Dans la méthode de déplacement, selon l'emplacement de la position de la balle pour déterminer si la balle est toujours vivante.
<code class="hljs cs"><code class="hljs cs"> public class Missile { private void move() { if(dir==Direction.L){//L,LU,U,RU,R,RD,D,LD,STOP x -= XSPEED; } else if(dir==Direction.LU){ x -= XSPEED; y -= YSPEED; } else if(dir==Direction.U){ y -= YSPEED; } else if(dir==Direction.RU){ x += XSPEED; y -= YSPEED; } else if(dir==Direction.R){ x += XSPEED; } else if(dir==Direction.RD){ x += XSPEED; y += YSPEED; } else if(dir==Direction.D){ y += YSPEED; } else if(dir==Direction.LD){ x -= XSPEED; y += YSPEED; } //根据子弹所在的位置x,y来判断子弹是否还存活在 if(x<0||x>TankClient.GAME_WIDTH||y<0||y>TankClient.GAME_HEIGHT){ live = false; } } public boolean isLive() { return live; } } </code></code>
Le contenu du fichier Tank.java est le suivant :
Dans la classe tank, dans la méthode keyPressed, à chaque appui sur la touche Ctrl, une balle est tirée.
<code class="hljs cs"><code class="hljs cs"> public class Tank { //记录键盘的按键情况 public void keyPressed(KeyEvent e){ int key=e.getKeyCode(); //System.out.println(key); switch(key){ case 17: tc.getMissiles().add(fire()); break; case KeyEvent.VK_LEFT: b_L=true; break; case KeyEvent.VK_UP: b_U=true; break; case KeyEvent.VK_RIGHT: b_R=true; break; case KeyEvent.VK_DOWN: b_D=true; break; } //根据上面的按键情况,确定坦克即将要运行的方向 moveDirection(); } } </code></code>
Lien de téléchargement du code complet : http://download.csdn.net/detail/u010412719/9555292
Fonction complète : résoudre le problème du passage des chars à la frontière
Réservoir traversant la frontière Le problème est relativement simple. Il vous suffit de déterminer si l'emplacement du réservoir traverse la frontière. Si c'est le cas, définissez sa position sur la position limite.
Le code d'implémentation est le suivant :
<code class="hljs cs"><code class="hljs cs"> /* * 函数功能:处理坦克越界问题 * */ private void dealTankBorder() { if(x<0){ x = 0; } else if(x > TankClient.GAME_WIDTH-this.WIDTH){ x = TankClient.GAME_WIDTH-this.WIDTH ; } if(y<0){ y = 0; } else if(y>TankClient.GAME_WIDTH - this.HEIGHT){ y = TankClient.GAME_WIDTH - this.HEIGHT; } }</code></code>
La fonction ci-dessus peut être appelée à la fin de la méthode move().
Fonction complète : ajouter des chars ennemis
Les fonctions implémentées précédemment sont de déplacer un char sur l'interface, de tirer des balles, etc.
Maintenant, nous finissons d'ajouter un char ennemi à l'interface.
Il existe deux façons d'implémenter les chars ennemis
1 La première consiste à créer une nouvelle classe EnemyTank,
2. propriété de classe A indiquant le type de ce réservoir.
Comme nous avons déjà une classe tank, par souci de commodité, voici la deuxième méthode : ajouter un attribut à la classe Tank d'origine pour indiquer le type de tank.
Le contenu nouvellement ajouté dans Tank.java comprend principalement
<code class="hljs cs"><code class="hljs java"> //添加一个属性,表示此坦克是好还是坏 private boolean good; //更改下构造方法 public Tank(int x, int y,boolean good) { this.x = x; this.y = y; this.good = good; } public Tank(int x, int y,boolean good, TankClient tc) { this(x,y,good); this.tc = tc; } //根据坦克的类型给出不同的颜色 public void draw(Graphics g){ 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();//根据键盘按键的结果改变坦克所在的位置 }
Il n'y a aucun changement dans la classe Missile.
Les contenus qui doivent être ajoutés au gestionnaire général TankClient.java sont :
1. Créez deux nouveaux objets réservoir
<code class="hljs cs"><code class="hljs cs">private Tank tk=new Tank(50,50,true,this); private Tank enemy = new Tank(100,100,false,this);</code></code>
2. Dessinez deux objets réservoir. dans le réservoir de méthode de peinture
<code class="hljs cs"><code class="hljs cs"> @Override public void paint(Graphics g) { //直接调用坦克类的draw方法 tk.draw(g); enemy.draw(g); //画子弹 for(int i=0;i<missiles.size();i++){ code="" missile="" ms="missiles.get(i);"></missiles.size();i++){></code></code>
< 喎�"/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxjb2RlIGNsYXNzPQ= =" hljs cs">Ce qui précède a implémenté la fonction d'ajout de chars ennemis, mais ne leur a pas encore ajouté de mouvement aléatoire.
Fonction terminée : les balles tuent les chars ennemis
Après la mise en œuvre ci-dessus, nous avons un char ennemi idiot qui ne bouge pas et ne peut pas tirer de balles, mais nous ne pouvons pas non plus le combattre, tuons-le. tuez ensuite le tank. Haha, n'est-ce pas un peu plus intéressant ?
Analyse :
1. Puisque la balle a tué le char ennemi, selon l'idée orientée objet, une méthode hitTank a été ajoutée à la classe de balle
<code class="hljs cs"><code class="hljs cs"><code>public boolean hitTank(Tank t){ } </code></code></code>
2. Alors, comment la méthode hitTank doit-elle déterminer si la balle a touché le char ? ? Cela implique un problème de collision. Puisque nos balles et nos chars sont tous deux des rectangles, le problème de collision est grandement simplifié. Il suffit de déterminer si les deux rectangles se chevauchent. Si tel est le cas, on estime qu'une collision s'est produite et que la balle a touché le char.
Par conséquent, dans la classe Missile et la classe Tank, ajoutez une méthode getRect() pour renvoyer l'objet de zone rectangulaire où se trouvent la balle et le char.
<code class="hljs cs"><code class="hljs cs"><code>public Rectangle getRect(){ return new Rectangle(x, y, WIDTH, HEIGHT); } </code></code></code>
3. Lorsque la balle touche le char, la balle et le char devraient disparaître. Il faut donc introduire une variable booléenne dans le tank pour déterminer si le tank est vivant
<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);//坦克死了 return true; } else{ return false; } }</code></code></code>
Si la balle disparaît, c'était géré dans la version précédente, mais le tank disparaît dans cette version. La méthode de traitement actuelle est Sans le dessiner, c'est-à-dire que dans la méthode draw, vérifiez d'abord si l'objet est vivant. S'il est vivant, dessinez-le.
Le code est le suivant :
<code class="hljs cs"><code class="hljs cs"><code class="hljs cs"> public void draw(Graphics g){ if(!live){ //判断坦克是否存活,如果死了,则不绘画出来,直接返回 return ; } 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();//根据键盘按键的结果改变坦克所在的位置 } </code></code></code>
Enfin, postez le code complet de la classe Tank, de la classe Missile et de la classe TankClient :
Classe Tank
<code class="hljs cs"><code class="hljs cs"><code class="hljs java"> public class Tank { //坦克所在的位置坐标 private int x; private int y; //坦克的高度和宽度 private static final int WIDTH = 30; private static final int HEIGHT = 30; //定义两个常量,表示运动的速度 private static final int XSPEED = 5; private static final int YSPEED = 5; //定义四个布尔类型变量来记录按键的情况,默认状态下为false,表示没有键按下 private boolean b_L,b_U,b_R,b_D; //添加一个属性,表示此坦克是好还是坏 private boolean good; public boolean isGood() { return good; } //用来标识此坦克对象是否存活 private boolean live =true; public boolean isLive() { return live; } public void setLive(boolean live) { this.live = live; } //定义一个枚举类型来表示运行的方向 public enum Direction{ L,LU,U,RU,R,RD,D,LD,STOP } //定义一个变量来表示坦克要运行的方向,初始状态为STOP private Direction dir = Direction.STOP; //炮筒方向 private Direction ptDir = Direction.D; private TankClient tc; public Tank(int x, int y,boolean good) { this.x = x; this.y = y; this.good = good; } public Tank(int x, int y,boolean good, TankClient tc) { this(x,y,good); this.tc = tc; } public void draw(Graphics g){ if(!live){ //判断坦克是否存活,如果死了,则不绘画出来,直接返回 return ; } 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();//根据键盘按键的结果改变坦克所在的位置 } private void drawGunBarrel(Graphics g) { int centerX = this.x + this.WIDTH/2; int centerY = this.y + this.HEIGHT/2; if(ptDir==Direction.L){//L,LU,U,RU,R,RD,D,LD,STOP g.drawLine(centerX, centerY, x, y + HEIGHT/2); } else if(ptDir==Direction.LU){ g.drawLine(centerX, centerY, x, y ); } else if(ptDir==Direction.U){ g.drawLine(centerX, centerY, x+ WIDTH/2, y ); } else if(ptDir==Direction.RU){ g.drawLine(centerX, centerY, x + WIDTH, y ); } else if(ptDir==Direction.R){ g.drawLine(centerX, centerY, x+ WIDTH, y + HEIGHT/2); } else if(ptDir==Direction.RD){ g.drawLine(centerX, centerY, x+ WIDTH, y + HEIGHT); } else if(ptDir==Direction.D){ g.drawLine(centerX, centerY, x+ WIDTH/2, y + HEIGHT); } else if(ptDir==Direction.LD){ g.drawLine(centerX, centerY, x, y + HEIGHT); } } //记录键盘的按键情况 public void keyPressed(KeyEvent e){ int key=e.getKeyCode(); //System.out.println(key); switch(key){ // case 17://避免因Ctrl一直按下,一直发射子弹,因此将这一功能放入keyReleased方法中了 // tc.getMissiles().add(fire()); // break; case KeyEvent.VK_LEFT: b_L=true; break; case KeyEvent.VK_UP: b_U=true; break; case KeyEvent.VK_RIGHT: b_R=true; break; case KeyEvent.VK_DOWN: b_D=true; break; } //根据上面的按键情况,确定坦克即将要运行的方向 moveDirection(); } //键盘按键松下时,也要进行记录 public void keyReleased(KeyEvent e) { int key=e.getKeyCode(); switch(key){ case 17: tc.getMissiles().add(fire()); break; case KeyEvent.VK_LEFT: b_L=false; break; case KeyEvent.VK_UP: b_U=false; break; case KeyEvent.VK_RIGHT: b_R=false; break; case KeyEvent.VK_DOWN: b_D=false; break; } } //根据键盘的按键情况来确定坦克的运行方向 private void moveDirection() {//L,LU,U,RU,R,RD,D,LD,STOP if(b_L&&!b_U&&!b_R&&!b_D){ dir = Direction.L; } else if(b_L&&b_U&&!b_R&&!b_D){ dir = Direction.LU; } else if(!b_L&&b_U&&!b_R&&!b_D){ dir = Direction.U; } else if(!b_L&&b_U&&b_R&&!b_D){ dir = Direction.RU; } else if(!b_L&&!b_U&&b_R&&!b_D){ dir = Direction.R; } else if(!b_L&&!b_U&&b_R&&b_D){ dir = Direction.RD; } else if(!b_L&&!b_U&&!b_R&&b_D){ dir = Direction.D; } else if(b_L&&!b_U&&!b_R&&b_D){ dir = Direction.LD; } else{//其它所有情况,都是不动 dir = Direction.STOP; } //将坦克方向赋值给炮筒方向 if(dir!=Direction.STOP){ ptDir = dir; } } //上面有运行方向,但是还缺少具体的运行细节,例如:假设是按下了右键,则应该横坐标x+=XSPEED; private void move(){ if(dir==Direction.L){//L,LU,U,RU,R,RD,D,LD,STOP x -= XSPEED; } else if(dir==Direction.LU){ x -= XSPEED; y -= YSPEED; } else if(dir==Direction.U){ y -= YSPEED; } else if(dir==Direction.RU){ x += XSPEED; y -= YSPEED; } else if(dir==Direction.R){ x += XSPEED; } else if(dir==Direction.RD){ x += XSPEED; y += YSPEED; } else if(dir==Direction.D){ y += YSPEED; } else if(dir==Direction.LD){ x -= XSPEED; y += YSPEED; } else if(dir==Direction.STOP){ //... nothing } //处理坦克越界问题 dealTankBorder(); } /* * 函数功能:处理坦克越界问题 * */ private void dealTankBorder() { if(x<0){ x = 0; } else if(x > TankClient.GAME_WIDTH-this.WIDTH){ x = TankClient.GAME_WIDTH-this.WIDTH ; } if(y<0){ y = 0; } else if(y>TankClient.GAME_WIDTH - this.HEIGHT){ y = TankClient.GAME_WIDTH - this.HEIGHT; } } public Missile fire(){ //计算子弹的位置,并利用炮筒的方向来new一个子弹对象 int x = this.x +(this.WIDTH)/2 - (Missile.WIDTH)/2; int y = this.y + (this.HEIGHT)/2 -(Missile.HEIGHT)/2; Missile ms = new Missile(x,y,this.ptDir); return ms; } /* * 函数功能:得到坦克所在位置的矩形框 * */ public Rectangle getRect(){ return new Rectangle(x, y, WIDTH, HEIGHT); } }</code></code></code>
Classe de missile
Le code est le suivant
<code class="hljs cs"><code class="hljs cs"><code class="hljs java"> public class Missile { //定义两个常量,表示运动的速度 private static final int XSPEED = 10; private static final int YSPEED = 10; //子弹所在的位置 private int x; private int y; //坦克的高度和宽度 public static final int WIDTH = 10; public static final int HEIGHT = 10; //子弹的运行方向 private Direction dir; private boolean live = true; public Missile(int x, int y, Direction dir) { this.x = x; this.y = y; this.dir = dir; } public void draw(Graphics g){ //如果该子弹不是存活的,则不进行绘图 if(!live){ return ; } Color c = g.getColor(); g.setColor(Color.YELLOW); g.fillOval(x, y, WIDTH, HEIGHT); g.setColor(c); move(); } private void move() { if(dir==Direction.L){//L,LU,U,RU,R,RD,D,LD,STOP x -= XSPEED; } else if(dir==Direction.LU){ x -= XSPEED; y -= YSPEED; } else if(dir==Direction.U){ y -= YSPEED; } else if(dir==Direction.RU){ x += XSPEED; y -= YSPEED; } else if(dir==Direction.R){ x += XSPEED; } else if(dir==Direction.RD){ x += XSPEED; y += YSPEED; } else if(dir==Direction.D){ y += YSPEED; } else if(dir==Direction.LD){ x -= XSPEED; y += YSPEED; } //根据子弹所在的位置x,y来判断子弹是否还存活在 if(x<0||x>TankClient.GAME_WIDTH||y<0||y>TankClient.GAME_HEIGHT){ live = false; } } public boolean isLive() { return live; } public Rectangle getRect(){ return new Rectangle(x, y, WIDTH, HEIGHT); } public boolean hitTank(Tank t){ //首先判断此坦克是否是存活的,如果是死的,就不打了 if(!t.isLive()){ return false; } if(this.getRect().intersects(t.getRect())){//判断是否有碰撞 //碰撞之后,子弹和该坦克就应该都死了 this.live = false;//子弹死了 t.setLive(false);//坦克死了 return true; } else{ return false; } } </code></code></code>
Le code de la classe TankClient est le suivant :
<code class="hljs cs"><code class="hljs cs"><code class="hljs java"> /* * 此版本添加了子弹打死敌对坦克 * */ public class TankClient extends Frame{ public final static int GAME_WIDTH=600; public final static int GAME_HEIGHT=600; private Tank tk=new Tank(50,50,true,this); private Tank enemy = new Tank(100,100,false,this); private List<missile> missiles = new ArrayList<missile> (); public List<missile> getMissiles() { return missiles; } private Image offScreenImage = null; public static void main(String[] args) { new TankClient().launchFrame(); } @Override public void update(Graphics g) { if (offScreenImage == null) { offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT); } Graphics goffScreen = offScreenImage.getGraphics();// 重新定义一个画虚拟桌布的画笔// Color c = goffScreen.getColor(); goffScreen.setColor(Color.darkGray); goffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT); goffScreen.setColor(c); paint(goffScreen); g.drawImage(offScreenImage, 0, 0, null); } @Override public void paint(Graphics g) { //直接调用坦克类的draw方法 tk.draw(g); enemy.draw(g); //画子弹 for(int i=0;i<missiles.size();i++){ catch="" code="" extends="" implements="" interruptedexception="" keyevent="" keymonitor="" missile="" ms="missiles.get(i);" myrepaint="" new="" override="" private="" public="" try="" void="" windowevent=""></missiles.size();i++){></missile></missile></missile></code></code></code>
Ce qui précède complète la fonction du char tirer des balles pour toucher les chars ennemis.
Pas encore terminé, voir le prochain article de blog pour les fonctions restantes
Ce qui précède est le contenu de "Java Mini Game Implementation" : Tank Battle (suite 2). Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (www.php.cn) !