Reputation: 16045
I'm creating a small game using Konva.
You control a single unit which can move around in a map and the "camera" is panned to it. I've achieved this effect by centering the screen on the x, y coordinates of the unit and then drawing everything else relative to that:
class GameWorld {
public entities = new Map();
public width = window.innerWidth;
public height = window.innerHeight;
public center = {
x: 0,
y: 0
};
tick(world: any) {
world.forEach((entity: any) => {
...
if (entity.id === user.id) {
// this is the user's unit
this.center.x = entity.x;
this.center.y = entity.y;
}
...
let dx = this.dx(entity.x);
let dy = this.dy(entity.y);
entity.shape.position({ x: dx, y: dy });
...
});
this.layer.draw();
}
dx(x: number) {
return x - this.center.x + this.width / 2;
}
dy(y: number) {
return y - this.center.y + this.height / 2;
}
}
Currently what I'm having trouble with is a simple blood splatter effect, which works by creating 5 "large" red circles and 15 small ones scattered at random directions and distances around a dying unit (not the player unit) at different speeds.
let bloodDot = (x: number, y: number, size: number) => {
let dx = this.dx(x);
let dy = this.dy(y);
let dot = new Konva.Circle({
x: dx,
y: dy,
radius: size,
fill: 'red',
});
this.layer.add(dot);
let dir = Math.random() * Math.PI * 2;
let dis = Math.random() * size * 5;
dot.to({
x: dx + Math.cos(dir) * dis,
y: dy + Math.sin(dir) * dis,
duration: Math.random() * 3,
easing: Konva.Easings.StrongEaseOut,
onFinish: () => dot.destroy()
});
}
for (let lg = 0; lg < 5; lg++) {
for (let sm = 0; sm < 3; sm++) {
bloodDot(entity.x, entity.y, entity.size / 6);
}
bloodDot(entity.x, entity.y, entity.size / 3);
}
The problem comes with using the .to()
method. It all works well if the player is stationary, but if the player is moving, and thus everything else, including the blood, should be moving relative to them, the x and y used in the .to
remain the ones that were at the time of creating the blood dots and it seems as if the blood is following the player or rather stuck on the same place on the screen, while everything else is relatively moving.
How can I dynamically change properties (coordinates) of the tween while Konva is still animating?
Upvotes: 1
Views: 520
Reputation: 16045
Well this is not a direct answer to the question asked but it is a solution to the problem so here it goes.
I did not find a way to modify a tween's properties while it's animating, but I found that I can group the dots, which will then animate relative to the group, and I'll have to draw the group on the derived x,y which is easy.
let bloodDot = (size: number) => {
let dot = new Konva.Circle({
x: 0,
y: 0,
radius: size,
fill: 'red',
});
let dir = Math.random() * Math.PI * 2;
let dis = Math.random() * size * 5;
g.add(dot);
dot.to({
x: Math.cos(dir) * dis,
y: Math.sin(dir) * dis,
duration: Math.random() * 3,
easing: Konva.Easings.StrongEaseOut,
onFinish: () => dot.destroy()
});
}
let g = new Konva.Group({
x: this.dx(entity.x),
y: this.dy(entity.y)
});
this.layer.add(g);
for (let lg = 0; lg < 5; lg++) {
for (let sm = 0; sm < 3; sm++) {
bloodDot(entity.size / 6);
}
bloodDot(entity.size / 3);
}
setTimeout(() => g.destroy(), 3000);
Upvotes: 1