Skip to content

Commit

Permalink
mega refactor, separate tile files, renderer to allow themes, & corru…
Browse files Browse the repository at this point in the history
…pt save handling
  • Loading branch information
Vulae committed Apr 25, 2024
1 parent a6c8aa3 commit 945a543
Show file tree
Hide file tree
Showing 19 changed files with 512 additions and 440 deletions.
16 changes: 8 additions & 8 deletions src/components/Game.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<script lang="ts">
import { tileset } from "$lib/game/Assets";
import { WorldRenderer } from "$lib/game/Renderer";
import { load, save } from "$lib/game/Save";
import { World } from "$lib/game/World";
Expand Down Expand Up @@ -39,14 +38,10 @@
let keys: Set<string> = new Set();
let keysInterval: number = -1;
onMount(() => {
onMount(async () => {
world = load(saveSlot);
renderer = new WorldRenderer(world, canvas);
tileset.onLoad(() => {
needsRerender = true;
});
// TODO: Clean Up!
clearInterval(keysInterval);
keysInterval = setInterval(() => {
Expand All @@ -72,7 +67,12 @@
}
}, 1000 / 60);
render();
// FIXME: Why is this not always accurate.
// Sometimes renderer.init() does not load theme fully before returning.
await renderer.init();
setTimeout(() => {
render();
}, 100);
});
onDestroy(() => {
Expand All @@ -90,7 +90,7 @@
on:keyup={ev => {
keys.delete(ev.key);
}}
on:unload={() => {
on:beforeunload={() => {
save(saveSlot, world);
}}
/>
Expand Down
8 changes: 8 additions & 0 deletions src/lib/Util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@



// https://stackoverflow.com/questions/41253310#answer-51399781
export type ArrayElement<ArrayType extends readonly unknown[]> =
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;


50 changes: 0 additions & 50 deletions src/lib/game/Assets.ts

This file was deleted.

14 changes: 7 additions & 7 deletions src/lib/game/Chunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import Pako from "pako";
import { BitIO } from "../BitIO";
import { CHUNK_SIZE } from "./Constants";
import { getTileType } from "./Generator";
import type { Tile } from "./Tile";
import type { World } from "./World";
import type { ValidTile } from "./tile/Tile";



Expand All @@ -31,7 +31,7 @@ export class Chunk {

console.log(`Generating new chunk: ${this.chunkX}, ${this.chunkY}`);

const tiles: Tile[] = [];
const tiles: ValidTile[] = [];

for(let dy = 0; dy < CHUNK_SIZE; dy++) {
for(let dx = 0; dx < CHUNK_SIZE; dx++) {
Expand All @@ -47,21 +47,21 @@ export class Chunk {


export class GeneratedChunk extends Chunk {
public readonly tiles: Tile[];
public readonly tiles: ValidTile[];

public constructor(world: World, chunkX: number, chunkY: number, tiles: Tile[]) {
public constructor(world: World, chunkX: number, chunkY: number, tiles: ValidTile[]) {
super(world, chunkX, chunkY);
this.tiles = tiles;
if(this.tiles.length != CHUNK_SIZE * CHUNK_SIZE) {
throw new Error('GeneratedChunk incorrect tiles length.');
}
}

public getTileAbsolute(tileX: number, tileY: number): Tile {
public getTileAbsolute(tileX: number, tileY: number): ValidTile {
return this.getTile(tileX - this.chunkX * CHUNK_SIZE, tileY - this.chunkY * CHUNK_SIZE);
}

public getTile(chunkTileX: number, chunkTileY: number): Tile {
public getTile(chunkTileX: number, chunkTileY: number): ValidTile {
return this.tiles[chunkTileX + chunkTileY * CHUNK_SIZE]!;
}

Expand All @@ -75,7 +75,7 @@ export class GeneratedChunk extends Chunk {

public static load(world: World, chunkX: number, chunkY: number, buffer: ArrayBuffer): GeneratedChunk {
const io = new BitIO(Pako.inflate(buffer));
let tiles: Tile[] = [];
let tiles: ValidTile[] = [];
for(let dy = 0; dy < CHUNK_SIZE; dy++) {
for(let dx = 0; dx < CHUNK_SIZE; dx++) {
const x = chunkX * CHUNK_SIZE + dx;
Expand Down
14 changes: 9 additions & 5 deletions src/lib/game/Generator.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@

import { perlin_noise2d, splitmix32, voronoi_noise2d } from "../RNG";
import { ChocolateTile, Stroopwafel, VanillaTile, WaffleTile, type Tile } from "./Tile";
import type { World } from "./World";
import { ChocolateTile } from "./tile/Chocolate";
import { StroopwafelTile } from "./tile/Stroopwafel";
import type { Tile, ValidTile, ValidTileConstructor } from "./tile/Tile";
import { VanillaTile } from "./tile/Vanilla";
import { WaffleTile } from "./tile/Waffle";



type Biome = {
type: 'biome',
weight: number;
tile: typeof Tile
tile: ValidTileConstructor;
} | {
type: 'collection',
weight: number;
Expand Down Expand Up @@ -48,7 +52,7 @@ const Biomes: Biome = {
}, {
type: 'biome',
weight: 2,
tile: Stroopwafel
tile: StroopwafelTile
}]
}]
};
Expand All @@ -62,7 +66,7 @@ function smoothNoisyVoronoi(seed: number, x: number, y: number, dist: number, we
return voronoi_noise2d(random(), x + dx, y + dy, weights);
}

export function getTileType(world: World, x: number, y: number): typeof Tile {
export function getTileType(world: World, x: number, y: number): ValidTileConstructor {
const random = splitmix32(world.biomeSeed, false);

let biome: Biome = Biomes;
Expand All @@ -79,7 +83,7 @@ export function getTileType(world: World, x: number, y: number): typeof Tile {
return biome.tile;
}

export function generateTile(world: World, x: number, y: number): Tile {
export function generateTile(world: World, x: number, y: number): ValidTile {
const tileConstructor = getTileType(world, x, y);
// @ts-ignore - TODO: How do I deal with this?
return new tileConstructor(world, x, y);
Expand Down
10 changes: 9 additions & 1 deletion src/lib/game/Renderer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@

import type { World } from "./World";
import type { Theme } from "./theme/Theme";
import { ThemeRetro } from "./theme/retro";



Expand All @@ -8,6 +10,8 @@ export class WorldRenderer {
public readonly canvas: HTMLCanvasElement;
public readonly ctx: CanvasRenderingContext2D;

public readonly theme: Theme = new ThemeRetro();

constructor(world: World, canvas: HTMLCanvasElement) {
this.world = world;
this.canvas = canvas;
Expand All @@ -18,6 +22,10 @@ export class WorldRenderer {
this.ctx = ctx;
}

public async init(): Promise<void> {
await this.theme.init();
}

// Camera position in tiles
public cameraX: number = 0;
public cameraY: number = 0;
Expand Down Expand Up @@ -101,7 +109,7 @@ export class WorldRenderer {
this.ctx.scale(1.01, 1.01);

const tile = this.world.getTile(x, y);
tile.render(this.ctx);
this.theme.drawTile(this.ctx, tile);

this.ctx.restore();
}
Expand Down
29 changes: 21 additions & 8 deletions src/lib/game/Save.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,32 @@ import { World, type WorldSave } from "./World";



function newWorld(saveSlot: string, overwrite: boolean): World {
console.log('Loaded new world');
if(overwrite) {
localStorage.setItem(saveSlot, 'PLACEHOLDER');
}
const world = new World(Math.floor(Math.random() * 0xFFFFFFFF));
const closest0 = world.closest0(0, 0);
world.reveal(closest0.x, closest0.y);
return world;
}

export function load(saveSlot: string): World {
const str = localStorage.getItem(saveSlot);
if(!str) {
console.log('Loaded new world');
localStorage.setItem(saveSlot, 'PLACEHOLDER');
const world = new World(Math.floor(Math.random() * 0xFFFFFFFF));
const closest0 = world.closest0(0, 0);
world.reveal(closest0.x, closest0.y);
return world;
return newWorld(saveSlot, true);
} else {
console.log('Loaded saved world');
const save: WorldSave = JSON.parse(str);
return World.load(save);
try {
const save: WorldSave = JSON.parse(str);
return World.load(save);
} catch(err) {
console.error('Failed to load world.');
console.error(err);

return newWorld(saveSlot, false);
}
}
}

Expand Down
Loading

0 comments on commit 945a543

Please sign in to comment.