All files / games/src/commands move.ts

100% Statements 113/113
100% Branches 17/17
100% Functions 7/7
100% Lines 113/113

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 1141x 1x 1x 1x 1x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 11x 11x 11x 11x 11x 11x 11x 16x 16x 5x 5x 5x 5x 5x 5x 5x 16x 16x 11x 11x 11x 11x 2x 2x 2x 11x 2x 2x 2x 11x 2x 2x 2x 11x 2x 2x 2x 11x 11x 11x 11x 11x 16x 16x 5x 5x 5x 5x 1x 1x 1x 5x 1x 1x 1x 5x 1x 1x 1x 5x 1x 1x 1x 5x 5x 5x 5x 5x 16x 16x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 12x 16x  
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;
    }
}