diff --git a/src/components.ts b/src/components.ts index e07d4e4..1ec99ea 100644 --- a/src/components.ts +++ b/src/components.ts @@ -96,13 +96,21 @@ export class Viewshed extends Component { } /** - * BlocksTile component. + * `BlocksTile` component. * Attached to `Entity` that exclusively occupies the space in a map tile from other entities that have the same tag. * Initiates `MapIndexingSystem`. */ export class BlocksTile extends Component { } +/** + * `CanDescend` component. + * Attached to `Entity` that allows us to descend a level. + * Initiates `LevelSystem` + */ +export class CanDescend extends Component { +} + /** * `Attributes` component. * Attached to `Entity` that might be in combat to initiate `MeleeCombatSystem`, `HealingSystem`, and `DamageSystem`. diff --git a/src/level-gen.ts b/src/level-gen.ts index 8fa3eb9..02c6545 100644 --- a/src/level-gen.ts +++ b/src/level-gen.ts @@ -1,5 +1,5 @@ import { Entity, World } from "ecsy"; -import { Rand, Vector2 } from "malwoden"; +import { Rand, Struct, Vector2 } from "malwoden"; import * as Components from "./components.ts"; import * as Prefabs from "./prefabs.ts"; @@ -56,6 +56,19 @@ export class LevelGenerator { return player; } + /** + * Get a random position within a specified room `Rect`. + * @param room Room `Rect`. + * @returns Vector2 Random position in the room + */ + getRandomRoomPosition(room: Struct.Rect): Vector2 { + // get a random x and y coordinate + const x = this.rng.nextInt(room.v1.x, room.v2.x + 1); + const y = this.rng.nextInt(room.v1.y, room.v2.y + 1); + + return { x, y }; + } + /** * Generate a level given configuration information. * @param config Map size and game world. @@ -78,19 +91,21 @@ export class LevelGenerator { // choose a creature type const creatureType = this.rng.nextInt(0, 100); if (creatureType < 50) - Prefabs.placeEntity(Prefabs.goblin(this.world), room.center()); + Prefabs.placeEntity(Prefabs.goblin(this.world), this.getRandomRoomPosition(room)); else - Prefabs.placeEntity(Prefabs.orc(this.world), room.center()); + Prefabs.placeEntity(Prefabs.orc(this.world), this.getRandomRoomPosition(room)); // create items if (this.rng.next() < 0.2) { - // get a random spot in the room - const randomX = this.rng.nextInt(room.v1.x, room.v2.x + 1); - const randomY = this.rng.nextInt(room.v1.y, room.v2.y + 1); - Prefabs.placeEntity(Prefabs.bandage(this.world), { x: randomX, y: randomY }); + Prefabs.placeEntity(Prefabs.bandage(this.world), this.getRandomRoomPosition(room)); } } + // create stairs in a room that isn't a player room + const stairRoomIndex = this.rng.nextInt(1, map.rooms.length); + const stairRoom = map.rooms[stairRoomIndex]; + Prefabs.placeEntity(Prefabs.stairs(this.world), this.getRandomRoomPosition(stairRoom)); + return { map, playerStart, diff --git a/src/main.ts b/src/main.ts index 4cd4996..0a1b418 100644 --- a/src/main.ts +++ b/src/main.ts @@ -120,6 +120,7 @@ export class Game { .registerComponent(Components.Consumable) .registerComponent(Components.IncomingHealing) .registerComponent(Components.Description) + .registerComponent(Components.CanDescend) // systems - order matters .registerSystem(Systems.VisibilitySystem, this) diff --git a/src/prefabs.ts b/src/prefabs.ts index 7b87ea6..8c3d348 100644 --- a/src/prefabs.ts +++ b/src/prefabs.ts @@ -106,4 +106,19 @@ export function bandage(world: World): Entity { .addComponent(Components.Description, { text: "Will patch up minor injuries." }); +} + +/** + * Create a stairs `Entity`. + * @param world Game world object. + * @return Entity Stairs `Entity`. + */ +export function stairs(world: World): Entity { + return world + .createEntity() + .addComponent(Components.Renderable, { + glyph: Glyph.fromCharCode(CharCode.blackDownPointingTriangle, Color.Cyan), + }) + .addComponent(Components.Name, { name: "Stairs" }) + .addComponent(Components.CanDescend); } \ No newline at end of file