Skip to content

Commit

Permalink
Merge pull request #486 from Annoraaq/bugfix/#485-fix-follow-multidir
Browse files Browse the repository at this point in the history
Bugfix/#485 fix follow multidir
  • Loading branch information
Annoraaq committed May 11, 2024
2 parents f97c614 + 1f86138 commit 2fc576f
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 18 deletions.
1 change: 1 addition & 0 deletions serve/js/phaser-3.80.1.min.js

Large diffs are not rendered by default.

77 changes: 72 additions & 5 deletions src/Movement/FollowMovement/FollowMovement.test.ts
Expand Up @@ -78,8 +78,8 @@ describe("FollowMovement", () => {
maxPathLength: Infinity,
ignoreLayers: false,
considerCosts: false,
ignoredChars: [targetChar.getId()],
},
ignoreBlockedTarget: true,
},
);
});
Expand All @@ -103,8 +103,8 @@ describe("FollowMovement", () => {
maxPathLength: Infinity,
ignoreLayers: false,
considerCosts: false,
ignoredChars: [targetChar.getId()],
},
ignoreBlockedTarget: true,
});
});

Expand Down Expand Up @@ -152,8 +152,8 @@ describe("FollowMovement", () => {
maxPathLength: 100,
ignoreLayers: true,
considerCosts: false,
ignoredChars: [targetChar.getId()],
},
ignoreBlockedTarget: true,
},
);
});
Expand Down Expand Up @@ -198,6 +198,73 @@ describe("FollowMovement", () => {
},
);

it.each([
{
dir: Direction.DOWN,
wantPos: { position: { x: 2, y: 1 }, layer: "layer1" },
},
{
dir: Direction.DOWN_LEFT,
wantPos: { position: { x: 2, y: 0 }, layer: "layer1" },
},
{
dir: Direction.DOWN_RIGHT,
wantPos: { position: { x: 2, y: 3 }, layer: "layer1" },
},
{
dir: Direction.UP,
wantPos: { position: { x: 5, y: 1 }, layer: "layer1" },
},
{
dir: Direction.UP_LEFT,
wantPos: { position: { x: 5, y: 0 }, layer: "layer1" },
},
{
dir: Direction.UP_RIGHT,
wantPos: { position: { x: 5, y: 3 }, layer: "layer1" },
},
{
dir: Direction.LEFT,
wantPos: { position: { x: 3, y: 0 }, layer: "layer1" },
},
{
dir: Direction.RIGHT,
wantPos: { position: { x: 3, y: 3 }, layer: "layer1" },
},
])(
"should update added multi-tile character with facing direction '$dir'",
({ dir, wantPos }) => {
const targetChar = new GridCharacter("targetChar", {
speed: 3,
collidesWithTiles: true,
numberOfDirections: NumberOfDirections.EIGHT,
tilemap: gridTilemap,
tileWidth: 2,
tileHeight: 2,
});

const targetCharPos = { position: new Vector2(3, 1), layer: "layer1" };
targetChar.setTilePosition(targetCharPos);
targetChar.turnTowards(Direction.RIGHT);
followMovement = new FollowMovement(char, gridTilemap, targetChar, {
distance: 0,
noPathFoundStrategy: NoPathFoundStrategy.STOP,
maxPathLength: 100,
ignoreLayers: true,
facingDirection: dir,
});
followMovement.update(100);
expect(TargetMovement).toHaveBeenCalledWith(
char,
gridTilemap,
wantPos,
expect.objectContaining({
distance: 0,
}),
);
},
);

it("should not update facing direction if distance > 0", () => {
targetChar.turnTowards(Direction.RIGHT);
followMovement = new FollowMovement(char, gridTilemap, targetChar, {
Expand Down Expand Up @@ -236,8 +303,8 @@ describe("FollowMovement", () => {
maxPathLength: Infinity,
ignoreLayers: false,
considerCosts: false,
ignoredChars: [targetChar.getId()],
},
ignoreBlockedTarget: true,
},
);
});
Expand All @@ -260,8 +327,8 @@ describe("FollowMovement", () => {
maxPathLength: Infinity,
ignoreLayers: false,
considerCosts: true,
ignoredChars: [targetChar.getId()],
},
ignoreBlockedTarget: true,
},
);
});
Expand Down
45 changes: 34 additions & 11 deletions src/Movement/FollowMovement/FollowMovement.ts
Expand Up @@ -103,21 +103,44 @@ export class FollowMovement implements Movement {
};
}

private getFacingPos(): Position {
const turnCount =
dirToNumber[this.options.facingDirection] +
dirToNumber[this.charToFollow.getFacingDirection()];

const newDir: Direction = turnClockwise(Direction.UP, turnCount);

const refPos = {
x: this.charToFollow.getTilePos().position.x,
y: this.charToFollow.getTilePos().position.y,
};
if (newDir === Direction.RIGHT) {
refPos.x += this.charToFollow.getTileWidth() - 1;
} else if (newDir === Direction.DOWN) {
refPos.y += this.charToFollow.getTileWidth() - 1;
} else if (newDir === Direction.DOWN_LEFT) {
refPos.y += this.charToFollow.getTileWidth() - 1;
} else if (newDir === Direction.DOWN_RIGHT) {
refPos.y += this.charToFollow.getTileWidth() - 1;
refPos.x += this.charToFollow.getTileWidth() - 1;
} else if (newDir === Direction.UP_RIGHT) {
refPos.x += this.charToFollow.getTileWidth() - 1;
}
return this.gridTilemap.getTilePosInDirection(
{
position: new Vector2(refPos),
layer: this.charToFollow.getTilePos().layer,
},
newDir,
).position;
}

