n-HIROKIの日常

n-HIROKIの取り組みを記録したものです。

シューティングゲームの敵を動かすプログラム

こんにちは、n-hirokiです。

今回はシューティングゲームの敵を動かすプログラムです。

完成したもの

enemyを10体3行分 生成して動かします。
一番後に全体のコードを載せています。

1、enemy生成

enemyオブジェクトで必要な変数定義
var canvas, ctx;
var Enemy, enemys = [];
canvas定義

htmlに記述します

    <canvas id="mycanvas" width="500" height="500">
        Canvasに対応したブラウザを使ってください。
    </canvas>
canvasを使用するための呪文
    canvas = document.getElementById('mycanvas');
    if(!canvas || !canvas.getContext) return false;
    ctx = canvas.getContext('2d');
enemyオブジェクトを作成
Enemy = function(x, y, row){
    this.x = x; //x座標
    this.y = y; //y座標
    this.r = 15; //辺の長さ
    this.row = row; //行目
    this.color = "#FF6060"; //色
};
enemy描画メソッド
Enemy.prototype.draw = function(){
    ctx.fillStyle = this.color;
    ctx.fillRect(this.x, this.y, this.r, this.r); //箱を描画
};
enemy生成関数

横にenemyを10体を3列生成します

    function formEnemy(){
        var x = 0, y = 0;
        for(var row = 0;row < 3;row++){ //行ループ
            for(var num = 0;num < 10;num++){
                x = 30 * num + 50; //x軸
                y = (15 * row + 20) + (row * 10); //y軸 同じ行のenemyのy軸は統一
                enemys.push(new Enemy(x, y, row)); //配列で管理
            }
        }
    }

ここまでのコードでenemyの表示までできました。
enemys配列で全てのenemyを格納しています。
行の違いはプロパティで持っています。(enemys.row)


次はこのenemyを動かします。

2、enemyを動かす

今回のプログラムで必要な変数定義
var Stage, stage;
var directionFlag = "RIGHT";
var flagY = false;
var ENDFLAG = false;
var maxRow = 2;

Stageでシューティングゲームの動きを管理します

Stageオブジェクト作成
Stage = function(){
    this.clear = function(){
        ctx.fillStyle = "#ecf0f1"; //背景色と同じ色
        ctx.fillRect(0, 0, canvas.width, canvas.height); //canvas全体
    };
    this.update = function(){
        this.clear(); //canvasクリア
        enemys.forEach(function(value, index){
            value.direct(value); //directメソッド(x軸を動かす)
            value.moveY(value, index); //moveYメソッド(y軸を動かす)
            value.flagJudge(value, index); //flagJudgeメソッド(x軸の方向 右か左か)
            value.draw(); //描画
        });
        setTimeout(function(){
            this.update(); //Stageオブジェクトのupdateメソッドを500ms後に実行する
        }.bind(this), 500); //thisをStageに
    };
};

updateメソッドを繰り返してゲームを進行します

・各メソッド
directメソッド
Enemy.prototype.direct = function(value){
    value.rowCheck(value, index); //いま何行あるかチェック
    if(directionFlag == "RIGHT"){ //右方向
        value.x += 10;
    }else if(directionFlag == "LEFT"){ //左方向
        value.x -= 10;   
    }
};
rowCheckメソッド(行判定)
Enemy.prototype.rowCheck = function(value, index){
    if(index == enemys.length - 1){
        maxRow = value.row;
    }
};
moveYメソッド
Enemy.prototype.moveY = function(value, index){
    if(flagY == true){
        value.y += 10;
        if(index == enemys.length - 1)){
            flagY = false;
        }
    }
};
flagJudgeメソッド
Enemy.prototype.flagJudge = function(value, index){
    if(value.x >= 450 && value.row == maxRow){  //x軸が450以上になったら左に
        directionFlag = "LEFT"; //flagを左に
        flagY = true; //左に動く前にy軸を動かす
    }
    if((value.x <= 30 && value.row == maxRow) || ENDFLAG == true){ //x軸が30以下になったら右に
        ENDFLAG = true; //enemyを全部チェックするための変数
        if(ENDFLAG == true && index == enemys.length - 1){
            directionFlag = "RIGHT"; //flagを右に
            flagY = true; //右に動く前にy軸を動かす
            ENDFLAG = false; //enemyを全てチェック
        }
    }
};

