This commit is contained in:
parent
ce403459fa
commit
42838864af
@ -48,7 +48,7 @@ export class Game {
|
||||
|
||||
public forEachEntityWithComponent(
|
||||
componentName: string,
|
||||
callback: (entity: Entity) => void,
|
||||
callback: (entity: Entity) => void
|
||||
) {
|
||||
this.componentEntities.get(componentName)?.forEach((entityId) => {
|
||||
const entity = this.getEntity(entityId);
|
||||
@ -84,12 +84,12 @@ export class Game {
|
||||
if (!this.componentEntities.has(component.name)) {
|
||||
this.componentEntities.set(
|
||||
component.name,
|
||||
new Set<string>([entity.id]),
|
||||
new Set<string>([entity.id])
|
||||
);
|
||||
return;
|
||||
}
|
||||
this.componentEntities.get(component.name)?.add(entity.id);
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
this.systemOrder.forEach((systemName) => {
|
||||
|
@ -41,7 +41,7 @@ export class TheAbstractionEngine {
|
||||
{
|
||||
width: Miscellaneous.GRID_CELL_WIDTH,
|
||||
height: Miscellaneous.GRID_CELL_HEIGHT,
|
||||
},
|
||||
}
|
||||
),
|
||||
new GridSpawner(),
|
||||
new Collision(),
|
||||
@ -76,7 +76,7 @@ export class TheAbstractionEngine {
|
||||
});
|
||||
|
||||
this.ctx.canvas.addEventListener("keyup", (e) =>
|
||||
input.keyReleased(e.key.toLowerCase()),
|
||||
input.keyReleased(e.key.toLowerCase())
|
||||
);
|
||||
|
||||
this.ctx.canvas.addEventListener("blur", () => input.clearKeys());
|
||||
|
@ -49,8 +49,8 @@ export class BoundingBox extends Component {
|
||||
const projection = dotProduct(normal, vertex);
|
||||
return [Math.min(min, projection), Math.max(max, projection)];
|
||||
},
|
||||
[Infinity, -Infinity],
|
||||
),
|
||||
[Infinity, -Infinity]
|
||||
)
|
||||
);
|
||||
|
||||
if (maxThis < minBox || maxBox < minThis) return false;
|
||||
|
@ -10,7 +10,7 @@ export class GridSpawn extends Component {
|
||||
constructor(
|
||||
spawnsLeft: number,
|
||||
spawner: () => Entity,
|
||||
direction = Direction.NONE,
|
||||
direction = Direction.NONE
|
||||
) {
|
||||
super(ComponentNames.GridSpawn);
|
||||
|
||||
|
@ -9,7 +9,7 @@ export class Highlight extends Component {
|
||||
constructor(
|
||||
onHighlight: (direction: Direction) => void,
|
||||
onUnhighlight: () => void,
|
||||
isHighlighted: boolean = false,
|
||||
isHighlighted: boolean = false
|
||||
) {
|
||||
super(ComponentNames.Highlight);
|
||||
|
||||
|
@ -23,7 +23,7 @@ export class Sprite extends Component implements Renderable {
|
||||
spriteImgPos: Coord2D,
|
||||
spriteImgDimensions: Dimension2D,
|
||||
msPerFrame: number,
|
||||
numFrames: number,
|
||||
numFrames: number
|
||||
) {
|
||||
super(ComponentNames.Sprite);
|
||||
|
||||
@ -78,7 +78,7 @@ export class Sprite extends Component implements Renderable {
|
||||
ctx.drawImage(
|
||||
this.sheet,
|
||||
...this.getSpriteArgs(),
|
||||
...this.getDrawArgs(drawArgs),
|
||||
...this.getDrawArgs(drawArgs)
|
||||
);
|
||||
|
||||
if (tint) {
|
||||
|
@ -10,7 +10,7 @@ export class Text extends Component {
|
||||
text: string,
|
||||
fillStyle = "white",
|
||||
font = "25px scientifica",
|
||||
textAlign: CanvasTextAlign = "center",
|
||||
textAlign: CanvasTextAlign = "center"
|
||||
) {
|
||||
super(ComponentNames.Text);
|
||||
|
||||
|
@ -1,7 +1,12 @@
|
||||
import { type SpriteSpec, SPRITE_SPECS } from ".";
|
||||
import { SOUND_SPECS, SoundSpec } from "./sounds";
|
||||
|
||||
export const FONT = new FontFace("scientifica", "url(/fonts/scientifica.ttf)");
|
||||
const BASE_URL = document.location;
|
||||
|
||||
export const FONT = new FontFace(
|
||||
"scientifica",
|
||||
`url(${BASE_URL}/fonts/scientifica.ttf)`
|
||||
);
|
||||
FONT.load().then((font) => {
|
||||
document.fonts.add(font);
|
||||
});
|
||||
@ -10,26 +15,26 @@ export const IMAGES = new Map<string, HTMLImageElement>();
|
||||
export const SOUNDS = new Map<string, HTMLAudioElement>();
|
||||
|
||||
export const loadSpritesIntoImageElements = (
|
||||
spriteSpecs: Partial<SpriteSpec>[],
|
||||
spriteSpecs: Partial<SpriteSpec>[]
|
||||
): Promise<void>[] => {
|
||||
const spritePromises: Promise<void>[] = [];
|
||||
|
||||
for (const spriteSpec of spriteSpecs) {
|
||||
if (spriteSpec.sheet) {
|
||||
const img = new Image();
|
||||
img.src = spriteSpec.sheet;
|
||||
img.src = BASE_URL + spriteSpec.sheet;
|
||||
IMAGES.set(spriteSpec.sheet, img);
|
||||
|
||||
spritePromises.push(
|
||||
new Promise((resolve) => {
|
||||
img.onload = () => resolve();
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (spriteSpec.states) {
|
||||
spritePromises.push(
|
||||
...loadSpritesIntoImageElements(Array.from(spriteSpec.states.values())),
|
||||
...loadSpritesIntoImageElements(Array.from(spriteSpec.states.values()))
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -38,13 +43,13 @@ export const loadSpritesIntoImageElements = (
|
||||
};
|
||||
|
||||
export const loadSoundsIntoAudioElements = (
|
||||
soundSpecs: SoundSpec[],
|
||||
soundSpecs: SoundSpec[]
|
||||
): Promise<void>[] => {
|
||||
const soundPromises: Promise<void>[] = [];
|
||||
|
||||
for (const soundSpec of soundSpecs) {
|
||||
if (soundSpec.url) {
|
||||
const promise = fetch(soundSpec.url)
|
||||
const promise = fetch(BASE_URL + soundSpec.url)
|
||||
.then((response) => response.blob())
|
||||
.then((blob) => {
|
||||
const audio = new Audio();
|
||||
@ -68,7 +73,7 @@ export const loadSoundsIntoAudioElements = (
|
||||
|
||||
if (soundSpec.states) {
|
||||
soundPromises.push(
|
||||
...loadSoundsIntoAudioElements(Array.from(soundSpec.states.values())),
|
||||
...loadSoundsIntoAudioElements(Array.from(soundSpec.states.values()))
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -80,8 +85,8 @@ export const loadAssets = () =>
|
||||
Promise.all([
|
||||
...loadSpritesIntoImageElements(
|
||||
Array.from(SPRITE_SPECS.keys()).map(
|
||||
(key) => SPRITE_SPECS.get(key) as SpriteSpec,
|
||||
),
|
||||
(key) => SPRITE_SPECS.get(key) as SpriteSpec
|
||||
)
|
||||
),
|
||||
FONT.load(),
|
||||
...loadSoundsIntoAudioElements(Array.from(SOUND_SPECS.values())),
|
||||
|
@ -31,7 +31,7 @@ export namespace KeyConstants {
|
||||
|
||||
// value -> [key] from KeyActions
|
||||
export const ActionKeys: Map<Action, string[]> = Object.keys(
|
||||
KeyActions,
|
||||
KeyActions
|
||||
).reduce((acc: Map<Action, string[]>, key) => {
|
||||
const action = KeyActions[key.toLowerCase()];
|
||||
|
||||
|
@ -42,7 +42,7 @@ playerSpriteSpec.states.set(Direction.NONE, {
|
||||
playerSpriteSpec.states.set(direction, {
|
||||
sheet: `/assets/lambda/${direction.toLowerCase()}.png`,
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
SPRITE_SPECS.set(Sprites.PLAYER, playerSpriteSpec);
|
||||
|
||||
|
@ -8,7 +8,7 @@ import { Level, SystemNames } from "../systems";
|
||||
|
||||
export class Curry extends Entity {
|
||||
private static spriteSpec: SpriteSpec = SPRITE_SPECS.get(
|
||||
Sprites.CURRY,
|
||||
Sprites.CURRY
|
||||
) as SpriteSpec;
|
||||
|
||||
constructor(gridPosition: Coord2D) {
|
||||
@ -28,8 +28,8 @@ export class Curry extends Entity {
|
||||
width: Curry.spriteSpec.width,
|
||||
height: Curry.spriteSpec.height,
|
||||
},
|
||||
0,
|
||||
),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(
|
||||
@ -41,8 +41,8 @@ export class Curry extends Entity {
|
||||
height: Curry.spriteSpec.height,
|
||||
},
|
||||
Curry.spriteSpec.msPerFrame,
|
||||
Curry.spriteSpec.frames,
|
||||
),
|
||||
Curry.spriteSpec.frames
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -56,8 +56,8 @@ export class FunctionApplication extends Entity {
|
||||
y: 0,
|
||||
},
|
||||
dimension,
|
||||
0,
|
||||
),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(new Grid(gridPosition));
|
||||
@ -70,8 +70,8 @@ export class FunctionApplication extends Entity {
|
||||
{ x: 0, y: 0 },
|
||||
dimension,
|
||||
FunctionApplication.spriteSpec.msPerFrame,
|
||||
FunctionApplication.spriteSpec.frames,
|
||||
),
|
||||
FunctionApplication.spriteSpec.frames
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(new Colliding(this.handleCollision.bind(this)));
|
||||
@ -94,7 +94,7 @@ export class FunctionApplication extends Entity {
|
||||
const gridSystem = game.getSystem<GridSystem>(SystemNames.Grid);
|
||||
const fail = () => {
|
||||
entityGrid.movingDirection = gridSystem.oppositeDirection(
|
||||
entityGrid.previousDirection,
|
||||
entityGrid.previousDirection
|
||||
);
|
||||
entity.addComponent(entityGrid);
|
||||
|
||||
@ -103,10 +103,10 @@ export class FunctionApplication extends Entity {
|
||||
};
|
||||
|
||||
const applicationTerm = this.getComponent<LambdaTerm>(
|
||||
ComponentNames.LambdaTerm,
|
||||
ComponentNames.LambdaTerm
|
||||
);
|
||||
const functionTerm = entity.getComponent<LambdaTerm>(
|
||||
ComponentNames.LambdaTerm,
|
||||
ComponentNames.LambdaTerm
|
||||
);
|
||||
const newCode = applicationTerm.code.replace("_INPUT", functionTerm.code);
|
||||
let result: DebrujinifiedLambdaTerm | null = null;
|
||||
@ -121,7 +121,7 @@ export class FunctionApplication extends Entity {
|
||||
const { dimension } = gridSystem;
|
||||
const nextPosition = gridSystem.getNewGridPosition(
|
||||
grid.gridPosition,
|
||||
entityGrid.previousDirection,
|
||||
entityGrid.previousDirection
|
||||
);
|
||||
|
||||
let applicationResultingEntity: Entity | null = null; // this should be its own function
|
||||
@ -142,7 +142,7 @@ export class FunctionApplication extends Entity {
|
||||
game.removeEntity(entity.id);
|
||||
if (applicationResultingEntity) {
|
||||
const grid = applicationResultingEntity.getComponent<Grid>(
|
||||
ComponentNames.Grid,
|
||||
ComponentNames.Grid
|
||||
);
|
||||
grid.movingDirection = entityGrid.previousDirection;
|
||||
applicationResultingEntity.addComponent(grid);
|
||||
|
@ -24,7 +24,7 @@ import { openModal, closeModal } from "../utils";
|
||||
|
||||
export class FunctionBox extends Entity {
|
||||
private static spriteSpec: SpriteSpec = SPRITE_SPECS.get(
|
||||
Sprites.FUNCTION_BOX,
|
||||
Sprites.FUNCTION_BOX
|
||||
) as SpriteSpec;
|
||||
|
||||
constructor(gridPosition: Coord2D, code: string) {
|
||||
@ -40,8 +40,8 @@ export class FunctionBox extends Entity {
|
||||
width: FunctionBox.spriteSpec.width,
|
||||
height: FunctionBox.spriteSpec.height,
|
||||
},
|
||||
0,
|
||||
),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(new Pushable());
|
||||
@ -57,8 +57,8 @@ export class FunctionBox extends Entity {
|
||||
height: FunctionBox.spriteSpec.height,
|
||||
},
|
||||
FunctionBox.spriteSpec.msPerFrame,
|
||||
FunctionBox.spriteSpec.frames,
|
||||
),
|
||||
FunctionBox.spriteSpec.frames
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(new LambdaTerm(code));
|
||||
@ -88,10 +88,10 @@ export const makeLambdaTermHighlightComponent = (entity: Entity) => {
|
||||
}
|
||||
|
||||
const code = entity.getComponent<LambdaTerm>(
|
||||
ComponentNames.LambdaTerm,
|
||||
ComponentNames.LambdaTerm
|
||||
)!.code;
|
||||
openModal(
|
||||
`<div style="text-align:center"><p>${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;
|
||||
SOUNDS.get(ModalOpen.name)!.play();
|
||||
|
@ -20,8 +20,8 @@ export class Grass extends Entity {
|
||||
height: Grass.spriteSpec.height,
|
||||
},
|
||||
Grass.spriteSpec.msPerFrame,
|
||||
Grass.spriteSpec.frames,
|
||||
),
|
||||
Grass.spriteSpec.frames
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { Coord2D } from "../interfaces";
|
||||
|
||||
export class Key extends Entity {
|
||||
private static spriteSpec: SpriteSpec = SPRITE_SPECS.get(
|
||||
Sprites.KEY,
|
||||
Sprites.KEY
|
||||
) as SpriteSpec;
|
||||
|
||||
constructor(gridPosition: Coord2D) {
|
||||
@ -25,8 +25,8 @@ export class Key extends Entity {
|
||||
width: Key.spriteSpec.width,
|
||||
height: Key.spriteSpec.height,
|
||||
},
|
||||
0,
|
||||
),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(
|
||||
@ -38,8 +38,8 @@ export class Key extends Entity {
|
||||
height: Key.spriteSpec.height,
|
||||
},
|
||||
Key.spriteSpec.msPerFrame,
|
||||
Key.spriteSpec.frames,
|
||||
),
|
||||
Key.spriteSpec.frames
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ const syntaxErrorDecoration = Decoration.mark({
|
||||
|
||||
export class LambdaFactory extends Entity {
|
||||
private static spriteSpec: SpriteSpec = SPRITE_SPECS.get(
|
||||
Sprites.LAMBDA_FACTORY,
|
||||
Sprites.LAMBDA_FACTORY
|
||||
) as SpriteSpec;
|
||||
|
||||
private codeEditorState: CodeEditorState | null;
|
||||
@ -99,8 +99,8 @@ export class LambdaFactory extends Entity {
|
||||
width: LambdaFactory.spriteSpec.width,
|
||||
height: LambdaFactory.spriteSpec.height,
|
||||
},
|
||||
0,
|
||||
),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(new Text(spawns.toString()));
|
||||
@ -110,8 +110,8 @@ export class LambdaFactory extends Entity {
|
||||
this.addComponent(
|
||||
new GridSpawn(
|
||||
this.spawns,
|
||||
() => new FunctionBox({ x: 0, y: 0 }, this.code),
|
||||
),
|
||||
() => new FunctionBox({ x: 0, y: 0 }, this.code)
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(new Grid(gridPosition));
|
||||
@ -125,15 +125,15 @@ export class LambdaFactory extends Entity {
|
||||
height: LambdaFactory.spriteSpec.height,
|
||||
},
|
||||
LambdaFactory.spriteSpec.msPerFrame,
|
||||
LambdaFactory.spriteSpec.frames,
|
||||
),
|
||||
LambdaFactory.spriteSpec.frames
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(
|
||||
new Highlight(
|
||||
(direction) => this.onHighlight(direction),
|
||||
() => this.onUnhighlight(),
|
||||
),
|
||||
() => this.onUnhighlight()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -179,10 +179,10 @@ export class LambdaFactory extends Entity {
|
||||
const codeBox = document.getElementById("code")!;
|
||||
const syntaxError = document.getElementById("syntax-error")!;
|
||||
const canvas = document.getElementById(
|
||||
Miscellaneous.CANVAS_ID,
|
||||
Miscellaneous.CANVAS_ID
|
||||
) as HTMLCanvasElement;
|
||||
const closeButton = document.getElementById(
|
||||
"close-modal",
|
||||
"close-modal"
|
||||
) as HTMLButtonElement;
|
||||
closeButton.addEventListener("click", () => this.saveAndCloseCodeEditor());
|
||||
|
||||
|
@ -21,7 +21,7 @@ import { colors } from "../utils";
|
||||
|
||||
export class LockedDoor extends Entity {
|
||||
private static spriteSpec: SpriteSpec = SPRITE_SPECS.get(
|
||||
Sprites.LOCKED_DOOR,
|
||||
Sprites.LOCKED_DOOR
|
||||
) as SpriteSpec;
|
||||
|
||||
constructor(gridPosition: Coord2D) {
|
||||
@ -41,8 +41,8 @@ export class LockedDoor extends Entity {
|
||||
width: LockedDoor.spriteSpec.width,
|
||||
height: LockedDoor.spriteSpec.height,
|
||||
},
|
||||
0,
|
||||
),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(
|
||||
@ -54,8 +54,8 @@ export class LockedDoor extends Entity {
|
||||
height: LockedDoor.spriteSpec.height,
|
||||
},
|
||||
LockedDoor.spriteSpec.msPerFrame,
|
||||
LockedDoor.spriteSpec.frames,
|
||||
),
|
||||
LockedDoor.spriteSpec.frames
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ class ParticleRenderer extends Component implements Renderable {
|
||||
particle.dimension.height / 2,
|
||||
0,
|
||||
0,
|
||||
Math.PI * 2,
|
||||
Math.PI * 2
|
||||
);
|
||||
ctx.fill();
|
||||
} else {
|
||||
@ -94,7 +94,7 @@ class ParticleRenderer extends Component implements Renderable {
|
||||
particle.position.x - particle.dimension.width / 2,
|
||||
particle.position.y - particle.dimension.height / 2,
|
||||
particle.dimension.width,
|
||||
particle.dimension.height,
|
||||
particle.dimension.height
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -119,7 +119,7 @@ export class Particles extends Entity {
|
||||
const life = this.getComponent<Life>(ComponentNames.Life);
|
||||
life.alive = false;
|
||||
this.addComponent(life);
|
||||
}),
|
||||
})
|
||||
);
|
||||
|
||||
this.addComponent(
|
||||
@ -132,8 +132,8 @@ export class Particles extends Entity {
|
||||
width: spawnOptions.spawnerDimensions.width,
|
||||
height: spawnOptions.spawnerDimensions.height,
|
||||
},
|
||||
0,
|
||||
),
|
||||
0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -141,15 +141,15 @@ export class Particles extends Entity {
|
||||
const angle = Math.random() * Math.PI * 2;
|
||||
const speed = normalRandom(
|
||||
options.particleMeanSpeed,
|
||||
options.particleSpeedVariance,
|
||||
options.particleSpeedVariance
|
||||
);
|
||||
const life = normalRandom(
|
||||
options.particleMeanLife,
|
||||
options.particleLifeVariance,
|
||||
options.particleLifeVariance
|
||||
);
|
||||
const size = normalRandom(
|
||||
options.particleMeanSize,
|
||||
options.particleSizeVariance,
|
||||
options.particleSizeVariance
|
||||
);
|
||||
const color =
|
||||
options.particleColors[
|
||||
|
@ -12,7 +12,7 @@ import { Coord2D, Direction } from "../interfaces/";
|
||||
|
||||
export class Player extends Entity {
|
||||
private static spriteSpec: SpriteSpec = SPRITE_SPECS.get(
|
||||
Sprites.PLAYER,
|
||||
Sprites.PLAYER
|
||||
) as SpriteSpec;
|
||||
|
||||
constructor(gridPosition: Coord2D) {
|
||||
@ -25,8 +25,8 @@ export class Player extends Entity {
|
||||
y: 0,
|
||||
},
|
||||
{ width: Player.spriteSpec.width, height: Player.spriteSpec.height },
|
||||
0,
|
||||
),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(new Pushable());
|
||||
@ -51,14 +51,14 @@ export class Player extends Entity {
|
||||
{ x: 0, y: 0 },
|
||||
{ width: Player.spriteSpec.width, height: Player.spriteSpec.height },
|
||||
Player.spriteSpec.msPerFrame,
|
||||
Player.spriteSpec.frames,
|
||||
Player.spriteSpec.frames
|
||||
);
|
||||
facingDirectionComponent.directionSprites.set(direction, sprite);
|
||||
});
|
||||
|
||||
this.addComponent(facingDirectionComponent);
|
||||
this.addComponent(
|
||||
facingDirectionComponent.directionSprites.get(Direction.NONE)!,
|
||||
facingDirectionComponent.directionSprites.get(Direction.NONE)!
|
||||
); // face no direction by default
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,8 @@ export class Portal extends Entity {
|
||||
width: Portal.spriteSpec.width,
|
||||
height: Portal.spriteSpec.height,
|
||||
},
|
||||
0,
|
||||
),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(
|
||||
@ -38,8 +38,8 @@ export class Portal extends Entity {
|
||||
height: Portal.spriteSpec.height,
|
||||
},
|
||||
Portal.spriteSpec.msPerFrame,
|
||||
Portal.spriteSpec.frames,
|
||||
),
|
||||
Portal.spriteSpec.frames
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(new Colliding(this.handleCollision.bind(this)));
|
||||
|
@ -5,7 +5,7 @@ import { Coord2D } from "../interfaces";
|
||||
|
||||
export class Wall extends Entity {
|
||||
private static spriteSpec: SpriteSpec = SPRITE_SPECS.get(
|
||||
Sprites.WALL,
|
||||
Sprites.WALL
|
||||
) as SpriteSpec;
|
||||
|
||||
constructor(gridPosition: Coord2D) {
|
||||
@ -25,8 +25,8 @@ export class Wall extends Entity {
|
||||
width: Wall.spriteSpec.width,
|
||||
height: Wall.spriteSpec.height,
|
||||
},
|
||||
0,
|
||||
),
|
||||
0
|
||||
)
|
||||
);
|
||||
|
||||
this.addComponent(
|
||||
@ -38,8 +38,8 @@ export class Wall extends Entity {
|
||||
height: Wall.spriteSpec.height,
|
||||
},
|
||||
Wall.spriteSpec.msPerFrame,
|
||||
Wall.spriteSpec.frames,
|
||||
),
|
||||
Wall.spriteSpec.frames
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ export class Collision extends System {
|
||||
return;
|
||||
}
|
||||
const collidingBox = entity.getComponent<BoundingBox>(
|
||||
ComponentNames.BoundingBox,
|
||||
ComponentNames.BoundingBox
|
||||
);
|
||||
let collidingGrid = entity.hasComponent(ComponentNames.Grid)
|
||||
? entity.getComponent<Grid>(ComponentNames.Grid)
|
||||
@ -39,7 +39,7 @@ export class Collision extends System {
|
||||
ComponentNames.BoundingBox,
|
||||
(otherEntity) => {
|
||||
const otherBoundingBox = otherEntity.getComponent<BoundingBox>(
|
||||
ComponentNames.BoundingBox,
|
||||
ComponentNames.BoundingBox
|
||||
);
|
||||
let otherGrid = otherEntity.hasComponent(ComponentNames.Grid)
|
||||
? otherEntity.getComponent<Grid>(ComponentNames.Grid)
|
||||
@ -58,7 +58,7 @@ export class Collision extends System {
|
||||
if (collidingBox.isCollidingWith(otherBoundingBox)) {
|
||||
collidingWith.push(otherEntity);
|
||||
}
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
for (const collision of collidingWith) {
|
||||
|
@ -32,16 +32,16 @@ export class FacingDirection extends System {
|
||||
}
|
||||
|
||||
const boundingBox = entity.getComponent<BoundingBox>(
|
||||
ComponentNames.BoundingBox,
|
||||
ComponentNames.BoundingBox
|
||||
)!;
|
||||
const facingDirection = entity.getComponent<FacingDirectionComponent>(
|
||||
ComponentNames.FacingDirection,
|
||||
ComponentNames.FacingDirection
|
||||
);
|
||||
|
||||
const { center } = boundingBox;
|
||||
const angle = Math.atan2(
|
||||
mousePosition.y - center.y,
|
||||
mousePosition.x - center.x,
|
||||
mousePosition.x - center.x
|
||||
);
|
||||
|
||||
const mouseInBoundingBox =
|
||||
@ -58,7 +58,7 @@ export class FacingDirection extends System {
|
||||
sprite.fillTimingsFromSprite(oldSprite);
|
||||
|
||||
entity.addComponent(sprite);
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ export class Grid extends System {
|
||||
|
||||
constructor(
|
||||
{ width: columns, height: rows }: Dimension2D,
|
||||
dimension: Dimension2D,
|
||||
dimension: Dimension2D
|
||||
) {
|
||||
super(SystemNames.Grid);
|
||||
|
||||
@ -50,11 +50,11 @@ export class Grid extends System {
|
||||
|
||||
const grid = entity.getComponent<GridComponent>(ComponentNames.Grid)!;
|
||||
const facingDirection = entity.getComponent<FacingDirection>(
|
||||
ComponentNames.FacingDirection,
|
||||
ComponentNames.FacingDirection
|
||||
)!;
|
||||
const lookingAt = this.getNewGridPosition(
|
||||
grid.gridPosition,
|
||||
facingDirection.currentDirection,
|
||||
facingDirection.currentDirection
|
||||
);
|
||||
if (
|
||||
facingDirection.currentDirection === Direction.NONE ||
|
||||
@ -66,14 +66,14 @@ export class Grid extends System {
|
||||
this.grid[lookingAt.y][lookingAt.x].forEach((id) => {
|
||||
highlightableEntities.push([id, facingDirection.currentDirection]);
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
highlightableEntities.forEach(([id, direction]) => {
|
||||
const entity = game.getEntity(id)!;
|
||||
if (entity.hasComponent(ComponentNames.Highlight)) {
|
||||
const highlight = entity.getComponent<Highlight>(
|
||||
ComponentNames.Highlight,
|
||||
ComponentNames.Highlight
|
||||
)!;
|
||||
highlight.highlight(direction);
|
||||
}
|
||||
@ -82,7 +82,7 @@ export class Grid extends System {
|
||||
game.forEachEntityWithComponent(ComponentNames.Highlight, (entity) => {
|
||||
if (!highlightableEntities.find(([id]) => id === entity.id)) {
|
||||
const highlight = entity.getComponent<Highlight>(
|
||||
ComponentNames.Highlight,
|
||||
ComponentNames.Highlight
|
||||
)!;
|
||||
highlight.unhighlight();
|
||||
}
|
||||
@ -124,23 +124,23 @@ export class Grid extends System {
|
||||
|
||||
const { x, y } = nextGridPosition;
|
||||
const entities = Array.from(this.grid[y][x]).map(
|
||||
(id) => game.getEntity(id)!,
|
||||
(id) => game.getEntity(id)!
|
||||
);
|
||||
|
||||
const collidingEntities = entities.filter((entity) =>
|
||||
entity.hasComponent(ComponentNames.Colliding),
|
||||
entity.hasComponent(ComponentNames.Colliding)
|
||||
);
|
||||
|
||||
if (collidingEntities.length > 0) {
|
||||
// i.e. key going into a door or function going into an application
|
||||
const allEntitiesInPreviousCellCanCollide = Array.from(
|
||||
this.grid[currentPosition.y][currentPosition.x],
|
||||
this.grid[currentPosition.y][currentPosition.x]
|
||||
)
|
||||
.map((id) => game.getEntity(id)!)
|
||||
.every((entity) =>
|
||||
collidingEntities.every((collidingEntity) =>
|
||||
Collision.canCollide(entity.name, collidingEntity.name),
|
||||
),
|
||||
Collision.canCollide(entity.name, collidingEntity.name)
|
||||
)
|
||||
);
|
||||
if (allEntitiesInPreviousCellCanCollide) {
|
||||
break;
|
||||
@ -153,7 +153,7 @@ export class Grid extends System {
|
||||
if (!entity.hasComponent(ComponentNames.Grid)) return false;
|
||||
|
||||
const { movingDirection } = entity.getComponent<GridComponent>(
|
||||
ComponentNames.Grid,
|
||||
ComponentNames.Grid
|
||||
)!;
|
||||
const pushable = entity.hasComponent(ComponentNames.Pushable);
|
||||
return movingDirection === Direction.NONE && pushable;
|
||||
@ -169,7 +169,7 @@ export class Grid extends System {
|
||||
currentPosition = nextGridPosition;
|
||||
nextGridPosition = this.getNewGridPosition(
|
||||
nextGridPosition,
|
||||
movingDirection,
|
||||
movingDirection
|
||||
);
|
||||
}
|
||||
|
||||
@ -196,7 +196,7 @@ export class Grid extends System {
|
||||
}
|
||||
|
||||
const boundingBox = entity.getComponent<BoundingBox>(
|
||||
ComponentNames.BoundingBox,
|
||||
ComponentNames.BoundingBox
|
||||
)!;
|
||||
boundingBox.center = this.gridToScreenPosition(grid.gridPosition);
|
||||
boundingBox.dimension = this.dimension;
|
||||
@ -210,7 +210,7 @@ export class Grid extends System {
|
||||
private updateMovingEntities(
|
||||
dt: number,
|
||||
game: Game,
|
||||
velocity = PhysicsConstants.GRID_MOVEMENT_VELOCITY,
|
||||
velocity = PhysicsConstants.GRID_MOVEMENT_VELOCITY
|
||||
) {
|
||||
game.forEachEntityWithComponent(ComponentNames.Grid, (entity) => {
|
||||
const grid = entity.getComponent<GridComponent>(ComponentNames.Grid)!;
|
||||
@ -221,12 +221,12 @@ export class Grid extends System {
|
||||
grid.previousDirection = grid.movingDirection;
|
||||
|
||||
const boundingBox = entity.getComponent<BoundingBox>(
|
||||
ComponentNames.BoundingBox,
|
||||
ComponentNames.BoundingBox
|
||||
)!;
|
||||
|
||||
const newGridPosition = this.getNewGridPosition(
|
||||
grid.gridPosition,
|
||||
grid.movingDirection,
|
||||
grid.movingDirection
|
||||
);
|
||||
if (this.isOutOfBounds(newGridPosition)) {
|
||||
grid.movingDirection = Direction.NONE;
|
||||
@ -255,7 +255,7 @@ export class Grid extends System {
|
||||
const passedCenter = this.isEntityPastCenterWhenMoving(
|
||||
grid.movingDirection,
|
||||
newGridPosition,
|
||||
nextPosition,
|
||||
nextPosition
|
||||
);
|
||||
|
||||
if (passedCenter) {
|
||||
@ -319,7 +319,7 @@ export class Grid extends System {
|
||||
private isEntityPastCenterWhenMoving(
|
||||
direction: Direction,
|
||||
gridPosition: Coord2D,
|
||||
entityPosition: Coord2D,
|
||||
entityPosition: Coord2D
|
||||
) {
|
||||
const { x, y } = this.gridToScreenPosition(gridPosition);
|
||||
switch (direction) {
|
||||
@ -368,7 +368,7 @@ export class Grid extends System {
|
||||
cell.delete(id);
|
||||
}
|
||||
}
|
||||
}),
|
||||
})
|
||||
);
|
||||
movedEntities.forEach((id) => {
|
||||
const entity = game.getEntity(id)!;
|
||||
|
@ -32,20 +32,20 @@ export class Input extends System {
|
||||
|
||||
public update(_dt: number, game: Game) {
|
||||
game.forEachEntityWithComponent(ComponentNames.Control, (entity) =>
|
||||
this.handleMovement(entity, game),
|
||||
this.handleMovement(entity, game)
|
||||
);
|
||||
game.forEachEntityWithComponent(ComponentNames.Interactable, (entity) =>
|
||||
this.handleInteraction(entity),
|
||||
this.handleInteraction(entity)
|
||||
);
|
||||
}
|
||||
|
||||
private handleInteraction(entity: Entity) {
|
||||
const interactable = entity.getComponent<Interactable>(
|
||||
ComponentNames.Interactable,
|
||||
ComponentNames.Interactable
|
||||
);
|
||||
|
||||
const interact = this.hasSomeKey(
|
||||
KeyConstants.ActionKeys.get(Action.INTERACT),
|
||||
KeyConstants.ActionKeys.get(Action.INTERACT)
|
||||
);
|
||||
|
||||
if (!interact) {
|
||||
@ -54,13 +54,13 @@ export class Input extends System {
|
||||
|
||||
interactable.interact();
|
||||
KeyConstants.ActionKeys.get(Action.INTERACT)!.forEach((key) =>
|
||||
this.keyReleased(key),
|
||||
this.keyReleased(key)
|
||||
);
|
||||
}
|
||||
|
||||
public handleMovement(entity: Entity, game: Game) {
|
||||
const controlComponent = entity.getComponent<Control>(
|
||||
ComponentNames.Control,
|
||||
ComponentNames.Control
|
||||
);
|
||||
if (!controlComponent.isControllable) return;
|
||||
|
||||
@ -85,22 +85,22 @@ export class Input extends System {
|
||||
if (moveUp) {
|
||||
gridComponent.movingDirection = Direction.UP;
|
||||
KeyConstants.ActionKeys.get(Action.MOVE_UP)!.forEach((key) =>
|
||||
this.keyReleased(key),
|
||||
this.keyReleased(key)
|
||||
);
|
||||
} else if (moveLeft) {
|
||||
gridComponent.movingDirection = Direction.LEFT;
|
||||
KeyConstants.ActionKeys.get(Action.MOVE_LEFT)!.forEach((key) =>
|
||||
this.keyReleased(key),
|
||||
this.keyReleased(key)
|
||||
);
|
||||
} else if (moveRight) {
|
||||
gridComponent.movingDirection = Direction.RIGHT;
|
||||
KeyConstants.ActionKeys.get(Action.MOVE_RIGHT)!.forEach((key) =>
|
||||
this.keyReleased(key),
|
||||
this.keyReleased(key)
|
||||
);
|
||||
} else if (moveDown) {
|
||||
gridComponent.movingDirection = Direction.DOWN;
|
||||
KeyConstants.ActionKeys.get(Action.MOVE_DOWN)!.forEach((key) =>
|
||||
this.keyReleased(key),
|
||||
this.keyReleased(key)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ export class Music extends System {
|
||||
super(SystemNames.Music);
|
||||
|
||||
this.songs = Array.from(GameMusic.states!.values()).map(
|
||||
(state) => state.name,
|
||||
(state) => state.name
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ export class Render extends System {
|
||||
sprite.update(dt);
|
||||
|
||||
const boundingBox = entity.getComponent<BoundingBox>(
|
||||
ComponentNames.BoundingBox,
|
||||
ComponentNames.BoundingBox
|
||||
);
|
||||
|
||||
// don't render if we're outside the screen
|
||||
@ -34,12 +34,12 @@ export class Render extends System {
|
||||
clamp(
|
||||
boundingBox.center.y,
|
||||
-boundingBox.dimension.height / 2,
|
||||
this.ctx.canvas.height + boundingBox.dimension.height / 2,
|
||||
this.ctx.canvas.height + boundingBox.dimension.height / 2
|
||||
) != boundingBox.center.y ||
|
||||
clamp(
|
||||
boundingBox.center.x,
|
||||
-boundingBox.dimension.width / 2,
|
||||
this.ctx.canvas.width + boundingBox.dimension.width / 2,
|
||||
this.ctx.canvas.width + boundingBox.dimension.width / 2
|
||||
) != boundingBox.center.x
|
||||
) {
|
||||
return;
|
||||
@ -52,7 +52,7 @@ export class Render extends System {
|
||||
};
|
||||
if (entity.hasComponent(ComponentNames.Highlight)) {
|
||||
const highlight = entity.getComponent<Highlight>(
|
||||
ComponentNames.Highlight,
|
||||
ComponentNames.Highlight
|
||||
);
|
||||
drawArgs.tint = highlight.isHighlighted ? "red" : undefined;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ let modalOpen = false;
|
||||
export const openModal = (
|
||||
content: string,
|
||||
id = Miscellaneous.MODAL_ID,
|
||||
contentId = Miscellaneous.MODAL_CONTENT_ID,
|
||||
contentId = Miscellaneous.MODAL_CONTENT_ID
|
||||
) => {
|
||||
const modal = document.getElementById(id);
|
||||
const modalContent = document.getElementById(contentId);
|
||||
@ -22,7 +22,7 @@ export const openModal = (
|
||||
|
||||
export const closeModal = (
|
||||
id = Miscellaneous.MODAL_ID,
|
||||
contentId = Miscellaneous.MODAL_CONTENT_ID,
|
||||
contentId = Miscellaneous.MODAL_CONTENT_ID
|
||||
) => {
|
||||
const modal = document.getElementById(id);
|
||||
const modalContent = document.getElementById(contentId);
|
||||
|
@ -4,6 +4,6 @@ export const normalRandom = (mean: number, stdDev: number, maxStdDevs = 2) => {
|
||||
mean + stdDev * Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v);
|
||||
return Math.min(
|
||||
mean + maxStdDevs * stdDev,
|
||||
Math.max(mean - maxStdDevs * stdDev, normal),
|
||||
Math.max(mean - maxStdDevs * stdDev, normal)
|
||||
);
|
||||
};
|
||||
|
@ -226,7 +226,7 @@ export default (function () {
|
||||
["0", "9"],
|
||||
],
|
||||
false,
|
||||
false,
|
||||
false
|
||||
);
|
||||
var peg$e1 = peg$literalExpectation("(", false);
|
||||
var peg$e2 = peg$literalExpectation(")", false);
|
||||
@ -260,7 +260,7 @@ export default (function () {
|
||||
if (options.startRule) {
|
||||
if (!(options.startRule in peg$startRuleFunctions)) {
|
||||
throw new Error(
|
||||
"Can't start parsing from rule \"" + options.startRule + '".',
|
||||
"Can't start parsing from rule \"" + options.startRule + '".'
|
||||
);
|
||||
}
|
||||
|
||||
@ -296,7 +296,7 @@ export default (function () {
|
||||
throw peg$buildStructuredError(
|
||||
[peg$otherExpectation(description)],
|
||||
input.substring(peg$savedPos, peg$currPos),
|
||||
location,
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
@ -417,7 +417,7 @@ export default (function () {
|
||||
peg$SyntaxError.buildMessage(expected, found),
|
||||
expected,
|
||||
found,
|
||||
location,
|
||||
location
|
||||
);
|
||||
}
|
||||
|
||||
@ -883,7 +883,7 @@ export default (function () {
|
||||
peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null,
|
||||
peg$maxFailPos < input.length
|
||||
? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1)
|
||||
: peg$computeLocation(peg$maxFailPos, peg$maxFailPos),
|
||||
: peg$computeLocation(peg$maxFailPos, peg$maxFailPos)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ export type DebrujinifiedLambdaTerm =
|
||||
|
||||
export const debrujinify = (
|
||||
term: LambdaTerm,
|
||||
symbolTable: SymbolTable,
|
||||
symbolTable: SymbolTable
|
||||
): DebrujinifiedLambdaTerm => {
|
||||
if (isVariable(term)) {
|
||||
if (!symbolTable.has(term)) {
|
||||
@ -65,14 +65,14 @@ export const debrujinify = (
|
||||
}
|
||||
|
||||
throw new InvalidLambdaTermError(
|
||||
`Invalid lambda term: ${JSON.stringify(term)}`,
|
||||
`Invalid lambda term: ${JSON.stringify(term)}`
|
||||
);
|
||||
};
|
||||
|
||||
export const substitute = (
|
||||
inTerm: DebrujinifiedLambdaTerm,
|
||||
index: number,
|
||||
withTerm: DebrujinifiedLambdaTerm,
|
||||
withTerm: DebrujinifiedLambdaTerm
|
||||
): DebrujinifiedLambdaTerm => {
|
||||
if ("index" in inTerm) {
|
||||
if (inTerm.index > index) {
|
||||
@ -108,13 +108,13 @@ export const substitute = (
|
||||
}
|
||||
|
||||
throw new InvalidLambdaTermError(
|
||||
`Invalid lambda term: ${JSON.stringify(inTerm)}`,
|
||||
`Invalid lambda term: ${JSON.stringify(inTerm)}`
|
||||
);
|
||||
};
|
||||
|
||||
export const adjustIndices = (
|
||||
term: DebrujinifiedLambdaTerm,
|
||||
delta: number,
|
||||
delta: number
|
||||
): DebrujinifiedLambdaTerm => {
|
||||
if ("index" in term) {
|
||||
return {
|
||||
@ -146,12 +146,12 @@ export const adjustIndices = (
|
||||
}
|
||||
|
||||
throw new InvalidLambdaTermError(
|
||||
`Invalid lambda term: ${JSON.stringify(term)}`,
|
||||
`Invalid lambda term: ${JSON.stringify(term)}`
|
||||
);
|
||||
};
|
||||
|
||||
export const betaReduce = (
|
||||
term: DebrujinifiedLambdaTerm,
|
||||
term: DebrujinifiedLambdaTerm
|
||||
): DebrujinifiedLambdaTerm => {
|
||||
if ("index" in term) {
|
||||
return term;
|
||||
@ -194,7 +194,7 @@ export const betaReduce = (
|
||||
}
|
||||
|
||||
throw new InvalidLambdaTermError(
|
||||
`Invalid lambda term: ${JSON.stringify(term)}`,
|
||||
`Invalid lambda term: ${JSON.stringify(term)}`
|
||||
);
|
||||
};
|
||||
|
||||
@ -214,7 +214,7 @@ export const emitDebrujin = (term: DebrujinifiedLambdaTerm): string => {
|
||||
}
|
||||
|
||||
throw new InvalidLambdaTermError(
|
||||
`Invalid lambda term: ${JSON.stringify(term)}`,
|
||||
`Invalid lambda term: ${JSON.stringify(term)}`
|
||||
);
|
||||
};
|
||||
|
||||
@ -225,7 +225,7 @@ export const emitNamed = (term: DebrujinifiedLambdaTerm): string => {
|
||||
|
||||
if ("abstraction" in term) {
|
||||
return `(λ (${term.abstraction.param}) . ${emitNamed(
|
||||
term.abstraction.body,
|
||||
term.abstraction.body
|
||||
)})`;
|
||||
}
|
||||
|
||||
@ -241,7 +241,7 @@ export const emitNamed = (term: DebrujinifiedLambdaTerm): string => {
|
||||
export const interpret = (
|
||||
term: string,
|
||||
symbolTable = new SymbolTable(),
|
||||
allowUnderscores = false,
|
||||
allowUnderscores = false
|
||||
): DebrujinifiedLambdaTerm => {
|
||||
const ast = parse(term, allowUnderscores);
|
||||
const debrujined = debrujinify(ast, symbolTable);
|
||||
|
2
src/typeshims/rainbowbrackets.d.ts
vendored
2
src/typeshims/rainbowbrackets.d.ts
vendored
@ -1 +1 @@
|
||||
declare module 'rainbowbrackets';
|
||||
declare module "rainbowbrackets";
|
||||
|