gibbon.js
Version:
Actor/Component system for use with pixi.js.
104 lines (74 loc) • 2.56 kB
text/typescript
import { Component } from '../core/component';
import type { IPoint, TPoint } from '../data/geom';
import { clampToPi } from '../utils/geom';
/**
* Linearly interpolate Actor between current
* position and target position
* over a period of time.
*/
export class LerpPos extends Component {
/**
* Time to reach target point in seconds.
* This may be an expected lag time from server.
*/
lerpTime: number = 0.300;
private target: TPoint = { x: 0, y: 0 };
private targetAngle?: number = 0;
/**
* Time spent on current interpolation.
*/
private deltaTime: number = 0;
private lerping: boolean = false;
setDest(target?: IPoint, angle?: number, time?: number) {
if (target) {
if (time) {
this.lerpTime = time;
}
this.targetAngle = angle;
this.target.x = target.x;
this.target.y = target.y;
this.lerping = true;
this.deltaTime = 0;
} else {
this.lerping = false;
}
}
/**
* Add an expected motion to the target.
* This is useful when the local simulation is behind
* a server, but the server point is expected to continue
* moving with a velocity or angular velocity.
* @param pt
* @param angle
*/
addDelta(pt: IPoint, angle?: number) {
this.target.x += pt.x;
this.target.y += pt.y;
if (this.targetAngle && angle) {
this.targetAngle += angle;
}
}
override update(deltaS: number) {
if (this.lerping && this.target != null) {
this.deltaTime += deltaS;
const t = this.deltaTime / this.lerpTime;
if (t >= 1) {
this.position.x = this.target.x;
this.position.y = this.target.y;
if (this.targetAngle) {
this.rotation = this.targetAngle;
}
this.lerping = false;
} else {
if (this.targetAngle) {
let dAngle = clampToPi(this.targetAngle - this.rotation);
this.rotation = t * dAngle + this.rotation;
}
this.position.set(
(1 - t) * this.position.x + t * this.target.x,
(1 - t) * this.position.y + t * this.target.y
);
}
}
}
}