Skip to content

Commit

Permalink
Merge pull request #442 from Annoraaq/feature/#242-save-load-state
Browse files Browse the repository at this point in the history
Feature/#242 save load state
  • Loading branch information
Annoraaq authored Oct 22, 2023
2 parents e4a6397 + 679bdef commit aab876f
Show file tree
Hide file tree
Showing 9 changed files with 535 additions and 0 deletions.
30 changes: 30 additions & 0 deletions src/GridCharacter/GridCharacter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,36 @@ describe("GridCharacter", () => {
);
});

it("should set movement progress", () => {
const { gridCharacter } = createDefaultTilemapMock();

expect(gridCharacter.getMovementProgress()).toBe(0);
gridCharacter.setMovementProgress(300);
expect(gridCharacter.getMovementProgress()).toBe(300);

gridCharacter.setMovementProgress(-10);
expect(gridCharacter.getMovementProgress()).toBe(0);

gridCharacter.setMovementProgress(10000);
expect(gridCharacter.getMovementProgress()).toBe(1000);
});

it("should set collidesWithTiles", () => {
const { gridCharacter } = createDefaultTilemapMock();

expect(gridCharacter.collidesWithTiles()).toBe(true);
gridCharacter.setCollidesWithTiles(false);
expect(gridCharacter.collidesWithTiles()).toBe(false);
});

it("should set ignoreMissingTiles", () => {
const { gridCharacter } = createDefaultTilemapMock();

expect(gridCharacter.getIgnoreMissingTiles()).toBe(false);
gridCharacter.setIgnoreMissingTiles(true);
expect(gridCharacter.getIgnoreMissingTiles()).toBe(true);
});

