Initial commit

This commit is contained in:
2026-02-24 15:36:10 -03:00
commit fe885a9e24
42 changed files with 2383 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
import { Component } from "$/common/ecs/component.ts";
export class Position extends Component {
x: number;
y: number;
constructor(x: number, y: number) {
super();
this.x = x;
this.y = y;
}
}
+12
View File
@@ -0,0 +1,12 @@
import { Component } from "$/common/ecs/component.ts";
export class Velocity extends Component {
vx: number;
vy: number;
constructor(vx: number, vy: number) {
super();
this.vx = vx;
this.vy = vy;
}
}
+11
View File
@@ -0,0 +1,11 @@
export const SLOT_SIZE = 18 * 3;
export interface SpriteRegion {
x: number;
y: number;
}
export const ITEM_SPRITES: Record<string, SpriteRegion> = {
"bworld:pickaxe": { x: 7, y: 9 },
"bworld:bomb": { x: 9, y: 8 },
};
+3
View File
@@ -0,0 +1,3 @@
export abstract class Component {
__component = true;
}
+28
View File
@@ -0,0 +1,28 @@
import type { Component } from "./component.ts";
// deno-lint-ignore no-explicit-any
type ComponentConstructor<T extends Component> = new (...args: any[]) => T;
export class Entity {
id: string;
// deno-lint-ignore no-explicit-any
components = new Map<ComponentConstructor<any>, Component>();
active = true;
constructor(id: string = crypto.randomUUID()) {
this.id = id;
}
add<T extends Component>(component: T): T {
this.components.set(component.constructor as ComponentConstructor<T>, component);
return component;
}
get<T extends Component>(type: ComponentConstructor<T>): T | undefined {
return this.components.get(type) as T;
}
get_all(): Iterable<Component> {
return this.components.values();
}
}
+4
View File
@@ -0,0 +1,4 @@
export * from "./component.ts";
export * from "./entity.ts";
export * from "./system.ts";
export * from "./world.ts";
+5
View File
@@ -0,0 +1,5 @@
import type { World } from "./world.ts";
export abstract class System {
abstract update(world: World, delta: number): void;
}
+34
View File
@@ -0,0 +1,34 @@
import type { Entity } from "./entity.ts";
import type { System } from "./system.ts";
export class World {
entities = new Set<Entity>();
systems = new Set<System>();
tags = new Map<string, Entity[]>();
add_entity(entity: Entity) {
this.entities.add(entity);
}
add_system(system: System) {
this.systems.add(system);
}
add_tag(tag: string, entities: Entity[]) {
this.tags.set(tag, entities);
}
get_tag(tag: string) {
return this.tags.get(tag);
}
update(delta: number) {
for (const system of this.systems) {
system.update(this, delta);
}
}
get_entities() {
return this.entities;
}
}
+19
View File
@@ -0,0 +1,19 @@
import { System, World } from "$/common/ecs/mod.ts";
import { Position } from "$/common/components/position.ts";
import { Velocity } from "$/common/components/velocity.ts";
export class MovementSystem extends System {
update(world: World, delta: number): void {
for (const entity of world.get_entities()) {
const position = entity.get(Position);
const velocity = entity.get(Velocity);
if (position && velocity) {
position.x += velocity.vx * delta;
position.y += velocity.vy * delta;
position.x = Math.round(position.x);
position.y = Math.round(position.y);
}
}
}
}
+19
View File
@@ -0,0 +1,19 @@
import { ITEM_SPRITES, SpriteRegion } from "./constants.ts";
export function point_inside_rec(
point_x: number,
point_y: number,
rec_x: number,
rec_y: number,
rec_w: number,
rec_h: number,
) {
return point_x > rec_x &&
point_x < rec_x + rec_w &&
point_y > rec_y &&
point_y < rec_y + rec_h;
}
export function get_sprite_region(id: string): SpriteRegion {
return ITEM_SPRITES[id] ?? { x: 0, y: 0 };
}