diff --git a/front/src/Phaser/Game/GameScene.ts b/front/src/Phaser/Game/GameScene.ts index d487e422..32085030 100644 --- a/front/src/Phaser/Game/GameScene.ts +++ b/front/src/Phaser/Game/GameScene.ts @@ -96,6 +96,7 @@ import {DEPTH_OVERLAY_INDEX} from "./DepthIndexes"; import {waScaleManager} from "../Services/WaScaleManager"; import {peerStore} from "../../Stores/PeerStore"; import {EmoteManager} from "./EmoteManager"; +import { InteractiveLayer } from "../Map/InteractiveLayer"; export interface GameSceneInitInterface { initPosition: PointInterface|null, @@ -418,15 +419,19 @@ export class GameScene extends DirtyScene implements CenterListener { let depth = -2; for (const layer of this.gameMap.layersIterator) { if (layer.type === 'tilelayer') { - this.addLayer(this.Map.createLayer(layer.name, this.Terrains, 0, 0).setDepth(depth)); + if (this.isLayerInteractive(layer) === false) { + this.addLayer(this.Map.createLayer(layer.name, this.Terrains, 0, 0).setDepth(depth)); - const exitSceneUrl = this.getExitSceneUrl(layer); - if (exitSceneUrl !== undefined) { - this.loadNextGame(exitSceneUrl); - } - const exitUrl = this.getExitUrl(layer); - if (exitUrl !== undefined) { - this.loadNextGame(exitUrl); + const exitSceneUrl = this.getExitSceneUrl(layer); + if (exitSceneUrl !== undefined) { + this.loadNextGame(exitSceneUrl); + } + const exitUrl = this.getExitUrl(layer); + if (exitUrl !== undefined) { + this.loadNextGame(exitUrl); + } + } else { + this.addInteractiveLayer(layer); } } if (layer.type === 'objectgroup' && layer.name === 'floorLayer') { @@ -1058,6 +1063,10 @@ ${escapedMessage} return this.getProperty(layer, "exitUrl") as string|undefined; } + private isLayerInteractive(layer: ITiledMapLayer): boolean { + return Boolean(this.getProperty(layer, "interactive")); + } + /** * @deprecated the map property exitSceneUrl is deprecated */ @@ -1138,6 +1147,10 @@ ${escapedMessage} this.Layers.push(Layer); } + addInteractiveLayer(layer: ITiledMapLayer): void { + new InteractiveLayer(this, layer); + } + createCollisionWithPlayer() { //add collision layer this.Layers.forEach((Layer: Phaser.Tilemaps.TilemapLayer) => { diff --git a/front/src/Phaser/Map/InteractiveLayer.ts b/front/src/Phaser/Map/InteractiveLayer.ts new file mode 100644 index 00000000..867cc35b --- /dev/null +++ b/front/src/Phaser/Map/InteractiveLayer.ts @@ -0,0 +1,159 @@ +import Sprite = Phaser.GameObjects.Sprite; +import Container = Phaser.GameObjects.Container; +import type { ITiledMapLayer } from "./ITiledMap"; +import type { GameScene } from "../Game/GameScene"; + +export class InteractiveLayer extends Container { + private activeSprite: string|null; + private spritesCollection: Array<{ + animation: string; + sprite: Sprite; + }>; + + private updateListener: Function; + + constructor(scene: GameScene, layer: ITiledMapLayer) { + const { x, y } = layer; + + super(scene, x, y); + + this.activeSprite = null; + this.spritesCollection = []; + + this.addSprites(layer); + + this.updateListener = this.update.bind(this); + scene.events.addListener('update', this.updateListener); + + this.setDepth(-2); + this.scene.add.existing(this); + } + + public update(): void { + const scene = this.getScene(); + + const x = scene.CurrentPlayer.x + scene.CurrentPlayer.width; + const y = scene.CurrentPlayer.y + scene.CurrentPlayer.height * 2; + + let foundSprite = false; + + for (const i in this.spritesCollection) { + const entity = this.spritesCollection[i]; + const sprite = entity.sprite; + + if (sprite.x < x && sprite.y < y && sprite.x + sprite.width > x && sprite.y + sprite.height > y) { + if (this.activeSprite !== i) { + sprite.play(entity.animation, true); + } + + foundSprite = true; + this.activeSprite = i; + break; + } + } + + if (foundSprite === false) { + this.activeSprite = null; + } + } + + public destroy(): void { + const scene = this.getScene(); + + for (const entity of this.spritesCollection) { + if (scene) { + scene.sys.updateList.remove(entity.sprite); + } + } + + if (scene) { + scene.events.removeListener('update', this.updateListener); + } + + super.destroy(); + } + + private addSprites(layer: ITiledMapLayer): void { + if (typeof layer.data === "string") { + return; + } + + const scene = this.getScene(); + + for (let i = 0; i < layer.data.length; i++) { + const index = layer.data[i]; + + if (index !== 0) { + const tileset = this.getTileset(index); + + if (tileset !== null) { + const x = (i % layer.width) * tileset.tileWidth; + const y = (Math.floor(i / layer.width)) * tileset.tileHeight; + + const animation = this.getAnimationFromTile(tileset, index); + const key = `interactive-layer-${tileset.name}-${index}`; + + if (animation !== null) { + if (typeof scene.anims.get(key) === 'undefined') { + for (const j in animation) { + if (!tileset.image.has(String(animation[j].tileid))) { + const frameCoordinates = (tileset.getTileTextureCoordinates(animation[j].tileid + tileset.firstgid) as any); + tileset.image.add(animation[j].tileid, 0, frameCoordinates.x, frameCoordinates.y, tileset.tileWidth, tileset.tileHeight); + } + } + + scene.anims.create({ + key, + frames: animation.map(frame => ({ + key: tileset.image.key, + frame: frame.tileid, + duration: frame.duration + })), + repeat: 0 + }); + } + } + + const sprite = new Sprite(scene, x, y, tileset.image, 0); + + scene.sys.updateList.add(sprite); + + this.add(sprite); + this.spritesCollection.push({ + animation: key, + sprite + }); + } + } + } + } + + private getTileset(index: number): Phaser.Tilemaps.Tileset|null { + const scene = this.getScene(); + + for (const i in scene.Map.tilesets) { + const tileset = scene.Map.tilesets[i]; + + if (tileset.getTileData(index) !== null) { + return tileset; + } + } + + return null; + } + + private getAnimationFromTile(tileset: Phaser.Tilemaps.Tileset, index: number) { + const data = tileset.getTileData(index); + + if (typeof data === "object" && data !== null && Array.isArray((data as any).animation)) { + const animation: Array<{duration: number; tileid: number}> = (data as any).animation; + return animation; + } + + return null + } + + private getScene(): GameScene { + return (this.scene as GameScene); + } +} diff --git a/maps/Interactive/tiles/plate.aseprite b/maps/Interactive/tiles/plate.aseprite new file mode 100644 index 00000000..29a2ddff Binary files /dev/null and b/maps/Interactive/tiles/plate.aseprite differ diff --git a/maps/Interactive/tiles/plate.png b/maps/Interactive/tiles/plate.png new file mode 100644 index 00000000..a7e8732b Binary files /dev/null and b/maps/Interactive/tiles/plate.png differ