javascriptでシューティングゲームみたいなものを作る③

こんにちはrihitoです。
javascriptでシューティングゲームみたいなものを作る第三回目です。

動機

暇だから

対象読者

・javascriptをある程度できる人
・ゲームを作りたい人
・暇な人
・とりあえず何かしたい人
今回は、当たり判定を実装していきたいと思います

記事

javascriptでシューティングゲームみたいなものを作る①
javascriptでシューティングゲームみたいなものを作る②
javascriptでシューティングゲームみたいなものを作る③
javascriptでシューティングゲームみたいなものを作る④
javascriptでシューティングゲームみたいなものを作る⑤
今回のソースコード

enemyとレーザーの当たり判定

playerのレーザーに当たるようにenemyの座標を変更します。
main.js 13行目~
    
//enemyの座標
var ex = [100];
var ey = [100];
var es = 36 //enemyの大きさ

main.js 38行目~
    
ctx.rect(ex[i],ey[i],es,es)

まず、当たり判定をするにはどのようにしたら良いのでしょうか?
当たり判定をするには、このようなことが考えられます。

  • レーザーのx座標 < enemyのx座標
  • レーザーのy座標 < enemyのy座標
  • レーザーのx座標+レーザーの横 > enemyのx
  • レーザーのy座標+レーザーの縦 > enemyのx

  • なぜ、このようになったのでしょうか?
    それはこの画像を見たらわかると思います。

    というわけで上で示したことをコードに書き下ろしていきたいと思います。
    main.js 44行目~
        
        function l_collision(){
            for(var i = 0;i < lx.length;i++){
                for(var j = 0;j < ex.length;j++){
                    if(ey[j] + es > ly[i]&& ex[j] + es >lx[i] &&ey[j] < ly[i]+lh&& ex[j] <lx[i]+lw){
                        console.log("衝突しました!")
                    }
                }
            }
        }
        
    
    main.js 80行目~
        
        l_collision()
        
    
    chromeの場合consoleを表示するには、Cnrl+Shift+Iキー。
    または、●が縦に連なっているメニューボタン>>そのほかのツール>>デベロッパーツール
    で確認することができます。

    では、今度はレーザーと衝突したenemyを削除するプログラムを書いてみましょう。
    main.js 44行目~
        
        function l_collision(){
            var collision = false   //衝突したか
            var collision_n = 0  //衝突したenemyの個体番号
            for(var i = 0;i < lx.length;i++){
                for(var j = 0;j < ex.length;j++){
                    if(ey[j] + 12 > ly[i]&& ex[j] + es >lx[i] &&ey[j] < ly[i]+lh&& ex[j] <lx[i]+lw){
                        console.log("衝突しました!")
                        collision = true
                        collision_n = j //個体番号を衝突した個体番号にする
                    }
                }
            }
            return [collision,collision_n]
        }
        
    
    main.js 85行目~
        
        var l_return = l_collision()   //衝突した個体番号などをl_returnに収納
        if(l_return[0]){
            //ぶつかった個体を削除する(リストから削除する)
            ex.splice(l_return[1],1)
            ey.splice(l_return[1],1)
        }
        
    

    ちなみに~.splice()は、リストの要素を削除するときに使う関数で、
    こんな感じで使います。
        
    /*リスト名*/.splice(/*削除はじめの位置*/,/*削除する要素の数*/)
    
    
    というわけで

    今回のコード

        
        <!DOCTYPE html>
        <html>
            <body>
                <canvas id="main" height="400" width="800" style="background:#000000"></canvas>
                <!--canvasの下にscriptを読み込まないとエラーがでる-->
                <script src="main.js"></script>
            </body>
        </html>
        
    
    
        var canvas = document.getElementById("main");//canvasを読み込む
        var ctx = canvas.getContext("2d");
        var px = 40    //player x座標
        var py = 300    //player y座標
        
        var p_dx = 0    //player xの速さ
        var p_dy = 0    //player yの速さ
        var ps = 30
        
        
        //レーザーの座標
        var lx =[0];   //レーザーをたくさん描けるようにするためリストにする
        var ly = [0];
        var lw = 15
        var lh = 6
        
        //enemyの座標
        var ex = [200];
        var ey = [100];
        var es = 36 //enemyの大きさ
        
        //playerを描く関数
        function player_draw(){
            ctx.beginPath()
            ctx.rect(px,py,ps,ps)
            ctx.fillStyle = "#00ff00"
            ctx.fill()
            ctx.closePath()
        }
        
        function l_draw(){
            for(var i = 0;i < lx.length;i++){
                ctx.beginPath()
                ctx.rect(lx[i],ly[i],lw,lh)
                ctx.fillStyle = "#ff0000"
                ctx.fill()
                ctx.closePath()
            }
        }
        function e_draw(){
            for(var i = 0;i < lx.length;i++){
                ctx.beginPath()
                ctx.rect(ex[i],ey[i],es,es)
                ctx.fillStyle="#ff00ff"
                ctx.fill()
                ctx.closePath()
            }
        }
        function l_collision(){
            var collision = false   //衝突したか
            var collision_n = 0  //衝突したenemyの個体番号
            for(var i = 0;i < lx.length;i++){
                for(var j = 0;j < ex.length;j++){
                    if(ey[j] + es > ly[i]&& ex[j] + es >lx[i] &&ey[j] < ly[i]+lh&& ex[j] < lx[i]+lw){
                        console.log("衝突しました!")
                        collision = true
                        collision_n = j //個体番号を衝突した個体番号にする
                    }
                }
            }
            return [collision,collision_n]
        }
        //キーが押されたときに実行される
        document.onkeydown = function(e){
            if(e.key == "ArrowUp"){  //↑
                p_dx = 0
                p_dy = -3
            }
            if(e.key == "ArrowDown"){//↓
                p_dx = 0
                p_dy = 3
            }
            if(e.key == " "){
                lx.push(px)    //レーザー発射開始位置(playerの位置)をリストに追加
                ly.push(py)
            }
            
        }
        //キーが離されたときに実行される
        document.onkeyup = function(e){
            p_dx = 0    //止める
            p_dy = 0
        }
        
        function draw(){
            ctx.clearRect(0/*開始地点*/,0,canvas.width/*終了地点*/,canvas.height)   //canvasをいったんクリアする
            player_draw()
            l_draw()
            e_draw()
            var l_return = l_collision()   //衝突した個体番号などをl_returnに収納
            if(l_return[0]){
                //ぶつかった個体を削除する(リストから削除する)
                ex.splice(l_return[1],1)
                ey.splice(l_return[1],1)
            }
            for(var i = 0;i < lx.length/*リストの長さ*/;i++){   //リストを読み込む
                lx[i] += 2  //今読み込んでいるレーザーを動かす
            }
            e_draw()
            for(var i = 0;i < ex.length/*リストの長さ*/;i++){   //リストを読み込む
                ex[i] -= 2  //今読み込んでいるenemyを動かす
            }
            //playerを動かす
            px += p_dx
            py += p_dy
        }
        setInterval(draw,10)    //10ミリ秒単位で実行
        
        draw();