Javascript 球与画布边缘的碰撞检测

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 &

我遵循Mozilla游戏开发教程,在HTML5画布和JS中制作了一个简单的突破游戏

但是,我想放大画布,因为它有点小,所以我尝试了800x600画布。然后,我注意到这个球对于这个新的画布尺寸来说有点太慢了

最初在mozilla教程中,球的速度是2。我试着用3代替。于是问题来了

当我使用requestAnimationFrame时,它每秒刷新大约60x,我们可以说我的球每秒移动大约3x60=180px

要检测与画布右边缘的碰撞,我使用以下条件:

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();