refactor spawners

This commit is contained in:
Elizabeth Hunt 2024-03-05 22:00:04 -07:00
parent 110fe21a23
commit ce06fa7c29
Signed by: simponic
GPG Key ID: 52B3774857EB24B1
14 changed files with 138 additions and 72 deletions

View File

@ -2,7 +2,6 @@ import { Game } from ".";
import { Miscellaneous, loadAssets } from "./config"; import { Miscellaneous, loadAssets } from "./config";
import { import {
Player, Player,
FunctionBox,
Wall, Wall,
LambdaFactory, LambdaFactory,
Key, Key,
@ -14,8 +13,8 @@ import {
FacingDirection, FacingDirection,
Input, Input,
Render, Render,
LambdaFactory as LambdaFactorySpawnSystem,
Collision, Collision,
GridSpawner,
} from "./systems"; } from "./systems";
export class TheAbstractionEngine { export class TheAbstractionEngine {
@ -47,7 +46,7 @@ export class TheAbstractionEngine {
height: Miscellaneous.GRID_CELL_HEIGHT, height: Miscellaneous.GRID_CELL_HEIGHT,
}, },
), ),
new LambdaFactorySpawnSystem(), new GridSpawner(),
new Collision(), new Collision(),
new Render(this.ctx), new Render(this.ctx),
].forEach((system) => this.game.addSystem(system)); ].forEach((system) => this.game.addSystem(system));

View File

@ -8,6 +8,7 @@ export namespace ComponentNames {
export const Interactable = "Interactable"; export const Interactable = "Interactable";
export const Pushable = "Pushable"; export const Pushable = "Pushable";
export const Colliding = "Colliding"; export const Colliding = "Colliding";
export const LambdaSpawn = "LambdaSpawn"; export const GridSpawn = "GridSpawn";
export const Text = "Text"; export const Text = "Text";
export const LambdaTerm = "LambdaTerm";
} }

View File

@ -0,0 +1,30 @@
import { Component, ComponentNames } from ".";
import { Entity } from "../entities";
import { Direction } from "../interfaces";
export class GridSpawn extends Component {
public direction: Direction;
public spawnsLeft: number;
public spawner: () => Entity;
constructor(
spawnsLeft: number,
spawner: () => Entity,
direction = Direction.NONE,
) {
super(ComponentNames.GridSpawn);
this.spawnsLeft = spawnsLeft;
this.direction = direction;
this.spawner = spawner;
}
public spawnEntity(direction: Direction): Entity | undefined {
if (this.spawnsLeft === 0) {
return;
}
this.direction = direction;
this.spawnsLeft -= 1;
}
}

View File

@ -1,29 +0,0 @@
import { Component, ComponentNames } from ".";
import { Direction } from "../interfaces";
export class LambdaSpawn extends Component {
public direction: Direction | null;
public spawnsLeft: number;
public code: string = "";
constructor(
spawnsLeft: number,
code: string,
direction: Direction | null = null,
) {
super(ComponentNames.LambdaSpawn);
this.spawnsLeft = spawnsLeft;
this.direction = direction;
this.code = code;
}
public spawn(direction: Direction) {
if (this.spawnsLeft <= 0) {
return;
}
this.direction = direction;
this.spawnsLeft -= 1;
}
}

View File

@ -0,0 +1,11 @@
import { Component, ComponentNames } from ".";
export class LambdaTerm extends Component {
public code: string;
constructor(code: string) {
super(ComponentNames.LambdaTerm);
this.code = code;
}
}

View File

@ -9,5 +9,6 @@ export * from "./Highlight";
export * from "./Interactable"; export * from "./Interactable";
export * from "./Pushable"; export * from "./Pushable";
export * from "./Colliding"; export * from "./Colliding";
export * from "./LambdaSpawn"; export * from "./GridSpawn";
export * from "./Text"; export * from "./Text";
export * from "./LambdaTerm";

View File

@ -6,4 +6,5 @@ export namespace EntityNames {
export const Key = "Key"; export const Key = "Key";
export const LockedDoor = "LockedDoor"; export const LockedDoor = "LockedDoor";
export const Curry = "Curry"; export const Curry = "Curry";
export const FunctionApplication = "FunctionApplication";
} }

View File

@ -0,0 +1,7 @@
import { Entity, EntityNames } from ".";
export class FunctionApplication extends Entity {
constructor() {
super(EntityNames.FunctionApplication);
}
}

View File

