【问题标题】:How do I move the paddle in Breakout using Javascript - when I've drawn the paddle using lineTo and moveTo?如何使用 Javascript 在 Breakout 中移动桨叶 - 当我使用 lineTo 和 moveTo 绘制桨叶时?
【发布时间】:2015-04-12 09:49:17
【问题描述】:

我目前正在尝试为大学制作一个 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);

感谢您抽出宝贵时间阅读本文 --困惑的学生

【问题讨论】:

    标签: javascript html canvas html5-canvas


    【解决方案1】:

    桨有很多问题。

    首先,您可能希望它具有固定大小,所以让我们定义 它的尺寸在文件的开头(把它放在代码的前两行之后,因为它使用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
    }
    

    xy 是桨叶的左上角,所以右侧在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 函数中删除,使其看起来像这样(我已经删除了大部分cmets):

    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;
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-06-05
      • 2022-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-17
      • 2021-07-17
      相关资源
      最近更新 更多