Skip to content
Advertisement

Bullets curving when player gets near

Is ther a way to make the bullets go in a straight line when the player gets near det bullet. Because when i move the player near the bullet the bullet curves. And if possible is ther a way that i can implement the particles code. I tried to remove the update function but that doesn’t seem to work.

Do I nee to use vectors in the code for bullets to make them go straight forward? Or is there another way to making that work?

<html>

<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta charset="UTF-8">
    <style>
        canvas {
            cursor: crosshair;
            background-color: cornflowerblue;
        }
    </style>
</head>

<body>
    <canvas id="Figure" width="900" height="440"></canvas>
    
    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js?fbclid"></script>
    <script>

        (async function main() {


            const fps = 60;
            const ronaNum = 100; // number of particles at start
            const ronaSize = 70; // corona size
            const ronaSpeed = 200; // speed




            function draw() {
    var canvas = document.getElementById('Figure');
    if (!canvas.getContext) return;
    var ctx = canvas.getContext('2d');

    //compatability            
    var requestAnimationFrame = window.requestAnimationFrame || //Chromium 
    window.webkitRequestAnimationFrame || //Webkit
    window.mozRequestAnimationFrame || //Mozilla Geko
    window.oRequestAnimationFrame || //Opera Presto
    window.msRequestAnimationFrame || //IE Trident?
        function (callback) { //Fallback function
            window.setTimeout(callback, 1000 / 60);
        };

    var DrawX = 0;
    var DrawY = 0;
    var time = 0;
    var width = canvas.width;
    var height = canvas.height;
    var offTop = canvas.offsetTop;
    var offLeft = canvas.offsetLeft;
    var rectWidth = 15;
    var rectHeight = 15;
    var speed = 1;
    var x = width / 2;
    var y = height / 2;
    var size = 30;
    var id = 0;
    var bulletId = 0;

    
    function player(id, color, size, x, y) {
        this.id = id;
        this.color = color;
        this.size = size;
        this.x = x;
        this.y = y;
        this.speed = speed;
    }
    var playerList = [];

    function addPlayer(color, size, x, y) {
        playerList[id] = new player(id, color, size, x, y);
        id += 1;
    }
    addPlayer("blue", size, width / 2 - 50, height / 2);

 
    var pressedKeys = [];




    function moveLeft(checkId, checkX, checkY, cSize, cSpeed, cKey) {
        var x = checkX - cSpeed;
        var y = checkY - cSpeed;
        var x2 = checkX + cSize + cSpeed;
        var y2 = checkY + cSize + cSpeed;
        if (x > 0) {
            playerList[checkId].x = checkX - cSpeed;
        } else {
            playerList[checkId].x = 0;
        }
    }

    function moveUp(checkId, checkX, checkY, cSize, cSpeed, cKey) {
        var x = checkX - cSpeed;
        var y = checkY - cSpeed;
        var x2 = checkX + cSize + cSpeed;
        var y2 = checkY + cSize + cSpeed;
        if (y > 0) {
            playerList[checkId].y = checkY - cSpeed;
        } else {
            playerList[checkId].y = 0;
        }
    }

    function moveRight(checkId, checkX, checkY, cSize, cSpeed, cKey) {
        var x = checkX - cSpeed;
        var y = checkY - cSpeed;
        var x2 = checkX + cSize + cSpeed;
        var y2 = checkY + cSize + cSpeed;
        if (x2 < width) {
            playerList[checkId].x = checkX + cSpeed;
        } else {
            playerList[checkId].x = width - cSize;
        }
    }

    function moveDown(checkId, checkX, checkY, cSize, cSpeed, cKey) {
        var x = checkX - cSpeed;
        var y = checkY - cSpeed;
        var x2 = checkX + cSize + cSpeed;
        var y2 = checkY + cSize + cSpeed;
        if (y2 < height) {
            playerList[checkId].y = checkY + cSpeed;
        } else {
            playerList[checkId].y = height - cSize;
        }
    }

    function Move(checkId, checkX, checkY, cSize, cSpeed, cKey) {


        
        if (checkId === 0) {
            switch (cKey) {
                case 65:
                    // left
                    moveLeft(checkId, checkX, checkY, cSize, cSpeed, cKey);
                    break;

                case 87:
                    // up 
                    moveUp(checkId, checkX, checkY, cSize, cSpeed, cKey);
                    break;

                case 68:
                    // right         
                    moveRight(checkId, checkX, checkY, cSize, cSpeed, cKey);
                    break;

                case 83:
                    // down         
                    moveDown(checkId, checkX, checkY, cSize, cSpeed, cKey);
                    break;

                default:
                    return; // exit this handler for other keys 
            }
        }
        
    }

    var validKeys = [];
    validKeys[0] = "65,87,68,83-107,109,80"; 

    // == KEYDOWN ==
    $(document.body).keydown(function (e) {
        e.preventDefault();

        //go through all players
        $.each(playerList, function (i, currentPlayer) {
            if (validKeys[currentPlayer.id].indexOf(e.which) == -1) return true;
            if (!pressedKeys[e.which]) {
                //set interval for the function
                pressedKeys[e.which] = setInterval(function () {
                    Move(currentPlayer.id, currentPlayer.x, currentPlayer.y, currentPlayer.size, currentPlayer.speed, e.which);
                }, 5);
            }
        });
    });

    // == KEYUP ==    
    $(document.body).keyup(function (e) {
        if (pressedKeys[e.which]) {
            clearInterval(pressedKeys[e.which]);
            delete pressedKeys[e.which];
        }
    });

    //===============================    SHOOTING   ===============================

    //Bullets
    function bullet(id, color, size, speed, x, y, eX, eY) {
        this.id = id;
        this.color = color;
        this.size = size;
        this.x = x;
        this.y = y;
        this.eX = eX;
        this.eY = eY;
        this.velocityX = 1;
        this.velocityY = 1;
        this.speed = speed;
    }

    var bulletList = [];

    function addBullet(color, bsize, bspeed, x, y, eX, eY) {
        bulletList[bulletId] = new bullet(bulletId, color, bsize, bspeed, x, y, eX, eY);
        bulletId += 1;
    }

    function updateBullet(bullet, player) {
        var dx = (bullet.eX - player.x);
        var dy = (bullet.eY - player.y);
        var mag = Math.sqrt(dx * dx + dy * dy);
        bullet.velocityX = (dx / mag) * speed;
        bullet.velocityY = (dy / mag) * speed;
        bullet.x += bullet.velocityX;
        bullet.y += bullet.velocityY;
    }

    // Add event listener for `click` events.
    canvas.onmousedown = function (e) {
        addBullet("green", 10, 2, playerList[0].x, playerList[0].y, e.x, e.y);
    };

    // ======= DRAWING =======      
    function drawFrame() {
        requestAnimationFrame(drawFrame);
        ctx.font = "15pt Georgia"; // sets the font and font size of the text
        ctx.clearRect(0, 0, width, height);
        $.each(playerList, function (index, currentPlayer) {
            //debug 
            ctx.fillStyle = "black";


            //draw players                           
            DrawX = currentPlayer.x;
            DrawY = currentPlayer.y;
            rectWidth = currentPlayer.size;
            rectHeight = currentPlayer.size;
            ctx.fillStyle = currentPlayer.color;
            ctx.fillRect(DrawX, DrawY, rectWidth, rectHeight);
            ctx.fillStyle = "black";
            ctx.fillText("x: " + currentPlayer.x, DrawX, DrawY - 40);
            ctx.fillText("y: " + currentPlayer.y, DrawX, DrawY - 60);
        });
        //draw bullets
        $.each(bulletList, function (index, bullet) {
            updateBullet(bullet, playerList[0]);
            ctx.fillStyle = bullet.color;
            ctx.fillRect(bullet.x, bullet.y, bullet.size, bullet.size);
        });
    }
    drawFrame();
}
$(draw);
            let corona = [];
            createCoronaParticles();
            // game loop
            setInterval(update, 1000 / fps);

            function createCoronaParticles() {
                corona = [];
                let cx, cy;
                for (var i = 0; i < ronaNum; i++) {
                    do {
                        cx = Math.floor(Math.random() * canvas.width);
                        cy = Math.floor(Math.random() * canvas.height);
                    } while (noSpawnOnFigure(canvas.height / 2, canvas.width / 2, cy, cx) < ronaSize * 5);
                    corona.push(newParticle(cx, cy));
                }
            }

            function noSpawnOnFigure(cy1, cx1, cy2, cx2) {
                return Math.sqrt(Math.pow(cy2 - cy1, 2) + Math.pow(cx2 - cx1, 2));
            }

            function newParticle(cx, cy) {
                let rona = {
                    ca: Math.random() * Math.PI * 2, //radians
                    cr: ronaSize / 2,
                    cx: cx,
                    cy: cy,
                    cxv: Math.random() * ronaSpeed / fps * (Math.random() < 0.5 ? 1 : -1),
                    cyv: Math.random() * ronaSpeed / fps * (Math.random() < 0.5 ? 1 : -1)
                };
                return rona;
            }

           


      

            function update() {
                // canvas
                ctx.clearRect(0, 0, canvas.width, canvas.height);
                // draw corona particles
                ctx.strokeStyle = "rgb(150, 0, 0)";
                ctx.lineWidth = 20;
                let ca, cr, cx, cy;
                for (let i = 0; i < corona.length; i++) {

                    // get properties
                    ca = corona[i].ca;
                    cr = corona[i].cr;
                    cx = corona[i].cx;
                    cy = corona[i].cy;

                    // draw path
                    ctx.beginPath();
                    ctx.fillStyle = "rgb(200, 0, 0)"
                    ctx.moveTo(
                        cx + cr * Math.cos(ca),
                        cy + cr * Math.sin(ca)
                    );

                    // draw circle
                    for (let j = 1; j < 180; j++) {
                        ctx.lineTo(
                            cx + cr * Math.cos(ca + j * Math.PI * 2 / 180),
                            cy + cr * Math.sin(ca + j * Math.PI * 2 / 180)
                        );
                    }

                    ctx.closePath();
                    ctx.stroke();
                    ctx.fill();

                    // move particles
                    corona[i].cx += corona[i].cxv;
                    corona[i].cy += corona[i].cyv;

                    // particle edge of screen
                    if (corona[i].cx < 0 - corona[i].cr) {
                        corona[i].cx = canvas.width + corona[i].cr;
                    } else if (corona[i].cx > canvas.width + corona[i].cr) {
                        corona[i].cx = 0 - corona[i].cr
                    }
                    if (corona[i].cy < 0 - corona[i].cr) {
                        corona[i].cy = canvas.height + corona[i].cr;
                    } else if (corona[i].cy > canvas.height + corona[i].cr) {
                        corona[i].cy = 0 - corona[i].cr
                    }
                }

                //(function loop(now) {



                //let t = (Math.min(now - prev, MAX_DELTA) / 1000);
                //prev = now;

                let dx = keys[RIGHT] - keys[LEFT];
                let dy = keys[DOWN] - keys[UP];

                x += dx * SPEED;
                y += dy * SPEED;

                let rx = mx - x;
                let ry = my - y;

                //ctx.fillStyle = '#fff';
                //ctx.fillRect(0, 0, canvas.width, canvas.height);

                ctx.save();
                ctx.translate(x, y);
                ctx.rotate(Math.atan2(ry, rx));
                ctx.drawImage(arrow, -arrow.width / 2, -arrow.height / 2);
                ctx.restore();

                //window.requestAnimationFrame(loop);
                //})(0);
            }

        })();

    </script>



