Adding custom character textures
This commit is contained in:
parent
a3816cd725
commit
78a4bf3189
22 changed files with 262 additions and 95 deletions
|
@ -21,7 +21,7 @@ class ConnectionManager {
|
|||
if(connexionType === GameConnexionTypes.register) {
|
||||
const organizationMemberToken = urlManager.getOrganizationToken();
|
||||
const data = await Axios.post(`${API_URL}/register`, {organizationMemberToken}).then(res => res.data);
|
||||
this.localUser = new LocalUser(data.userUuid, data.authToken);
|
||||
this.localUser = new LocalUser(data.userUuid, data.authToken, data.textures);
|
||||
localUserStore.saveUser(this.localUser);
|
||||
|
||||
const organizationSlug = data.organizationSlug;
|
||||
|
@ -34,7 +34,7 @@ class ConnectionManager {
|
|||
} else if (connexionType === GameConnexionTypes.anonymous || connexionType === GameConnexionTypes.empty) {
|
||||
const localUser = localUserStore.getLocalUser();
|
||||
|
||||
if (localUser && localUser.jwtToken && localUser.uuid) {
|
||||
if (localUser && localUser.jwtToken && localUser.uuid && localUser.textures) {
|
||||
this.localUser = localUser;
|
||||
try {
|
||||
await this.verifyToken(localUser.jwtToken);
|
||||
|
@ -78,12 +78,12 @@ class ConnectionManager {
|
|||
|
||||
private async anonymousLogin(): Promise<void> {
|
||||
const data = await Axios.post(`${API_URL}/anonymLogin`).then(res => res.data);
|
||||
this.localUser = new LocalUser(data.userUuid, data.authToken);
|
||||
this.localUser = new LocalUser(data.userUuid, data.authToken, []);
|
||||
localUserStore.saveUser(this.localUser);
|
||||
}
|
||||
|
||||
public initBenchmark(): void {
|
||||
this.localUser = new LocalUser('', 'test');
|
||||
this.localUser = new LocalUser('', 'test', []);
|
||||
}
|
||||
|
||||
public connectToRoomSocket(roomId: string, name: string, characterLayers: string[], position: PositionInterface, viewport: ViewportInterface): Promise<RoomConnection> {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {PlayerAnimationNames} from "../Phaser/Player/Animation";
|
||||
import {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
|
||||
import {SignalData} from "simple-peer";
|
||||
import {BodyResourceDescriptionInterface} from "../Phaser/Entity/body_character";
|
||||
|
||||
export enum EventMessage{
|
||||
WEBRTC_SIGNAL = "webrtc-signal",
|
||||
|
@ -49,7 +50,7 @@ export class Point implements PointInterface{
|
|||
export interface MessageUserPositionInterface {
|
||||
userId: number;
|
||||
name: string;
|
||||
characterLayers: string[];
|
||||
characterLayers: BodyResourceDescriptionInterface[];
|
||||
position: PointInterface;
|
||||
}
|
||||
|
||||
|
@ -61,7 +62,7 @@ export interface MessageUserMovedInterface {
|
|||
export interface MessageUserJoined {
|
||||
userId: number;
|
||||
name: string;
|
||||
characterLayers: string[];
|
||||
characterLayers: BodyResourceDescriptionInterface[];
|
||||
position: PointInterface
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
export interface CharacterTexture {
|
||||
id: number,
|
||||
level: number,
|
||||
url: string,
|
||||
rights: string
|
||||
}
|
||||
|
||||
export class LocalUser {
|
||||
public uuid: string;
|
||||
public jwtToken: string;
|
||||
|
||||
constructor(uuid:string, jwtToken: string) {
|
||||
this.uuid = uuid;
|
||||
this.jwtToken = jwtToken;
|
||||
constructor(public readonly uuid:string, public readonly jwtToken: string, public readonly textures: CharacterTexture[]) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,11 @@ import {
|
|||
WebRtcSignalToServerMessage,
|
||||
WebRtcStartMessage,
|
||||
ReportPlayerMessage,
|
||||
TeleportMessageMessage, QueryJitsiJwtMessage, SendJitsiJwtMessage, SendUserMessage
|
||||
TeleportMessageMessage,
|
||||
QueryJitsiJwtMessage,
|
||||
SendJitsiJwtMessage,
|
||||
CharacterLayerMessage,
|
||||
SendUserMessage
|
||||
} from "../Messages/generated/messages_pb"
|
||||
|
||||
import {UserSimplePeerInterface} from "../WebRtc/SimplePeer";
|
||||
|
@ -36,6 +40,7 @@ import {
|
|||
ViewportInterface, WebRtcDisconnectMessageInterface,
|
||||
WebRtcSignalReceivedMessageInterface,
|
||||
} from "./ConnexionModels";
|
||||
import {BodyResourceDescriptionInterface} from "../Phaser/Entity/body_character";
|
||||
|
||||
export class RoomConnection implements RoomConnection {
|
||||
private readonly socket: WebSocket;
|
||||
|
@ -169,10 +174,10 @@ export class RoomConnection implements RoomConnection {
|
|||
}
|
||||
}
|
||||
|
||||
public emitPlayerDetailsMessage(userName: string, characterLayersSelected: string[]) {
|
||||
public emitPlayerDetailsMessage(userName: string, characterLayersSelected: BodyResourceDescriptionInterface[]) {
|
||||
const message = new SetPlayerDetailsMessage();
|
||||
message.setName(userName);
|
||||
message.setCharacterlayersList(characterLayersSelected);
|
||||
message.setCharacterlayersList(characterLayersSelected.map((characterLayer) => characterLayer.name));
|
||||
|
||||
const clientToServerMessage = new ClientToServerMessage();
|
||||
clientToServerMessage.setSetplayerdetailsmessage(message);
|
||||
|
@ -277,10 +282,18 @@ export class RoomConnection implements RoomConnection {
|
|||
if (position === undefined) {
|
||||
throw new Error('Invalid JOIN_ROOM message');
|
||||
}
|
||||
|
||||
const characterLayers = message.getCharacterlayersList().map((characterLayer: CharacterLayerMessage): BodyResourceDescriptionInterface => {
|
||||
return {
|
||||
name: characterLayer.getName(),
|
||||
img: characterLayer.getUrl()
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
userId: message.getUserid(),
|
||||
name: message.getName(),
|
||||
characterLayers: message.getCharacterlayersList(),
|
||||
characterLayers,
|
||||
position: ProtobufClientUtils.toPointInterface(position)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,22 +61,7 @@ export abstract class Character extends Container {
|
|||
|
||||
this.sprites = new Map<string, Sprite>();
|
||||
|
||||
for (const texture of textures) {
|
||||
const sprite = new Sprite(scene, 0, 0, texture, frame);
|
||||
sprite.setInteractive({useHandCursor: true});
|
||||
this.add(sprite);
|
||||
this.getPlayerAnimations(texture).forEach(d => {
|
||||
this.scene.anims.create({
|
||||
key: d.key,
|
||||
frames: this.scene.anims.generateFrameNumbers(d.frameModel, {start: d.frameStart, end: d.frameEnd}),
|
||||
frameRate: d.frameRate,
|
||||
repeat: d.repeat
|
||||
});
|
||||
})
|
||||
// Needed, otherwise, animations are not handled correctly.
|
||||
this.scene.sys.updateList.add(sprite);
|
||||
this.sprites.set(texture, sprite);
|
||||
}
|
||||
this.addTextures(textures, frame);
|
||||
|
||||
/*this.teleportation = new Sprite(scene, -20, -10, 'teleportation', 3);
|
||||
this.teleportation.setInteractive();
|
||||
|
@ -107,6 +92,25 @@ export abstract class Character extends Container {
|
|||
this.playAnimation(direction, moving);
|
||||
}
|
||||
|
||||
public addTextures(textures: string[], frame?: string | number): void {
|
||||
for (const texture of textures) {
|
||||
const sprite = new Sprite(this.scene, 0, 0, texture, frame);
|
||||
sprite.setInteractive({useHandCursor: true});
|
||||
this.add(sprite);
|
||||
this.getPlayerAnimations(texture).forEach(d => {
|
||||
this.scene.anims.create({
|
||||
key: d.key,
|
||||
frames: this.scene.anims.generateFrameNumbers(d.frameModel, {start: d.frameStart, end: d.frameEnd}),
|
||||
frameRate: d.frameRate,
|
||||
repeat: d.repeat
|
||||
});
|
||||
})
|
||||
// Needed, otherwise, animations are not handled correctly.
|
||||
this.scene.sys.updateList.add(sprite);
|
||||
this.sprites.set(texture, sprite);
|
||||
}
|
||||
}
|
||||
|
||||
private getPlayerAnimations(name: string): AnimationData[] {
|
||||
return [{
|
||||
key: `${name}-${PlayerAnimationNames.WalkDown}`,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import LoaderPlugin = Phaser.Loader.LoaderPlugin;
|
||||
import {PLAYER_RESOURCES, PlayerResourceDescriptionInterface} from "./Character";
|
||||
import {CharacterTexture} from "../../Connexion/LocalUser";
|
||||
|
||||
export interface BodyResourceDescriptionInterface {
|
||||
name: string,
|
||||
|
@ -312,6 +313,15 @@ export const loadAllLayers = (load: LoaderPlugin) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const loadCustomTexture = (load: LoaderPlugin, texture: CharacterTexture) => {
|
||||
const name = 'customCharacterTexture'+texture.id;
|
||||
load.spritesheet(
|
||||
name,
|
||||
texture.url,
|
||||
{frameWidth: 32, frameHeight: 32}
|
||||
);
|
||||
}
|
||||
|
||||
export const OBJECTS: Array<PlayerResourceDescriptionInterface> = [
|
||||
{name:'layout_modes', img:'resources/objects/layout_modes.png'},
|
||||
{name:'teleportation', img:'resources/objects/teleportation.png'},
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import {PointInterface} from "../../Connexion/ConnexionModels";
|
||||
import {BodyResourceDescriptionInterface} from "../Entity/body_character";
|
||||
|
||||
export interface AddPlayerInterface {
|
||||
userId: number;
|
||||
name: string;
|
||||
characterLayers: string[];
|
||||
characterLayers: BodyResourceDescriptionInterface[];
|
||||
position: PointInterface;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import {RemotePlayer} from "../Entity/RemotePlayer";
|
|||
import {Queue} from 'queue-typescript';
|
||||
import {SimplePeer, UserSimplePeerInterface} from "../../WebRtc/SimplePeer";
|
||||
import {ReconnectingSceneName} from "../Reconnecting/ReconnectingScene";
|
||||
import {loadAllLayers, loadObject, loadPlayerCharacters} from "../Entity/body_character";
|
||||
import {loadAllLayers, loadCustomTexture, loadObject, loadPlayerCharacters} from "../Entity/body_character";
|
||||
import {CenterListener, layoutManager, LayoutMode} from "../../WebRtc/LayoutManager";
|
||||
import Texture = Phaser.Textures.Texture;
|
||||
import Sprite = Phaser.GameObjects.Sprite;
|
||||
|
@ -475,7 +475,6 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
if (newValue === undefined) {
|
||||
this.stopJitsi();
|
||||
} else {
|
||||
console.log("JITSI_PRIVATE_MODE", JITSI_PRIVATE_MODE);
|
||||
if (JITSI_PRIVATE_MODE) {
|
||||
const adminTag = allProps.get("jitsiRoomAdminTag") as string|undefined;
|
||||
|
||||
|
@ -1022,7 +1021,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
/**
|
||||
* Create new player
|
||||
*/
|
||||
private doAddPlayer(addPlayerData : AddPlayerInterface) : void {
|
||||
private async doAddPlayer(addPlayerData : AddPlayerInterface) : Promise<void> {
|
||||
//check if exist player, if exist, move position
|
||||
if(this.MapPlayersByKey.has(addPlayerData.userId)){
|
||||
this.updatePlayerPosition({
|
||||
|
@ -1031,6 +1030,20 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
});
|
||||
return;
|
||||
}
|
||||
// Load textures (in case it is a custom texture)
|
||||
const characterLayerList: string[] = [];
|
||||
const loadPromises: Promise<void>[] = [];
|
||||
for (const characterLayer of addPlayerData.characterLayers) {
|
||||
characterLayerList.push(characterLayer.name);
|
||||
if (characterLayer.img) {
|
||||
console.log('LOADING ', characterLayer.name, characterLayer.img)
|
||||
loadPromises.push(this.loadSpritesheet(characterLayer.name, characterLayer.img));
|
||||
}
|
||||
}
|
||||
if (loadPromises.length > 0) {
|
||||
this.load.start();
|
||||
}
|
||||
|
||||
//initialise player
|
||||
const player = new RemotePlayer(
|
||||
addPlayerData.userId,
|
||||
|
@ -1038,7 +1051,7 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
addPlayerData.position.x,
|
||||
addPlayerData.position.y,
|
||||
addPlayerData.name,
|
||||
addPlayerData.characterLayers,
|
||||
[], // Let's go with no textures and let's load textures when promises have returned.
|
||||
addPlayerData.position.direction,
|
||||
addPlayerData.position.moving
|
||||
);
|
||||
|
@ -1046,10 +1059,15 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
this.MapPlayersByKey.set(player.userId, player);
|
||||
player.updatePosition(addPlayerData.position);
|
||||
|
||||
|
||||
await Promise.all(loadPromises);
|
||||
|
||||
player.addTextures(characterLayerList, 1);
|
||||
//init collision
|
||||
/*this.physics.add.collider(this.CurrentPlayer, player, (CurrentPlayer: CurrentGamerInterface, MapPlayer: GamerInterface) => {
|
||||
CurrentPlayer.say("Hello, how are you ? ");
|
||||
});*/
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1245,4 +1263,18 @@ export class GameScene extends ResizableScene implements CenterListener {
|
|||
CoWebsiteManager.closeCoWebsite();
|
||||
mediaManager.showGameOverlay();
|
||||
}
|
||||
|
||||
private loadSpritesheet(name: string, url: string): Promise<void> {
|
||||
return new Promise<void>(((resolve, reject) => {
|
||||
this.load.spritesheet(
|
||||
name,
|
||||
url,
|
||||
{frameWidth: 32, frameHeight: 32}
|
||||
);
|
||||
this.load.on('filecomplete-spritesheet-'+name, () => {
|
||||
console.log('RESOURCE LOADED!');
|
||||
resolve();
|
||||
});
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,13 @@ import {EnableCameraSceneName} from "./EnableCameraScene";
|
|||
import {TextField} from "../Components/TextField";
|
||||
import Image = Phaser.GameObjects.Image;
|
||||
import Rectangle = Phaser.GameObjects.Rectangle;
|
||||
import {LAYERS, loadAllLayers} from "../Entity/body_character";
|
||||
import {BodyResourceDescriptionInterface, LAYERS, loadAllLayers, loadCustomTexture} from "../Entity/body_character";
|
||||
import Sprite = Phaser.GameObjects.Sprite;
|
||||
import Container = Phaser.GameObjects.Container;
|
||||
import {gameManager} from "../Game/GameManager";
|
||||
import {ResizableScene} from "./ResizableScene";
|
||||
import {localUserStore} from "../../Connexion/LocalUserStore";
|
||||
import {PlayerResourceDescriptionInterface} from "../Entity/Character";
|
||||
|
||||
export const CustomizeSceneName = "CustomizeScene";
|
||||
|
||||
|
@ -36,6 +37,7 @@ export class CustomizeScene extends ResizableScene {
|
|||
private selectedLayers: number[] = [0];
|
||||
private containersRow: Container[][] = [];
|
||||
private activeRow:number = 0;
|
||||
private layers: BodyResourceDescriptionInterface[][] = [];
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
|
@ -51,6 +53,23 @@ export class CustomizeScene extends ResizableScene {
|
|||
|
||||
//load all the png files
|
||||
loadAllLayers(this.load);
|
||||
|
||||
// load custom layers
|
||||
this.layers = LAYERS;
|
||||
|
||||
const localUser = localUserStore.getLocalUser();
|
||||
|
||||
const textures = localUser?.textures;
|
||||
if (textures) {
|
||||
for (const texture of textures) {
|
||||
loadCustomTexture(this.load, texture);
|
||||
const name = 'customCharacterTexture'+texture.id;
|
||||
this.layers[texture.level].unshift({
|
||||
name,
|
||||
img: texture.url
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
create() {
|
||||
|
@ -94,7 +113,7 @@ export class CustomizeScene extends ResizableScene {
|
|||
let i = 0;
|
||||
for (const layerItem of this.selectedLayers) {
|
||||
if (layerItem !== undefined) {
|
||||
layers.push(LAYERS[i][layerItem].name);
|
||||
layers.push(this.layers[i][layerItem].name);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
@ -108,7 +127,7 @@ export class CustomizeScene extends ResizableScene {
|
|||
this.input.keyboard.on('keydown-LEFT', () => this.moveCursorHorizontally(-1));
|
||||
this.input.keyboard.on('keydown-DOWN', () => this.moveCursorVertically(1));
|
||||
this.input.keyboard.on('keydown-UP', () => this.moveCursorVertically(-1));
|
||||
|
||||
|
||||
const customCursorPosition = localUserStore.getCustomCursorPosition();
|
||||
if (customCursorPosition) {
|
||||
this.activeRow = customCursorPosition.activeRow;
|
||||
|
@ -117,34 +136,34 @@ export class CustomizeScene extends ResizableScene {
|
|||
this.updateSelectedLayer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private moveCursorHorizontally(index: number): void {
|
||||
this.selectedLayers[this.activeRow] += index;
|
||||
if (this.selectedLayers[this.activeRow] < 0) {
|
||||
this.selectedLayers[this.activeRow] = 0
|
||||
} else if(this.selectedLayers[this.activeRow] > LAYERS[this.activeRow].length - 1) {
|
||||
this.selectedLayers[this.activeRow] = LAYERS[this.activeRow].length - 1
|
||||
} else if(this.selectedLayers[this.activeRow] > this.layers[this.activeRow].length - 1) {
|
||||
this.selectedLayers[this.activeRow] = this.layers[this.activeRow].length - 1
|
||||
}
|
||||
this.moveLayers();
|
||||
this.updateSelectedLayer();
|
||||
this.saveInLocalStorage();
|
||||
}
|
||||
|
||||
|
||||
private moveCursorVertically(index:number): void {
|
||||
this.activeRow += index;
|
||||
if (this.activeRow < 0) {
|
||||
this.activeRow = 0
|
||||
} else if (this.activeRow > LAYERS.length - 1) {
|
||||
this.activeRow = LAYERS.length - 1
|
||||
} else if (this.activeRow > this.layers.length - 1) {
|
||||
this.activeRow = this.layers.length - 1
|
||||
}
|
||||
this.moveLayers();
|
||||
this.saveInLocalStorage();
|
||||
}
|
||||
|
||||
|
||||
private saveInLocalStorage() {
|
||||
localUserStore.setCustomCursorPosition(this.activeRow, this.selectedLayers);
|
||||
}
|
||||
|
||||
|
||||
update(time: number, delta: number): void {
|
||||
super.update(time, delta);
|
||||
this.enterField.setVisible(!!(Math.floor(time / 500) % 2));
|
||||
|
@ -153,7 +172,7 @@ export class CustomizeScene extends ResizableScene {
|
|||
/**
|
||||
* @param x, the layer's vertical position
|
||||
* @param y, the layer's horizontal position
|
||||
* @param layerNumber, index of the LAYERS array
|
||||
* @param layerNumber, index of the this.layers array
|
||||
* create the layer and display it on the scene
|
||||
*/
|
||||
private createCustomizeLayer(x: number, y: number, layerNumber: number): void {
|
||||
|
@ -161,7 +180,7 @@ export class CustomizeScene extends ResizableScene {
|
|||
this.selectedLayers[layerNumber] = 0;
|
||||
let alpha = 0;
|
||||
let layerPosX = 0;
|
||||
for (let i = 0; i < LAYERS[layerNumber].length; i++) {
|
||||
for (let i = 0; i < this.layers[layerNumber].length; i++) {
|
||||
const container = this.generateCharacter(300 + x + layerPosX, y, layerNumber, i);
|
||||
|
||||
this.containersRow[layerNumber][i] = container;
|
||||
|
@ -190,13 +209,13 @@ export class CustomizeScene extends ResizableScene {
|
|||
const children: Array<Sprite> = new Array<Sprite>();
|
||||
for (let j = 0; j <= layerNumber; j++) {
|
||||
if (j === layerNumber) {
|
||||
children.push(this.generateLayers(0, 0, LAYERS[j][selectedItem].name));
|
||||
children.push(this.generateLayers(0, 0, this.layers[j][selectedItem].name));
|
||||
} else {
|
||||
const layer = this.selectedLayers[j];
|
||||
if (layer === undefined) {
|
||||
continue;
|
||||
}
|
||||
children.push(this.generateLayers(0, 0, LAYERS[j][layer].name));
|
||||
children.push(this.generateLayers(0, 0, this.layers[j][layer].name));
|
||||
}
|
||||
}
|
||||
return children;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue