サブマリンバスターの全コード

ソースコード

game.js 内のソースコードです。

Crafty.init(600,450, document.getElementById('game'));

const assetsObj = {
    "sprites": {    // スプライトとして読み込み
        "sky.png": {
            "tile":20, "tileh":90, "map":{ "Sky":[0,0] }
        },
        "sea.png": {
            "tile":20, "tileh":365, "map":{ "Sea":[0,0] }
        },
        "titlename.png": {
            "tile":525, "tileh":104, "map":{ "Title":[0,0] }
        },
        "gameover.png": {
            "tile":506, "tileh":102, "map":{ "Gameover":[0,0] }
        },
        "player.png": {
            "tile":115, "tileh":41, "map":{ "Player":[0,0] }
        },
        "submarine.png": {
            "tile":72, "tileh":27, "map":{ "Enemy":[0,0],"Explosion":[1,0] }
        },
        "bomb1.png": {
            "tile":17, "tileh":7, "map":{ "Bomb1":[0,0] }
        },
        "bomb2.png": {
            "tile":16, "tileh":16, "map":{ "Bomb2":[0,0] }
        },
        "flame.png": {
            "tile":24, "tileh":47, "map":{ "Flame":[0,0] }
        }
    }
};

Crafty.load( assetsObj,
    function() {    // ファイルロード後に実行
        Crafty.scene("title");
    }
);

Crafty.scene("title", function() {
    Crafty.e('Sky, 2D, Canvas').attr({x:0, y:0, w:600});
    Crafty.e('Sea, 2D, Canvas').attr({x:0, y:85, w:600});
    Crafty.e('Title, 2D, Canvas').attr({x:40, y:160});
    Crafty.e('2D, DOM, Text')
        .attr({x:200, y:280, w:400, cnt:0})
        .text("Z キーでスタート").textColor('#ff7f00')
        .bind('KeyDown', function(e) {
            if( e.key == Crafty.keys.Z ) {
                Crafty.scene("main");   // ゲームメイン処理へ
            }
        })
        .bind('EnterFrame', function () {
            this.cnt++;
            if( this.cnt %90 < 60 ){
                this.textColor('#ff7f00');
            } else {
                this.textColor('#333333');            
            }
        })
        .textFont({size:'24px'});
});

let bomb1_cnt;  // プレイヤー爆弾カウンター
let stock_cnt;  // 爆弾のストック
let score;
let gameover;   // ゲームオーバー(プレイヤーのやられフラグ兼用)

Crafty.scene("main", function() {
    let enemyCnt = Crafty.frame() +100;     // +100:敵の発生タイミング
    bomb1_cnt = 0;
    stock_cnt = 0;
    score = 0;
    gameover = 0;   // 0ならプレイヤーはやられていない
    
    Crafty.e('Sky, 2D, Canvas').attr({x:0, y:0, w:600});
    Crafty.e('Player, 2D, Canvas, Twoway, Collision')
        .attr({x:250, y:45})
        .bind('EnterFrame', function () {
            if( this.x < 0 ) this.x = 0;
            if( this.x > 600-this.w ) this.x = 600 - this.w;
            if( gameover > 0 ){     // 撃沈演出
                this.y += 0.3;
                if( this.y > 85 ) this.destroy();
            }
        })
        .bind('KeyDown', function(e) {
            if( e.key == Crafty.keys.Z && gameover == 0 ) {
                setPlayerBomb(this.x+this.w/2,this.y+30);   // プレイヤー爆弾
            }
        })
        .onHit('Flame', function (hitDatas) {  // 火柱に当たったら
            if( gameover == 0 ){
                gameover = 1;
                this.disableControl();     // 入力イベント応答しないように
                this.vx = 0;    // 移動を停止
                Crafty.e("Delay").delay(disp_gameover, 1500, 0);
            }
        })
        .twoway(100, 0);       // 移動速度, jump速度
    Crafty.e('Sea, 2D, Canvas')
        .bind("EnterFrame", function(){
            if( Crafty.frame() > enemyCnt ){
                enemyCnt += Crafty.math.randomInt(30, 150);  // 敵の発生間隔
                setEnemy();
            }
            stockBomb();
        })
        .attr({x:0, y:85, w:600});
    // スコア
    Crafty.e("Score, DOM, 2D, Text")
        .attr({ x:10, y:3, w:280, h:20 })
        .textFont({size:'20px', weight:'bold'})
        .textColor('#222222')
        .text("SCORE: 0");
});

