All files / games/engine/src engine.ts

100% Statements 34/34
87.5% Branches 7/8
100% Functions 13/13
100% Lines 34/34

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 9711x 11x       11x   11x 11x     11x             11x 11x 11x 11x       7x   7x   7x       2x   2x   2x       3x       2x       1x 1x         4x 3x       3x     1x       1x       1x       1x             4x 8x 8x     4x 1x   1x     4x      
import { random } from "jga-algorithms-random";
import { Engine as BaseEngine, EntityInterface } from "jga-patterns-ecs";
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 Engine extends BaseEngine {
    private player!: Player;
    private scheduler: Scheduler;
    private map: GameMap;
    private loop: Loop;
 
    public constructor(scheduler: Scheduler, map: GameMap) {
        super();
        this.scheduler = scheduler;
        this.map = map;
        this.loop = new Loop(this.scheduler);
    }
 
    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 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();
    }
}