碰撞检测的问题是 JS canvas 游戏
Problem with collision detection is JS canvas game
我正在尝试构建类似于 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++;
}
}
}
您的 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++;
}
}
}
我正在尝试构建类似于 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++;
}
}
}
您的 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++;
}
}
}