// ゲームオーバーの表示
function disp_gameover(){
    Crafty.e('Gameover, 2D, Canvas, Tween')
        .attr({x:45, y:160, z:100, h:1})
        .tween({h:102}, 800, "easeOutQuad");
    Crafty.e("Delay").delay(function() {    // 指定秒後に実行する
        Crafty.e('2D, DOM, Text').attr({x:200, y:280, w:300, z:100, cnt:0})
            .text("Zキーを押してください").textColor('#ff7f00')
            .textFont({size:'18px'})
            .bind('KeyDown', function(e) {
                if( e.key == Crafty.keys.Z ) {
                    Crafty.scene("title");   // タイトルへ
                }
            })
            .bind('EnterFrame', function () {
                this.cnt++;
                if( this.cnt %80 < 50 ){
                    this.textColor('#ff7f00');
                } else {
                    this.textColor('#333333');            
                }
            });
    }, 2000, 0);    // delayの時間はここで設定(単位はミリ秒)
}

// 爆弾のストック表示
function stockBomb(){
    let cnt = bomb1_cnt + stock_cnt;
    while( cnt < 5 ){
        Crafty.e('Bomb1, Stock, 2D, Canvas')
            .attr({x:260+stock_cnt*20, y:10, rotation:90, no:stock_cnt});
        stock_cnt++;
        cnt++;
    }
}

// プレイヤー爆弾
function setPlayerBomb(ix,iy){
    if( bomb1_cnt >= 5 ) return;
    bomb1_cnt++;

    Crafty("Stock").each(function () {  // ストック表示を1つ消す
        if( this.no == stock_cnt-1 ){
            stock_cnt--;
            this.destroy();
        }
    });

    Crafty.e('Bomb1, 2D, Canvas, Collision')
        .attr({x:ix, y:iy})
        .origin("center")
        .onHit('Enemy', function (hitDatas) {  // 敵に当たったら
            for( let i=0, l=hitDatas.length; i<l; i++ ){
                let obj = hitDatas[i].obj;     // 当たった相手
                Crafty.e('Explosion, 2D, Canvas')   // 爆発演出
                    .attr({x:obj.x, y:obj.y, cnt:20})
                    .bind("EnterFrame", function(){
                        this.cnt--;
                        if( this.cnt%4 <2 ){
                            this.flip("X");
                        } else {
                            this.unflip("X");                        
                        }
                        if( this.cnt == 0){
                            this.destroy();
                        }
                    });
                obj.destroy();      // 当たったobjを消す
                score += 100;
                Crafty("Score").text("SCORE: "+score);
            }
            bomb1_cnt--;
            this.destroy();
        })
        .bind("EnterFrame", function(){
            this.y += 1;
            this.rotation += 2;
            if( this.y > 450 ){
                bomb1_cnt--;
                this.destroy();
            }
        });
}

// 敵の爆弾
function setEnemyBomb(ix,iy){
    Crafty.e('Bomb2, 2D, Canvas')
        .attr({x:ix, y:iy})
        .bind("EnterFrame", function(){
            this.y -= 0.6;
            if( this.y < 85 ){  // 海面まで来たか
                this.destroy();
                
                // 火柱
                Crafty.e('Flame, 2D, Canvas')
                    .attr({x:this.x-5, y:this.y-44})
                    .timeout(function(){this.destroy();},300);
            }
        });
}

// 敵の発生
function setEnemy(){
    const ypos = Crafty.math.randomInt(120, 415);
    const speed = Crafty.math.randomNumber(0.5,1.5);
    let sw, xpos;
    if( Crafty.math.randomInt(0, 1) == 1 ){
        sw = 1;
        xpos = -70;
    } else {
        sw = -1;    
        xpos = 600;
    }
    const ce = Crafty.e('Enemy, 2D, Canvas')
        .attr({x:xpos, y:ypos, dir:sw, spd:speed})
        .bind("EnterFrame", function(){
            if( Crafty.math.randomInt(1,1000) < 8 && gameover == 0 ){  // 敵爆弾の発生率
                setEnemyBomb(this.x,this.y);
            }
            this.x += this.dir * this.spd;
            if( (this.dir == 1 && this.x > 600) || (this.dir == -1 && this.x < -70) ){
                this.destroy();
            }
        });
    if( sw == -1 ){
        ce.flip("X");
    }
}

 

『サブマリンバスター』

ゲームを作ってみよう

  1. サブマリンバスター挑戦
  2. タイトルとキャラ表示
  3. プレイヤーの爆弾
  4. 敵の爆弾と当たり判定