Adding event support to items

This commit is contained in:
David Négrier 2020-07-27 22:36:07 +02:00
parent 513244ae1f
commit ee612f6585
11 changed files with 253 additions and 36 deletions

View file

@ -4,15 +4,23 @@
*/
import Sprite = Phaser.GameObjects.Sprite;
import {OutlinePipeline} from "../Shaders/OutlinePipeline";
import {GameScene} from "../Game/GameScene";
type EventCallback = (state: unknown, parameters: unknown) => void;
export class ActionableItem {
private readonly activationRadiusSquared : number;
private isSelectable: boolean = false;
private callbacks: Map<string, Array<EventCallback>> = new Map<string, Array<EventCallback>>();
public constructor(private sprite: Sprite, private activationRadius: number) {
public constructor(private id: number, private sprite: Sprite, private eventHandler: GameScene, private activationRadius: number, private onActivateCallback: (item: ActionableItem) => void) {
this.activationRadiusSquared = activationRadius * activationRadius;
}
public getId(): number {
return this.id;
}
/**
* Returns the square of the distance to the object center IF we are in item action range
* OR null if we are out of range.
@ -54,7 +62,31 @@ export class ActionableItem {
* Triggered when the "space" key is pressed and the object is in range of being activated.
*/
public activate(): void {
this.onActivateCallback(this);
}
public emit(eventName: string, state: unknown, parameters: unknown = null): void {
this.eventHandler.emitActionableEvent(this.id, eventName, state, parameters);
// Also, execute the action locally.
this.fire(eventName, state, parameters);
}
public on(eventName: string, callback: EventCallback): void {
let callbacksArray: Array<EventCallback>|undefined = this.callbacks.get(eventName);
if (callbacksArray === undefined) {
callbacksArray = new Array<EventCallback>();
this.callbacks.set(eventName, callbacksArray);
}
callbacksArray.push(callback);
}
public fire(eventName: string, state: unknown, parameters: unknown): void {
const callbacksArray = this.callbacks.get(eventName);
if (callbacksArray === undefined) {
return;
}
for (const callback of callbacksArray) {
callback(state, parameters);
}
}
}

View file

@ -5,20 +5,82 @@ import {ITiledMapObject} from "../../Map/ITiledMap";
import {ItemFactoryInterface} from "../ItemFactoryInterface";
import {GameScene} from "../../Game/GameScene";
import {ActionableItem} from "../ActionableItem";
import * as tg from "generic-type-guard";
const isComputerState =
new tg.IsInterface().withProperties({
status: tg.isString,
}).get();
type ComputerState = tg.GuardedType<typeof isComputerState>;
let state: ComputerState = {
'status': 'off'
};
export default {
preload: (loader: Phaser.Loader.LoaderPlugin): void => {
loader.atlas('computer', '/resources/items/computer/computer.png', '/resources/items/computer/computer_atlas.json');
},
create: (scene: GameScene): void => {
scene.anims.create({
key: 'computer_off',
frames: [
{
key: 'computer',
frame: 'computer_off'
}
],
frameRate: 10,
repeat: -1
});
scene.anims.create({
key: 'computer_run',
frames: [
{
key: 'computer',
frame: 'computer_on1'
},
{
key: 'computer',
frame: 'computer_on2'
}
],
frameRate: 5,
repeat: -1
});
},
factory: (scene: GameScene, object: ITiledMapObject): ActionableItem => {
// Idée: ESSAYER WebPack? https://paultavares.wordpress.com/2018/07/02/webpack-how-to-generate-an-es-module-bundle/
const foo = new Sprite(scene, object.x, object.y, 'computer');
scene.add.existing(foo);
factory: (scene: GameScene, object: ITiledMapObject, initState: unknown): ActionableItem => {
if (initState !== undefined) {
if (!isComputerState(initState)) {
throw new Error('Invalid state received for computer object');
}
state = initState;
}
return new ActionableItem(foo, 32);
// Idée: ESSAYER WebPack? https://paultavares.wordpress.com/2018/07/02/webpack-how-to-generate-an-es-module-bundle/
const computer = new Sprite(scene, object.x, object.y, 'computer');
scene.add.existing(computer);
if (state.status === 'on') {
computer.anims.play('computer_run');
}
const item = new ActionableItem(object.id, computer, scene, 32, (item: ActionableItem) => {
if (state.status === 'off') {
state.status = 'on';
item.emit('TURN_ON', state);
} else {
state.status = 'off';
item.emit('TURN_OFF', state);
}
});
item.on('TURN_ON', () => {
computer.anims.play('computer_run');
});
item.on('TURN_OFF', () => {
computer.anims.play('computer_off');
});
return item;
//scene.add.sprite(object.x, object.y, 'computer');
}
} as ItemFactoryInterface;

View file

@ -6,5 +6,5 @@ import {ActionableItem} from "./ActionableItem";
export interface ItemFactoryInterface {
preload: (loader: LoaderPlugin) => void;
create: (scene: GameScene) => void;
factory: (scene: GameScene, object: ITiledMapObject) => ActionableItem;
factory: (scene: GameScene, object: ITiledMapObject, state: unknown) => ActionableItem;
}