代码之家  ›  专栏  ›  技术社区  ›  Saif Taher

碰撞检测的问题是JS画布游戏

  •  0
  • Saif Taher  · 技术社区  · 7 年前

    Chicken Invaders ,但我在碰撞检测方面遇到了一个问题。当玩家射击时,如果击中敌人,这个敌人应该消失。但我不能让它工作。这是笔:

    https://codepen.io/Undefined_Variable/pen/bxxqBo

    代码如下:

    //Drawing & Animating: Classes & Variables Definitions
    let canvas = document.body.querySelector("#gameCanvas");
    let ctx = canvas.getContext("2d");
    canvas.width =  window.innerWidth;
    canvas.height = 0.9 * window.innerHeight;
    let CW = canvas.width;
    let CH = canvas.height;
    let easyPlaneArr = [];
    let hotShotsArr = [];
    let easyPlaneCounter = 0;
    class plane {
        constructor(x, y, size, color) {
            this.x = x;
            this.y = y;
            this.size = size;
            this.color = color;
        }
        drawPlane() {
            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.scale(this.size, this.size)
            ctx.strokeStyle = this.color;
            ctx.fillStyle = this.color;
            ctx.beginPath();
            ctx.moveTo(0, 0);
            ctx.lineTo(10, -30);
            ctx.lineTo(10, -100);
            ctx.lineTo(40, -100);
            ctx.lineTo(40, -120);
            ctx.lineTo(-10, -100);
            ctx.lineTo(-40, -100);
            ctx.lineTo(-40, -120);
            ctx.lineTo(10, -100);
            ctx.lineTo(-10, -100);
            ctx.lineTo(-10, -75);
            ctx.lineTo(-70, -75);
            ctx.lineTo(-60, -60);
            ctx.lineTo(-10, -60);
            ctx.lineTo(10, -60);
            ctx.lineTo(60, -60);
            ctx.lineTo(70, -75);
            ctx.lineTo(10, -75);
            ctx.lineTo(-10, -60);
            ctx.lineTo(-10, -30);
            ctx.stroke();
            ctx.fill();
            ctx.closePath();
            ctx.clearRect(-140, 0, 0, -120)
            ctx.restore();
        }
        animatePlane() {
            this.y += 5;
        }
    }
    class hotShot {
        constructor(x) {
            this.x = x;
            this.y = 0.95 * CH;
        }
    }
    let player = {
        x: CW / 2,
        y: 0.95 * CH
    }
    //Drawing & Animating: Functions Definitions
    function drawPlayer() {
        ctx.save();
        ctx.translate(player.x, player.y);
        ctx.clearRect(-20, -40, 20, 0);
        ctx.beginPath();
        ctx.moveTo(0, -40);
        ctx.lineTo(-20, 0);
        ctx.lineTo(0, -10);
        ctx.lineTo(20, 0);
        ctx.closePath();
        ctx.stroke();
        ctx.fill()
        ctx.restore();
    }
    function drawHotShots() {
        for (let shot of hotShotsArr) {
            ctx.save()
            ctx.translate(shot.x, shot.y)
            ctx.fillRect(-10,0,20,20)
            ctx.restore()
            shot.y -= 10
        }
    }
    function detectHits() {
        for (let shot in hotShotsArr) {
            easyPlaneCounter = 0;
            for (let plane in easyPlaneArr) {
                if (shot.y > 0) {
                    easyPlaneArr.splice(easyPlaneCounter, 1)
                }
                easyPlaneCounter++;
            }
        }
    }
    function mainLoop() {
        canvas.width = window.innerWidth;
        canvas.height = 0.9 * window.innerHeight;
        CW = canvas.width;
        CH = canvas.height;
        player.y = 0.95 * CH;
    
        for (let plane of easyPlaneArr) {
            plane.drawPlane();
            plane.animatePlane();
        }
    
        drawHotShots();
        drawPlayer();
        detectHits()
        requestAnimationFrame(mainLoop);
    }
    //Drawing & Animating: Program Flow
    let easyPlanes = setInterval(function () {
        easyPlaneArr.push(new plane(Math.random() * ((CW - 150) - 150) + 150, -100, 1, "green"));
    }, 1000)
    canvas.addEventListener("mousemove", function (e) {
        player.x = e.clientX;
    })
    canvas.addEventListener("click", function (e) {
        hotShotsArr.push(new hotShot(player.x))
    })
    mainLoop();
    body{
        margin: 0px auto;
        overflow:hidden;
    }
    #levelDiv {
        height:10vh;
        width:100vw;
        border-bottom: 1px solid black;
        background:linear-gradient(90deg, yellow 40%, red)
    }
    <!DOCTYPE html>
    
    <html lang="en" xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta charset="utf-8" />
        <title>Attack On Ship!</title>
    </head>
    <body>
        <div id="levelDiv"></div>
        <canvas id="gameCanvas"></canvas>
        <script src="AttackOnShip.js"></script>
    </body>
    </html>

    我尝试过碰撞检测,但没有成功:

    function detectHits() {
        for (let shot in hotShotsArr) {
            easyPlaneCounter = 0;
            for (let plane in easyPlaneArr) {
                if ((shot.x - 10) > (plane.x - 70) && (shot.x + 10) < (plane.x + 70)) {
                    easyPlaneArr.splice(easyPlaneCounter, 1)
                }
                easyPlaneCounter++;
            }
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Petr Broz    7 年前

    你的 detectHits 函数-虽然它不是一个真正正确的碰撞检测-不起作用,因为它使用 for..in 而不是 for..of 循环。尝试这样实现:

    function detectHits() {
        for (let shot of hotShotsArr) {
            easyPlaneCounter = 0;
            for (let plane of easyPlaneArr) {
                if (shot.y > 0) {
                    easyPlaneArr.splice(easyPlaneCounter, 1)
                }
                easyPlaneCounter++;
            }
        }
    }
    

    更好的碰撞检测可以检查快照X和Y是否在平面的边界框内,例如:

    const PlaneWidth = 100.0;
    const PlaneHeight = 100.0;
    function detectHits() {
        for (let shot of hotShotsArr) {
            easyPlaneCounter = 0;
            for (let plane of easyPlaneArr) {
                if (Math.abs(shot.x - plane.x) < 0.5 * PlaneWidth && Math.abs(shot.y - plane.y) < 0.5 * PlaneHeight) {
                    easyPlaneArr.splice(easyPlaneCounter, 1)
                }
                easyPlaneCounter++;
            }
        }
    }