2016-12-02 38 views
0

我正在嘗試製作像乒乓一樣的視頻遊戲。球被困在槳內

我已經分別使用rect()arc()函數繪製了槳和球。這些繪製在HTML <canvas>元素上。事件處理程序附加到文檔的上下箭頭鍵。這些允許能夠移動槳。球的x和y座標使用setInterval()函數在10毫秒後改變。

我遇到的問題是,有時球會被困在槳中,並開始以鋸齒形的方式移動。

我該如何解決這個問題?我想在球擊中槳的前端時立即改變球的x速度,如果球撞擊球的兩側,則要改變其速度。

這裏是我的代碼:

<!-- index.html --> 
<html> 
    <head> 
     <link type="text/css" rel="stylesheet" href="stylesheet.css"/> 
    </head> 
    <body> 
     <canvas id="my-canvas" height="300px" width="400px"></canvas> 

     <script src="jquery-3.1.1.min.js"></script> 
     <script src="script.js"></script> 
    </body> 
</html> 

/* stylesheet.css */ 
body { 
    background-color: #f00; 
} 

canvas { 
    background-color: #fff; 
} 

/* script.js */ 
$(document).ready(function() { 
    var canvas = $("#my-canvas")[0]; 
    var ctx = canvas.getContext("2d"); 
    var paddleHeight = 8; 
    var paddleWidth = 70; 
    var paddleY = (canvas.height - paddleWidth)/2; 
    var ballRadius = 8; 
    var ballX = canvas.width/2; 
    var ballY = canvas.height/2; 
    var xDir = 2; 
    var yDir = -2; 
    var upPressed = false; 
    var downPressed = false; 

    $(document).keydown(function (e) { 
     switch (e.which) { 
      case 38: 
       upPressed = true; 
       break; 
      case 40: 
       downPressed = true; 
     } 
    }); 

    $(document).keyup(function (e) { 
     switch (e.which) { 
      case 38: 
       upPressed = false; 
       break; 
      case 40: 
       downPressed = false; 
     } 
    }); 

    function drawPaddle() { 
     ctx.beginPath(); 
     ctx.rect(0, paddleY, paddleHeight, paddleWidth); 
     ctx.fillStyle = "#0f0"; 
     ctx.fill(); 
     ctx.closePath(); 
    } 

    function drawBall() { 
     ctx.beginPath(); 
     ctx.arc(ballX, ballY, ballRadius, 0, Math.PI*2); 
     ctx.fillStyle = "#00f"; 
     ctx.fill(); 
     ctx.closePath(); 
    } 

    function draw() { 
     ctx.clearRect(0, 0, canvas.width, canvas.height); 
     drawPaddle(); 

     ballX += xDir; 
     ballY += yDir; 

     // Collision detection with the sides of the canvas 
     if (ballY == canvas.height - ballRadius || ballY == ballRadius) { 
      yDir = -yDir; 
     } else if (ballX == ballRadius || ballX == canvas.width - ballRadius) { 
      xDir = -xDir; 
     } 

     // Collision detection with the front of the paddle 
     if (ballX == paddleHeight + ballRadius && ballY >= paddleY && ballY <= paddleY + paddleWidth) { 
      xDir = -xDir; 
     } 
     // Collision detection with the top side of the paddle 
     if (ballX < paddleHeight + ballRadius && ballY < paddleY && ballY >= paddleY - ballRadius) { 
      yDir = -yDir; 
     } 
     // Collision detection with the bottom side of the paddle 
     if (ballX < paddleHeight + ballRadius && ballY > paddleY + paddleWidth && ballY <= paddleY + paddleWidth + ballRadius) { 
      yDir = -yDir; 
     } 

     drawBall(); 

     // Paddle moving logic 
     if (downPressed && paddleY < canvas.height - paddleWidth) { 
      paddleY += 7; 
     } else if (upPressed && paddleY > 0) { 
      paddleY -= 7; 
     } 
    } 

    setInterval(draw, 10); 
}); 
+0

一個值得考慮的方法是:「在我移動球之後,它會與任何東西碰撞嗎?」 - 這是計算一個_potential_新的位置,然後測試它的碰撞。如果碰撞_will_(但尚未)發生,然後作出相應的反應 - 這將防止你目前面臨的情況。我的google-foo目前需要一項服務,但我已經看到一些優秀的論文在過去討論這種方法。當運動速度足夠快以至於你碰撞這個框架並且下一幀你通過一個物體達到數英里時,這是非常好的。 – enhzflep

