So, i am just making a javascript canvas only game. I know game engines like Godot but its just more like a challenge for me, thats why i choose javascript. The first thing i did was coding the enemies.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var x = 0;
var y = 0;
var x_add = 2;
var y_add = 2;
animate();
function animate(){
draw();
setTimeout(animate, 10);
};
function draw(){
ctx.clearRect(0,0,1500, 500);
//draw_enemy(0, 0, "green", 30, 30);
draw_enemy(900, 100, "red", 40, 50);
};
function draw_enemy(start_x, start_y, fill, w, h){
if(x w start_x == 1000){
x_add = -2;
}
if(y h start_y == 500){
y_add = -2;
}
if(y start_y == 0){
y_add = 2;
}
if(x start_x == 0){
x_add = 2;
}
x = x_add;
y = y_add;
ctx.fillStyle = fill;
ctx.fillRect(x start_x, y start_y, w, h);
};
<!DOCTYPE html>
<html>
<head>
<title>local storage test</title>
<style>
</style>
</head>
<body>
<div style="text-align: center">
<canvas id="canvas" width="1000" height="500" style="border: 1px solid black; padding: 5 px">
</canvas>
</div>
<script src="script.js">
</script>
</body>
</html>
So i made a function for creating enemies. If i have one enemy spawned, everything works fine. But if i include 2 or more enemies, They all move the same and their movement is random. I think i know what the problem in my code is but i dont know how to do fix it. I think that the problem is, that if enemy 1 touches the border, x_add changes. But if then the function for enemy 2 is executed, it doesnt touches the border, but still, the x_add var is the same like the variable from enemy 1. So how can i make variables for every enemy, maybe with an enemy array? Or should i make an else statement, if the enemy doesnt touch the border? But then how i know in which direction the enemy was going before? Can smb explain how i can fix it? thx
CodePudding user response:
Using a class
for this is the best option. A class
allows you to create multiple instances of the same object while allowing each instance to be individually controlled.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
let enemies = [];
class Enemy {
constructor(c) {
this.x = 50 Math.random() * canvas.width;
this.y = 50 Math.random() * canvas.height;
this.w = 40;
this.h = 50;
this.c = c;
this.vx = 2;
this.vy = 2;
}
draw() {
ctx.fillStyle = this.c;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
update() {
if (this.x this.w >= canvas.width) {
this.vx = -2;
}
if (this.y this.h >= canvas.height) {
this.vy = -2;
}
if (this.y <= 0) {
this.vy = 2;
}
if (this.x <= 0) {
this.vx = 2;
}
this.x = this.vx;
this.y = this.vy;
this.draw()
}
}
function createEnemies() {
for (let i=0; i < 5; i ) {
enemies.push(new Enemy('red'))
}
}
createEnemies()
enemies.push(new Enemy('green'))
enemies.push(new Enemy('blue'))
/*
There may be times where you want to pass in specific values for the properties for each individual enemy. i.e. color, x, y, health, defense, etc
*/
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
enemies.forEach(e => e.update())
}
/*
forEach is the same as saying...
for (let i = 0; i < enemies.length; i ) {
enemies[i].update()
}
...but shorter and cleaner
*/
function animate() {
draw();
setTimeout(animate, 10);
}
animate()
//suggest using requestAnimationFrame() instead of setTimeout
<canvas id="canvas" width="1000" height="500" style="border: 1px solid black; padding: 5 px">
</canvas>
A couple things to keep in mind. For this example you will want to push all of your objects to an array and draw/update them in a loop in the animate function. You can also choose to pass in any of the property values i.e. you want certain enemies to have a specific color. Or maybe you want each enemy to start at a specific location then pass the x and y value to the constructor.
I also recommend using canvas.width
and canvas.height
over the actual numerical size.