Merge branch 'develop' of github.com:thecodingmachine/workadventure into metadataScriptingApi

This commit is contained in:
GRL 2021-05-26 10:58:25 +02:00
commit 17261dfab6
35 changed files with 538 additions and 114 deletions

View file

@ -0,0 +1,8 @@
//this file contains all the depth indexes which will be used in our game
export const DEPTH_TILE_INDEX = 0;
//Note: Player characters use their y coordinate as their depth to simulate a perspective.
//See the Character class.
export const DEPTH_OVERLAY_INDEX = 10000;
export const DEPTH_INGAME_TEXT_INDEX = 100000;
export const DEPTH_UI_INDEX = 1000000;

View file

@ -0,0 +1,73 @@
import type {BodyResourceDescriptionInterface} from "../Entity/PlayerTextures";
import {emoteEventStream} from "../../Connexion/EmoteEventStream";
import type {GameScene} from "./GameScene";
import type {RadialMenuItem} from "../Components/RadialMenu";
import LoaderPlugin = Phaser.Loader.LoaderPlugin;
import type {Subscription} from "rxjs";
interface RegisteredEmote extends BodyResourceDescriptionInterface {
name: string;
img: string;
}
export const emotes: {[key: string]: RegisteredEmote} = {
'emote-heart': {name: 'emote-heart', img: 'resources/emotes/heart-emote.png'},
'emote-clap': {name: 'emote-clap', img: 'resources/emotes/clap-emote.png'},
'emote-hand': {name: 'emote-hand', img: 'resources/emotes/hand-emote.png'},
'emote-thanks': {name: 'emote-thanks', img: 'resources/emotes/thanks-emote.png'},
'emote-thumb-up': {name: 'emote-thumb-up', img: 'resources/emotes/thumb-up-emote.png'},
'emote-thumb-down': {name: 'emote-thumb-down', img: 'resources/emotes/thumb-down-emote.png'},
};
export class EmoteManager {
private subscription: Subscription;
constructor(private scene: GameScene) {
this.subscription = emoteEventStream.stream.subscribe((event) => {
const actor = this.scene.MapPlayersByKey.get(event.userId);
if (actor) {
this.lazyLoadEmoteTexture(event.emoteName).then(emoteKey => {
actor.playEmote(emoteKey);
})
}
})
}
createLoadingPromise(loadPlugin: LoaderPlugin, playerResourceDescriptor: BodyResourceDescriptionInterface) {
return new Promise<string>((res) => {
if (loadPlugin.textureManager.exists(playerResourceDescriptor.name)) {
return res(playerResourceDescriptor.name);
}
loadPlugin.image(playerResourceDescriptor.name, playerResourceDescriptor.img);
loadPlugin.once('filecomplete-image-' + playerResourceDescriptor.name, () => res(playerResourceDescriptor.name));
});
}
lazyLoadEmoteTexture(textureKey: string): Promise<string> {
const emoteDescriptor = emotes[textureKey];
if (emoteDescriptor === undefined) {
throw 'Emote not found!';
}
const loadPromise = this.createLoadingPromise(this.scene.load, emoteDescriptor);
this.scene.load.start();
return loadPromise
}
getMenuImages(): Promise<RadialMenuItem[]> {
const promises = [];
for (const key in emotes) {
const promise = this.lazyLoadEmoteTexture(key).then((textureKey) => {
return {
image: textureKey,
name: textureKey,
}
});
promises.push(promise);
}
return Promise.all(promises);
}
destroy() {
this.subscription.unsubscribe();
}
}

View file

@ -1,6 +1,7 @@
import type {ITiledMap, ITiledMapLayer, ITiledMapTileLayer} from "../Map/ITiledMap";
import { flattenGroupLayersMap } from "../Map/LayersFlattener";
import TilemapLayer = Phaser.Tilemaps.TilemapLayer;
import {DEPTH_OVERLAY_INDEX} from "./DepthIndexes";
export type PropertyChangeCallback = (newValue: string | number | boolean | undefined, oldValue: string | number | boolean | undefined, allProps: Map<string, string | boolean | number>) => void;
@ -23,7 +24,7 @@ export class GameMap {
this.phaserLayers.push(phaserMap.createLayer(layer.name, terrains, 0, 0).setDepth(depth));
}
if (layer.type === 'objectgroup' && layer.name === 'floorLayer') {
depth = 10000;
depth = DEPTH_OVERLAY_INDEX;
}
}
}