回答

0

可能:

<!-- index.html --> 
<html> 
    <head> 
     <link type="text/css" rel="stylesheet" href="stylesheet.css"/> 
    </head> 
    <body> 
     <canvas id="my-canvas" height="300px" width="400px"></canvas> 

     <script src="jquery-3.1.1.min.js"></script> 
     <script src="script.js"></script> 
    </body> 
</html> 

/* stylesheet.css */ 
body { 
    background-color: #f00; 
} 

canvas { 
    background-color: #fff; 
} 

/* script.js */ 
$(document).ready(function() { 
    var canvas = $("#my-canvas")[0]; 
    var ctx = canvas.getContext("2d"); 
    var paddleHeight = 8; 
    var paddleWidth = 70; 
    var paddleY = (canvas.height - paddleWidth)/2; 
    var ballRadius = 8; 
    var ballX = canvas.width/2; 
    var ballY = canvas.height/2; 
    var xDir = 2; 
    var yDir = -2; 
    var upPressed = false; 
    var downPressed = false; 

    $(document).keydown(function (e) { 
     switch (e.which) { 
      case 38: 
       upPressed = true; 
       break; 
      case 40: 
       downPressed = true; 
     } 
    }); 

    $(document).keyup(function (e) { 
     switch (e.which) { 
      case 38: 
       upPressed = false; 
       break; 
      case 40: 
       downPressed = false; 
     } 
    }); 

    function escapePaddle() { 
     // I copy and pasted your collision logic and composed a super long condition. Brace yourself... 
     while ((ballX == paddleHeight + ballRadius && ballY >= paddleY && ballY <= paddleY + paddleWidth) || (ballX < paddleHeight + ballRadius && ballY < paddleY && ballY >= paddleY - ballRadius) || (ballX < paddleHeight + ballRadius && ballY > paddleY + paddleWidth && ballY <= paddleY + paddleWidth + ballRadius)) { 
     ballX+= xDir; 
     ballY += yDir; 
     } 
    } 

    function drawPaddle() { 
     ctx.beginPath(); 
     ctx.rect(0, paddleY, paddleHeight, paddleWidth); 
     ctx.fillStyle = "#0f0"; 
     ctx.fill(); 
     ctx.closePath(); 
    } 

    function drawBall() { 
     ctx.beginPath(); 
     ctx.arc(ballX, ballY, ballRadius, 0, Math.PI*2); 
     ctx.fillStyle = "#00f"; 
     ctx.fill(); 
     ctx.closePath(); 
    } 

    function draw() { 
     ctx.clearRect(0, 0, canvas.width, canvas.height); 
     drawPaddle(); 

     ballX += xDir; 
     ballY += yDir; 

     // Collision detection with the sides of the canvas 
     if (ballY == canvas.height - ballRadius || ballY == ballRadius) { 
      yDir = -yDir; 
     } else if (ballX == ballRadius || ballX == canvas.width - ballRadius) { 
      xDir = -xDir; 
     } 

     // Collision detection with the front of the paddle 
     if (ballX == paddleHeight + ballRadius && ballY >= paddleY && ballY <= paddleY + paddleWidth) { 
      xDir = -xDir; 
      escapePaddle(); 
     } 
     // Collision detection with the top side of the paddle 
     if (ballX < paddleHeight + ballRadius && ballY < paddleY && ballY >= paddleY - ballRadius) { 
      yDir = -yDir; 
      escapePaddle(); 
     } 
     // Collision detection with the bottom side of the paddle 
     if (ballX < paddleHeight + ballRadius && ballY > paddleY + paddleWidth && ballY <= paddleY + paddleWidth + ballRadius) { 
      yDir = -yDir; 
      escapePaddle(); 
     } 

     drawBall(); 

     // Paddle moving logic 
     if (downPressed && paddleY < canvas.height - paddleWidth) { 
      paddleY += 7; 
     } else if (upPressed && paddleY > 0) { 
      paddleY -= 7; 
     } 
    } 

    setInterval(draw, 10); 
}); 

我增加了一個escapePaddle()功能,直到它不與槳碰撞基本上移動球。然後我添加了所有的槳碰撞測試條件。