All files / apps/roguelike/src/game/commands move.ts

100% Statements 42/42
100% Branches 11/11
100% Functions 6/6
100% Lines 42/42

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 118 119 12012x 12x                     12x           16x 16x 16x 16x       11x   11x             5x   5x             11x   11x   2x 2x     2x 2x     2x 2x     2x 2x         11x       5x   5x   1x 1x     1x 1x     1x 1x     1x 1x         5x       12x   12x   12x 12x         12x         12x 12x   12x     12x      
import { Command, CommandResultInterface } from "@jga/patterns";
import {
    Actor,
    ComponentName,
    Entity,
    MovementSystem,
    isPositionComponent,
    World,
    Directions,
    PositionInterface,
} from "@jga/games";
 
export class MoveCommand extends Command {
    protected actor: Actor;
    protected direction: Directions;
    protected engine: World;
 
    public constructor(actor: Actor, direction: Directions, engine: World) {
        super();
        this.actor = actor;
        this.direction = direction;
        this.engine = engine;
    }
 
    public execute(): CommandResultInterface {
        const result = this.move();
 
        return {
            message: `Move => ${this.direction}`,
            result: result,
        };
    }
 
    public undo(): CommandResultInterface | null {
        const result = this.moveBack();
 
        return {
            message: `Move => ${this.direction}`,
            result: result,
        };
    }
 
    protected move(): PositionInterface | null {
        let result: PositionInterface | null = null;
 
        switch (this.direction) {
            case Directions.DOWN: {
                result = this.moveTo(0, 1);
                break;
            }
            case Directions.LEFT: {
                result = this.moveTo(-1, 0);
                break;
            }
            case Directions.RIGHT: {
                result = this.moveTo(1, 0);
                break;
            }
            case Directions.UP: {
                result = this.moveTo(0, -1);
                break;
            }
            default:
        }
 
        return result;
    }
 
    protected moveBack(): PositionInterface | null {
        let result: PositionInterface | null = null;
 
        switch (this.direction) {
            case Directions.DOWN: {
                result = this.moveTo(0, -1);
                break;
            }
            case Directions.LEFT: {
                result = this.moveTo(1, 0);
                break;
            }
            case Directions.RIGHT: {
                result = this.moveTo(-1, 0);
                break;
            }
            case Directions.UP: {
                result = this.moveTo(0, 1);
                break;
            }
            default:
        }
 
        return result;
    }
 
    protected moveTo(dX: number, dY: number): PositionInterface {
        const newPosition: PositionInterface = { x: 0, y: 0 };
 
        const actorPosition = this.actor.getComponent(ComponentName.POSITION);
 
        if (isPositionComponent(actorPosition)) {
            newPosition.x = Math.max(
                0,
                Math.min(this.engine.getMap().getWidth() - 1, actorPosition.getPosition().x + dX),
            );
 
            newPosition.y = Math.max(
                0,
                Math.min(this.engine.getMap().getHeight() - 1, actorPosition.getPosition().y + dY),
            );
 
            const entities = new Map<string, Entity>();
            entities.set(this.actor.getId(), this.actor);
 
            this.engine.run(new MovementSystem(entities, newPosition, this.engine.getEntities()));
        }
 
        return newPosition;
    }
}