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>