人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

エイリアンの攻撃

エイリアンがビームを撃つようにします。

invader06.jar

ビームの実装

エイリアンが発射するビームを実装します。まずShotクラスを全部コピーしてください。これで9割方完成です(笑)プレイヤーが発射する弾とエイリアンが発射するビームはほとんど同じです。弾は上に飛んでいくのに対し、ビームは下に飛んでいくことだけが違います。なのでmove()を少し変えるだけです。

    /**
     * ビームを移動する
     */
    public void move() {
        // 保管庫に入っているなら何もしない
        if (isInStorage())
            return;

        // ビームはy方向にしか移動しない
        y += SPEED;
        // 画面外のビームは保管庫行き
        if (y > MainPanel.HEIGHT) {
            store();
        }
    }

ほとんど同じなのでこういう場合は継承を使った方がよさそうです。あとで取り上げるかもしれません。

エイリアンの攻撃

次にビームを使ってエイリアンが攻撃する処理です。MainPanelのalienAttack()です。

    /**
     * エイリアンの攻撃
     */
    private void alienAttack() {
        // 1ターンでNUM_BEAMだけ発射する
        // つまりエイリアン1人になってもそいつがNUM_BEAM発射する
        for (int i = 0; i < NUM_BEAM; i++) {
            // エイリアンの攻撃
            // ランダムにエイリアンを選ぶ
            int n = rand.nextInt(NUM_ALIEN);
            // そのエイリアンが生きていればビーム発射
            if (aliens[n].isAlive()) {
                // 発射されていないビームを見つける
                // 1つ見つけたら発射してbreakでループをぬける
                for (int j = 0; j < NUM_BEAM; j++) {
                    if (beams[j].isInStorage()) {
                        // ビームが保管庫にあれば発射できる
                        // ビームの座標をエイリアンの座標にセットすれば発射される
                        Point pos = aliens[n].getPos();
                        beams[j].setPos(pos.x + aliens[n].getWidth() / 2,
                                        pos.y);
                        break;
                    }
                }
            }
        }
    }

NUM_BEAMは用意したビームの個数です。とりあえず20にしました。この20発に対して発射するエイリアンをランダムに決めて発射させています。死んでいるエイリアンがビームを発射したり、保管庫にないビームが発射されたら変なので、forループをまわして生きているエイリアン、保管庫にあるビームを探す処理が入っています。プレイヤーとビームの衝突判定

最後にエイリアンの発射したビームとプレイヤーの衝突判定を実装します。この処理はエイリアンと弾の衝突判定(2005/3/12)とほとんど同じです。

まずPlayerクラスにcollideWith()を作ります。今回はプレイヤーとビームの矩形が重なっているか調べています。

    /**
     * プレイヤーとビームの衝突を判定する
     * 
     * @param beam 衝突しているか調べるビームオブジェクト
     * @return 衝突していたらtrueを返す
     */
    public boolean collideWith(Beam beam) {
        // プレイヤーの矩形を求める
        Rectangle rectPlayer = new Rectangle(x, y, width, height);
        // ビームの矩形を求める
        Point pos = beam.getPos();
        Rectangle rectBeam = new Rectangle(pos.x, pos.y, 
                beam.getWidth(), beam.getHeight());

        // 矩形同士が重なっているか調べる
        // 重なっていたら衝突している
        return rectPlayer.intersects(rectBeam);
    }

次にMainPanelクラスのcollisionDetection()にプレイヤーとビームの衝突検出を追加します。

    private void collisionDetection() {
        // エイリアンと弾の衝突検出
        ・・・
        
        // プレーヤーとビームの衝突検出
        for (int i = 0; i < NUM_BEAM; i++) {
            if (player.collideWith(beams[i])) {
                // プレーヤーとi番目のビームが衝突
                // ビームは保管庫へ
                beams[i].store();
                // ゲームオーバー
                initGame();
            }
        }
    }

プレイヤーがビームにあたったらゲームオーバーです。initGame()を呼び出してゲームを初期化しています。

これで一応インベーダーゲームっぽくなりました。