View file

@ -9,7 +9,7 @@ import type {
PositionInterface,
RoomJoinedMessageInterface
} from "../../Connexion/ConnexionModels";
import { CurrentGamerInterface, hasMovedEventName, Player } from "../Player/Player";
import { hasMovedEventName, Player , requestEmoteEventName} from "../Player/Player";
import {
DEBUG_MODE,
JITSI_PRIVATE_MODE,
@ -90,10 +90,11 @@ import { TextUtils } from "../Components/TextUtils";
import { touchScreenManager } from "../../Touch/TouchScreenManager";
import { PinchManager } from "../UserInput/PinchManager";
import { joystickBaseImg, joystickBaseKey, joystickThumbImg, joystickThumbKey } from "../Components/MobileJoystick";
import { MenuScene, MenuSceneName } from '../Menu/MenuScene';
import {waScaleManager } from "../Services/WaScaleManager";
import { DEPTH_OVERLAY_INDEX } from "./DepthIndexes";
import { waScaleManager } from "../Services/WaScaleManager";
import { EmoteManager } from "./EmoteManager";
import type { HasPlayerMovedEvent } from '../../Api/Events/HasPlayerMovedEvent';
import { MenuScene, MenuSceneName } from '../Menu/MenuScene';
export interface GameSceneInitInterface {
initPosition: PointInterface | null,
@ -134,7 +135,7 @@ const defaultStartLayerName = 'start';
export class GameScene extends DirtyScene implements CenterListener {
Terrains: Array<Phaser.Tilemaps.Tileset>;
CurrentPlayer!: CurrentGamerInterface;
CurrentPlayer!: Player;
MapPlayers!: Phaser.Physics.Arcade.Group;
MapPlayersByKey: Map<number, RemotePlayer> = new Map<number, RemotePlayer>();
Map!: Phaser.Tilemaps.Tilemap;
@ -191,6 +192,7 @@ export class GameScene extends DirtyScene implements CenterListener {
private physicsEnabled: boolean = true;
private mapTransitioning: boolean = false; //used to prevent transitions happenning at the same time.
private onVisibilityChangeCallback: () => void;
private emoteManager!: EmoteManager;
constructor(private room: Room, MapUrlFile: string, customKey?: string | undefined) {
super({
@ -228,6 +230,11 @@ export class GameScene extends DirtyScene implements CenterListener {
this.load.image(joystickBaseKey, joystickBaseImg);
this.load.image(joystickThumbKey, joystickThumbImg);
}
//todo: in an emote manager.
this.load.spritesheet('emote-music', 'resources/emotes/pipo-popupemotes005.png', {
frameHeight: 32,
frameWidth: 32,
});
this.load.on(FILE_LOAD_ERROR, (file: { src: string }) => {
// If we happen to be in HTTP and we are trying to load a URL in HTTPS only... (this happens only in dev environments)
if (window.location.protocol === 'http:' && file.src === this.MapUrlFile && file.src.startsWith('http:') && this.originalMapUrl === undefined) {
@ -502,6 +509,8 @@ export class GameScene extends DirtyScene implements CenterListener {
}
console.log('display');
document.addEventListener('visibilitychange', this.onVisibilityChangeCallback);
this.emoteManager = new EmoteManager(this);
}
/**
@ -986,6 +995,7 @@ ${escapedMessage}
this.messageSubscription?.unsubscribe();
this.userInputManager.destroy();
this.pinchManager?.destroy();
this.emoteManager.destroy();
for (const iframeEvents of this.iframeSubscriptionList) {
iframeEvents.unsubscribe();
@ -1178,6 +1188,12 @@ ${escapedMessage}
this.companion,
this.companion !== null ? lazyLoadCompanionResource(this.load, this.companion) : undefined
);
this.CurrentPlayer.on('pointerdown', () => {
this.emoteManager.getMenuImages().then((emoteMenuElements) => this.CurrentPlayer.openOrCloseEmoteMenu(emoteMenuElements))
})
this.CurrentPlayer.on(requestEmoteEventName, (emoteKey: string) => {
this.connection?.emitEmoteEvent(emoteKey);
})
} catch (err) {
if (err instanceof TextureError) {
gameManager.leaveGame(this, SelectCharacterSceneName, new SelectCharacterScene());