for pathfinding we are now taking into consideration all tiles, looking for 'collides' property
This commit is contained in:
parent
7576cea7e0
commit
391fe7eed3
@ -115,15 +115,11 @@ export class GameMap {
|
||||
}
|
||||
|
||||
public getCollisionsGrid(): number[][] {
|
||||
const collisionsLayer = this.findPhaserLayer("collisions");
|
||||
if (!collisionsLayer) {
|
||||
return [];
|
||||
}
|
||||
const grid: number[][] = [];
|
||||
for (let y = 0; y < collisionsLayer.height; y += 1) {
|
||||
for (let y = 0; y < this.map.height; y += 1) {
|
||||
const row: number[] = [];
|
||||
for (let x = 0; x < collisionsLayer.width; x += 1) {
|
||||
row.push(collisionsLayer.getTileAt(x, y) ? 1 : 0);
|
||||
for (let x = 0; x < this.map.width; x += 1) {
|
||||
row.push(this.isCollidingAt(x, y) ? 1 : 0);
|
||||
}
|
||||
grid.push(row);
|
||||
}
|
||||
@ -138,10 +134,6 @@ export class GameMap {
|
||||
return { x: Math.floor(x / this.map.tilewidth), y: Math.floor(y / this.map.tileheight) };
|
||||
}
|
||||
|
||||
private getLayersByKey(key: number): Array<ITiledMapLayer> {
|
||||
return this.flatLayers.filter((flatLayer) => flatLayer.type === "tilelayer" && flatLayer.data[key] !== 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position of the current player (in pixels)
|
||||
* This will trigger events if properties are changing.
|
||||
@ -167,6 +159,151 @@ export class GameMap {
|
||||
this.triggerLayersChange();
|
||||
}
|
||||
|
||||
public getCurrentProperties(): Map<string, string | boolean | number> {
|
||||
return this.lastProperties;
|
||||
}
|
||||
|
||||
public getMap(): ITiledMap {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves to a tile where the property propName is different from the last tile the user was on.
|
||||
*/
|
||||
public onPropertyChange(propName: string, callback: PropertyChangeCallback) {
|
||||
let callbacksArray = this.propertiesChangeCallbacks.get(propName);
|
||||
if (callbacksArray === undefined) {
|
||||
callbacksArray = new Array<PropertyChangeCallback>();
|
||||
this.propertiesChangeCallbacks.set(propName, callbacksArray);
|
||||
}
|
||||
callbacksArray.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves inside another layer.
|
||||
*/
|
||||
public onEnterLayer(callback: layerChangeCallback) {
|
||||
this.enterLayerCallbacks.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves outside another layer.
|
||||
*/
|
||||
public onLeaveLayer(callback: layerChangeCallback) {
|
||||
this.leaveLayerCallbacks.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves inside another zone.
|
||||
*/
|
||||
public onEnterZone(callback: zoneChangeCallback) {
|
||||
this.enterZoneCallbacks.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves outside another zone.
|
||||
*/
|
||||
public onLeaveZone(callback: zoneChangeCallback) {
|
||||
this.leaveZoneCallbacks.push(callback);
|
||||
}
|
||||
|
||||
public findLayer(layerName: string): ITiledMapLayer | undefined {
|
||||
return this.flatLayers.find((layer) => layer.name === layerName);
|
||||
}
|
||||
|
||||
public findPhaserLayer(layerName: string): TilemapLayer | undefined {
|
||||
return this.phaserLayers.find((layer) => layer.layer.name === layerName);
|
||||
}
|
||||
|
||||
public findPhaserLayers(groupName: string): TilemapLayer[] {
|
||||
return this.phaserLayers.filter((l) => l.layer.name.includes(groupName));
|
||||
}
|
||||
|
||||
public addTerrain(terrain: Phaser.Tilemaps.Tileset): void {
|
||||
for (const phaserLayer of this.phaserLayers) {
|
||||
phaserLayer.tileset.push(terrain);
|
||||
}
|
||||
}
|
||||
|
||||
public putTile(tile: string | number | null, x: number, y: number, layer: string): void {
|
||||
const phaserLayer = this.findPhaserLayer(layer);
|
||||
if (phaserLayer) {
|
||||
if (tile === null) {
|
||||
phaserLayer.putTileAt(-1, x, y);
|
||||
return;
|
||||
}
|
||||
const tileIndex = this.getIndexForTileType(tile);
|
||||
if (tileIndex !== undefined) {
|
||||
this.putTileInFlatLayer(tileIndex, x, y, layer);
|
||||
const phaserTile = phaserLayer.putTileAt(tileIndex, x, y);
|
||||
for (const property of this.getTileProperty(tileIndex)) {
|
||||
if (property.name === GameMapProperties.COLLIDES && property.value) {
|
||||
phaserTile.setCollision(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error("The tile '" + tile + "' that you want to place doesn't exist.");
|
||||
}
|
||||
} else {
|
||||
console.error("The layer '" + layer + "' does not exist (or is not a tilelaye).");
|
||||
}
|
||||
}
|
||||
|
||||
public setLayerProperty(
|
||||
layerName: string,
|
||||
propertyName: string,
|
||||
propertyValue: string | number | undefined | boolean
|
||||
) {
|
||||
const layer = this.findLayer(layerName);
|
||||
if (layer === undefined) {
|
||||
console.warn('Could not find layer "' + layerName + '" when calling setProperty');
|
||||
return;
|
||||
}
|
||||
if (layer.properties === undefined) {
|
||||
layer.properties = [];
|
||||
}
|
||||
const property = layer.properties.find((property) => property.name === propertyName);
|
||||
if (property === undefined) {
|
||||
if (propertyValue === undefined) {
|
||||
return;
|
||||
}
|
||||
layer.properties.push({ name: propertyName, type: typeof propertyValue, value: propertyValue });
|
||||
return;
|
||||
}
|
||||
if (propertyValue === undefined) {
|
||||
const index = layer.properties.indexOf(property);
|
||||
layer.properties.splice(index, 1);
|
||||
}
|
||||
property.value = propertyValue;
|
||||
|
||||
this.triggerAllProperties();
|
||||
this.triggerLayersChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger all the callbacks (used when exiting a map)
|
||||
*/
|
||||
public triggerExitCallbacks(): void {
|
||||
const emptyProps = new Map<string, string | boolean | number>();
|
||||
for (const [oldPropName, oldPropValue] of this.lastProperties.entries()) {
|
||||
// We found a property that disappeared
|
||||
this.trigger(oldPropName, oldPropValue, undefined, emptyProps);
|
||||
}
|
||||
}
|
||||
|
||||
private getLayersByKey(key: number): Array<ITiledMapLayer> {
|
||||
return this.flatLayers.filter((flatLayer) => flatLayer.type === "tilelayer" && flatLayer.data[key] !== 0);
|
||||
}
|
||||
|
||||
private isCollidingAt(x: number, y: number): boolean {
|
||||
for (const layer of this.phaserLayers) {
|
||||
if (layer.getTileAt(x, y)?.properties[GameMapProperties.COLLIDES]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private triggerAllProperties(): void {
|
||||
const newProps = this.getProperties(this.key ?? 0);
|
||||
const oldProps = this.lastProperties;
|
||||
@ -265,10 +402,6 @@ export class GameMap {
|
||||
}
|
||||
}
|
||||
|
||||
public getCurrentProperties(): Map<string, string | boolean | number> {
|
||||
return this.lastProperties;
|
||||
}
|
||||
|
||||
private getProperties(key: number): Map<string, string | boolean | number> {
|
||||
const properties = new Map<string, string | boolean | number>();
|
||||
|
||||
@ -310,10 +443,6 @@ export class GameMap {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public getMap(): ITiledMap {
|
||||
return this.map;
|
||||
}
|
||||
|
||||
private getTileProperty(index: number): Array<ITiledMapProperty> {
|
||||
if (this.tileSetPropertyMap[index]) {
|
||||
return this.tileSetPropertyMap[index];
|
||||
@ -335,64 +464,6 @@ export class GameMap {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves to a tile where the property propName is different from the last tile the user was on.
|
||||
*/
|
||||
public onPropertyChange(propName: string, callback: PropertyChangeCallback) {
|
||||
let callbacksArray = this.propertiesChangeCallbacks.get(propName);
|
||||
if (callbacksArray === undefined) {
|
||||
callbacksArray = new Array<PropertyChangeCallback>();
|
||||
this.propertiesChangeCallbacks.set(propName, callbacksArray);
|
||||
}
|
||||
callbacksArray.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves inside another layer.
|
||||
*/
|
||||
public onEnterLayer(callback: layerChangeCallback) {
|
||||
this.enterLayerCallbacks.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves outside another layer.
|
||||
*/
|
||||
public onLeaveLayer(callback: layerChangeCallback) {
|
||||
this.leaveLayerCallbacks.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves inside another zone.
|
||||
*/
|
||||
public onEnterZone(callback: zoneChangeCallback) {
|
||||
this.enterZoneCallbacks.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a callback called when the user moves outside another zone.
|
||||
*/
|
||||
public onLeaveZone(callback: zoneChangeCallback) {
|
||||
this.leaveZoneCallbacks.push(callback);
|
||||
}
|
||||
|
||||
public findLayer(layerName: string): ITiledMapLayer | undefined {
|
||||
return this.flatLayers.find((layer) => layer.name === layerName);
|
||||
}
|
||||
|
||||
public findPhaserLayer(layerName: string): TilemapLayer | undefined {
|
||||
return this.phaserLayers.find((layer) => layer.layer.name === layerName);
|
||||
}
|
||||
|
||||
public findPhaserLayers(groupName: string): TilemapLayer[] {
|
||||
return this.phaserLayers.filter((l) => l.layer.name.includes(groupName));
|
||||
}
|
||||
|
||||
public addTerrain(terrain: Phaser.Tilemaps.Tileset): void {
|
||||
for (const phaserLayer of this.phaserLayers) {
|
||||
phaserLayer.tileset.push(terrain);
|
||||
}
|
||||
}
|
||||
|
||||
private putTileInFlatLayer(index: number, x: number, y: number, layer: string): void {
|
||||
const fLayer = this.findLayer(layer);
|
||||
if (fLayer == undefined) {
|
||||
@ -414,30 +485,6 @@ export class GameMap {
|
||||
fLayer.data[x + y * fLayer.width] = index;
|
||||
}
|
||||
|
||||
public putTile(tile: string | number | null, x: number, y: number, layer: string): void {
|
||||
const phaserLayer = this.findPhaserLayer(layer);
|
||||
if (phaserLayer) {
|
||||
if (tile === null) {
|
||||
phaserLayer.putTileAt(-1, x, y);
|
||||
return;
|
||||
}
|
||||
const tileIndex = this.getIndexForTileType(tile);
|
||||
if (tileIndex !== undefined) {
|
||||
this.putTileInFlatLayer(tileIndex, x, y, layer);
|
||||
const phaserTile = phaserLayer.putTileAt(tileIndex, x, y);
|
||||
for (const property of this.getTileProperty(tileIndex)) {
|
||||
if (property.name === GameMapProperties.COLLIDES && property.value) {
|
||||
phaserTile.setCollision(true);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.error("The tile '" + tile + "' that you want to place doesn't exist.");
|
||||
}
|
||||
} else {
|
||||
console.error("The layer '" + layer + "' does not exist (or is not a tilelaye).");
|
||||
}
|
||||
}
|
||||
|
||||
private getIndexForTileType(tile: string | number): number | undefined {
|
||||
if (typeof tile == "number") {
|
||||
return tile;
|
||||
@ -445,48 +492,6 @@ export class GameMap {
|
||||
return this.tileNameMap.get(tile);
|
||||
}
|
||||
|
||||
public setLayerProperty(
|
||||
layerName: string,
|
||||
propertyName: string,
|
||||
propertyValue: string | number | undefined | boolean
|
||||
) {
|
||||
const layer = this.findLayer(layerName);
|
||||
if (layer === undefined) {
|
||||
console.warn('Could not find layer "' + layerName + '" when calling setProperty');
|
||||
return;
|
||||
}
|
||||
if (layer.properties === undefined) {
|
||||
layer.properties = [];
|
||||
}
|
||||
const property = layer.properties.find((property) => property.name === propertyName);
|
||||
if (property === undefined) {
|
||||
if (propertyValue === undefined) {
|
||||
return;
|
||||
}
|
||||
layer.properties.push({ name: propertyName, type: typeof propertyValue, value: propertyValue });
|
||||
return;
|
||||
}
|
||||
if (propertyValue === undefined) {
|
||||
const index = layer.properties.indexOf(property);
|
||||
layer.properties.splice(index, 1);
|
||||
}
|
||||
property.value = propertyValue;
|
||||
|
||||
this.triggerAllProperties();
|
||||
this.triggerLayersChange();
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger all the callbacks (used when exiting a map)
|
||||
*/
|
||||
public triggerExitCallbacks(): void {
|
||||
const emptyProps = new Map<string, string | boolean | number>();
|
||||
for (const [oldPropName, oldPropValue] of this.lastProperties.entries()) {
|
||||
// We found a property that disappeared
|
||||
this.trigger(oldPropName, oldPropValue, undefined, emptyProps);
|
||||
}
|
||||
}
|
||||
|
||||
private getObjectsFromLayers(layers: ITiledMapLayer[]): ITiledMapObject[] {
|
||||
const objects: ITiledMapObject[] = [];
|
||||
|
||||
|
@ -42,12 +42,16 @@ export class Player extends Character {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.pathToFollow && activeUserInputEvents.anyExcept(UserInputEvent.SpeedUp)) {
|
||||
this.pathToFollow = undefined;
|
||||
}
|
||||
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
if ((state === "active" || state === "ending") && role === "follower") {
|
||||
[x, y] = this.computeFollowMovement();
|
||||
}
|
||||
if (this.pathToFollow && this.pathToFollow.length !== 0) {
|
||||
if (this.pathToFollow) {
|
||||
[x, y] = this.computeFollowPathMovement();
|
||||
}
|
||||
this.inputStep(activeUserInputEvents, x, y);
|
||||
@ -144,7 +148,10 @@ export class Player extends Character {
|
||||
}
|
||||
|
||||
private computeFollowPathMovement(): number[] {
|
||||
if (!this.pathToFollow || this.pathToFollow.length === 0) {
|
||||
if (this.pathToFollow?.length === 0) {
|
||||
this.pathToFollow = undefined;
|
||||
}
|
||||
if (!this.pathToFollow) {
|
||||
return [0, 0];
|
||||
}
|
||||
const nextStep = this.pathToFollow[0];
|
||||
@ -153,7 +160,7 @@ export class Player extends Character {
|
||||
const xDistance = nextStep.x - this.x;
|
||||
const yDistance = nextStep.y - this.y;
|
||||
const distance = Math.pow(xDistance, 2) + Math.pow(yDistance, 2);
|
||||
if (distance < 10) {
|
||||
if (distance < 200) {
|
||||
this.pathToFollow.shift();
|
||||
}
|
||||
return this.getMovementDirection(xDistance, yDistance, distance);
|
||||
|
@ -37,6 +37,15 @@ export class ActiveEventList {
|
||||
any(): boolean {
|
||||
return Array.from(this.eventMap.values()).reduce((accu, curr) => accu || curr, false);
|
||||
}
|
||||
anyExcept(...exceptions: UserInputEvent[]): boolean {
|
||||
const userInputEvents = Array.from(this.eventMap);
|
||||
for (const event of userInputEvents) {
|
||||
if (event[1] && !exceptions.includes(event[0])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//this class is responsible for catching user inputs and listing all active user actions at every game tick events.
|
||||
|
Loading…
Reference in New Issue
Block a user