所以,我只是做一个javascript画布游戏。我知道像Godot这样的游戏引擎,但它对我来说更像是一个挑战,这就是我选择javascript的原因。我做的第一件事就是给敌人编码。
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>
所以我创造了一个创造敌人的函数。如果我有一个敌人生成,一切工作正常。但如果我包含2个或更多敌人,那么它们的移动都是相同的,并且它们的移动是随机的。我想我知道我的代码中的问题是什么,但我不知道如何修复它。我认为问题在于,如果敌人1触及边界,x_add就会改变。但如果敌人2的函数被执行,它不会触及边界,但x_add变量仍然与敌人1中的变量相同。所以我如何为每个敌人创造变量,也许是一个敌人数组?或者,如果敌人没有触及边界,我应该发表另一份声明吗?但我怎么知道敌人之前是朝哪个方向去的呢?smb可以解释我如何修复它吗?thx
使用class
是最好的选择。class
允许您创建同一对象的多个实例,同时允许每个实例单独控制。
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>
有几件事要记住。在这个例子中,你需要将所有的对象放入一个数组中,并在animate函数的循环中绘制/更新它们。你也可以选择传递任何属性值,例如,你希望某些敌人具有特定的颜色。或者你可能希望每个敌人从一个特定的位置开始,然后将x和y值传递给构造函数。
我还建议使用canvas.width
和canvas.height
,而不是实际的数值大小。