Propagating customized sprites all over the game

This commit is contained in:
David Négrier 2020-07-28 17:43:33 +02:00
parent 6d0bccc0e1
commit 84529d6e99
14 changed files with 99 additions and 73 deletions

View file

@ -177,7 +177,7 @@ export class IoSocketController {
//add function to refresh position user in real time.
//this.refreshUserPosition(Client);
const messageUserJoined = new MessageUserJoined(Client.userId, Client.name, Client.character, Client.position);
const messageUserJoined = new MessageUserJoined(Client.userId, Client.name, Client.characterLayers, Client.position);
socket.to(roomId).emit(SockerIoEvent.JOIN_ROOM, messageUserJoined);
@ -188,7 +188,7 @@ export class IoSocketController {
console.warn('Something went wrong. The World contains a user "'+user.id+"' but this user does not exist in the sockets list!");
return null;
}
return new MessageUserPosition(user.id, player.name, player.character, player.position);
return new MessageUserPosition(user.id, player.name, player.characterLayers, player.position);
}).filter((item: MessageUserPosition|null) => item !== null);
answerFn(listOfUsers);
} catch (e) {
@ -278,7 +278,7 @@ export class IoSocketController {
}
const Client = (socket as ExSocketInterface);
Client.name = playerDetails.name;
Client.character = playerDetails.character;
Client.characterLayers = playerDetails.characterLayers;
answerFn(Client.userId);
});
});

View file

@ -9,6 +9,6 @@ export interface ExSocketInterface extends Socket, Identificable {
webRtcRoomId: string;
userId: string;
name: string;
character: string;
characterLayers: string[];
position: PointInterface;
}

View file

