d3/server/entities/enemy.ts
2024-04-10 03:15:15 +02:00

64 lines
1.9 KiB
TypeScript

import { assert } from "https://deno.land/std@0.221.0/assert/assert.ts";
import { v2 } from "../../common/utils.ts";
import { Vec2 } from "../../common/utils.ts";
import { CompDisplay } from "../components/display.ts";
import { query_in_rect } from "../components/world.ts";
import { CompPos } from "../components/world.ts";
import { CompId, Query } from "../engine.ts";
import { Engine } from "../engine.ts";
import { CompPlayer } from "./player.ts";
export class CompEnemy {
target;
life;
constructor() {
this.target = null as number | null;
this.life = 10;
}
get_target_pos(engine: Engine) {
if (this.target === null) return null;
const result = engine.one(Query.with(CompId).filter(([c]) => c.id === this.target).with(CompPos));
if (result === null) return null;
const [_, pos] = result;
return pos.pos;
}
find_target_from(engine: Engine, pos: Vec2) {
const RANGE = v2(2, 2);
const found = engine.one(Query.with(CompPlayer).with(CompId).and(query_in_rect(pos.sub(RANGE), pos.add(RANGE))));
if (found === null) return this.target = null;
const [_, id, __] = found;
return this.target = id.id;
}
}
export function sys_spawn_enemy(pos: Vec2) {
return (engine: Engine) => {
return engine.spawn((entity) =>
entity.insert(
new CompEnemy(),
new CompPos(entity, pos),
new CompDisplay("èé"),
)
);
};
}
export function sys_update_enemy() {
return (engine: Engine) => {
for (const [enemy, enemy_pos] of engine.all(Query.with(CompEnemy).with(CompPos))) {
if (enemy.target === null) enemy.find_target_from(engine, enemy_pos.pos);
if (enemy.target === null) continue;
const pos = enemy.get_target_pos(engine);
assert(pos !== null);
const direction = pos.sub(enemy_pos.pos);
enemy_pos.move_collide(engine, direction.normalize());
}
};
}
export function enemy_plugin(engine: Engine) {
engine.global_system_loop(sys_update_enemy(), 500);
}