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

100% Statements 43/43
100% Branches 10/10
100% Functions 6/6
100% Lines 43/43

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  12x 12x 12x 12x 12x     20x 20x 20x 20x     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                                                            
import { Command, CommandResultInterface } from "jga-patterns-command";
import { Actor, ComponentName, Entity, MovementSystem, PositionComponent, World } from "jga-games-engine";
import { Directions, PositionInterface } from "jga-games-maps";
 
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 };
 
        newPosition.x = Math.max(
            0,
            Math.min(
                this.engine.getMap().getWidth() - 1,
                (this.actor.getComponent(ComponentName.POSITION) as PositionComponent).getPosition().x + dX,
            ),
        );
 
        newPosition.y = Math.max(
            0,
            Math.min(
                this.engine.getMap().getHeight() - 1,
                (this.actor.getComponent(ComponentName.POSITION) as PositionComponent).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;
    }
}