@ -1,6 +1,6 @@
import {PointInterface} from "_Model/Websocket/PointInterface";
export class MessageUserJoined {
constructor(public userId: string, public name: string, public character: string, public position: PointInterface) {
constructor(public userId: string, public name: string, public characterLayers: string[], public position: PointInterface) {
}
}

View file

@ -6,6 +6,6 @@ export class Point implements PointInterface{
}
export class MessageUserPosition {
constructor(public userId: string, public name: string, public character: string, public position: PointInterface) {
constructor(public userId: string, public name: string, public characterLayers: string[], public position: PointInterface) {
}
}

View file

@ -3,6 +3,6 @@ import * as tg from "generic-type-guard";
export const isSetPlayerDetailsMessage =
new tg.IsInterface().withProperties({
name: tg.isString,
character: tg.isString
characterLayers: tg.isArray(tg.isString)
}).get();
export type SetPlayerDetailsMessage = tg.GuardedType<typeof isSetPlayerDetailsMessage>;

View file

@ -44,7 +44,7 @@ export class Point implements PointInterface{
export interface MessageUserPositionInterface {
userId: string;
name: string;
character: string;
characterLayers: string[];
position: PointInterface;
}
@ -56,7 +56,7 @@ export interface MessageUserMovedInterface {
export interface MessageUserJoined {
userId: string;
name: string;
character: string;
characterLayers: string[];
position: PointInterface
}
@ -109,7 +109,7 @@ export class Connection implements Connection {
})
}
public static createConnection(name: string, characterSelected: string): Promise<Connection> {
public static createConnection(name: string, characterLayersSelected: string[]): Promise<Connection> {
return Axios.post(`${API_URL}/login`, {name: name})
.then((res) => {
@ -123,7 +123,7 @@ export class Connection implements Connection {
connection.socket.emit(EventMessage.SET_PLAYER_DETAILS, {
name: name,
character: characterSelected
characterLayers: characterLayersSelected
} as SetPlayerDetailsMessage, (id: string) => {
connection.userId = id;
});
@ -135,7 +135,7 @@ export class Connection implements Connection {
// Let's retry in 4-6 seconds
return new Promise<Connection>((resolve, reject) => {
setTimeout(() => {
Connection.createConnection(name, characterSelected).then((connection) => resolve(connection))
Connection.createConnection(name, characterLayersSelected).then((connection) => resolve(connection))
.catch((error) => reject(error));
}, 4000 + Math.floor(Math.random() * 2000) );
});

View file

@ -1,4 +1,4 @@
export interface SetPlayerDetailsMessage {
name: string,
character: string
characterLayers: string[]
}

View file

@ -1,6 +1,8 @@
import {PlayerAnimationNames} from "../Player/Animation";
import {SpeechBubble} from "./SpeechBubble";
import BitmapText = Phaser.GameObjects.BitmapText;
import Container = Phaser.GameObjects.Container;
import Sprite = Phaser.GameObjects.Sprite;
export interface PlayerResourceDescriptionInterface {
name: string,
@ -38,57 +40,62 @@ interface AnimationData {
frameEnd: number;
}
export abstract class Character extends Phaser.Physics.Arcade.Sprite {
export abstract class Character extends Container {
private bubble: SpeechBubble|null = null;
private readonly playerName: BitmapText;
public PlayerValue: string;
public PlayerTexture: string;
public sprites: Map<string, Sprite>;
private lastDirection: string = PlayerAnimationNames.WalkDown;
constructor(scene: Phaser.Scene,
x: number,
y: number,
texture: string,
textures: string[],
name: string,
direction: string,
moving: boolean,
frame?: string | number
) {
super(scene, x, y, texture, frame);
super(scene, x, y/*, texture, frame*/);
this.sprites = new Map<string, Sprite>();
for (const texture of textures) {
const sprite = new Sprite(scene, 0, 0, texture, frame);
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
});
})
this.add(sprite);
this.scene.sys.updateList.add(sprite);
this.scene.sys.displayList.add(sprite);
this.sprites.set(texture, sprite);
}
this.PlayerValue = name;
this.PlayerTexture = texture;
this.playerName = new BitmapText(scene, x, y - 25, 'main_font', name, 8);
this.playerName.setOrigin(0.5).setCenterAlign().setDepth(99999);
scene.add.existing(this.playerName);
this.scene.sys.updateList.add(this);
this.scene.sys.displayList.add(this);
//this.setScale(2);
scene.add.existing(this);
this.scene.physics.world.enableBody(this);
this.setImmovable(true);
this.setCollideWorldBounds(true);
this.setSize(16, 16); //edit the hitbox to better match the character model
this.setOffset(8, 16);
this.getBody().setImmovable(true);
this.getBody().setCollideWorldBounds(true);
this.setSize(16, 16);
this.getBody().setSize(16, 16); //edit the hitbox to better match the character model
this.getBody().setOffset(0, 8);
this.setDepth(-1);
this.scene.events.on('postupdate', this.postupdate.bind(this));
this.initAnimation();
this.playAnimation(direction, moving);
}
private initAnimation(): void {
this.getPlayerAnimations(this.PlayerTexture).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
});
})
}
private getPlayerAnimations(name: string): AnimationData[] {
return [{
key: `${name}-${PlayerAnimationNames.WalkDown}`,
@ -122,34 +129,53 @@ export abstract class Character extends Phaser.Physics.Arcade.Sprite {
}
protected playAnimation(direction : string, moving: boolean): void {
if (!this.anims) {
console.error('ANIMS IS NOT DEFINED!!!');
return;
}
if (moving && (!this.anims.currentAnim || this.anims.currentAnim.key !== direction)) {
this.play(this.PlayerTexture+'-'+direction, true);
} else if (!moving) {
/*if (this.anims.currentAnim) {
this.anims.stop();
}*/
this.play(this.PlayerTexture+'-'+direction, true);
this.stop();
for (const [texture, sprite] of this.sprites.entries()) {
if (!sprite.anims) {
console.error('ANIMS IS NOT DEFINED!!!');
return;
}
if (moving && (!sprite.anims.currentAnim || sprite.anims.currentAnim.key !== direction)) {
sprite.play(texture+'-'+direction, true);
} else if (!moving) {
/*if (this.anims.currentAnim) {
this.anims.stop();
}*/
sprite.play(texture+'-'+direction, true);
sprite.anims.stop();
}
}
}
move(x: number, y: number) {
protected getBody(): Phaser.Physics.Arcade.Body {
const body = this.body;
if (!(body instanceof Phaser.Physics.Arcade.Body)) {
throw new Error('Container does not have arcade body');
}
return body;
}
this.setVelocity(x, y);
move(x: number, y: number) {
const body = this.getBody();
body.setVelocity(x, y);
// up or down animations are prioritized over left and right
if (this.body.velocity.y < 0) { //moving up
this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkUp}`, true);
} else if (this.body.velocity.y > 0) { //moving down
this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkDown}`, true);
} else if (this.body.velocity.x > 0) { //moving right
this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkRight}`, true);
} else if (this.body.velocity.x < 0) { //moving left
this.anims.playReverse(`${this.PlayerTexture}-${PlayerAnimationNames.WalkLeft}`, true);
if (body.velocity.y < 0) { //moving up
this.lastDirection = PlayerAnimationNames.WalkUp;
this.playAnimation(PlayerAnimationNames.WalkUp, true);
//this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkUp}`, true);
} else if (body.velocity.y > 0) { //moving down
this.lastDirection = PlayerAnimationNames.WalkDown;
this.playAnimation(PlayerAnimationNames.WalkDown, true);
//this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkDown}`, true);
} else if (body.velocity.x > 0) { //moving right
this.lastDirection = PlayerAnimationNames.WalkRight;
this.playAnimation(PlayerAnimationNames.WalkRight, true);
//this.play(`${this.PlayerTexture}-${PlayerAnimationNames.WalkRight}`, true);
} else if (body.velocity.x < 0) { //moving left
this.lastDirection = PlayerAnimationNames.WalkLeft;
this.playAnimation(PlayerAnimationNames.WalkLeft, true);
//this.anims.playReverse(`${this.PlayerTexture}-${PlayerAnimationNames.WalkLeft}`, true);
}
if (this.bubble) {
@ -166,8 +192,8 @@ export abstract class Character extends Phaser.Physics.Arcade.Sprite {
}
stop(){
this.setVelocity(0, 0);
this.anims.stop();
this.getBody().setVelocity(0, 0);
this.playAnimation(this.lastDirection, false);
}
say(text: string) {

View file

@ -16,11 +16,11 @@ export class RemotePlayer extends Character {
x: number,
y: number,
name: string,
PlayerTexture: string,
PlayerTextures: string[],
direction: string,
moving: boolean
) {
super(Scene, x, y, PlayerTexture, name, direction, moving, 1);
super(Scene, x, y, PlayerTextures, name, direction, moving, 1);
//set data
this.userId = userId;

View file

@ -3,6 +3,6 @@ import {PointInterface} from "../../Connection";
export interface AddPlayerInterface {
userId: string;
name: string;
character: string;
characterLayers: string[];
position: PointInterface;
}

View file

@ -42,8 +42,8 @@ export class GameManager {
return this.playerName;
}
getCharacterSelected(): string {
return this.characterLayers[0];
getCharacterSelected(): string[] {
return this.characterLayers;
}
loadMap(mapUrl: string, scene: Phaser.Scenes.ScenePlugin, instance: string): string {

View file

@ -166,7 +166,7 @@ export class GameScene extends Phaser.Scene {
connection.onUserJoins((message: MessageUserJoined) => {
const userMessage: AddPlayerInterface = {
userId: message.userId,
character: message.character,
characterLayers: message.characterLayers,
name: message.name,
position: message.position
}
@ -704,7 +704,7 @@ export class GameScene extends Phaser.Scene {
addPlayerData.position.x,
addPlayerData.position.y,
addPlayerData.name,
addPlayerData.character,
addPlayerData.characterLayers,
addPlayerData.position.direction,
addPlayerData.position.moving
);

View file

@ -104,7 +104,7 @@ export class CustomizeScene extends Phaser.Scene {
this.input.keyboard.on('keyup-ENTER', () => {
const layers: string[] = [];
let i = 0;
for (let layerItem of this.selectedLayers) {
for (const layerItem of this.selectedLayers) {
console.log(i, layerItem, LAYERS);
if (layerItem !== undefined) {
layers.push(LAYERS[i][layerItem].name);

View file

@ -21,17 +21,17 @@ export class Player extends Character implements CurrentGamerInterface {
x: number,
y: number,
name: string,
PlayerTexture: string,
PlayerTextures: string[],
direction: string,
moving: boolean
) {
super(Scene, x, y, PlayerTexture, name, direction, moving, 1);
super(Scene, x, y, PlayerTextures, name, direction, moving, 1);
//create input to move
this.userInputManager = new UserInputManager(Scene);
//the current player model should be push away by other players to prevent conflict
this.setImmovable(false);
this.getBody().setImmovable(false);
}
moveUser(delta: number): void {