Search code examples
javascriptpong

pong paddles ticking when using setinterval and settiomeout


so I'm trying ti create a pong game and the paddles of the pong are ticiking.. i am using two functions for the ball and for the paddles, also im using canvas There are paddles object and event listener for the movment Please help :)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Pong</title>
    <script type="text/javascript">

        function canvas() {
            var can = document.getElementById('theCanvas');
            can.style.backgroundColor = "black";
            var ctx = can.getContext('2d');
            var keys = [];
            
        var ball = {    
            x: (can.width-10)/2,
            y: (can.width-10)/2,
            dx: 8,
            dy: 8
            }
        
        var playerOne = {
            x: can.width-50,
            y: (can.width-50)/2,
            H: 100,
            W: 20,
            hitDir: 0
        }
        
        var playerTwo = {
            x: 50,
            y: (can.width-50)/2,
            H: 100,
            W: 20,
            hitDir: 0
        }
            ctx.fillStyle ="white";
            ctx.fillRect(playerOne.x,playerOne.y,playerOne.W,playerOne.H);
            ctx.fillRect(playerTwo.x,playerTwo.y,playerTwo.W,playerTwo.H);
            
            function draw()
            {
            ctx.clearRect(0,0, 800,800);
            ctx.beginPath();
            ctx.fillStyle="#0000ff";
            ctx.arc(ball.x,ball.y,10,0,Math.PI*2,true);
            ctx.closePath();
            ctx.fill();
            if( ball.x<10 || ball.x>790) 
            {
            ball.dx=-ball.dx
            }
            
            if( ball.y<10 || ball.y>790) {
                ball.dy=-ball.dy
            }
            ball.x+=ball.dx; 
            ball.y+=ball.dy;
            
            ctx.fillStyle ="white";
            ctx.fillRect(playerOne.x,playerOne.y,playerOne.W,playerOne.H);
            ctx.fillRect(playerTwo.x,playerTwo.y,playerTwo.W,playerTwo.H);
            
            }
            setInterval(draw,10);

            function move() {
                ctx.clearRect(0,0,800,800);
                if (keys[38]) {
                playerTwo.y-=10;
            }

                if (keys[40]) {
                playerTwo.y+=10;
            
            }
            ctx.fillStyle ="white";
            ctx.fillRect(playerOne.x,playerOne.y,playerOne.W,playerOne.H);
            ctx.fillRect(playerTwo.x,playerTwo.y,playerTwo.W,playerTwo.H);
            ctx.clearRect(0,0, 800,800);
            ctx.beginPath();
            ctx.fillStyle="#0000ff";
            ctx.arc(ball.x,ball.y,10,0,Math.PI*2,true);
            ctx.closePath();
            ctx.fill();
            setTimeout(move, 1000/60);
            }
            move();
            document.body.addEventListener("keydown", function (e) {
            keys[e.keyCode] = true;
            });
            document.body.addEventListener("keyup", function (e) {
            keys[e.keyCode] = false;
            });
            
             }
             
    </script>
</head>
<body onload="canvas()">
    <canvas id="theCanvas" width="800" height="800"></canvas>
</body>
</html>


Solution

  • Thanks for the interesting problem.

    What you want to do is combine the two setInterval/setTimeout into a single render function. This is then used by a single window.requestAnimationFrame function which is called when the browser is ready to paint the next frame. This is superior to setTimeout or setInterval which might be the reason for the "ticking" as your canvas might be trying to paint the frame when the browser isn't ready to render that frame yet.

    I have also refactored your game into the following pseudocode

    1) Set up the canvas and event listeners
    2) Declare the render function
      2a) Change the position data of the ball & paddles
      2b) Render the ball & paddles based on its data
      2c) request another animation frame
    3) request an animation frame with the render function
    

    Here is my jsfiddle