Javascript 球与画布边缘的碰撞检测
我遵循Mozilla游戏开发教程,在HTML5画布和JS中制作了一个简单的突破游戏 但是,我想放大画布,因为它有点小,所以我尝试了800x600画布。然后,我注意到这个球对于这个新的画布尺寸来说有点太慢了 最初在mozilla教程中,球的速度是2。我试着用3代替。于是问题来了 当我使用requestAnimationFrame时,它每秒刷新大约60x,我们可以说我的球每秒移动大约3x60=180px 要检测与画布右边缘的碰撞,我使用以下条件:Javascript 球与画布边缘的碰撞检测,javascript,html5-canvas,collision-detection,Javascript,Html5 Canvas,Collision Detection,我遵循Mozilla游戏开发教程,在HTML5画布和JS中制作了一个简单的突破游戏 但是,我想放大画布,因为它有点小,所以我尝试了800x600画布。然后,我注意到这个球对于这个新的画布尺寸来说有点太慢了 最初在mozilla教程中,球的速度是2。我试着用3代替。于是问题来了 当我使用requestAnimationFrame时,它每秒刷新大约60x,我们可以说我的球每秒移动大约3x60=180px 要检测与画布右边缘的碰撞,我使用以下条件: if (ball.x + ball.radius &
if (ball.x + ball.radius >= canvas.width) {
ball.speed = -ball.speed;
// I reverse the speed, which goes from 3 to -3, so the ball bounces.
}
问题是:
如果我把球放在起始位置x=2,我的画布是600像素宽。
当球以3px乘以3px的速度移动,半径为10px时,球将到达589。。。只有在592点它才会反弹。而它应该在590点反弹
我尝试了很多方法,但似乎没有任何方法可以解决这个问题
目标是使球在590位置反弹(也就是canvas.width-ball.radius),而不考虑速度或起始位置
问题可能出在我的游戏循环中。
我使用的是这样一个简单的游戏循环:
function update {
requestAnimationFrame(update)
Drawball();
Moveball()
Collision();
}
requestAnimationFrame(update);
这样做不对吗
谢谢你的帮助,我两周以来一直在处理这个问题!
我将提供我的代码
<style>
* {
padding: 0;
margin: 0;
}
body {
position: relative;
background-color: black;
background-image: radial-gradient(rgba(0, 150, 0, 0.3), black 120%);
height: 100vh;
}
canvas {
background: #000;
display: block;
position: absolute;
top: 20px;
right: 20px;
border: solid #00FA61 1px;
}
#debug {
position: absolute;
padding: 10px;
top: 20px;
left: 20px;
border: solid #00FA61 1px;
color: #00FA61;
font-family: 'Courier', monospace;
font-size: 18px;
text-align: center;
}
#debug span {
font-size: 2em;
font-weight: bold;
}
</style>
</head>
<body>
<div id="debug">
<h3>Debug mode</h3>
<p id="posX"></p>
<p id="posY"></p>
<p id="collision"></p>
</div>
<canvas id="myCanvas" width="800" height="600"></canvas>
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var hauteur_canvas = canvas.height;
var largeur_canvas = canvas.width;
var infoPosX = document.getElementById("posX");
var infoPosY = document.getElementById("posY");
var infoCollide = document.getElementById("collision");
/* BALL POS X/Y */
var x = canvas.width / 2;
var y = canvas.height - 40;
/* BALL SPEED */
var direction_x = 8;
var direction_y = -direction_x;
/* RAYON DE LA BOULE */
var rayon_balle = 10;
var timer = 0;
var id_frame;
var currentSeconde = 0,
frameCount = 0,
frameLastSecond = 0;
var colorBall = "#00FA61";
/* HAUTEUR ET LARGEUR DU PADDLE */
var paddleHeight = 10;
var paddleWidth = 75;
/* POSITION X ET Y DU COIN GAUCHE HAUT */
var paddleX = (largeur_canvas - paddleWidth) / 2;
var paddleY = hauteur_canvas - paddleHeight;
/* DISTANCES ENTRE BOULES ET PADDLE */
var dist_center_X;
var dist_center_Y;
/* DETECTION DES INPUTS */
var rightPressed = false;
var leftPressed = false;
/* GESTION DES BRIQUES */
var brickRowCount = 3;
var brickColumnCount = 5;
var brick = {
hauteur: 50,
largeur: 132,
padding: 20,
offsettop: 30,
offsetleft: 30
};
var bricks = [];
for (var c = 0; c < brickColumnCount; c++) {
bricks[c] = [];
for (var r = 0; r < brickRowCount; r++) {
bricks[c][r] = {
x: 0,
y: 0
};
}
}
/* ------------------- */
function drawBall() {
ctx.beginPath();
ctx.arc(x, y, rayon_balle, 0, Math.PI * 2);
ctx.fillStyle = colorBall;
ctx.fill();
ctx.closePath();
}
function drawPaddle() {
ctx.beginPath();
ctx.rect(paddleX, paddleY, paddleWidth, paddleHeight);
ctx.fillStyle = "#00FA61";
ctx.fill();
ctx.closePath();
}
function drawBricks() {
for (var c = 0; c < brickColumnCount; c++) {
for (var r = 0; r < brickRowCount; r++) {
var brickX = (c * (brick.largeur + brick.padding)) + brick.offsetleft;
var brickY = (r * (brick.hauteur + brick.padding)) + brick.offsettop;
bricks[c][r].x = brickX;
bricks[c][r].y = brickY;
ctx.beginPath();
ctx.rect(brickX, brickY, brick.largeur, brick.hauteur);
ctx.fillStyle = "#1aa829";
ctx.fill();
ctx.closePath();
}
}
}
function distance_boule_paddle() {
/* CALCUL DES DISTANCES ENTRE BOULES ET PADDLE */
dist_center_X = Math.abs(x - paddleX - paddleWidth / 2);
dist_center_Y = Math.abs(y - paddleY - paddleHeight / 2);
}
function fps_count() {
var sec = Math.floor(Date.now() / 1000);
if (sec != currentSeconde) {
currentSeconde = sec;
frameLastSecond = frameCount;
frameCount = 1;
} else {
frameCount++;
}
ctx.fillText("FPS : " + frameLastSecond, 10, 20);
}
function clear() {ctx.clearRect(0, 0, largeur_canvas, hauteur_canvas);}
function collide_paddle() {
if (dist_center_X > (paddleWidth / 2 + rayon_balle)) {
return false;}
if (dist_center_Y > (paddleHeight / 2 + rayon_balle)) {
return false;}
if (dist_center_X <= (paddleWidth / 2)) {
return true;}
if (dist_center_Y <= (paddleHeight / 2)) {
return true;}
var dx = dist_center_X - paddleWidth / 2;
var dy = dist_center_Y - paddleHeight / 2;
return (dx * dx + dy * dy <= (rayon_balle * rayon_balle));
}
function collision() {
/* COLLIDE AVEC LE HAUT DU CANVAS */
if (y - rayon_balle <= 0) {
direction_y = -direction_y;
collideInfo();
} else {
if (y + rayon_balle >= hauteur_canvas - paddleHeight) {
if (collide_paddle()) {
direction_y = -direction_y;
} else {
if (y - rayon_balle > hauteur_canvas) {
// so if the ball is 100% off screen of the down edge its gameover
collideInfo();
alert("GAME OVER");
document.location.reload();
}
}
}
}
/* COLLIDE WITH LEFT AND RIGHT EDGES */
if (x + rayon_balle >= largeur_canvas) {
direction_x = -direction_x;
collideInfo();
} else {
if (x - rayon_balle <= 0) {
direction_x = -direction_x;
collideInfo();
}
}
}
function move_ball() {
x += direction_x;
y += direction_y;
}
function move_paddle() {
if (rightPressed && paddleX < canvas.width - paddleWidth) {
paddleX += 7;
} else if (leftPressed && paddleX > 0) {
paddleX -= 7;
}
}
/* EVENTS LISTENERS */
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if (e.keyCode == 39) {
rightPressed = true;
} else if (e.keyCode == 37) {
leftPressed = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 39) {
rightPressed = false;
} else if (e.keyCode == 37) {
leftPressed = false;
}
}
function collideInfo() {
infoCollide.innerHTML = "<br>La collision s'est produite <br> à la position X <span>: " + x + "</span>" + "<br> la position Y : <span>" + y + "</span>";
}
function gameInfo() {
infoPosX.innerHTML = "La position X de la balle : " + x;
infoPosY.innerHTML = "La position Y de la balle : " + y;
}
function draw() {
id_frame = requestAnimationFrame(draw);
clear();
fps_count();
drawBall();
drawPaddle();
drawBricks();
move_ball();
move_paddle();
distance_boule_paddle();
collision();
gameInfo();
timer++;
if (timer === 2500) {
console.log("STOP !");
cancelAnimationFrame(id_frame);
}
}
requestAnimationFrame(draw);
</script>
</body>
</html>
* {
填充:0;
保证金:0;
}
身体{
位置:相对位置;
背景色:黑色;
背景图像:径向梯度(rgba(0,150,0,0.3),黑色120%);
高度:100vh;
}
帆布{
背景:#000;
显示:块;
位置:绝对位置;
顶部:20px;
右:20px;
边框:实心#00FA61 1px;
}
#调试{
位置:绝对位置;
填充:10px;
顶部:20px;
左:20px;
边框:实心#00FA61 1px;
颜色:#00FA61;
字体系列:“Courier”,单空格;
字号:18px;
文本对齐:居中;
}
#调试范围{
字号:2em;
字体大小:粗体;
}
调试模式
var canvas=document.getElementById(“myCanvas”);
var ctx=canvas.getContext(“2d”);
var hauteur_canvas=canvas.height;
var largeur_canvas=canvas.width;
var infoPosX=document.getElementById(“posX”);
var infoPosY=document.getElementById(“posY”);
var infoCollide=document.getElementById(“冲突”);
/*球位置X/Y*/
var x=画布宽度/2;
变量y=画布高度-40;
/*球速*/
var方向_x=8;
var方向y=-方向x;
/*布勒人造丝*/
var rayon_balle=10;
var定时器=0;
变量id_框架;
var currentSeconde=0,
帧数=0,
frameLastSecond=0;
var colorBall=“#00FA61”;
/*高傲而伟大的船桨*/
高度=10;
宽度=75;
/*位置X和Y都是硬币的高切上*/
var PapperX=(大画布-桨宽)/2;
var Pailey=傲慢的画布-桨高;
/*船桨中心距离*/
var dist_中心;
可变区中心;
/*检测DES输入*/
var-rightspressed=false;
var leftPressed=false;
/*布里克斯手势*/
var brickRowCount=3;
var brickColumnCount=5;
var砖={
傲慢者:50,
largeur:132,
填充:20,
抵销:30,
offsetleft:30
};
var=[];
对于(var c=0;cfunction update {
requestAnimationFrame(update)
Drawball();
Moveball()
Collision();
}
requestAnimationFrame(update);
function update {
requestAnimationFrame(update)
Drawball();
Moveball()
Collision();
}
update();