summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElizabeth Hunt <elizabeth@simponic.xyz>2025-03-01 15:31:27 -0700
committerElizabeth Hunt <elizabeth@simponic.xyz>2025-03-01 15:31:27 -0700
commit07f508365f619d6bfe0a074dcf98c5ae8db17f08 (patch)
tree16b2a072998452ad72529e3d617f5c4a2df63c0c
parent309ed20627ed798c464a9f97d9c32ceb1a314595 (diff)
downloadthe-abstraction-engine-07f508365f619d6bfe0a074dcf98c5ae8db17f08.tar.gz
the-abstraction-engine-07f508365f619d6bfe0a074dcf98c5ae8db17f08.zip
add carcadr level
-rw-r--r--src/App.tsx2
-rw-r--r--src/components/GameCanvas.tsx4
-rw-r--r--src/engine/components/Sprite.ts14
-rw-r--r--src/engine/entities/FunctionApplication.ts2
-rw-r--r--src/engine/levels/CarCadr.ts60
-rw-r--r--src/engine/levels/LevelNames.ts1
-rw-r--r--src/engine/levels/LevelSelection.ts47
-rw-r--r--src/engine/levels/Tutorial.ts2
-rw-r--r--src/engine/levels/index.ts10
-rw-r--r--src/engine/systems/Level.ts1
10 files changed, 118 insertions, 25 deletions
diff --git a/src/App.tsx b/src/App.tsx
index b8582de..89b7cbc 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -21,7 +21,7 @@ export const App = () => {
<div className="footer">
<span>
built by{" "}
- <a href="https://github.com/simponic" target="_blank" className="tf">
+ <a href="https://git.simponic.xyz/simponic" target="_blank" className="tf">
simponic
</a>{" "}
| inspired by{" "}
diff --git a/src/components/GameCanvas.tsx b/src/components/GameCanvas.tsx
index b6c585d..98ba506 100644
--- a/src/components/GameCanvas.tsx
+++ b/src/components/GameCanvas.tsx
@@ -11,7 +11,9 @@ export interface GameCanvasProps {
export const GameCanvas = ({ width, height }: GameCanvasProps) => {
const canvasRef = useRef<HTMLCanvasElement>(null);
const [game, setGame] = useState<TheAbstractionEngine>();
- const [ready, setReady] = useState(false);
+ // TODO: go back to this after done
+ // const [ready, setReady] = useState(false);
+ const [ready, setReady] = useState(document.location.hostname.includes("localhost"));
const [loading, setLoading] = useState(true);
useEffect(() => {
diff --git a/src/engine/components/Sprite.ts b/src/engine/components/Sprite.ts
index fdf9675..6c0549b 100644
--- a/src/engine/components/Sprite.ts
+++ b/src/engine/components/Sprite.ts
@@ -55,7 +55,7 @@ export class Sprite extends Component implements Renderable {
ctx.save();
ctx.translate(center.x, center.y);
- if (rotation != undefined && rotation != 0) {
+ if (typeof rotation !== "undefined" && rotation != 0) {
ctx.rotate(rotation * (Math.PI / 180));
}
ctx.translate(-center.x, -center.y);
@@ -64,6 +64,12 @@ export class Sprite extends Component implements Renderable {
ctx.globalAlpha = opacity;
}
+ ctx.drawImage(
+ this.sheet,
+ ...this.getSpriteArgs(),
+ ...this.getDrawArgs(drawArgs),
+ );
+
if (backgroundText) {
// draw text
const { fillStyle, font, textAlign, text } = backgroundText;
@@ -75,12 +81,6 @@ export class Sprite extends Component implements Renderable {
ctx.fillText(text, center.x, center.y + height / 2);
}
- ctx.drawImage(
- this.sheet,
- ...this.getSpriteArgs(),
- ...this.getDrawArgs(drawArgs),
- );
-
if (tint) {
ctx.globalAlpha = 0.5;
ctx.globalCompositeOperation = "source-atop";
diff --git a/src/engine/entities/FunctionApplication.ts b/src/engine/entities/FunctionApplication.ts
index f15fcb9..bd88bda 100644
--- a/src/engine/entities/FunctionApplication.ts
+++ b/src/engine/entities/FunctionApplication.ts
@@ -155,7 +155,6 @@ export class FunctionApplication extends Entity {
return;
}
- const { dimension } = gridSystem;
const nextPosition = gridSystem.getNewGridPosition(
grid.gridPosition,
entityGrid.previousDirection
@@ -194,6 +193,7 @@ export class FunctionApplication extends Entity {
}
SOUNDS.get(LambdaTransformSound.name)!.play();
+ const { dimension } = gridSystem;
const particles = new Particles({
center: gridSystem.gridToScreenPosition(nextPosition),
spawnerDimensions: {
diff --git a/src/engine/levels/CarCadr.ts b/src/engine/levels/CarCadr.ts
new file mode 100644
index 0000000..e3d1eb9
--- /dev/null
+++ b/src/engine/levels/CarCadr.ts
@@ -0,0 +1,60 @@
+import { Level, LevelNames } from ".";
+import { Game } from "..";
+import {
+ Curry,
+ FunctionApplication,
+ Grass,
+ LambdaFactory,
+ LockedDoor,
+ Player,
+ Wall,
+} from "../entities";
+import { Grid, SystemNames } from "../systems";
+import { normalRandom } from "../utils";
+
+export class CarCadr extends Level {
+ constructor() {
+ super(LevelNames.CarCadr);
+ }
+
+ public init(game: Game) {
+ const grid = game.getSystem<Grid>(SystemNames.Grid);
+ const dimensions = grid.getGridDimensions();
+
+ const grasses = Array.from({ length: dimensions.width })
+ .fill(0)
+ .map(() => {
+ // random grass
+ return new Grass({
+ x: Math.floor(
+ normalRandom(dimensions.width / 2, dimensions.width / 4, 1.5),
+ ),
+ y: Math.floor(
+ normalRandom(dimensions.height / 2, dimensions.height / 4, 1.5),
+ ),
+ });
+ });
+
+ const entities = [
+ ...grasses,
+ new Player({ x: 9, y: 5 }),
+ new Wall({ x: 4, y: 3 }),
+ new Wall({ x: 4, y: 4 }),
+ new LambdaFactory({ x: 6, y: 4 }, "(\\ (x) . x)", 1),
+ new FunctionApplication({ x: 5, y: 5 }, "(_INPUT _KEY)"),
+ new Wall({ x: 4, y: 5 }),
+ new Wall({ x: 6, y: 5 }),
+ new FunctionApplication({ x: 4, y: 6 }, "(_INPUT _NULL)"),
+ new Wall({ x: 6, y: 7 }),
+ new Wall({ x: 5, y: 7 }),
+ new Wall({ x: 4, y: 7 }),
+ new LockedDoor({ x: 3, y: 8 }),
+ new Curry({ x: 3, y: 9 }),
+ new Wall({ x: 2, y: 9 }),
+ new Wall({ x: 4, y: 9 }),
+ new Wall({ x: 3, y: 10 }),
+ ];
+
+ entities.forEach((entity) => game.addEntity(entity));
+ }
+} \ No newline at end of file
diff --git a/src/engine/levels/LevelNames.ts b/src/engine/levels/LevelNames.ts
index e90b29a..7f3c4f1 100644
--- a/src/engine/levels/LevelNames.ts
+++ b/src/engine/levels/LevelNames.ts
@@ -1,4 +1,5 @@
export namespace LevelNames {
export const Tutorial = "0";
+ export const CarCadr = "1";
export const LevelSelection = "LevelSelection";
}
diff --git a/src/engine/levels/LevelSelection.ts b/src/engine/levels/LevelSelection.ts
index a970d9c..9e46274 100644
--- a/src/engine/levels/LevelSelection.ts
+++ b/src/engine/levels/LevelSelection.ts
@@ -1,9 +1,12 @@
import { LEVELS, Level, LevelNames } from ".";
import { Game } from "..";
-import { Player, Portal } from "../entities";
+import { Grass, Player, Portal } from "../entities";
import { Grid, Level as LevelSystem, SystemNames } from "../systems";
+import { normalRandom } from "../utils";
export class LevelSelection extends Level {
+ public static RADIUS = 5;
+
constructor() {
super(LevelNames.LevelSelection);
}
@@ -11,23 +14,43 @@ export class LevelSelection extends Level {
public init(game: Game): void {
const gridSystem = game.getSystem<Grid>(SystemNames.Grid);
const center = gridSystem.getCenterGrid();
+ const dimensions = gridSystem.getGridDimensions();
const levelSystem = game.getSystem<LevelSystem>(SystemNames.Level);
const unlocked = levelSystem.getUnlockedLevels();
- LEVELS.forEach((level, i) => {
- if (
- !unlocked.has(level.name) ||
- level.name === LevelNames.LevelSelection
- ) {
- return;
- }
-
- const portal = new Portal(level.name, { x: i, y: 7 });
- game.addEntity(portal);
- });
+ const renderableLevels = LEVELS.filter(
+ ({ name }) => name !== LevelNames.LevelSelection
+ );
+ const radiansPerLevel = (2 * Math.PI) / renderableLevels.length;
+ renderableLevels
+ .filter(({ name }) => unlocked.has(name))
+ .map((level, i) => {
+ const radians = i * radiansPerLevel;
+ const coords = {
+ x: Math.floor(Math.cos(radians) * LevelSelection.RADIUS + center.x),
+ y: Math.floor(Math.sin(radians) * LevelSelection.RADIUS + center.y),
+ };
+ return new Portal(level.name, coords);
+ })
+ .forEach((e) => game.addEntity(e));
const player = new Player(center);
game.addEntity(player);
+
+ Array.from({ length: dimensions.width })
+ .fill(0)
+ .map(() => {
+ // random grass
+ return new Grass({
+ x: Math.floor(
+ normalRandom(dimensions.width / 2, dimensions.width / 4, 1.5)
+ ),
+ y: Math.floor(
+ normalRandom(dimensions.height / 2, dimensions.height / 4, 1.5)
+ ),
+ });
+ })
+ .forEach((e) => game.addEntity(e));
}
}
diff --git a/src/engine/levels/Tutorial.ts b/src/engine/levels/Tutorial.ts
index 895b569..97a6826 100644
--- a/src/engine/levels/Tutorial.ts
+++ b/src/engine/levels/Tutorial.ts
@@ -43,7 +43,7 @@ export class Tutorial extends Level {
{ x: 4, y: 3 },
),
new Sign(
- "this is a Term Application; interact to view its code<br><br>push the term ➡️ created by the factory any direction into the Application to produce a new one 💭<br><br>note that:<br><br>+ _INPUT is the term replaced by the pushed term<br><br>+ in this case _KEY is applied to the function to make a new KEY! 🔑",
+ "<div>this is a Term Application; interact to view its code<br><br>push the term ➡️ created by the factory any direction into the Application to produce a new one 💭<br><br>note that:<br><br>+ _INPUT is the term replaced by the pushed term<br><br>+ in this case _KEY is applied to the function to make a new KEY! 🔑</div>",
{ x: 4, y: 6 },
),
new Wall({ x: 10, y: 9 }),
diff --git a/src/engine/levels/index.ts b/src/engine/levels/index.ts
index bae7fea..216453c 100644
--- a/src/engine/levels/index.ts
+++ b/src/engine/levels/index.ts
@@ -2,11 +2,17 @@ export * from "./LevelNames";
export * from "./Level";
export * from "./LevelSelection";
export * from "./Tutorial";
+export * from "./CarCadr";
import { LevelNames } from ".";
-import { LevelSelection, Tutorial, Level } from ".";
+import { CarCadr, LevelSelection, Tutorial, Level } from ".";
-export const LEVELS: Level[] = [new LevelSelection(), new Tutorial()];
+export const LEVELS: Level[] = [
+ new LevelSelection(),
+ new Tutorial(),
+ new CarCadr(),
+];
export const LEVEL_PROGRESSION: Record<string, string[]> = {
[LevelNames.LevelSelection]: [LevelNames.Tutorial],
+ [LevelNames.Tutorial]: [LevelNames.CarCadr],
};
diff --git a/src/engine/systems/Level.ts b/src/engine/systems/Level.ts
index 824895d..99fe452 100644
--- a/src/engine/systems/Level.ts
+++ b/src/engine/systems/Level.ts
@@ -3,6 +3,7 @@ import { Game } from "..";
import { type Level as LevelType, LEVELS, LEVEL_PROGRESSION } from "../levels";
export class Level extends System {
+ // TODO: read from localstorage
private unlockedLevels: Set<string> = new Set();
private currentLevel: LevelType | null = null;
private moveToLevel: string | null;