マイペースなプログラミング日記

x86エミュレータやFPGA、WebGLにお熱なd-kamiがマイペースに書くブログ

簡単なシューティングゲーム作成 その5

JavaScriptが少しずつわかって気になってる今日このごろ。頑張ってCanvasシューティングゲーム作ります、はい。それでまずHTMLを修正。キーイベントで方向キー(?)も使えるようにしてみた。keyydownとkeyupのswitch文を若干変更。移動につかうキーを増やした。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <script type="text/javascript" src="./util/Point.js"></script>
    <script type="text/javascript" src="./util/Rect.js"></script>
    <script type="text/javascript" src="./object/GameObject.js"></script>
    <script type="text/javascript" src="./object/Player.js"></script>
    <script type="text/javascript" src="./object/PlayerBullet1.js"></script>
    <script type="text/javascript" src="./object/Enemy1.js"></script>
    <script type="text/javascript" src="./info/GameInfo.js"></script>
    <script type="text/javascript" src="./view/GameView.js"></script>
    <script type="text/javascript">
var IMAGE_NAMES = ["Player", "Enemy1"];
var IMAGE_FILES = ["./image/player.png", "./image/enemy1.png"];

var view;

function game(){
    var canvas = document.getElementById("canvas");
    var context = canvas.getContext("2d");

    view = new GameView(context, 600, 400);
    view.loadImages(IMAGE_NAMES, IMAGE_FILES);
    
    document.onkeydown = keydown;
    document.onkeyup = keyup;

    setInterval(function(){
        view.draw();
    }, 16);
}

function keydown(event){
    var code = event.keyCode;

    switch(code){
        //'A' 後ろ
        case 65:
        case 37:
            view.onDirection(0x02);
            break;

        //'D' 前
        case 68:
        case 39:
            view.onDirection(0x01);
            break;

        //'W' 上
        case 87:
        case 38:
            view.onDirection(0x08);
            break;

        //'S' 下
        case 83:
        case 40:
            view.onDirection(0x04);
            break;

        //'space' 攻撃
        case 32:
            view.fire(true);
            break;
    }
}

function keyup(event){
    var code = event.keyCode;

    switch(code){
        //'A' 後ろ
        case 65:
        case 37:
            view.offDirection(0x02);
            break;

        //'D' 前
        case 68:
        case 39:
            view.offDirection(0x01);
            break;

        //'W' 上
        case 87:
        case 38:
            view.offDirection(0x08);
            break;

        //'S' 下
        case 83:
        case 40:
            view.offDirection(0x04);
            break;

        //'space' 攻撃
        case 32:
            view.fire(false);
            break;
    }
}

    </script>
  </head>
  <body onload="game()">
    <canvas id="canvas" width="600" height="400">Canvasをサポートしたブラウザで見てください</canvas>
  </body>
</html>

あとRect.jsのintersectを修正。長方形が別の長方形に完全に含まれてるときの処理が足りてなかった

this.intersect = function(rect){
    if(this.left <= rect.left && rect.left <= this.right && this.top <= rect.top && rect.top <= this.bottom){
        return true;
    }
        
    if(this.left <= rect.right && rect.right <= this.right && this.top <= rect.top && rect.top <= this.bottom){
        return true;
    }
        
    if(this.left <= rect.left && rect.left <= this.right && this.top <= rect.bottom && rect.bottom <= this.bottom){
        return true;
    }
        
    if(this.left <= rect.right && rect.right <= this.right && this.top <= rect.bottom && rect.bottom <= this.bottom){
        return true;
    }
        
    if(rect.left <= this.left && this.right <= rect.right && rect.top <= this.top && this.bottom <= rect.bottom){
        return true;
    }
        
    return false;
}

あとGameView.jsを変更。drawメソッドの中の処理をいくつかの関数に分割した。また敵に弾が当たったときに弾を消す処理追加。また敵のライフが0になったときに消す処理追加(enemyCollisionCheck関数)

var GameView = function(context, width, height){
    var images = new Array();
    var isLoadedImage = false;
    var player;
    var gameInfo;

    this.draw = function(){
        if(!isLoadedImage){
            return;
        }

        context.fillStyle = 'rgb(0, 0, 0)';
        context.fillRect(0, 0, 600, 400);

        //プレイヤー機の移動と描画
        playerAction();

        //プレイヤー機が撃った弾の移動と描画
        bulletsAction();
        
        //敵の行動と描画
        enemiesAction();

    }
    
    function playerAction(){
        //プレイヤー機の移動と描画
        player.doAction(gameInfo);
        player.draw(context);
    }
    
    function bulletsAction(){
        //弾削除用の配列
        var removeBullets = new Array();
        
        //敵削除用の配列
        var removeEnemies = new Array();

        //プレイヤー機が撃った弾の移動と描画
        for(i = 0; i < gameInfo.bullets.length; i++){
            var bullet = gameInfo.bullets[i];
            bullet.doAction(gameInfo);
            bullet.draw(context);
            
            enemyCollisionCheck(bullet, removeBullets, removeEnemies);
        }
        
        for(i = 0; i < removeBullets.length; i++){
            gameInfo.bullets.splice(removeBullets[i], 1);
        }
        
        for(i = 0; i < removeEnemies.length; i++){
            gameInfo.enemies.splice(removeEnemies[i], 1);
        }
    }
    
    
    function enemyCollisionCheck(bullet, removeBullets, removeEnemies){
        for(j = 0; j < gameInfo.enemies.length; j++){
            var enemy = gameInfo.enemies[j];
                
            if(bullet.intersect(enemy)){
                if(!enemy.applyDamage(bullet.damage)){
                    removeEnemies.push(j);
                }
                    
                removeBullets.push(i);
            }
        }
    }
    
    function enemiesAction(){
        //敵の行動と描画
        for(i = 0; i < gameInfo.enemies.length; i++){
            var enemy = gameInfo.enemies[i];
            enemy.doAction(gameInfo);
            enemy.draw(context);
        }
    }
    
    this.loadImages = function(names, files){
        var count = 0;

        for(i = 0; i < files.length; i++){
            var image = new Image();
            image.src = files[i];
            images[names[i]] = image;

            image.onload = function(){
                count++;

                if(count == files.length){
                    init();
                }
            }
        }
    }
    
    this.onDirection = function(direction){
        player.onDirection(direction);
    }
    
    this.offDirection = function(direction){
        player.offDirection(direction);
    }
    
    this.fire = function(fire){
        player.fire = fire;
    }
    
    function init(){
        player = new Player(images["Player"]);
        gameInfo = new GameInfo();
        gameInfo.player = player;
        gameInfo.width = width;
        gameInfo.height = height;
        
        //敵を一体だけ追加する
        var enemy = new Enemy1(images["Enemy1"]);
        enemy.move(650, 100);
        gameInfo.enemies.push(enemy);
        
        isLoadedImage = true;
    }
}