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>