ecs refactor

This commit is contained in:
Matthieu Jolimaitre 2024-04-09 04:25:34 +02:00
parent 28b026a614
commit f2e5d13000
8 changed files with 410 additions and 170 deletions

View file

@ -0,0 +1,6 @@
export class CompDisplay {
display;
constructor(display: string) {
this.display = display;
}
}

101
server/components/world.ts Normal file
View file

@ -0,0 +1,101 @@
import { spiral } from "../../common/utils.ts";
import { chunks, enumerate, log_from, Vec2 } from "../../common/utils.ts";
import { Engine, Entity, Query } from "../engine.ts";
import { CompDisplay } from "./display.ts";
const log = log_from(import.meta);
export class CompPos {
position;
entity;
constructor(entity: Entity, position: Vec2) {
this.position = position;
this.entity = entity;
}
move(displacement: Vec2) {
this.position = this.position.add(displacement);
}
move_collide(engine: Engine, displacement: Vec2) {
let result = false;
for (const step of displacement_steps(this.position, displacement)) {
const collider_exists = engine.query_one(query_at(step)) !== null;
if (collider_exists) return result;
this.position = step;
result = true;
}
return result;
}
}
function* displacement_steps(position: Vec2, displacement: Vec2) {
let pos = position;
let left = displacement;
while (left.len() >= 1) {
if (left.x() >= 1) {
pos = pos.add(new Vec2(1, 0));
left = left.sub(new Vec2(1, 0));
}
if (left.x() <= -1) {
pos = pos.add(new Vec2(-1, 0));
left = left.sub(new Vec2(-1, 0));
}
if (left.y() >= 1) {
pos = pos.add(new Vec2(0, 1));
left = left.sub(new Vec2(0, 1));
}
if (left.y() <= -1) {
pos = pos.add(new Vec2(0, -1));
left = left.sub(new Vec2(0, -1));
}
yield pos;
}
}
export function query_at(pos: Vec2) {
return Query.filter(CompPos, (c) => c.position.overlaps(pos));
}
export function query_in_rect(min: Vec2, max: Vec2) {
return Query.filter(CompPos, (c) => c.position.inside(min, max));
}
class CompStructure {}
export function sys_spawn_obstacle(pos: Vec2, display: string) {
return (engine: Engine) =>
engine.spawn((entity) =>
entity.insert(
new CompStructure(),
new CompDisplay(display),
new CompPos(entity, pos),
)
);
}
export async function sys_spawn_structure(file_path: string, origin: Vec2) {
const content = await Deno.readTextFile(file_path);
return (engine: Engine) => {
let count = 0;
for (const [y, line] of enumerate(content.split("\n"))) {
for (const [x, chars] of enumerate(chunks(line, 2))) {
const display = chars[0] + chars[1];
if (display === " ") continue;
engine.run(sys_spawn_obstacle(origin.add(new Vec2(x, y)), display));
count += 1;
}
}
log("Spawned", count, "tiles from", file_path);
};
}
export function sys_find_free_pos(target: Vec2) {
return (engine: Engine) => {
for (const pos of spiral(target)) {
const found = engine.query_one(query_at(pos));
if (found === null) return pos;
}
throw new Error("Unreachable.");
};
}