@ -12,6 +12,7 @@ import {
Grid, Grid,
Highlight, Highlight,
Interactable, Interactable,
LambdaTerm,
Pushable, Pushable,
Sprite, Sprite,
} from "../components"; } from "../components";
@ -23,13 +24,9 @@ export class FunctionBox extends Entity {
Sprites.FUNCTION_BOX, Sprites.FUNCTION_BOX,
) as SpriteSpec; ) as SpriteSpec;
private code: string;
constructor(gridPosition: Coord2D, code: string) { constructor(gridPosition: Coord2D, code: string) {
super(EntityNames.FunctionBox); super(EntityNames.FunctionBox);
this.code = code;
this.addComponent( this.addComponent(
new BoundingBox( new BoundingBox(
{ {
@ -61,20 +58,19 @@ export class FunctionBox extends Entity {
), ),
); );
this.addComponent( this.addComponent(new LambdaTerm(code));
new Highlight(
(_direction) => this.onHighlight(),
() => this.onUnhighlight(),
),
);
}
private onUnhighlight() { this.addComponent(makeLambdaTermHighlightComponent(this));
}
}
export const makeLambdaTermHighlightComponent = (entity: Entity) => {
const onUnhighlight = () => {
closeModal(); closeModal();
this.removeComponent(ComponentNames.Interactable); entity.removeComponent(ComponentNames.Interactable);
} };
private onHighlight() { const onHighlight = () => {
let modalOpen = false; let modalOpen = false;
const interaction = () => { const interaction = () => {
if (modalOpen) { if (modalOpen) {
@ -82,10 +78,14 @@ export class FunctionBox extends Entity {
closeModal(); closeModal();
return; return;
} }
modalOpen = true;
const code = entity.getComponent<LambdaTerm>(
ComponentNames.LambdaTerm,
)!.code;
openModal( openModal(
`<div style="text-align:center"><p>${this.code}</p> <br> <button id="close">Close</button></div>`, `<div style="text-align:center"><p>${code}</p> <br> <button id="close">Close</button></div>`,
); );
modalOpen = true;
document.getElementById("close")!.addEventListener("click", () => { document.getElementById("close")!.addEventListener("click", () => {
closeModal(); closeModal();
@ -93,6 +93,8 @@ export class FunctionBox extends Entity {
}); });
}; };
this.addComponent(new Interactable(interaction)); entity.addComponent(new Interactable(interaction));
} };
}
return new Highlight(onHighlight, onUnhighlight);
};

View File

@ -5,15 +5,15 @@ import {
SpriteSpec, SpriteSpec,
Sprites, Sprites,
} from "../config"; } from "../config";
import { Entity, EntityNames } from "."; import { Entity, EntityNames, FunctionBox } from ".";
import { import {
BoundingBox, BoundingBox,
Colliding, Colliding,
ComponentNames, ComponentNames,
Grid, Grid,
GridSpawn,
Highlight, Highlight,
Interactable, Interactable,
LambdaSpawn,
Sprite, Sprite,
Text, Text,
} from "../components"; } from "../components";
@ -75,11 +75,13 @@ export class LambdaFactory extends Entity {
private codeEditorState: CodeEditorState | null; private codeEditorState: CodeEditorState | null;
private spawns: number; private spawns: number;
private code: string;
constructor(gridPosition: Coord2D, code: string, spawns: number) { constructor(gridPosition: Coord2D, code: string, spawns: number) {
super(EntityNames.LambdaFactory); super(EntityNames.LambdaFactory);
this.spawns = spawns; this.spawns = spawns;
this.code = code;
this.codeEditorState = null; this.codeEditorState = null;
this.addComponent( this.addComponent(
@ -100,7 +102,12 @@ export class LambdaFactory extends Entity {
this.addComponent(new Colliding()); this.addComponent(new Colliding());
this.addComponent(new LambdaSpawn(this.spawns, code)); this.addComponent(
new GridSpawn(
this.spawns,
() => new FunctionBox({ x: 0, y: 0 }, this.code),
),
);
this.addComponent(new Grid(gridPosition)); this.addComponent(new Grid(gridPosition));
@ -131,8 +138,8 @@ export class LambdaFactory extends Entity {
} }
private spawnNewLambda(direction: Direction) { private spawnNewLambda(direction: Direction) {
const spawner = this.getComponent<LambdaSpawn>(ComponentNames.LambdaSpawn); const spawner = this.getComponent<GridSpawn>(ComponentNames.GridSpawn);
spawner.spawn(direction); spawner.spawnEntity(direction);
const text = this.getComponent<Text>(ComponentNames.Text); const text = this.getComponent<Text>(ComponentNames.Text);
text.text = spawner.spawnsLeft.toString(); text.text = spawner.spawnsLeft.toString();
@ -144,9 +151,8 @@ export class LambdaFactory extends Entity {
"<div class='code'><div id='code'></div><br><p id='syntax-error' class='error'></p><button id='close-modal'>Save</button></div>"; "<div class='code'><div id='code'></div><br><p id='syntax-error' class='error'></p><button id='close-modal'>Save</button></div>";
openModal(modalContent); openModal(modalContent);
const { code } = this.getComponent<LambdaSpawn>(ComponentNames.LambdaSpawn);
const startState = EditorState.create({ const startState = EditorState.create({
doc: code, doc: this.code,
extensions: [ extensions: [
basicSetup, basicSetup,
keymap.of(defaultKeymap), keymap.of(defaultKeymap),
@ -236,9 +242,7 @@ export class LambdaFactory extends Entity {
return; return;
} }
const spawner = this.getComponent<LambdaSpawn>(ComponentNames.LambdaSpawn); this.code = text;
spawner.code = text;
this.addComponent(spawner);
view.destroy(); view.destroy();
editorElement.innerHTML = ""; editorElement.innerHTML = "";

View File

@ -0,0 +1,39 @@
import { System, SystemNames } from ".";
import { Game } from "..";
import { ComponentNames, Grid, GridSpawn } from "../components";
import { Direction } from "../interfaces";
export class GridSpawner extends System {
constructor() {
super(SystemNames.GridSpawner);
}
public update(_dt: number, game: Game) {
game.forEachEntityWithComponent(ComponentNames.GridSpawn, (entity) => {
const spawn = entity.getComponent<GridSpawn>(ComponentNames.GridSpawn)!;
const hasGrid = entity.hasComponent(SystemNames.Grid);
if (spawn.direction === Direction.NONE || !hasGrid) {
return;
}
const grid = entity.getComponent<Grid>(SystemNames.Grid)!;
const direction = spawn.direction;
const spawned = spawn.spawner();
if (!spawned) {
return;
}
spawn.direction = Direction.NONE;
entity.addComponent(spawn);
const spawnedGrid = spawned.getComponent<Grid>(SystemNames.Grid)!;
spawnedGrid.gridPosition = grid.gridPosition;
spawnedGrid.movingDirection = direction;
spawned.addComponent(spawnedGrid);
game.addEntity(spawned);
entity.addComponent(spawned);
});
}
}

View File

@ -1,17 +1,17 @@
import { System, SystemNames } from "."; import { System, SystemNames } from ".";
import { Game } from ".."; import { Game } from "..";
import { ComponentNames, Grid, LambdaSpawn } from "../components"; import { ComponentNames, Grid, GridSpawn } from "../components";
import { FunctionBox } from "../entities"; import { FunctionBox } from "../entities";
export class LambdaFactory extends System { export class GridSpawner extends System {
constructor() { constructor() {
super(SystemNames.LambdaFactory); super(SystemNames.GridSpawner);
} }
public update(_dt: number, game: Game) { public update(_dt: number, game: Game) {
game.forEachEntityWithComponent(ComponentNames.LambdaSpawn, (entity) => { game.forEachEntityWithComponent(ComponentNames.GridSpawn, (entity) => {
const lambdaSpawn = entity.getComponent<LambdaSpawn>( const lambdaSpawn = entity.getComponent<GridSpawn>(
ComponentNames.LambdaSpawn, ComponentNames.GridSpawn,
)!; )!;
const hasGrid = entity.hasComponent(SystemNames.Grid); const hasGrid = entity.hasComponent(SystemNames.Grid);

View File

@ -3,6 +3,6 @@ export namespace SystemNames {
export const Input = "Input"; export const Input = "Input";
export const FacingDirection = "FacingDirection"; export const FacingDirection = "FacingDirection";
export const Grid = "Grid"; export const Grid = "Grid";
export const LambdaFactory = "LambdaFactory"; export const GridSpawner = "GridSpawner";
export const Collision = "Collision"; export const Collision = "Collision";
} }

View File

@ -4,5 +4,5 @@ export * from "./Render";
export * from "./Input"; export * from "./Input";
export * from "./FacingDirection"; export * from "./FacingDirection";
export * from "./Grid"; export * from "./Grid";
export * from "./LambdaFactory"; export * from "./GridSpawner";
export * from "./Collision"; export * from "./Collision";