All files / games/engine/src world.ts

100% Statements 36/36
87.5% Branches 7/8
100% Functions 14/14
100% Lines 36/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 10411x 11x         11x   11x 11x     11x               12x 12x 12x 12x 12x       7x   7x   7x       2x   2x   2x       3x       2x       1x       1x 1x         4x 3x       3x     1x       1x       1x       1x             4x 8x 8x     4x 1x   1x     4x      
import { random } from "jga-algorithms-random";
import { World as BaseWorld, EntityInterface } from "jga-patterns-ecs";
import { Command, CommandManager, CommandResultInterface } from "jga-patterns-command";
import { GameMap, PositionInterface } from "jga-games-maps";
 
import { Scheduler } from "./scheduler";
import { Loop } from "./loop";
 
import { Entity, Player } from "./entities";
import { ComponentName, PositionComponent } from "./components";
import { System } from "./systems";
 
export class World extends BaseWorld {
    private player!: Player;
    private scheduler: Scheduler;
    private map: GameMap;
    private loop: Loop;
    private commandManager: CommandManager;
 
    public constructor(scheduler: Scheduler, map: GameMap, commandManager: CommandManager) {
        super();
        this.scheduler = scheduler;
        this.map = map;
        this.loop = new Loop(this.scheduler);
        this.commandManager = commandManager;
    }
 
    public addEntity(entity: Entity, repeatable = false): Map<string, EntityInterface> {
        const entities = super.addEntity(entity);
 
        this.scheduler.add(entity, repeatable);
 
        return entities;
    }
 
    public createPlayer(): Player {
        this.player = new Player(this.generateId());
 
        this.addEntityAtRandomPosition(this.player, true);
 
        return this.getPlayer();
    }
 
    public getPlayer(): Player {
        return this.player;
    }
 
    public getMap(): GameMap {
        return this.map;
    }
 
    public execute(command: Command): CommandResultInterface {
        return this.commandManager.execute(command);
    }
 
    public process(systems: System[]): void {
        return systems.forEach((system): void => {
            system.run(this.map);
        });
    }
 
    public addEntityAtRandomPosition(entity: Entity, repeatable = false): Map<string, EntityInterface> {
        if (true === entity.hasComponent(ComponentName.POSITION)) {
            (entity.getComponent(ComponentName.POSITION) as PositionComponent).setPosition(
                this.getRandomFloorPosition(),
            );
 
            return this.addEntity(entity, repeatable);
        }
 
        return this.entities;
    }
 
    public lock(): Loop {
        return this.loop.lock();
    }
 
    public unlock(): Loop {
        return this.loop.unlock();
    }
 
    public async mainLoop(): Promise<Loop> {
        return this.loop.start();
    }
 
    private getRandomFloorPosition(): PositionInterface {
        let x: number;
        let y: number;
 
        do {
            x = random(0, this.map.getWidth());
            y = random(0, this.map.getHeight());
        } while (null !== this.map.getTile({ x, y }) && !this.map.getTile({ x, y }).isWalkable);
 
        const targets: EntityInterface[] = Array.from(this.entities.values()).filter((entity) => {
            const entityPosition = entity.getComponent(ComponentName.POSITION) as PositionComponent;
 
            return { x, y } === entityPosition.getPosition();
        });
 
        return targets.length === 0 ? { x, y } : this.getRandomFloorPosition();
    }
}