This commit is contained in:
parent
309ed20627
commit
07f508365f
@ -21,7 +21,7 @@ export const App = () => {
|
|||||||
<div className="footer">
|
<div className="footer">
|
||||||
<span>
|
<span>
|
||||||
built by{" "}
|
built by{" "}
|
||||||
<a href="https://github.com/simponic" target="_blank" className="tf">
|
<a href="https://git.simponic.xyz/simponic" target="_blank" className="tf">
|
||||||
simponic
|
simponic
|
||||||
</a>{" "}
|
</a>{" "}
|
||||||
| inspired by{" "}
|
| inspired by{" "}
|
||||||
|
@ -11,7 +11,9 @@ export interface GameCanvasProps {
|
|||||||
export const GameCanvas = ({ width, height }: GameCanvasProps) => {
|
export const GameCanvas = ({ width, height }: GameCanvasProps) => {
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
const [game, setGame] = useState<TheAbstractionEngine>();
|
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);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -55,7 +55,7 @@ export class Sprite extends Component implements Renderable {
|
|||||||
|
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.translate(center.x, center.y);
|
ctx.translate(center.x, center.y);
|
||||||
if (rotation != undefined && rotation != 0) {
|
if (typeof rotation !== "undefined" && rotation != 0) {
|
||||||
ctx.rotate(rotation * (Math.PI / 180));
|
ctx.rotate(rotation * (Math.PI / 180));
|
||||||
}
|
}
|
||||||
ctx.translate(-center.x, -center.y);
|
ctx.translate(-center.x, -center.y);
|
||||||
@ -64,6 +64,12 @@ export class Sprite extends Component implements Renderable {
|
|||||||
ctx.globalAlpha = opacity;
|
ctx.globalAlpha = opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.drawImage(
|
||||||
|
this.sheet,
|
||||||
|
...this.getSpriteArgs(),
|
||||||
|
...this.getDrawArgs(drawArgs),
|
||||||
|
);
|
||||||
|
|
||||||
if (backgroundText) {
|
if (backgroundText) {
|
||||||
// draw text
|
// draw text
|
||||||
const { fillStyle, font, textAlign, text } = backgroundText;
|
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.fillText(text, center.x, center.y + height / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.drawImage(
|
|
||||||
this.sheet,
|
|
||||||
...this.getSpriteArgs(),
|
|
||||||
...this.getDrawArgs(drawArgs),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (tint) {
|
if (tint) {
|
||||||
ctx.globalAlpha = 0.5;
|
ctx.globalAlpha = 0.5;
|
||||||
ctx.globalCompositeOperation = "source-atop";
|
ctx.globalCompositeOperation = "source-atop";
|
||||||
|
@ -155,7 +155,6 @@ export class FunctionApplication extends Entity {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { dimension } = gridSystem;
|
|
||||||
const nextPosition = gridSystem.getNewGridPosition(
|
const nextPosition = gridSystem.getNewGridPosition(
|
||||||
grid.gridPosition,
|
grid.gridPosition,
|
||||||
entityGrid.previousDirection
|
entityGrid.previousDirection
|
||||||
@ -194,6 +193,7 @@ export class FunctionApplication extends Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SOUNDS.get(LambdaTransformSound.name)!.play();
|
SOUNDS.get(LambdaTransformSound.name)!.play();
|
||||||
|
const { dimension } = gridSystem;
|
||||||
const particles = new Particles({
|
const particles = new Particles({
|
||||||
center: gridSystem.gridToScreenPosition(nextPosition),
|
center: gridSystem.gridToScreenPosition(nextPosition),
|
||||||
spawnerDimensions: {
|
spawnerDimensions: {
|
||||||
|
60
src/engine/levels/CarCadr.ts
Normal file
60
src/engine/levels/CarCadr.ts
Normal file
@ -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));
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
export namespace LevelNames {
|
export namespace LevelNames {
|
||||||
export const Tutorial = "0";
|
export const Tutorial = "0";
|
||||||
|
export const CarCadr = "1";
|
||||||
export const LevelSelection = "LevelSelection";
|
export const LevelSelection = "LevelSelection";
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import { LEVELS, Level, LevelNames } from ".";
|
import { LEVELS, Level, LevelNames } from ".";
|
||||||
import { Game } from "..";
|
import { Game } from "..";
|
||||||
import { Player, Portal } from "../entities";
|
import { Grass, Player, Portal } from "../entities";
|
||||||
import { Grid, Level as LevelSystem, SystemNames } from "../systems";
|
import { Grid, Level as LevelSystem, SystemNames } from "../systems";
|
||||||
|
import { normalRandom } from "../utils";
|
||||||
|
|
||||||
export class LevelSelection extends Level {
|
export class LevelSelection extends Level {
|
||||||
|
public static RADIUS = 5;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(LevelNames.LevelSelection);
|
super(LevelNames.LevelSelection);
|
||||||
}
|
}
|
||||||
@ -11,23 +14,43 @@ export class LevelSelection extends Level {
|
|||||||
public init(game: Game): void {
|
public init(game: Game): void {
|
||||||
const gridSystem = game.getSystem<Grid>(SystemNames.Grid);
|
const gridSystem = game.getSystem<Grid>(SystemNames.Grid);
|
||||||
const center = gridSystem.getCenterGrid();
|
const center = gridSystem.getCenterGrid();
|
||||||
|
const dimensions = gridSystem.getGridDimensions();
|
||||||
|
|
||||||
const levelSystem = game.getSystem<LevelSystem>(SystemNames.Level);
|
const levelSystem = game.getSystem<LevelSystem>(SystemNames.Level);
|
||||||
const unlocked = levelSystem.getUnlockedLevels();
|
const unlocked = levelSystem.getUnlockedLevels();
|
||||||
|
|
||||||
LEVELS.forEach((level, i) => {
|
const renderableLevels = LEVELS.filter(
|
||||||
if (
|
({ name }) => name !== LevelNames.LevelSelection
|
||||||
!unlocked.has(level.name) ||
|
);
|
||||||
level.name === LevelNames.LevelSelection
|
const radiansPerLevel = (2 * Math.PI) / renderableLevels.length;
|
||||||
) {
|
renderableLevels
|
||||||
return;
|
.filter(({ name }) => unlocked.has(name))
|
||||||
}
|
.map((level, i) => {
|
||||||
|
const radians = i * radiansPerLevel;
|
||||||
const portal = new Portal(level.name, { x: i, y: 7 });
|
const coords = {
|
||||||
game.addEntity(portal);
|
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);
|
const player = new Player(center);
|
||||||
game.addEntity(player);
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ export class Tutorial extends Level {
|
|||||||
{ x: 4, y: 3 },
|
{ x: 4, y: 3 },
|
||||||
),
|
),
|
||||||
new Sign(
|
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 },
|
{ x: 4, y: 6 },
|
||||||
),
|
),
|
||||||
new Wall({ x: 10, y: 9 }),
|
new Wall({ x: 10, y: 9 }),
|
||||||
|
@ -2,11 +2,17 @@ export * from "./LevelNames";
|
|||||||
export * from "./Level";
|
export * from "./Level";
|
||||||
export * from "./LevelSelection";
|
export * from "./LevelSelection";
|
||||||
export * from "./Tutorial";
|
export * from "./Tutorial";
|
||||||
|
export * from "./CarCadr";
|
||||||
|
|
||||||
import { LevelNames } from ".";
|
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[]> = {
|
export const LEVEL_PROGRESSION: Record<string, string[]> = {
|
||||||
[LevelNames.LevelSelection]: [LevelNames.Tutorial],
|
[LevelNames.LevelSelection]: [LevelNames.Tutorial],
|
||||||
|
[LevelNames.Tutorial]: [LevelNames.CarCadr],
|
||||||
};
|
};
|
||||||
|
@ -3,6 +3,7 @@ import { Game } from "..";
|
|||||||
import { type Level as LevelType, LEVELS, LEVEL_PROGRESSION } from "../levels";
|
import { type Level as LevelType, LEVELS, LEVEL_PROGRESSION } from "../levels";
|
||||||
|
|
||||||
export class Level extends System {
|
export class Level extends System {
|
||||||
|
// TODO: read from localstorage
|
||||||
private unlockedLevels: Set<string> = new Set();
|
private unlockedLevels: Set<string> = new Set();
|
||||||
private currentLevel: LevelType | null = null;
|
private currentLevel: LevelType | null = null;
|
||||||
private moveToLevel: string | null;
|
private moveToLevel: string | null;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user