ecs refactor
This commit is contained in:
parent
28b026a614
commit
f2e5d13000
8 changed files with 410 additions and 170 deletions
|
@ -1,21 +1,32 @@
|
|||
import { mts } from "../../common/mod.ts";
|
||||
import { log_from, Vec2 } from "../../common/utils.ts";
|
||||
import { World, WorldEntity } from "../engine.ts";
|
||||
import { range } from "../../common/utils.ts";
|
||||
import { log_from, v2, Vec2 } from "../../common/utils.ts";
|
||||
import { CompDisplay } from "../components/display.ts";
|
||||
import { sys_find_free_pos } from "../components/world.ts";
|
||||
import { CompPos, query_in_rect } from "../components/world.ts";
|
||||
import { Engine, Entity } from "../engine.ts";
|
||||
import { ClientInterface } from "../network.ts";
|
||||
const log = log_from(import.meta);
|
||||
|
||||
export class Session {
|
||||
client;
|
||||
world;
|
||||
player_entity;
|
||||
engine;
|
||||
entity;
|
||||
|
||||
constructor(client: ClientInterface, world: World, player_entity: WorldEntity) {
|
||||
constructor(client: ClientInterface, engine: Engine, entity: Entity) {
|
||||
this.client = client;
|
||||
this.world = world;
|
||||
this.player_entity = player_entity;
|
||||
this.engine = engine;
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
async spin() {
|
||||
static init(client: ClientInterface, engine: Engine) {
|
||||
const spawn_pos = engine.run(sys_find_free_pos(v2(0, 0)));
|
||||
const entity = engine.run(sys_spawn_player(spawn_pos));
|
||||
const self = new Session(client, engine, entity);
|
||||
return self;
|
||||
}
|
||||
|
||||
async start() {
|
||||
try {
|
||||
for await (const input of this.client.inputs.iter()) {
|
||||
if (input.kind !== "request_display") log("Received", input);
|
||||
|
@ -23,39 +34,61 @@ export class Session {
|
|||
if (input.kind === "ping") this.client.outputs.send({ kind: "ping_response", content: input.content });
|
||||
if (input.kind === "request_display") this.send_display(input.content.width, input.content.height);
|
||||
if (input.kind === "input") this.handle_input(input);
|
||||
if (input.kind === "exit") this.world.kill(this.player_entity.identifier);
|
||||
if (input.kind === "exit") this.engine.delete(this.entity.identifier);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Session loop failed, ", error);
|
||||
this.world.kill(this.player_entity.identifier);
|
||||
this.engine.delete(this.entity.identifier);
|
||||
}
|
||||
}
|
||||
|
||||
handle_input(input: mts.MsgInput) {
|
||||
if (input.content.control === "up") this.move(v2(0, 1));
|
||||
if (input.content.control === "down") this.move(v2(0, -1));
|
||||
if (input.content.control === "left") this.move(v2(-1, 0));
|
||||
if (input.content.control === "right") this.move(v2(1, 0));
|
||||
}
|
||||
|
||||
send_display(width: number, height: number) {
|
||||
const raw = this.world.render(this.player_entity.position, new Vec2(width, height));
|
||||
const raw = this.engine.run(sys_render_world(this.entity.get_force(CompPos).position, v2(width, height)));
|
||||
this.client.outputs.send({ kind: "display", content: { raw } });
|
||||
}
|
||||
|
||||
handle_input(input: mts.MsgInput) {
|
||||
if (input.content.control === "up") this.world.move_collide(this.player_entity.identifier, new Vec2(0, 1));
|
||||
if (input.content.control === "down") this.world.move_collide(this.player_entity.identifier, new Vec2(0, -1));
|
||||
if (input.content.control === "left") this.world.move_collide(this.player_entity.identifier, new Vec2(-1, 0));
|
||||
if (input.content.control === "right") this.world.move_collide(this.player_entity.identifier, new Vec2(1, 0));
|
||||
}
|
||||
}
|
||||
|
||||
export class PlayerComponent {
|
||||
entity;
|
||||
|
||||
constructor(entity: WorldEntity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
move(direction: Vec2) {
|
||||
return this.entity.world.move_collide(this.entity.identifier, direction);
|
||||
}
|
||||
|
||||
render(res: Vec2) {
|
||||
return this.entity.world.render(this.entity.position, res);
|
||||
const pos = this.entity.get_force(CompPos);
|
||||
pos.move_collide(this.engine, direction);
|
||||
}
|
||||
}
|
||||
|
||||
export function sys_render_world(center: Vec2, size: Vec2) {
|
||||
return (engine: Engine) => {
|
||||
const radius = size.scale(0.5);
|
||||
const result = Array.from(range(0, size.y())).map(() => Array.from(range(0, size.x())).map(() => " "));
|
||||
const min = center.sub(radius);
|
||||
const max = center.add(radius);
|
||||
for (const entity of engine.query_all(query_in_rect(min, max).with(CompDisplay))) {
|
||||
const local_pos = entity.get_force(CompPos).position.sub(min);
|
||||
result[local_pos.y()][local_pos.x()] = entity.get_force(CompDisplay).display;
|
||||
}
|
||||
return result.map((line) => line.join("")).toReversed().join("\n");
|
||||
};
|
||||
}
|
||||
|
||||
export function sys_spawn_player(position: Vec2) {
|
||||
return (engine: Engine) => {
|
||||
return engine.spawn((entity) =>
|
||||
entity.insert(
|
||||
new CompPlayer(),
|
||||
new CompPos(entity, position),
|
||||
new CompDisplay("`/"),
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
class CompPlayer {
|
||||
life;
|
||||
constructor() {
|
||||
this.life = 10;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue