All files / games/src/commands move.ts

100% Statements 43/43
100% Branches 11/11
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 11444x 44x 44x   44x               12x 12x 12x 12x       7x   7x             5x   5x             7x   7x   1x 1x     1x 1x     1x 1x     1x 1x         7x       5x   5x   1x 1x     1x 1x     1x 1x     1x 1x         5x       8x   8x   8x 8x         8x         8x 8x   8x     8x      
import { Command, type CommandResultInterface } from "@jga/patterns";
import { Directions, type PositionInterface } from "../maps/index";
import { Actor, ComponentName, Entity, isPositionComponent, MovementSystem, World } from "../engine/index";
 
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,
        };
    }
 
    public undo(): CommandResultInterface | null {
        const result = this.moveBack();
 
        return {
            message: `Move => ${this.direction}`,
            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;
    }
}