我目前正在尝试创建一个 2d 游戏,其中“僵尸”追逐玩家,场景在 p5j 中四处移动。我的问题是僵尸直线前往点 (0,0),然后绕着它旋转,有效地停留在那里。
我创建了一个测试项目,其中僵尸跟随鼠标。它使用几乎相同的代码,但我不知道有什么区别。
这是使用我原始项目中的一些代码的堆栈片段。如果有人能帮助我解决这个错误,那就太好了。它包含相同的错误。与僵尸相关的代码位于 ZombieHandler 类下
winX = 666
winY = 400
//If you are looking through this for the issue go down to the class ZombieHandler
function setup() {
createCanvas(winX, winY);
background(150);
angleMode(DEGREES)
rectMode(CENTER)
}
class User {
constructor(x, y, rotation, speed, rotspeed) {
this.posX = x;
this.posY = y;
this.rotation = rotation;
this.speed = speed;
this.size = 30;
this.rotspeed = 0;
}
render() {
translate(winX / 2, winY / 2);
rotate(this.rotation);
translate(-winX / 2, -winY / 2);
fill(70);
rect(winX / 2 + this.size / 2, winY / 2, this.size, this.size / 2, 5, 5, 5, 5);
fill(0);
rect(winX / 2, winY / 2, this.size, this.size, 5, 5, 5, 5);
translate(winX / 2, winY / 2);
rotate(-this.rotation);
translate(-winX / 2, -winY / 2);
}
control(cameraX, cameraY) {
this.rotation += this.rotspeed;
let pos = createVector(this.speed, 0)
pos.rotate(this.rotation)
console.log("Player.posX: " + this.posX.toString())
console.log("Player.posY: " + this.posY.toString())
//set x to left if past right, and vice versa
//update pos
if (this.posX - pos.x < 2295 && this.posX - pos.x > -1630) {
this.posX -= pos.x;
cameraX -= pos.x;
}
if (this.posY - pos.y < 860 && this.posY - pos.y > -1065) {
this.posY -= pos.y;
cameraY -= pos.y
}
//speed decay
this.speed *= 0.91;
if (this.speed < 0.5 && this.speed > 0 || this.speed > 0.5 && this.speed < 0) {
this.speed = 0;
}
//rot decay
this.rotspeed *= 0.95;
if (this.rotspeed > 0) {
this.rotspeed -= 0.5
} else if (this.rotspeed < 0) {
this.rotspeed += 0.5
}
return [cameraX, cameraY]
}
}
class ZombieHandler {
constructor(list) {
this.list = list;
}
render(Player) {
//zombie list format [[x,y,speed],[x,y,speed]]
this.list.forEach(zombie => {
var x = zombie[0] - Player.posX;
var y = zombie[1] - Player.posY;
var hyp = Math.hypot(x, y)
var point = Math.acos(x / hyp) * (180 / Math.PI)
fill(0)
rect(zombie[0] + Player.posX + winX / 2, zombie[1] + Player.posY + winY / 2, 30, 30, 5, 5, 5, 5)
});
}
control(Player) {
for (let i = 0; i < this.list.length; i++) {
let angle = Math.atan2(Player.posY - this.list[i][1], Player.posX - this.list[i][0]);
if (angle < 0) {
angle += Math.PI * 2
}
// at this point the zombie is attempting to rotate between angles 145 and -35 around 0, leaving it trapped in a loop
this.list[i][0] += this.list[i][2] * Math.cos(angle);
this.list[i][1] += this.list[i][2] * Math.sin(angle);
}
}
}
Player = new User(50, 50, 0, 0, 0)
Zombie = new ZombieHandler([])
var inputchecker = [0, 0, 0, 0, 0];
var tick = 0
var zombie_timer = 0
var cameraX = 0
var cameraY = 0
function draw() {
background(150)
noStroke()
//Input Handler
document.onkeydown = (e) => { //inputlist input checker
e = e || window.event;
if (e.key === "ArrowUp") {
inputchecker[0] = 1;
} else if (e.key === "ArrowLeft") {
inputchecker[1] = 1;
} else if (e.key === "ArrowRight") {
inputchecker[2] = 1;
} else if (e.key === "ArrowDown") {
inputchecker[3] = 1;
}
};
document.onkeyup = (e) => { //inputlist input checker
e = e || window.event;
if (e.key === "ArrowUp") {
inputchecker[0] = 0;
} else if (e.key === "ArrowLeft") {
inputchecker[1] = 0;
} else if (e.key === "ArrowRight") {
inputchecker[2] = 0;
} else if (e.key === "ArrowDown") {
inputchecker[3] = 0;
}
};
if (tick == 4) {
if (inputchecker[0] == 1) {
Player.speed += 3
} else if (inputchecker[3] == 1) {
Player.speed -= 2
}
if (inputchecker[1] == 1) {
Player.rotspeed -= 2.5;
} else if (inputchecker[2] == 1) {
Player.rotspeed += 2.5;
}
tick = 0
};
//Function Call
var camera = Player.control(cameraX, cameraY)
cameraX = parseInt(camera[0])
cameraY = parseInt(camera[1])
if (zombie_timer == 50) {
//add zombie creation code here
//distance 1000
//create a 0-359 random number generator for angle
//zombie list format [[x,y,speed],[x,y,speed]]
let pos = createVector(200, 0)
pos.rotate(Math.floor(Math.random() * 360))
Zombie.list.push([cameraX + pos.x, cameraY + pos.y, 3])
}
Zombie.control(Player)
Player.render()
Zombie.render(Player)
zombie_timer += 1;
tick += 1;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js"></script>
我认为这个错误存在于渲染/显示代码中,而不是
control(...)
函数将僵尸移向玩家。
再看看您的
rect(...)
来电 ZombieHandler.render(Player)
;我认为您错误地将僵尸坐标添加到玩家的坐标中,而不是计算它们之间的差异。
这个 codepen 做了一个小调整,它似乎让僵尸向玩家移动:https://codepen.io/lecrte/pen/PoVmrzV?editors=0010
另外,您可能想研究一下聚集代码,例如:https://p5js.org/examples/simulate-flocking.html ...这样僵尸就不会堆叠在一起。
您可以将这些
document.onkeydown
和 document.onkeyup
移到您的 draw() 函数之外,因为它们只需要设置一次;每帧设置关键侦听器的额外开销很小。 (有 https://p5js.org/reference/#/p5/keyPressed 和类似的 keyReleased 您可以查看)
编码快乐!