No more ecs
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import type { ClientLevel } from "../level/client_level.ts";
|
||||
|
||||
// anything that exists in the level and moves, like minecraft's Entity. position is the middle of its feet
|
||||
export abstract class Entity {
|
||||
id: string;
|
||||
level: ClientLevel;
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
// blocks per second
|
||||
vx = 0;
|
||||
vy = 0;
|
||||
vz = 0;
|
||||
yaw = 0;
|
||||
pitch = 0;
|
||||
|
||||
// the collision box, width is used for both x and z
|
||||
width: number;
|
||||
height: number;
|
||||
eye_height: number;
|
||||
gravity = -15.8;
|
||||
|
||||
// which way it hit something on each axis in the last move: 1 or -1, 0 for nothing.
|
||||
// 1 on y means it's standing on something
|
||||
colliding_x = 0;
|
||||
colliding_y = 0;
|
||||
colliding_z = 0;
|
||||
|
||||
constructor(level: ClientLevel, id: string, width: number, height: number, eye_height: number) {
|
||||
this.level = level;
|
||||
this.id = id;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.eye_height = eye_height;
|
||||
}
|
||||
|
||||
get on_ground() {
|
||||
return this.colliding_y === 1;
|
||||
}
|
||||
|
||||
set_position(x: number, y: number, z: number) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
abstract tick(delta: number): void;
|
||||
|
||||
// falls and moves by its velocity, stopping on each axis it would run into a block on
|
||||
move(delta: number) {
|
||||
this.vy += this.gravity * delta;
|
||||
|
||||
this.colliding_x = this.vx !== 0 && this.#collides(this.x + this.vx * delta, this.y, this.z)
|
||||
? -Math.sign(this.vx)
|
||||
: 0;
|
||||
if (this.colliding_x !== 0) {
|
||||
this.vx = 0;
|
||||
}
|
||||
|
||||
this.colliding_y = this.vy !== 0 && this.#collides(this.x, this.y + this.vy * delta, this.z)
|
||||
? -Math.sign(this.vy)
|
||||
: 0;
|
||||
if (this.colliding_y !== 0) {
|
||||
this.vy = 0;
|
||||
}
|
||||
|
||||
this.colliding_z = this.vz !== 0 && this.#collides(this.x, this.y, this.z + this.vz * delta)
|
||||
? -Math.sign(this.vz)
|
||||
: 0;
|
||||
if (this.colliding_z !== 0) {
|
||||
this.vz = 0;
|
||||
}
|
||||
|
||||
this.x += this.vx * delta;
|
||||
this.y += this.vy * delta;
|
||||
this.z += this.vz * delta;
|
||||
}
|
||||
|
||||
// whether the collision box at x/y/z overlaps any block, unloaded chunks included
|
||||
#collides(x: number, y: number, z: number) {
|
||||
const min_x = Math.floor(x - this.width / 2);
|
||||
const max_x = Math.floor(x + this.width / 2);
|
||||
const min_y = Math.floor(y);
|
||||
const max_y = Math.floor(y + this.height);
|
||||
const min_z = Math.floor(z - this.width / 2);
|
||||
const max_z = Math.floor(z + this.width / 2);
|
||||
|
||||
for (let bx = min_x; bx <= max_x; bx++) {
|
||||
for (let by = min_y; by <= max_y; by++) {
|
||||
for (let bz = min_z; bz <= max_z; bz++) {
|
||||
if (this.level.get_block(bx, by, bz)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user