これでenemyを動かせます
次はコードを組み合わせます

3、コードを組み合わせる

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>enemySystem</title>
</head>
<body>
    <canvas id="mycanvas" width="500" height="500">
        Canvasに対応したブラウザを使ってください。
    </canvas>
    <script>
        (function(){
            'use strict';
            var canvas, ctx;
            var Enemy, enemys = [];
            var Stage, stage;
            var directionFlag = "RIGHT";
            var flagY = false;
            var ENDFLAG = false;
            var maxRow = 2;
            
            canvas = document.getElementById('mycanvas');
            if(!canvas || !canvas.getContext) return false;
            ctx = canvas.getContext('2d');
            
            Enemy = function(x, y, row){
                this.x = x;
                this.y = y;
                this.r = 15;
                this.row = row;
                this.color = "#FF6060";
            };
            Enemy.prototype.draw = function(){
                ctx.fillStyle = this.color;
                ctx.fillRect(this.x, this.y, this.r, this.r);
            };
            Enemy.prototype.direct = function(value){
                if(directionFlag == "RIGHT"){
                    value.x += 10;
                }else if(directionFlag == "LEFT"){
                    value.x -= 10;   
                }
            };
            Enemy.prototype.moveY = function(value, index){
                if(flagY == true){
                    value.y += 10;
                    if(index == enemys.length - 1){
                        flagY = false;
                    }
                }
            };
            Enemy.prototype.flagJudge = function(value, index){
                if(value.x >= 450 && value.row == 2){
                    directionFlag = "LEFT";
                    flagY = true;
                }
                if((value.x <= 30 && value.row == 2) || ENDFLAG == true){
                    ENDFLAG = true;
                    if(ENDFLAG == true && index == enemys.length - 1){
                        directionFlag = "RIGHT";
                        flagY = true;
                        ENDFLAG = false;
                    }
                }
            };
            //行判定
            Enemy.prototype.rowCheck = function(value, index){
                if(index == enemys.length - 1){
                    maxRow = value.row;
                }
            }
            function formEnemy(){
                var x = 0, y = 0;
                for(var row = 0;row < 3;row++){
                    for(var num = 0; num < 10;num++){
                        x = 30 * num + 50;
                        y = (15 * row + 20) + (row * 10);
                        enemys.push(new Enemy(x, y, row));
                    }
                }
            }
            Stage = function(){
                this.clear = function(){
                    ctx.fillStyle = "#ecf0f1";
                    ctx.fillRect(0, 0, canvas.width, canvas.height);
                };
                this.update = function(){
                    this.clear();
                    enemys.forEach(function(value, index){
                        value.direct(value);
                        value.moveY(value, index);
                        value.flagJudge(value, index);
                        value.draw();
                    });
                    setTimeout(function(){
                        this.update();
                    }.bind(this), 500);
                };
            };
            formEnemy();
            stage = new Stage();
            stage.update();
        })();
    </script>
</body>
</html>

簡単にですがこのコードでenemyを動かすことができました。
シューティングゲーム作り方などで検索しないで、自分で全部考えて書きました。
まだ日本語から書かないとうまく作れないですが、自分の成長がわかり嬉しいです!

多分シューティングゲームのオーソドックスな書き方とかあると思いますが、それは調べずに我流でのコードです。
なのであまり参考にならないかもしれません。

enemy以外の機能も簡単にはできたので、またこのブログに書きたいと思います!

追記:
プレイヤー機を動かすプログラムのブログ書きました!!
hiroki-prog.hatenablog.com