ホームページ  >  記事  >  Java  >  「Javaミニゲーム実装」:戦車戦(続き3)

「Javaミニゲーム実装」:戦車戦(続き3)

黄舟
黄舟オリジナル
2016-12-27 13:21:191616ブラウズ

ブログ投稿「Java ミニゲーム実装」: 戦車戦 (続き 2) では、戦車が弾を発射して敵戦車を攻撃できることが実現しました。このブログ投稿では、これに基づいてさらに多くの機能を実装し続けます。

完成した機能: 爆発エフェクトの追加

以前のバージョンでは、敵の戦車に攻撃を当てましたが、敵の戦車は私たちがよく知っている爆発のようなエフェクトを生成せずに消えるだけでした。次に、この爆発エフェクトを追加します。

「Javaミニゲーム実装」:戦車戦(続き3)

vcSjxOLV4tK7uabE3KGjPGJyIC8+DQo8aW1nIGFsdD0="" src="/uploadfile/Collfiles/20160623/20160623091322277.png" title="" />

まず、爆発クラスを作成します Explode.

爆発クラスでは、以下の属性とメソッドがあります

1. 位置情報 x、y;

2. 爆発を生成する画像の配列 (ここでは直径描画に置き換えられます)

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 クラスでテストできます。テストのために追加する必要があるコードは次のとおりです。テストの結果、爆発に似た効果が確認されたことがわかりました。

完全な機能: 弾丸が戦車に当たったときに爆発エフェクトを追加します

弾丸が戦車に当たったときに爆発エフェクトを追加します; この文からわかるように、戦車に当たったときに爆発オブジェクトを追加する必要があります。したがって、この機能を完了するには、以下の 2 つの手順に従ってください。

1. コレクションクラスに爆発が存在する必要があります。

<code class="hljs java">    private Explode explode = new Explode(200,200,this);
    @Override
    public void paint(Graphics g) {
        //炸弹对象
        explode.draw(g);
    }
</code>

TankClient クラスに次のコードを追加します:

<code>与子弹类似,在TankClient类中加入集合
将集合中的爆炸逐一画出(如果死去就去除)
</code>

2. 弾丸が戦車に当たると、爆発オブジェクトが生成され、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>

Missile クラスの hitTank メソッドのコードは次のとおりです:

<code class="hljs cs"><code>在Missile类中hitTank方法中添加相关代码
</code></code>

上記は、弾丸が戦車に命中したときに爆発エフェクトを実現します。

完成した機能: 複数の敵戦車の追加

以前のバージョンでは、私たちの戦車が1台あり、移動することも弾を発射することもできない敵の戦車がいて、それに当たるとすぐに死んでしまいました。 , したがって、A ボタンを押すことで複数の敵戦車をインターフェースに追加したり、ランダムに戦車を生成したりすることができます。

実際のゲームでは、戦車は通常ランダムに生成され、それを破壊すると別のバッチが生成されます。

実装プロセスは次のとおりです:

1. TankClient.java で List 敵タンク オブジェクトを宣言し、一定数の敵タンク オブジェクトを格納します。

2. 以下の関数を作成して、ランダムな位置に一定数の戦車を生成します。

<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>

3. TankClient.java の描画関数で描画するだけです。

<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>

4. 現時点では複数の敵戦車が存在するため、一連の戦車を攻撃するための hitTanks (List Tanks) メソッドが Missile に追加されます。 TankClient では、すべての弾丸が戦車に発射されます。

<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>

完全な機能: 敵の戦車をより賢く(移動)します

以前のバージョンでは特定のランダムな数の戦車を生成することしかできませんでしたが、このバージョンでは敵をランダムに移動させることができます。

変更は次のとおりです:

1. Tank クラスに次のコンストラクターを追加します

<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>

2. 次に、TankClient クラスのProduceTank メソッドで上記のコンストラクターを使用して、各敵の戦車オブジェクトを新しくします

<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>

ステップ 1 と 2 では、敵の戦車が動き始めることがありますが、初期化されたばかりの方向に動き続けるため、これでは十分ではありません。

この問題を解決するには。 Tankクラスのdrawメソッドでは、敵戦車の移動回数がstepに達するとランダムに方向を変えるように設定しています。

上記の考えに基づいて、Tank クラスのdrawメソッドのコードは次のようになります:

<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. 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">        //坦克没走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>

2. Tankクラスで弾を生成するfire()メソッドで、上記のコンストラクターを使用します。弾丸ミサイルを構築します 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)!


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。