我正在尝试实现一个能够检测2个移动圆和矩形之间碰撞的函数,对于我正在做的小游戏。 它很接近,但它不能像它应该的那样工作,我无法弄清楚原因。任何帮助非常感谢。
/**************/
//Game Framework
/**************/
window.onload = function init() {
//Starting a new game
var game = new GF();
game.start();
};
var GF = function() {
//Variables
var canvas, ctx, w, h;
var height, width;
var frameCount = 0;
var lastTime;
var fps, fpsContainer;
var gamepad;
var inputStates = {};
var score;
var bullets = [];
var numberOfShips;
var delta, oldTime = 0;
var tank = {
x: 10,
y: 10,
cx: 115 + 0.5 * 10,
cy: 65 + 0.5 * 15,
angle: 0,
speed: 100,
};
var tankBoundingRect = {
x: tank.x,
y: tank.y,
width: 40,
height: 45
}
var enemy = {
x: 0,
y: 0,
width: 10,
height: 80,
speed: 1
}
var weapon = {
x: 955,
y: 10,
startX: 0,
startY: 0,
r: 3,
speed: 5
}
var weapon2 = {
y: 70,
startY: 0
}
var distanceToMove = function(delta, speed) {
return (speed * delta) / 1000;
}
var measureFPS = function(newTime) {
if (lastTime === undefined) {
lastTime = newTime;
return;
}
var diffTime = newTime - lastTime;
if (diffTime >= 1000) {
fps = frameCount;
frameCount = 0;
lastTime = newTime;
}
fpsContainer.innerHTML = "FPS: " + fps;
frameCount++;
};
function timer(currentTime) {
var delta = currentTime - oldTime;
oldTime = currentTime;
return delta;
}
function clearCanvas() {
ctx.clearRect(0, 0, w, h);
}
function drawTank(x, y) {
ctx.save();
ctx.translate(x, y);
drawBoundingRect();
ctx.strokeStyle = "#ffa64d";
ctx.fillStyle = "#b1b181"
ctx.strokeRect(100, 50, 40, 15);
ctx.strokeRect(100, 80, 40, 15);
drawCanon(tank.cx, tank.cy, tank.angle);
ctx.restore();
}
function drawCanon(cx, cy, angle) {
ctx.translate(cx, cy);
ctx.rotate(angle);
ctx.translate(-cx, -cy);
ctx.fillRect(115, 65, 10, 15);
ctx.strokeRect(125, 72.5, 5, 2);
}
function drawBoundingRect() {
ctx.strokeStyle = "white";
ctx.strokeRect(100, 50, 40, 45);
}
function tankFire() {
ctx.save();
}
function updatetankPosition() {
tank.speedX = tank.speedY = 0;
if (inputStates.left) {
//ctx.fillText('left', 150, 20);
tank.speedX = -tank.speed;
}
if (inputStates.right) {
//ctx.fillText('right', 150, 50);
tank.speedX = tank.speed;
}
if (inputStates.up) {
//ctx.fillText('up', 150, 80);
tank.speedY = -tank.speed;
}
if (inputStates.down) {
//ctx.fillText('down', 150, 120);
tank.speedY = tank.speed;
}
if (inputStates.space) {
//ctx.fillText('space bar', 160, 150);
}
if (inputStates.mousePos) {
/*ctx.fillText("x = " + inputStates.mousePos.x + " y = " +
inputStates.mousePos.y, 5, 150);*/
}
if (inputStates.mousedown) {
//ctx.fillText("mousedown b" + inputStates.mouseButton, 5, 180);
tank.speed = 500;
} else {
tank.speed = 100;
}
tank.x += distanceToMove(delta, tank.speedX);
tank.y += distanceToMove(delta, tank.speedY);
if (tank.y < -50) {
tank.y = -50;
}
if (tank.y > 555) {
tank.y = 555;
}
if (tank.x < -100) {
tank.x = -100;
}
}
function drawEnemy(x, y) {
ctx.save();
ctx.strokeStyle = "red";
ctx.strokeRect(w - enemy.width, y, enemy.width, enemy.height);
drawEnemyWeapons();
ctx.restore();
}
function drawEnemyWeapons() {
ctx.save();
ctx.strokeStyle = "green";
ctx.strokeRect(w - enemy.width - 30, enemy.y + 10, 30, 2);
ctx.strokeRect(w - enemy.width - 30, enemy.y + 70, 30, 2);
ctx.restore();
}
function moveEnemy() {
enemy.y += enemy.speed;
checkEnemyPosition();
}
function checkEnemyPosition() {
if (enemy.y + enemy.height > h || enemy.y <= 0) {
enemy.speed = -enemy.speed;
}
}
function enemyFire(x, y) {
ctx.save();
ctx.fillStyle = "yellow";
ctx.beginPath();
ctx.arc(weapon.x, weapon.startY, weapon.r, 0, 2 * Math.PI);
ctx.arc(weapon.x, weapon2.startY, weapon.r, 0, 2 * Math.PI);
ctx.fill();
ctx.restore();
}
function startShooting() {
weapon.startX = weapon.x;
weapon.startY = enemy.y + weapon.y;
weapon2.startY = enemy.y + weapon2.y;
weapon.targetX = tank.x;
weapon.targetY = tank.y;
var dx = tank.x - weapon.startX;
var dy = tank.y - weapon.startY;
weapon.angle = Math.atan2(dy, dx);
console.log(tank.x);
console.log(tank.y);
console.log(weapon.x);
console.log(weapon.startY);
console.log(weapon2.startY);
}
function moveShot() {
weapon.x += weapon.speed * Math.cos(weapon.angle);
if (weapon.x < 0) {
weapon.x = 955;
startShooting();
}
}
function tankHit(x0, y0, w0, h0, cx, cy, r) {
var testX = cx;
var testY = cy;
if (testX < x0) testX = x0;
if (testX > (x0 + w0)) testX = (x0 + w0);
if (testY < y0) testY = y0;
if (testY > (y0 + h0)) testY = (y0 + h0);
return (((cx - testX) * (cx - testX) + (cy - testY) * (cy - testY)) < r * r);
}
var mainLoop = function(time) {
clearCanvas();
measureFPS(time);
delta = timer(time);
updateGamePadStatus();
drawTank(tank.x, tank.y, tank.angle);
drawEnemy(enemy.x, enemy.y);
enemyFire();
moveEnemy();
moveShot();
updatetankPosition(delta);
if (tankHit(tank.x, tank.y, 40, 45, weapon.x, weapon.startY, weapon.r) || tankHit(tank.x, tank.y, 40, 45, weapon.x, weapon2.startY, weapon.r)) {
ctx.fillStyle = "red";
ctx.fillText("HIT", 400, 50);
};
requestAnimationFrame(mainLoop);
};
function getMousePos(evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
function updateGamePadStatus() {
scangamepads();
checkButtons(gamepad);
checkAxes(gamepad);
}
window.addEventListener("gamepadconnected", function(evt) {
gamepad = evt.gamepad;
var index = gamepad.index;
var id = gamepad.id;
console.log("Gamepad connected");
});
window.addEventListener("gamepaddisconnected", function(evt) {
var gamepad = evt.gamepad;
var index = gamepad.index;
console.log("Gamepad No " + index + " has been disconnected.");
});
function checkAxes(gamepad) {
if (gamepad === undefined) return;
if (!gamepad.connected) return;
inputStates.left = inputStates.right = inputStates.up = inputStates.down = false;
if (gamepad.axes[0] > 0.5) {
inputStates.right = true;
inputStates.left = false;
} else if (gamepad.axes[0] < -0.5) {
inputStates.left = true;
inputStates.right = false;
}
if (gamepad.axes[1] > 0.5) {
inputStates.down = true;
inputStates.up = false;
} else if (gamepad.axes[1] < -0.5) {
inputStates.up = true;
inputStates.down = false;
}
inputStates.angle = Math.atan2(-gamepad.axes[1], gamepad.axes[0]);
}
function checkButtons(gamepad) {
if (gamepad === undefined) return;
if (!gamepad.connected) return;
for (var i = 0; i < gamepad.buttons.length; i++) {
var b = gamepad.buttons[i];
if (b.pressed) {
console.log(i + ":" + b.value);
}
var gas = gamepad.buttons[7];
var moveRight = gamepad.buttons[5];
var moveLeft = gamepad.buttons[4];
if (gas.pressed) {
tank.speed = gas.value * 500;
}
/*if (moveRight.pressed) {
tank.angle += (Math.PI / 800);
}
if (moveLeft.pressed) {
tank.angle -= (Math.PI / 800);
}
*/
}
}
function scangamepads() {
var gamepads = navigator.getGamepads();
for (var i = 0; i < gamepads.length; i++) {
if (gamepads[i])
gamepad = gamepads[i];
}
}
/****************/
//Creating enemies
/****************/
/* function enemyFire(n) {
var enemiesArray = [];
for (var i=0; i < n; i++) {
var enemy = {
x: w-
}
}
*/
var start = function() {
fpsContainer = document.createElement('div');
document.body.appendChild(fpsContainer);
canvas = document.getElementById('myCanvas');
w = canvas.width;
h = canvas.height;
ctx = canvas.getContext('2d');
ctx.font = "20px Back to Black Demo";
var slide = document.querySelector("#fps");
slide.addEventListener('input', function(e) {
if (enemy.speed > 0) {
enemy.speed = slide.value * 1;
} else {
enemy.speed = slide.value * -1;
}
});
// Listener for pressed keys
window.addEventListener('keydown', function(evt) {
if (evt.keyCode === 37) {
inputStates.left = true;
} else if (evt.keyCode === 38) {
inputStates.up = true;
} else if (evt.keyCode === 39) {
inputStates.right = true;
} else if (evt.keyCode === 40) {
inputStates.down = true;
} else if (evt.keyCode === 32) {
inputStates.space = true;
}
}, false);
// Listener for released keys
window.addEventListener('keyup', function(evt) {
if (evt.keyCode === 37) {
inputStates.left = false;
} else if (evt.keyCode === 38) {
inputStates.up = false;
} else if (evt.keyCode === 39) {
inputStates.right = false;
} else if (evt.keyCode === 40) {
inputStates.down = false;
} else if (evt.keyCode === 32) {
inputStates.space = false;
}
}, false);
canvas.addEventListener('mousemove', function(evt) {
inputStates.mousePos = getMousePos(evt);
}, false);
canvas.addEventListener('mousedown', function(evt) {
inputStates.mousedown = true;
inputStates.mouseButton = evt.button;
}, false);
canvas.addEventListener('mouseup', function(evt) {
inputStates.mousedown = false;
}, false);
startShooting();
requestAnimationFrame(mainLoop);
};
return {
start: start
};
};
<span id="fps"></span>
<canvas id="myCanvas" width="250" height="150" />