All files / roguelike-engine/src game.ts

89.74% Statements 105/117
100% Branches 9/9
100% Functions 9/9
89.74% Lines 105/117

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 104 105 106 107 108 109 110 111 112 113 114 115 116 117 1181x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 1x 1x 1x 1x 1x 1x 1x 1x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 5x 1x 1x 5x 5x 7x 7x 5x 5x 3x 3x 3x 3x 3x 3x 3x 3x 5x 5x 5x 5x 5x                         5x 5x 5x 5x 5x 5x 5x 3x 3x 3x 5x  
import {
    CellularMapGenerator,
    GameMap,
    Display,
    World,
    Scheduler,
    Keys,
    TileFactory,
    type DisplayInterface,
    type ScreenInterface,
} from "@jga/games";
 
import { CommandManager } from "@jga/patterns";
 
import { ScreenFactory, type ScreenFactoryCreateParametersInterface } from "./screens/index";
 
import { EntityFactory } from "./entities/index";
 
function createMap(): GameMap {
    const mapWidth = 80;
    const mapHeight = 60;
 
    const generator = new CellularMapGenerator(mapWidth, mapHeight, new TileFactory());
 
    return new GameMap({
        generator,
        height: mapHeight,
        tileFactory: new TileFactory(),
        width: mapWidth,
    });
}
 
export interface GameInterface {
    getCurrentScreen(): ScreenInterface;
    getDisplay(): DisplayInterface;
    switchScreen(screen: ScreenInterface): void;
}
 
export class Game implements GameInterface {
    protected display: DisplayInterface;
 
    protected currentScreen: ScreenInterface;
 
    protected screenFactory: ScreenFactory;
 
    protected engine: World;
 
    private readonly screenHeight = 24;
 
    private readonly screenWidth = 80;
 
    public constructor() {
        this.engine = new World(new Scheduler(), createMap(), new CommandManager(), new EntityFactory());
 
        // Create player;
        this.engine.createPlayer();
 
        this.display = new Display(this.screenHeight, this.screenWidth);
        this.screenFactory = new ScreenFactory();
 
        const createParameters: ScreenFactoryCreateParametersInterface = {
            engine: this.engine,
            type: "start",
            display: this.display,
        };
 
        this.currentScreen = this.screenFactory.create(createParameters);
        this.currentScreen.render();
 
        this.init();
    }
 
    public getCurrentScreen(): ScreenInterface {
        return this.currentScreen;
    }
 
    public getDisplay(): DisplayInterface {
        return this.display;
    }
 
    public switchScreen(screen: ScreenInterface): void {
        this.currentScreen.exit();
        this.getDisplay().clear();
 
        this.currentScreen = screen;
 
        this.currentScreen.enter();
        this.refresh();
    }
 
    private init(): void {
        // eslint-disable-next-line unicorn/consistent-function-scoping
        const bindEventToScreen = (eventName: string): void => {
            window.addEventListener(eventName, (event) => {
                const inputEvent: KeyboardEvent = event as KeyboardEvent;
                const newScreenName = this.currentScreen.handleInput(eventName, { code: inputEvent.code as Keys });

                if (newScreenName !== null) {
                    const newScreen = this.screenFactory.create({
                        type: newScreenName,
                        engine: this.engine,
                        display: this.display,
                    });
                    this.switchScreen(newScreen);
                }
                this.refresh();
            });
        };
 
        bindEventToScreen("keydown");
    }
 
    private refresh(): void {
        this.getDisplay().clear();
        this.currentScreen.render();
    }
}