private updateTarget(targetPos: Position, targetLayer: CharLayer): void {
const useFacingDir =
this.options.facingDirection !== Direction.NONE &&
this.options.distance === 0;
if (useFacingDir) {
const turnCount =
dirToNumber[this.options.facingDirection] +
dirToNumber[this.charToFollow.getFacingDirection()];

const newDir: Direction = turnClockwise(Direction.UP, turnCount);

targetPos = this.gridTilemap.getTilePosInDirection(
{ position: new Vector2(targetPos), layer: targetLayer },
newDir,
).position;
targetPos = this.getFacingPos();
}
this.targetMovement = new TargetMovement(
this.character,
Expand All @@ -134,8 +157,8 @@ export class FollowMovement implements Movement {
maxPathLength: this.options.maxPathLength,
ignoreLayers: this.options.ignoreLayers,
considerCosts: this.options.considerCosts,
ignoredChars: [this.charToFollow.getId()],
},
ignoreBlockedTarget: true,
},
);
}
Expand Down
45 changes: 45 additions & 0 deletions src/Movement/TargetMovement/TargetMovement.test.ts
Expand Up @@ -1875,6 +1875,51 @@ describe("TargetMovement", () => {
);
});

it("should not consider ignored blocking chars", () => {
const charPos = layerPos(new Vector2(1, 0));
const targetPos = layerPos(new Vector2(1, 2));
const mockChar = createMockChar("char", charPos, {
...TEST_CHAR_CONFIG,
tilemap: gridTilemap,
});

const blockMap = [
{
layer: "lowerCharLayer",
blockMap: [
// prettier-ignore
".s..",
"ccc.",
".t..",
],
},
];
tilemapMock = mockLayeredBlockMap(blockMap);
gridTilemap = new GridTilemap(
tilemapMock,
"ge_collide",
CollisionStrategy.BLOCK_TWO_TILES,
);
mockCharMap(gridTilemap, blockMap);
gridTilemap.addCharacter(mockChar);

targetMovement = new TargetMovement(mockChar, gridTilemap, targetPos, {
config: {
algorithm: shortestPathAlgo,
ignoredChars: [mockChar.getId()],
},
});

expectWalkedPath(
targetMovement,
mockChar,
createPath([
[1, 1],
[1, 2],
]),
);
});

it("should not collide with tiles", () => {
const charPos = layerPos(new Vector2(1, 0));
const targetPos = layerPos(new Vector2(1, 2));
Expand Down
11 changes: 9 additions & 2 deletions src/Movement/TargetMovement/TargetMovement.ts
Expand Up @@ -10,7 +10,7 @@ import {
} from "./../../Pathfinding/ShortestPathAlgorithm.js";
import { DistanceUtils } from "./../../Utils/DistanceUtils.js";
import { GridTilemap } from "../../GridTilemap/GridTilemap.js";
import { GridCharacter } from "../../GridCharacter/GridCharacter.js";
import { CharId, GridCharacter } from "../../GridCharacter/GridCharacter.js";
import { Direction } from "../../Direction/Direction.js";
import { Movement, MovementInfo } from "../Movement.js";
import { Vector2 } from "../../Utils/Vector2/Vector2.js";
Expand Down Expand Up @@ -147,6 +147,11 @@ export interface MoveToConfig {
* In case all these targets are blocked this is the fallback strategy.
*/
noPathFoundAlternativeTargetsFallbackStrategy?: NoPathFoundStrategy;

/**
* Set of characters to ignore at collision checking.
*/
ignoredChars?: CharId[];
}

/**
Expand Down Expand Up @@ -218,6 +223,7 @@ export class TargetMovement implements Movement {
"BIDIRECTIONAL_SEARCH";
private maxPathLength = Infinity;
private considerCosts = false;
private ignoredChars: CharId[] = [];

constructor(
private character: GridCharacter,
Expand Down Expand Up @@ -286,6 +292,7 @@ export class TargetMovement implements Movement {
character.getNumberOfDirections(),
);
this.pathBlockedWaitTimeoutMs = config?.pathBlockedWaitTimeoutMs || -1;
this.ignoredChars = config?.ignoredChars ?? [];
this.finished$ = new Subject<Finished>();
this.setCharacter(character);
}
Expand Down Expand Up @@ -323,7 +330,7 @@ export class TargetMovement implements Movement {
numberOfDirections: this.character.getNumberOfDirections(),
isPositionAllowed: this.isPositionAllowed,
collisionGroups: this.character.getCollisionGroups(),
ignoredChars: [this.character.getId()],
ignoredChars: [this.character.getId(), ...this.ignoredChars],
ignoreTiles: !this.character.collidesWithTiles(),
ignoreMapBounds: this.character.getIgnoreMissingTiles(),
ignoreBlockedTarget: this.ignoreBlockedTarget,
Expand Down

0 comments on commit 2fc576f

Please sign in to comment.