Sunday 18 October 2020

Running multiple requestAnimation loops to fire multiple balls?

I'm trying to get the ball below to keep appearing and firing up accross the y axis at a set interval and always from where the x position of paddle(mouse) is, i need there to be a delay between each ball firing. I'm trying to make space invaders but with the ball constantly firing at a set interval.

Do I need to create multiple requestAnimationFrame loops for each ball? Can someone help with a very basic example of how this should be done please or link a good article? I am stuck at creating an array for each ball and not sure how to architect the loop to achieve this effect. All the examples I can find are too complex


<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <style>
    * {
      padding: 0;
      margin: 0;
    }

    canvas {
      background: #eee;
      display: block;
      margin: 0 auto;
      width: 30%;
    }
  </style>
</head>

<body>
  <canvas id="myCanvas" height="400"></canvas>

  <script>

    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("2d");
    //start the requestAnimationFrame loop
    var myRequestAnimation;
    var myRequestAnimationBall;
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||
      window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
    var cancelAnimationFrame = window.cancelAnimationFrame || window.mozCancelAnimationFrame;
    drawLoop();
    setInterval(drawBallLoop, 400);

    var x = canvas.width / 2;
    var y = canvas.height - 30;
    var defaultSpeedX = 0;
    var defaultSpeedY = 4;
    var dx = defaultSpeedX;
    var dy = -defaultSpeedY;
    var ballRadius = 10;

    var paddleX = (canvas.width - paddleWidth) / 2;

    var paddleHeight = 10;
    var paddleWidth = 70;

    //control stuff
    var rightPressed = false;
    var leftPressed = false;

    var brickRowCount = 1;
    var brickColumnCount = 1;
    var brickWidth = 40;
    var brickHeight = 20;
    var brickPadding = 10;
    var brickOffsetTop = 30;
    var brickOffsetLeft = 30;

    var score = 0;
    var lives = 3;



  

    //paddle
    function drawPaddle() {
      ctx.beginPath();
      ctx.rect(paddleX, canvas.height - paddleHeight, paddleWidth, paddleHeight);
      ctx.fillStyle = "#0095DD";
      ctx.fill();
      ctx.closePath();
    }

    //bricks
    function drawBricks() {
      for (var c = 0; c < brickColumnCount; c++) {
        for (var r = 0; r < brickRowCount; r++) {
          if (bricks[c][r].status == 1) {
            var brickX = (c * (brickWidth + brickPadding)) + brickOffsetLeft;
            var brickY = (r * (brickHeight + brickPadding)) + brickOffsetTop;
            bricks[c][r].x = brickX;
            bricks[c][r].y = brickY;
            ctx.beginPath();
            ctx.rect(brickX, brickY, brickWidth, brickHeight);
            ctx.fillStyle = "#0095DD";
            ctx.fill();
            ctx.closePath();
          }
        }
      }
    }

    //collision detection
    function collisionDetection() {
      for (var c = 0; c < brickColumnCount; c++) {
        for (var r = 0; r < brickRowCount; r++) {
          var b = bricks[c][r];
          if (b.status == 1) {
            if (x > b.x && x < b.x + brickWidth && y > b.y && y < b.y + brickHeight) {
              dy = -dy;
              b.status = 0;
              score++;
              console.log(score);
              if (score == brickRowCount * brickColumnCount) {
                console.log("YOU WIN, CONGRATS!");
                window.cancelAnimationFrame(myRequestAnimation);
              }
            }
          }
        }
      }
    }

    //default bricks
    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, status: 1 };
      }
    }

    //lives
    function drawLives() {
      ctx.font = "16px Arial";
      ctx.fillStyle = "#0095DD";
      ctx.fillText("Lives: " + lives, canvas.width - 65, 20);
    }


    // ball1
    var ball1 = {
      x,
      y,
      directionX: 0,
      directionY: -5
    }

    // ball1
    var ball2 = {
      x,
      y,
      directionX: 0,
      directionY: -2
    }

    // put each ball in a balls[] array
    var balls = [ball1, ball2];

    
    function drawBall() {
      // clearCanvas();
      for (var i = 0; i < balls.length; i++) {
        var ball = balls[i]

        ctx.beginPath();
        ctx.arc(ball.x, ball.y, ballRadius, 0, Math.PI * 2);
        ctx.fillStyle = "#0095DD";
        ctx.fill();
        ctx.closePath();
      }
    }

    ///////DRAW BALL LOOP////////
    function drawBallLoop() {
      myRequestAnimationBall = requestAnimationFrame(drawBallLoop);

      // clear frame
      //ctx.clearRect(0, 0, canvas.width, canvas.height);

      //draw ball
      drawBall();

      //move balls
      for (var i = 0; i < balls.length; i++) {
        balls[i].y += balls[i].directionY;
      }
    }

    //Clear Canvas
    function clearCanvas() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
    }





    ///////DRAW MAIN LOOP////////
    function drawLoop() {
      myRequestAnimation = requestAnimationFrame(drawLoop);

      // clear frame
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      //draw ball
      drawPaddle();
      drawBricks();
      collisionDetection();
      drawLives();


      //bounce off walls
      if (x + dx > canvas.width - ballRadius || x + dx < ballRadius) {
        dx = -dx;
      }

      if (rightPressed) {
        paddleX += 7;
        if (paddleX + paddleWidth > canvas.width) {
          paddleX = canvas.width - paddleWidth;
        }
      }

      else if (leftPressed) {
        paddleX -= 7;
        if (paddleX < 0) {
          paddleX = 0;
        }
      }
    }


    //keyboard left/right logic
    document.addEventListener("keydown", keyDownHandler, false);
    document.addEventListener("keyup", keyUpHandler, false);
    function keyDownHandler(e) {
      if (e.key == "Right" || e.key == "ArrowRight") {
        rightPressed = true;
      }
      else if (e.key == "Left" || e.key == "ArrowLeft") {
        leftPressed = true;
      }
    }
    function keyUpHandler(e) {
      if (e.key == "Right" || e.key == "ArrowRight") {
        rightPressed = false;
      }
      else if (e.key == "Left" || e.key == "ArrowLeft") {
        leftPressed = false;
      }
    }

    //relative mouse pos
    function getMousePos(canvas, evt) {
      var rect = canvas.getBoundingClientRect(), // abs. size of element
        scaleX = canvas.width / rect.width,    // relationship bitmap vs. element for X
        scaleY = canvas.height / rect.height;  // relationship bitmap vs. element for Y

      return {
        x: (evt.clientX - rect.left) * scaleX,   // scale mouse coordinates after they have
        y: (evt.clientY - rect.top) * scaleY     // been adjusted to be relative to element
      }
    }

    //mouse movemment
    document.addEventListener("mousemove", mouseMoveHandler, false);

    function mouseMoveHandler(e) {
      var mouseX = getMousePos(canvas, e).x;
      //e.clientX = the horizontal mouse position in the viewport
      //canvas.offsetLeft = the distance between the left edge of the canvas and left edge of the viewport
      var relativeX = mouseX;
      // console.log('mouse= ',relativeX, canvas.offsetLeft)
      // console.log('paddle= ', paddleX);
      // console.log(getMousePos(canvas, e).x);

      if (relativeX - (paddleWidth / 2) > 0 && relativeX < canvas.width - (paddleWidth / 2)) {
        paddleX = relativeX - (paddleWidth / 2);
      }
    }


  </script>

</body>

</html>


from Running multiple requestAnimation loops to fire multiple balls?

No comments:

Post a Comment