it("should update vertically", () => {
const { gridCharacter } = createDefaultTilemapMock();

Expand Down
13 changes: 13 additions & 0 deletions src/GridCharacter/GridCharacter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,18 @@ export class GridCharacter {
return this.collidesWithTilesInternal;
}

setCollidesWithTiles(collidesWithTiles: boolean): void {
this.collidesWithTilesInternal = collidesWithTiles;
}

getIgnoreMissingTiles(): boolean {
return this.ignoreMissingTiles;
}

setIgnoreMissingTiles(ignoreMissingTiles: boolean): void {
this.ignoreMissingTiles = ignoreMissingTiles;
}

setTilePosition(tilePosition: LayerVecPos): void {
if (this.isMoving()) {
this.movementStopped$.next(this.movementDirection);
Expand Down Expand Up @@ -362,6 +370,11 @@ export class GridCharacter {
return this.movementProgress;
}

setMovementProgress(progress: number): void {
const newProgress = Math.max(0, Math.min(MAX_MOVEMENT_PROGRESS, progress));
this.movementProgress = newProgress;
}

hasWalkedHalfATile(): boolean {
return this.movementProgress > MAX_MOVEMENT_PROGRESS / 2;
}
Expand Down
13 changes: 13 additions & 0 deletions src/GridCharacter/GridCharacterState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Direction } from "../Direction/Direction";
import { CollisionConfig } from "../GridEngineHeadless";
import { LayerPosition } from "../IGridEngine";
import { CharId } from "./GridCharacter";

export interface GridCharacterState {
id: CharId;
position: LayerPosition;
facingDirection: Direction;
speed: number;
movementProgress: number;
collisionConfig: CollisionConfig;
}
171 changes: 171 additions & 0 deletions src/GridEngine.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { NoPathFoundStrategy } from "./Pathfinding/NoPathFoundStrategy.js";
import { PathBlockedStrategy } from "./Pathfinding/PathBlockedStrategy.js";
import { createSpriteMock } from "./Utils/MockFactory/MockFactory.js";
import { createPhaserTilemapStub } from "./Utils/MockFactory/MockPhaserTilemap.js";
import { GridEngineState } from "./GridEngineState.js";

describe("GridEngine", () => {
let gridEngine: GridEngine;
Expand Down Expand Up @@ -2042,6 +2043,176 @@ describe("GridEngine", () => {
);
});

it("should get state", () => {
gridEngine.create(
createPhaserTilemapStub(new Map([["someLayer", ["...", "..."]]])),
{
characters: [
{
id: "char1",
startPosition: { x: 1, y: 0 },
charLayer: "someLayer",
collides: {
collisionGroups: ["cGroup1"],
collidesWithTiles: true,
ignoreMissingTiles: true,
},
speed: 1,
},
{
id: "char2",
startPosition: { x: 2, y: 0 },
charLayer: "someOtherLayer",
collides: {
collisionGroups: ["cGroup2"],
collidesWithTiles: false,
},
},
],
},
);
gridEngine.move("char1", Direction.LEFT);
gridEngine.update(0, 10);

const want: GridEngineState = {
characters: [
{
id: "char1",
position: { position: { x: 1, y: 0 }, charLayer: "someLayer" },
collisionConfig: {
collisionGroups: ["cGroup1"],
collidesWithTiles: true,
ignoreMissingTiles: true,
},
facingDirection: Direction.LEFT,
speed: 1,
movementProgress: 10,
},
{
id: "char2",
position: { position: { x: 2, y: 0 }, charLayer: "someOtherLayer" },
collisionConfig: {
collisionGroups: ["cGroup2"],
collidesWithTiles: false,
ignoreMissingTiles: false,
},
speed: 4,
movementProgress: 0,
facingDirection: Direction.DOWN,
},
],
};

expect(gridEngine.getState()).toEqual(want);
});

it("should set state", () => {
gridEngine.create(
createPhaserTilemapStub(new Map([["someLayer", ["...", "..."]]])),
{
characters: [
{
id: "char1",
startPosition: { x: 1, y: 0 },
charLayer: "someLayer",
collides: {
collisionGroups: ["cGroup1"],
collidesWithTiles: true,
ignoreMissingTiles: true,
},
speed: 1,
},
{
id: "char2",
startPosition: { x: 2, y: 0 },
charLayer: "someOtherLayer",
collides: {
collisionGroups: ["cGroup2"],
collidesWithTiles: false,
},
},
],
},
);

const want: GridEngineState = {
characters: [
{
id: "char1",
position: { position: { x: 2, y: 3 }, charLayer: "someOtherLayer" },
collisionConfig: {
collisionGroups: ["cGroup3"],
collidesWithTiles: false,
ignoreMissingTiles: false,
},
facingDirection: Direction.UP,
speed: 2,
movementProgress: 20,
},
{
id: "char2",
position: { position: { x: 2, y: 0 }, charLayer: "someOtherLayer" },
collisionConfig: {
collisionGroups: ["cGroup2"],
collidesWithTiles: false,
ignoreMissingTiles: false,
},
speed: 4,
movementProgress: 0,
facingDirection: Direction.DOWN,
},
],
};

gridEngine.setState({ characters: [want.characters[0]] });

expect(gridEngine.getState()).toEqual(want);
});

it("should not reset tile position if it did not change", () => {
gridEngine.create(
createPhaserTilemapStub(new Map([["someLayer", ["...", "..."]]])),
{
characters: [
{
id: "char1",
startPosition: { x: 1, y: 0 },
charLayer: "someLayer",
collides: {
collisionGroups: ["cGroup1"],
collidesWithTiles: true,
ignoreMissingTiles: true,
},
speed: 1,
},
],
},
);

const want: GridEngineState = {
characters: [
{
id: "char1",
position: { position: { x: 1, y: 0 }, charLayer: "someLayer" },
collisionConfig: {
collisionGroups: ["cGroup3"],
collidesWithTiles: false,
ignoreMissingTiles: false,
},
facingDirection: Direction.UP,
speed: 2,
movementProgress: 20,
},
],
};

const mock = jest.fn();
gridEngine.positionChangeFinished().subscribe(mock);

gridEngine.setState({ characters: [want.characters[0]] });
expect(mock).not.toHaveBeenCalled();
});

describe("Error Handling unknown char id", () => {
const UNKNOWN_CHAR_ID = "unknownCharId";

Expand Down
19 changes: 19 additions & 0 deletions src/GridEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import {
import { TiledTilemap } from "./GridTilemap/TiledTilemap/TiledTilemap.js";
import { TiledLayer } from "./GridTilemap/TiledTilemap/TiledLayer.js";
import { TiledTile } from "./GridTilemap/TiledTilemap/TiledTile.js";
import { GridEngineState } from "./GridEngineState.js";

export {
ArrayTilemap,
Expand Down Expand Up @@ -930,6 +931,24 @@ export class GridEngine implements IGridEngine {
return this.geHeadless.clearEnqueuedMovements(charId);
}

/**
* {@inheritDoc IGridEngine.getState}
*
* @category GridEngine
*/
getState(): GridEngineState {
return this.geHeadless.getState();
}

/**
* {@inheritDoc IGridEngine.setState}
*
* @category GridEngine
*/
setState(state: GridEngineState): void {
this.geHeadless.setState(state);
}

/**
* {@inheritDoc IGridEngine.getTileCost}
*
Expand Down
Loading

0 comments on commit aab876f

Please sign in to comment.