</body>

</html>

Advertisement

Answer

Your bullet drawing is relative to the position of the player, I’m not sure why you are doing that…
Here is what I would do:

        function updateBullet(bullet) {
          bullet.x += bullet.velocityX;
          bullet.y += bullet.velocityY;
        }

In that function, we just update the position of the bullet, nothing more.
The calculation of the bullet velocity is now where we create the bullet:

        function bullet(id, color, size, speed, x, y, eX, eY, player) {
          this.id = id;
          ...
          
          var dx = (this.eX - player.x);
          var dy = (this.eY - player.y);
          var mag = Math.sqrt(dx * dx + dy * dy);
          this.velocityX = (dx / mag) * speed;
          this.velocityY = (dy / mag) * speed;
        }

That is all, to me it makes sense there was no reason to recalculate velocity on the update, we just change the position there.

Here is your full code:

<html>

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta charset="UTF-8">
  <style>
    canvas {
      cursor: crosshair;
      background-color: cornflowerblue;
    }
  </style>
</head>

<body>
  <canvas id="Figure" width="700" height="280"></canvas>

  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js?fbclid"></script>
  <script>
    (async function main() {
      const fps = 60;
      const ronaNum = 100; // number of particles at start
      const ronaSize = 70; // corona size
      const ronaSpeed = 200; // speed

      function draw() {
        var canvas = document.getElementById('Figure');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext('2d');

        //compatability            
        var requestAnimationFrame = window.requestAnimationFrame || //Chromium 
          window.webkitRequestAnimationFrame || //Webkit
          window.mozRequestAnimationFrame || //Mozilla Geko
          window.oRequestAnimationFrame || //Opera Presto
          window.msRequestAnimationFrame || //IE Trident?
          function(callback) { //Fallback function
            window.setTimeout(callback, 1000 / 60);
          };

        var DrawX = 0;
        var DrawY = 0;
        var time = 0;
        var width = canvas.width;
        var height = canvas.height;
        var offTop = canvas.offsetTop;
        var offLeft = canvas.offsetLeft;
        var rectWidth = 15;
        var rectHeight = 15;
        var speed = 1;
        var x = width / 2;
        var y = height / 2;
        var size = 30;
        var id = 0;
        var bulletId = 0;


        function player(id, color, size, x, y) {
          this.id = id;
          this.color = color;
          this.size = size;
          this.x = x;
          this.y = y;
          this.speed = speed;
        }
        var playerList = [];

        function addPlayer(color, size, x, y) {
          playerList[id] = new player(id, color, size, x, y);
          id += 1;
        }
        addPlayer("blue", size, width / 2 - 50, height / 2);
        var pressedKeys = [];

        function moveLeft(checkId, checkX, checkY, cSize, cSpeed, cKey) {
          var x = checkX - cSpeed;
          var y = checkY - cSpeed;
          var x2 = checkX + cSize + cSpeed;
          var y2 = checkY + cSize + cSpeed;
          if (x > 0) {
            playerList[checkId].x = checkX - cSpeed;
          } else {
            playerList[checkId].x = 0;
          }
        }

        function moveUp(checkId, checkX, checkY, cSize, cSpeed, cKey) {
          var x = checkX - cSpeed;
          var y = checkY - cSpeed;
          var x2 = checkX + cSize + cSpeed;
          var y2 = checkY + cSize + cSpeed;
          if (y > 0) {
            playerList[checkId].y = checkY - cSpeed;
          } else {
            playerList[checkId].y = 0;
          }
        }

        function moveRight(checkId, checkX, checkY, cSize, cSpeed, cKey) {
          var x = checkX - cSpeed;
          var y = checkY - cSpeed;
          var x2 = checkX + cSize + cSpeed;
          var y2 = checkY + cSize + cSpeed;
          if (x2 < width) {
            playerList[checkId].x = checkX + cSpeed;
          } else {
            playerList[checkId].x = width - cSize;
          }
        }

        function moveDown(checkId, checkX, checkY, cSize, cSpeed, cKey) {
          var x = checkX - cSpeed;
          var y = checkY - cSpeed;
          var x2 = checkX + cSize + cSpeed;
          var y2 = checkY + cSize + cSpeed;
          if (y2 < height) {
            playerList[checkId].y = checkY + cSpeed;
          } else {
            playerList[checkId].y = height - cSize;
          }
        }

        function Move(checkId, checkX, checkY, cSize, cSpeed, cKey) {
          if (checkId === 0) {
            switch (cKey) {
              case 65:
                // left
                moveLeft(checkId, checkX, checkY, cSize, cSpeed, cKey);
                break;

              case 87:
                // up 
                moveUp(checkId, checkX, checkY, cSize, cSpeed, cKey);
                break;

              case 68:
                // right         
                moveRight(checkId, checkX, checkY, cSize, cSpeed, cKey);
                break;

              case 83:
                // down         
                moveDown(checkId, checkX, checkY, cSize, cSpeed, cKey);
                break;

              default:
                return; // exit this handler for other keys 
            }
          }

        }

        var validKeys = [];
        validKeys[0] = "65,87,68,83-107,109,80";

        // == KEYDOWN ==
        $(document.body).keydown(function(e) {
          e.preventDefault();

          //go through all players
          $.each(playerList, function(i, currentPlayer) {
            if (validKeys[currentPlayer.id].indexOf(e.which) == -1) return true;
            if (!pressedKeys[e.which]) {
              //set interval for the function
              pressedKeys[e.which] = setInterval(function() {
                Move(currentPlayer.id, currentPlayer.x, currentPlayer.y, currentPlayer.size, currentPlayer.speed, e.which);
              }, 5);
            }
          });
        });

        // == KEYUP ==    
        $(document.body).keyup(function(e) {
          if (pressedKeys[e.which]) {
            clearInterval(pressedKeys[e.which]);
            delete pressedKeys[e.which];
          }
        });

        //===============================    SHOOTING   ===============================

        //Bullets
        function bullet(id, color, size, speed, x, y, eX, eY, player) {
          this.id = id;
          this.color = color;
          this.size = size;
          this.x = x;
          this.y = y;
          this.eX = eX;
          this.eY = eY;
          this.speed = speed;
          
          var dx = (this.eX - player.x);
          var dy = (this.eY - player.y);
          var mag = Math.sqrt(dx * dx + dy * dy);
          this.velocityX = (dx / mag) * speed;
          this.velocityY = (dy / mag) * speed;
        }

        var bulletList = [];

        function addBullet(color, bsize, bspeed, x, y, eX, eY) {
          bulletList[bulletId] = new bullet(bulletId, color, bsize, bspeed, x, y, eX, eY, playerList[0]);
          bulletId += 1;
        }

        function updateBullet(bullet) {
          bullet.x += bullet.velocityX;
          bullet.y += bullet.velocityY;
        }

        // Add event listener for `click` events.
        canvas.onmousedown = function(e) {
          addBullet("green", 10, 2, playerList[0].x, playerList[0].y, e.x, e.y);
        };

        // ======= DRAWING =======      
        function drawFrame() {
          requestAnimationFrame(drawFrame);
          ctx.font = "15pt Georgia"; // sets the font and font size of the text
          ctx.clearRect(0, 0, width, height);
          $.each(playerList, function(index, currentPlayer) {
            //debug 
            ctx.fillStyle = "black";


            //draw players                           
            DrawX = currentPlayer.x;
            DrawY = currentPlayer.y;
            rectWidth = currentPlayer.size;
            rectHeight = currentPlayer.size;
            ctx.fillStyle = currentPlayer.color;
            ctx.fillRect(DrawX, DrawY, rectWidth, rectHeight);
            ctx.fillStyle = "black";
            ctx.fillText("x: " + currentPlayer.x, DrawX, DrawY - 10);
            ctx.fillText("y: " + currentPlayer.y, DrawX, DrawY - 30);
          });
          //draw bullets
          $.each(bulletList, function(index, bullet) {
            updateBullet(bullet);
            ctx.fillStyle = bullet.color;
            ctx.fillRect(bullet.x, bullet.y, bullet.size, bullet.size);
          });
        }
        drawFrame();
      }
      $(draw);
      let corona = [];
      createCoronaParticles();
      // game loop
      setInterval(update, 1000 / fps);

      function createCoronaParticles() {
        corona = [];
        let cx, cy;
        for (var i = 0; i < ronaNum; i++) {
          do {
            cx = Math.floor(Math.random() * canvas.width);
            cy = Math.floor(Math.random() * canvas.height);
          } while (noSpawnOnFigure(canvas.height / 2, canvas.width / 2, cy, cx) < ronaSize * 5);
          corona.push(newParticle(cx, cy));
        }
      }

      function noSpawnOnFigure(cy1, cx1, cy2, cx2) {
        return Math.sqrt(Math.pow(cy2 - cy1, 2) + Math.pow(cx2 - cx1, 2));
      }

      function newParticle(cx, cy) {
        let rona = {
          ca: Math.random() * Math.PI * 2, //radians
          cr: ronaSize / 2,
          cx: cx,
          cy: cy,
          cxv: Math.random() * ronaSpeed / fps * (Math.random() < 0.5 ? 1 : -1),
          cyv: Math.random() * ronaSpeed / fps * (Math.random() < 0.5 ? 1 : -1)
        };
        return rona;
      }






      function update() {
        // canvas
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        // draw corona particles
        ctx.strokeStyle = "rgb(150, 0, 0)";
        ctx.lineWidth = 20;
        let ca, cr, cx, cy;
        for (let i = 0; i < corona.length; i++) {

          // get properties
          ca = corona[i].ca;
          cr = corona[i].cr;
          cx = corona[i].cx;
          cy = corona[i].cy;

          // draw path
          ctx.beginPath();
          ctx.fillStyle = "rgb(200, 0, 0)"
          ctx.moveTo(
            cx + cr * Math.cos(ca),
            cy + cr * Math.sin(ca)
          );

          // draw circle
          for (let j = 1; j < 180; j++) {
            ctx.lineTo(
              cx + cr * Math.cos(ca + j * Math.PI * 2 / 180),
              cy + cr * Math.sin(ca + j * Math.PI * 2 / 180)
            );
          }

          ctx.closePath();
          ctx.stroke();
          ctx.fill();

          // move particles
          corona[i].cx += corona[i].cxv;
          corona[i].cy += corona[i].cyv;

          // particle edge of screen
          if (corona[i].cx < 0 - corona[i].cr) {
            corona[i].cx = canvas.width + corona[i].cr;
          } else if (corona[i].cx > canvas.width + corona[i].cr) {
            corona[i].cx = 0 - corona[i].cr
          }
          if (corona[i].cy < 0 - corona[i].cr) {
            corona[i].cy = canvas.height + corona[i].cr;
          } else if (corona[i].cy > canvas.height + corona[i].cr) {
            corona[i].cy = 0 - corona[i].cr
          }
        }

        //(function loop(now) {



        //let t = (Math.min(now - prev, MAX_DELTA) / 1000);
        //prev = now;

        let dx = keys[RIGHT] - keys[LEFT];
        let dy = keys[DOWN] - keys[UP];

        x += dx * SPEED;
        y += dy * SPEED;

        let rx = mx - x;
        let ry = my - y;

        //ctx.fillStyle = '#fff';
        //ctx.fillRect(0, 0, canvas.width, canvas.height);

        ctx.save();
        ctx.translate(x, y);
        ctx.rotate(Math.atan2(ry, rx));
        ctx.drawImage(arrow, -arrow.width / 2, -arrow.height / 2);
        ctx.restore();

        //window.requestAnimationFrame(loop);
        //})(0);
      }

    })();
  </script>



</body>

</html>
Advertisement