67 lines
1.7 KiB
TypeScript
67 lines
1.7 KiB
TypeScript
import type { PlayerInfo } from "$/common/protocol.ts";
|
|
import { TICK_DELTA } from "$/common/constants.ts";
|
|
import type { ClientLevel } from "../level/client_level.ts";
|
|
import { Player } from "./player.ts";
|
|
|
|
const SMOOTHING = 12;
|
|
|
|
// another player on the server, it moves where the server says instead of simulating anything
|
|
export class RemotePlayer extends Player {
|
|
color: [number, number, number];
|
|
|
|
// where the server last said it is, the drawn position eases towards it so movement isn't choppy
|
|
target_x: number;
|
|
target_y: number;
|
|
target_z: number;
|
|
|
|
constructor(level: ClientLevel, info: PlayerInfo) {
|
|
super(level, info.id, info.name);
|
|
this.set_position(info.x, info.y, info.z);
|
|
this.target_x = info.x;
|
|
this.target_y = info.y;
|
|
this.target_z = info.z;
|
|
this.yaw = info.yaw;
|
|
this.pitch = info.pitch;
|
|
this.color = color_from_name(info.name);
|
|
}
|
|
|
|
lerp_to(x: number, y: number, z: number, yaw: number, pitch: number) {
|
|
this.target_x = x;
|
|
this.target_y = y;
|
|
this.target_z = z;
|
|
this.yaw = yaw;
|
|
this.pitch = pitch;
|
|
}
|
|
|
|
tick() {
|
|
const t = Math.min(1, TICK_DELTA * SMOOTHING);
|
|
this.x += (this.target_x - this.x) * t;
|
|
this.y += (this.target_y - this.y) * t;
|
|
this.z += (this.target_z - this.z) * t;
|
|
}
|
|
}
|
|
|
|
function color_from_name(name: string): [number, number, number] {
|
|
let hash = 0;
|
|
for (const ch of name) {
|
|
hash = (hash * 31 + ch.charCodeAt(0)) | 0;
|
|
}
|
|
const hue = ((hash % 360) + 360) % 360;
|
|
// hsl with s=0.6 l=0.6 to rgb
|
|
const c = 0.48;
|
|
const x = c * (1 - Math.abs(((hue / 60) % 2) - 1));
|
|
const m = 0.36;
|
|
const [r, g, b] = hue < 60
|
|
? [c, x, 0]
|
|
: hue < 120
|
|
? [x, c, 0]
|
|
: hue < 180
|
|
? [0, c, x]
|
|
: hue < 240
|
|
? [0, x, c]
|
|
: hue < 300
|
|
? [x, 0, c]
|
|
: [c, 0, x];
|
|
return [r + m, g + m, b + m];
|
|
}
|