我目前正在尝试为大学制作一个Breakout版本。谢谢你帮我画了划桨。我现在发现自己无法让球在画布的边缘反弹 - 除了在中间。我已尝试向ball.x和ball.y(大于或等于canvas.width和canvas.height两者都有效)添加和减去分数,但是对于小于或等于0,似乎没有任何成功。这是javascript代码:
var canvas = document.getElementById("breakout");
var ctx = canvas.getContext("2d");
var PADDLE_WIDTH_PX = canvas.width / 5;
var PADDLE_HEIGHT_PX = 10;
var PADDLE_SPEED = 450;
var ball = {
x: canvas.width / 2, //pixels
y: canvas.height / 2, //pixels
xSpeed: 500, //pixels per second
ySpeed: 500, //pixels per second
radius: 100 //the ball is exceptionally large so that I can see what part of the ball is surpassing the canvas edge before the motion is reversed
}
var paddle = {
//radius: 5,
/*speed: 500,
TopRight: ctx.moveTo(canvas.width / 1.35, canvas.height - (canvas.height / 12.5)),
TopSide: ctx.lineTo(canvas.width / 2, canvas.height - (canvas.height / 12.5)),
RightSide: ctx.lineTo(canvas.width / 1.35, canvas.height - (canvas.height / 27.5)),
BottomLeft: ctx.moveTo(canvas.width / 2, canvas.height - (canvas.height / 27.5)),
LeftSide: ctx.lineTo(canvas.width / 2, canvas.height - (canvas.height / 12.5)),
BottomSide: ctx.lineTo(canvas.width / 1.35, canvas.height - (canvas.height / 27.5))*/
xSpeed: 450,
x: (canvas.width - PADDLE_WIDTH_PX) / 2,
y: canvas.height - PADDLE_HEIGHT_PX
}
var keysDown = {};
window.addEventListener("keydown",function(e) {
keysDown[e.keyCode] = true;
});
window.addEventListener("keyup",function(e) {
delete keysDown[e.keyCode];
});
function render() {
//clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height)
// draw the ball
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
ctx.beginPath();
//ctx.fillStyle = "red";
/*ctx.moveTo(canvas.width - (2*paddle.x), canvas.height - (2*paddle.y));
/*ctx.lineTo(canvas.width / 2, canvas.height - (canvas.height / 12.5));
ctx.lineTo(canvas.width / 1.35, canvas.height - (canvas.height / 27.5));
ctx.moveTo(canvas.width / 2, canvas.height - (canvas.height / 27.5));
ctx.lineTo(canvas.width / 2, canvas.height - (canvas.height / 12.5));
ctx.lineTo(canvas.width / 1.35, canvas.height - (canvas.height / 27.5));
ctx.fill();
ctx.closePath();*/
/*ctx.lineTo(canvas.width - (2*paddle.x), canvas.height - paddle.y);
ctx.moveTo(canvas.width - paddle.x, canvas.height - paddle.y);
ctx.lineTo(canvas.width - paddle.x, canvas.height - (2*paddle.y));
ctx.lineTo(canvas.width - (2*paddle.x), (canvas.height -paddle.y));*/
ctx.fillRect(paddle.x, paddle.y, PADDLE_WIDTH_PX, PADDLE_HEIGHT_PX);
/*ctx.closePath();
ctx.fill();*/
}
function update(elapsed) {
//update the ball position according to the elapsed time
ball.y += ball.ySpeed * elapsed;
ball.x += ball.xSpeed * elapsed;
/*paddle.TopRight += paddle.speed * elapsed;
paddle.BottomLeft += paddle.speed * elapsed;
paddle.RightSide += paddle.speed * elapsed;
paddle.LeftSide += paddle.speed * elapsed;
paddle.TopSide += paddle.speed * elapsed;
paddle.BottomSide += paddle.speed * elapsed;*/
/*paddle.x += paddle.xSpeed * elapsed;
paddle.y += paddle.xSpeed * elapsed;*/
//bounce the ball of all edges
if (37 in keysDown && paddle.x > 0)
paddle.x -= PADDLE_SPEED * elapsed;
if (39 in keysDown && paddle.x + PADDLE_WIDTH_PX < canvas.width)
paddle.x += PADDLE_SPEED * elapsed;
if (ball.x+(ball.x/7) >= canvas.width) {
ball.x -= 5;
ball.xSpeed *= -1;
}
if (ball.x-(ball.x/7) <= 0) {
ball.x += 5;
ball.xSpeed *= -1;
}
if (ball.y+(ball.y/100) <= 0) {
ball.y += 5;
ball.ySpeed *= -1;
}
if (ball.y+(ball.y/3) >= canvas.height) {
ball.y -= 5;
ball.ySpeed *= -1;
}
/*
The problem here is that sometimes the ball gets 'stuck' to an edge.
This can occur when the ball passes beyond an edge in a frame when the
elapsed time is relatively large. In some cases, when the elapsed time in the
next frame is relatively short, the ball doesn't reach the edge to get back
into play. This results in another flip of the velocity and the ball becomes
'trapped' on the edge.
e.g.
xSpeed = -500, x = 10, elapsed = 0.2 => xSpeed = 500, x = -90 (xMovement = -100)
xSpeed = 500, x = -90, elapsed = 0.1 => xSpeed = -500, x = -40 (xMovement = +50)
xSpeed = -500, x = -40, elapsed = 0.1 => xSpeed = 500, x = -40 (xMovement = -50)
and so on ...until a larger elapsed time occurs in the right direction
The fix for this is to move the ball to the edge when the velocity is flipped.
*/
}
var previous;
function run(timestamp) {
if (!previous) previous = timestamp; //start with no elapsed time
var elapsed = (timestamp - previous) / 1000; //work out the elapsed time
update(elapsed); //update the game with the elapsed time
render(); //render the scene
previous = timestamp; //set the (globally defined) previous timestamp ready for next time
window.requestAnimationFrame(run); //ask browser to call this function again, when it's ready
}
//trigger the game loop
window.requestAnimationFrame(run);
感谢您花时间阅读本文 --ConfusedStudent
答案 0 :(得分:0)
划水板存在许多问题。
首先,您可能希望它具有固定大小,所以让我们来定义
它在文件开头的尺寸(把它放在代码的前两行之后,因为它使用canvas
将桨宽设置为其宽度的1/5 - 我认为这是你试图做的事情) :
var PADDLE_WIDTH_PX = canvas.width / 5;
var PADDLE_HEIGHT_PX = 10;
使用此功能,您可以将球拍初始化到画布的底部和中间:
var paddle = {
x: (canvas.width - PADDLE_WIDTH_PX) / 2,
y: canvas.height - PADDLE_HEIGHT_PX
}
x
和y
是左下角的左上角,因此右侧位于x + PADDLE_WIDTH_PX
,底侧位于y + PADDLE_HEIGHT_PX
。
知道了这一点,你就可以在这四个角上绘制一条路径:
ctx.beginPath();
ctx.moveTo(paddle.x, paddle.y);
ctx.lineTo(paddle.x + PADDLE_WIDTH_PX, paddle.y);
ctx.lineTo(paddle.x + PADDLE_WIDTH_PX, paddle.y + PADDLE_HEIGHT_PX);
ctx.lineTo(paddle.x, paddle.y + PADDLE_HEIGHT_PX);
ctx.lineTo(paddle.x, paddle.y);
ctx.closePath();
但由于桨只是一个矩形,因此使用方法绘制矩形更容易 - fillRect
,如下所示:
ctx.fillRect(paddle.x, paddle.y, PADDLE_WIDTH_PX, PADDLE_HEIGHT_PX);
无论哪种方式,桨的所有四个角都移动到一起,所以它不会增长或缩小。
因此,如果您将其放在render
函数中,它看起来像这样:
function render() {
//clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height)
// draw the ball
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
// draw the paddle
ctx.fillStyle = "red";
ctx.fillRect(paddle.x, paddle.y, PADDLE_WIDTH_PX, PADDLE_HEIGHT_PX);
}
最后一件事是在按下左右箭头键时让拨片移动。
只有在向左箭头或向右箭头按下时,球拍才会移动。否则它的速度为0并且它就位于其位置。因此paddle
对象不需要xSpeed
成员变量
此外,球拍只能水平移动,因此只有x
变量变化,y
始终相同。
让我们首先在文件开头定义球拍的速度:
var PADDLE_SPEED = 300;
然后让我们将移动逻辑放在update
函数中:
if (37 in keysDown && paddle.x > 0)
paddle.x -= PADDLE_SPEED * elapsed;
else if (39 in keysDown && paddle.x + PADDLE_WIDTH_PX < canvas.width)
paddle.x += PADDLE_SPEED * elapsed;
您可以注意到,仅当按下箭头键并且桨叶不在边缘时才会更改桨位置。
应该从paddle
函数中删除处理update
的所有其他代码,以便它看起来像这样(我删除了大部分注释):
function update(elapsed) {
//update the ball position according to the elapsed time
ball.y += ball.ySpeed * elapsed;
ball.x += ball.xSpeed * elapsed;
if (37 in keysDown && paddle.x > 0)
paddle.x -= PADDLE_SPEED * elapsed;
else if (39 in keysDown && paddle.x + PADDLE_WIDTH_PX < canvas.width)
paddle.x += PADDLE_SPEED * elapsed;
//bounce the ball of all edges
if/*(*/(ball.x /*- (ball.x / 2))*/<= 0) {
ball.x = 1;
ball.xSpeed *= -1;
}
if /*(*/(ball.x /*+ (ball.x / 2))*/>= canvas.width) {
ball.x = ball.x -1;
ball.xSpeed *= -1;
}
if/*(*/(ball.y /*- (ball.y / 2))*/<= 0) {
ball.y = 1;
ball.ySpeed *= -1;
}
if /*(*/(ball.y /*+ (ball.y / 2))*/>= canvas.height) {
ball.y = ball.y -1;
ball.ySpeed *= -1;
}
}