level builder
This commit is contained in:
77
src/levels/LevelLoader.ts
Normal file
77
src/levels/LevelLoader.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import Phaser from "phaser";
|
||||
import { Player } from "../entities/Player";
|
||||
import { Exit } from "../entities/Exit";
|
||||
import { Platform } from "../entities/Platform";
|
||||
import { LevelMatrix, TILE_SIZE, TileType } from "./levels";
|
||||
|
||||
export interface LoadedLevel {
|
||||
player: Player;
|
||||
exit: Exit;
|
||||
platforms: Platform[];
|
||||
}
|
||||
|
||||
interface Cell {
|
||||
row: number;
|
||||
col: number;
|
||||
}
|
||||
|
||||
export class LevelLoader {
|
||||
constructor(private readonly scene: Phaser.Scene) {}
|
||||
|
||||
load(matrix: LevelMatrix): LoadedLevel {
|
||||
const platforms = this.buildPlatforms(matrix);
|
||||
const player = this.buildPlayer(matrix);
|
||||
const exit = this.buildExit(matrix);
|
||||
return { player, exit, platforms };
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge contiguous Platform tiles in each row into a single rectangle to
|
||||
* avoid corner-catching issues between adjacent 1-tile static bodies.
|
||||
*/
|
||||
private buildPlatforms(matrix: LevelMatrix): Platform[] {
|
||||
const result: Platform[] = [];
|
||||
for (let row = 0; row < matrix.length; row++) {
|
||||
const cols = matrix[row].length;
|
||||
let runStart = -1;
|
||||
for (let col = 0; col <= cols; col++) {
|
||||
const isPlatform = col < cols && matrix[row][col] === TileType.Platform;
|
||||
if (isPlatform && runStart === -1) {
|
||||
runStart = col;
|
||||
} else if (!isPlatform && runStart !== -1) {
|
||||
const width = (col - runStart) * TILE_SIZE;
|
||||
const x = runStart * TILE_SIZE + width / 2;
|
||||
const y = row * TILE_SIZE + TILE_SIZE / 2;
|
||||
result.push(new Platform(this.scene, x, y, width, TILE_SIZE));
|
||||
runStart = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private buildPlayer(matrix: LevelMatrix): Player {
|
||||
const cell = this.findTile(matrix, TileType.Player);
|
||||
if (!cell) throw new Error("Level matrix has no Player tile");
|
||||
const x = cell.col * TILE_SIZE + TILE_SIZE / 2;
|
||||
const y = (cell.row + 1) * TILE_SIZE - Player.SIZE / 2;
|
||||
return new Player(this.scene, x, y);
|
||||
}
|
||||
|
||||
private buildExit(matrix: LevelMatrix): Exit {
|
||||
const cell = this.findTile(matrix, TileType.Exit);
|
||||
if (!cell) throw new Error("Level matrix has no Exit tile");
|
||||
const x = cell.col * TILE_SIZE + TILE_SIZE / 2;
|
||||
const y = (cell.row + 1) * TILE_SIZE - Exit.HEIGHT / 2;
|
||||
return new Exit(this.scene, x, y);
|
||||
}
|
||||
|
||||
private findTile(matrix: LevelMatrix, tile: TileType): Cell | null {
|
||||
for (let row = 0; row < matrix.length; row++) {
|
||||
for (let col = 0; col < matrix[row].length; col++) {
|
||||
if (matrix[row][col] === tile) return { row, col };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user