「Java ミニゲーム実装」: 戦車戦
「Java ミニゲーム実装」: 戦車戦 (続き 1)
ブログ投稿「Java ミニゲーム実装」: 戦車戦 (続き 1) 戦車ができることが実現しましたミサイルを発射してください。弾は消えました。このブログ投稿では、これに基づいてさらに多くの機能を実装し続けます。
完全な関数: 戦車は複数の弾丸を発射します
1 つの弾丸を発射する戦車の基礎により、複数の弾丸を格納するコンテナを TankClien クラスに追加するだけで済みます。容器の容量にも限りがあるので、詰め続けることはできません。したがって、弾丸クラスでは、弾丸がまだ生きているかどうかを判断するために、弾丸オブジェクトの live 属性を導入しました。弾丸がまだ生きているかどうかは、弾丸の位置が範囲外かどうかに基づいて判断されます。
この機能を完了するための関連コードのみを以下に掲載します
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>
Missile.java class
moveメソッドでは、弾丸がその位置に基づいてまだ生きているかどうかを判断します。
<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>
Tank.java ファイルの内容は次のとおりです:
Tank クラスの keyPressed メソッドで、Ctrl キーが押されるたびに弾丸が発射されます。
<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>
完全なコードのダウンロード リンク: http://download.csdn.net/detail/u010412719/9555292
完全な機能: 戦車の国境を越える問題を解決する
戦車の国境を越える問題は比較的単純で、必要なのはタンクの位置が境界を越えているかどうかを判断するには、タンクの位置を境界の位置に設定するだけです。
実装コードは以下の通りです:
<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>
上記の関数はmove()メソッドの最後で呼び出すことができます。
完全な機能: 敵戦車の追加
以前に実装された機能は、インターフェイス上で戦車を移動したり、弾を発射したりすることです。
これで、インターフェースへの敵戦車の追加が完了しました。
敵の戦車を実装するには 2 つの方法があります
1。1 つ目は、新しい EnemyTank クラスを作成することです
2。2 つ目は、元の Tank クラスに戦車のタイプを表す属性を追加することです。
タンク クラスがあるため、便宜上、2 番目の方法を示します。元のタンク クラスに属性を追加して、このタンクのタイプを表します。
Tank.java に新しく追加されたコンテンツには、主に
<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();//根据键盘按键的结果改变坦克所在的位置 }
Missile クラスがそのまま含まれています。
ゼネラルマネージャー TankClient.java に追加する必要がある内容は次のとおりです:
1. New で 2 つの戦車オブジェクトを作成します
<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. ペイント メソッドで 2 つの戦車を描画します
<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>
vcD4NCjxwPjxjb2RlIGNsYXNzPQ=="hljs cs">上記は敵戦車を追加する機能を実装しましたが、まだ敵戦車にランダムな動きは追加されていません。
完成した機能: 弾丸で敵の戦車を殺す
上記の実装後、動かず、弾丸を発射できない愚かな敵の戦車ができました。次はそれを実装しましょう。 戦車を殺します。ははは、もう少し面白くないですか?
分析:
1. オブジェクト指向の考え方に従って、弾丸クラスに hitTank メソッドを追加します
<code class="hljs cs"><code class="hljs cs"><code>public boolean hitTank(Tank t){ } </code></code></code>
2. では、hitTank メソッドは弾丸が戦車に命中したかどうかをどのように判断する必要がありますか。タンクはどうですか? ?これには衝突の問題が伴います。弾丸と戦車はどちらも長方形であるため、衝突の問題は 2 つの長方形が重なっているかどうかを判断するだけで済みます。そうであれば、衝突が発生して弾がタンクに命中したと判断される。
そこで、MissileクラスとTankクラスに、弾丸と戦車が配置されている長方形の領域オブジェクトを返すgetRect()メソッドを追加します。
<code class="hljs cs"><code class="hljs cs"><code>public Rectangle getRect(){ return new Rectangle(x, y, WIDTH, HEIGHT); } </code></code></code>
3. 弾丸が戦車に当たると、弾丸と戦車の両方が消えるはずです。そのため、戦車が生きているかどうかを判断するには、戦車にブール変数を導入する必要があります
<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>
弾が消えるかどうかは以前のバージョンでも対応していましたが、今回のバージョンでは戦車が消えるのが現状の対処方法です。それは描画することではありません。つまり、draw メソッドで、まずオブジェクトが生きているかどうかを確認し、生きている場合は描画します。
コードは次のとおりです:
<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>
最後に、Tankクラス、Missileクラス、TankClientクラスの完全なコードを投稿します:
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>
Missileクラス
コードは次のとおりです
<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>
TankClientクラスのコードは以下の通りです:
<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>
以上です。戦車が敵戦車に弾を発射できるようにする機能が完成しました。
まだ完成していません。残りの機能については次のブログ投稿を参照してください
上記は「Java ミニゲーム実装」の内容です: 戦車戦 (続き 2) 関連コンテンツの詳細については、PHP 中国語 Web サイトをご覧ください。 (www.php.cn)!