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

时间:2018-09-16 08:07:34

标签: javascript html5-canvas collision-detection 2d-games

我正在尝试制作一个类似于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 个答案:

答案 0 :(得分:1)

您的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++;
        }
    }
}