Hi,
I want some NPCs to follow the player with a delay of x seconds. I’m using a queue of positions and times. I can’t get the delay to work: now followers move at the exact same position as the player, instead of moving x seconds behind.
Thanks!
update(time,delta) {
let isPlayerMoving = this.player.body.velocity.x != 0 || this.player.body.velocity.y != 0;
if(isPlayerMoving) {
//add the player's current position at time now
this.queue.add(time, this.player.body.position);
//if the player met the follower
if(this.follower.canFollow) {
//remove all positions older than the time of the position we want to follow
while(this.queue.getFirst().time < (time - this.followerDelay)){
this.queue.remove();
}
//pass to the follower the first position that hasn't been removed
let pos = this.queue.getFirst().position;
this.follower.move(pos.x, pos.y);
}
}
This is the Queue class
class TimePositionData {
constructor(time, position) {
this.time = time;
this.position = position;
}
}
export default class Queue {
constructor() {
this.elements = [];
}
//add an element at the end of the queue
add(time, position) {
let data = new TimePositionData(time, position);
this.elements.push(data);
}
// remove an element from the beginning of the queue
remove() {
return this.elements.shift();
}
//get the element at the beginning of the queue
getFirst() {
return !this.isEmpty() ? this.elements[0] : undefined;
}
So every follower deletes all the player data up to its own delay? That seems wrong… As soon as there are multiple followers, some won’t be getting data.
Try to visualize the queue (on screen).
I started working on one follower first (and that’s the code I posted) but your are right, other followers would not get any data.
So I modified my script to include more followers, and they all follow now but irregularly and not taking in account the delay at all times. So any suggestion would be appreciated, thanks!
let isPlayerMoving = this.player.body.velocity.x != 0 || this.player.body.velocity.y != 0;
if(isPlayerMoving) {
//add the player's current position at time now
this.queue.add(time, this.player.body.position);
for (var i = 0; i < this.followers.getChildren().length; i++) {
let follower = this.followers.getChildren()[i];
//if a follower exists and has met the player
if(follower && follower.canFollow) {
let positionData = this.queue.getAtTime(time - this.followersDelay * (i+1));
if(positionData) follower.move(positionData.x,positionData.y);
}
}
}
Here’s a new function in the Queue class
getAtTime(time) {
if (!this.isEmpty()) {
for (var i = 0; i < this.getLength(); i++) {
if (Phaser.Math.CeilTo(this.elements[i].time,0) === Phaser.Math.CeilTo(time,0)) {
return this.elements[i].position;
}
}
}
}
This seems incredibly expensive. I wouldn’t be surprised if your CPU is boiling
Obviously you need a better lookup system than a for loop…
I seem to recall we did this before, that didn’t work?
Personally, I would just adapt the numbers. Get the fps, divide it by 60 and use that as multiplier.
With your timestamp method you’ll need to use a timer (an increasing value) not ‘time’ itself. Then you can store it with timer as key, and have instant lookup. Obviously this number will grow fast, so it will have to reset after a while…