我正在尝试制作像乒乓球这样的视频游戏。

我分别使用rect()arc()函数绘制了桨和球。这些是在HTML <canvas>元素上绘制的。事件处理程序附加到文档中的向上和向下箭头键。这些允许能够移动桨。使用setInterval()功能在10毫秒后更改球的x和y坐标。

我遇到的问题是,有时球会被困在桨中,并开始以锯齿形的方式在其中运动。

我怎样才能解决这个问题?我想在击中球拍的前部时立即更改球的x速度,如果击中其侧面则更改其y速度。

这是我的代码:

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

最佳答案

也许:

<!-- 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()函数,该函数基本上将球移动到不与球拍碰撞为止。然后我添加了所有桨碰撞测试条件。

09-18 04:34