2020-07-23 18:09:24 +02:00
|
|
|
/**
|
|
|
|
* An actionable item represents an in-game object that can be activated using the space-bar.
|
|
|
|
* It has coordinates and an "activation radius"
|
|
|
|
*/
|
|
|
|
import Sprite = Phaser.GameObjects.Sprite;
|
2021-09-06 14:27:54 +02:00
|
|
|
import type { GameScene } from "../Game/GameScene";
|
2021-06-22 16:35:57 +02:00
|
|
|
import type OutlinePipelinePlugin from "phaser3-rex-plugins/plugins/outlinepipeline-plugin.js";
|
2020-07-27 22:36:07 +02:00
|
|
|
|
|
|
|
type EventCallback = (state: unknown, parameters: unknown) => void;
|
2020-07-23 18:09:24 +02:00
|
|
|
|
|
|
|
export class ActionableItem {
|
2021-09-06 14:27:54 +02:00
|
|
|
private readonly activationRadiusSquared: number;
|
2020-07-23 18:09:24 +02:00
|
|
|
private isSelectable: boolean = false;
|
2020-07-27 22:36:07 +02:00
|
|
|
private callbacks: Map<string, Array<EventCallback>> = new Map<string, Array<EventCallback>>();
|
2020-07-23 18:09:24 +02:00
|
|
|
|
2021-09-06 14:27:54 +02:00
|
|
|
public constructor(
|
|
|
|
private id: number,
|
|
|
|
private sprite: Sprite,
|
|
|
|
private eventHandler: GameScene,
|
|
|
|
private activationRadius: number,
|
|
|
|
private onActivateCallback: (item: ActionableItem) => void
|
|
|
|
) {
|
2020-07-23 18:09:24 +02:00
|
|
|
this.activationRadiusSquared = activationRadius * activationRadius;
|
|
|
|
}
|
|
|
|
|
2020-07-27 22:36:07 +02:00
|
|
|
public getId(): number {
|
|
|
|
return this.id;
|
|
|
|
}
|
|
|
|
|
2020-07-23 18:09:24 +02:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2021-09-06 14:27:54 +02:00
|
|
|
public actionableDistance(x: number, y: number): number | null {
|
|
|
|
const distanceSquared = (x - this.sprite.x) * (x - this.sprite.x) + (y - this.sprite.y) * (y - this.sprite.y);
|
2020-07-23 18:09:24 +02:00
|
|
|
if (distanceSquared < this.activationRadiusSquared) {
|
|
|
|
return distanceSquared;
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Show the outline of the sprite.
|
|
|
|
*/
|
|
|
|
public selectable(): void {
|
|
|
|
if (this.isSelectable) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.isSelectable = true;
|
2021-06-22 16:35:57 +02:00
|
|
|
|
|
|
|
this.getOutlinePlugin()?.add(this.sprite, {
|
|
|
|
thickness: 2,
|
2021-09-06 14:27:54 +02:00
|
|
|
outlineColor: 0xffff00,
|
2021-06-22 16:35:57 +02:00
|
|
|
});
|
2020-07-23 18:09:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Hide the outline of the sprite
|
|
|
|
*/
|
|
|
|
public notSelectable(): void {
|
|
|
|
if (!this.isSelectable) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.isSelectable = false;
|
2021-06-22 16:35:57 +02:00
|
|
|
this.getOutlinePlugin()?.remove(this.sprite);
|
|
|
|
}
|
|
|
|
|
2021-09-06 14:27:54 +02:00
|
|
|
private getOutlinePlugin(): OutlinePipelinePlugin | undefined {
|
|
|
|
return this.sprite.scene.plugins.get("rexOutlinePipeline") as unknown as OutlinePipelinePlugin | undefined;
|
2020-07-23 18:09:24 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Triggered when the "space" key is pressed and the object is in range of being activated.
|
|
|
|
*/
|
|
|
|
public activate(): void {
|
2020-07-27 22:36:07 +02:00
|
|
|
this.onActivateCallback(this);
|
|
|
|
}
|
2020-07-23 18:09:24 +02:00
|
|
|
|
2020-07-27 22:36:07 +02:00
|
|
|
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);
|
2020-07-23 18:09:24 +02:00
|
|
|
}
|
|
|
|
|
2020-07-27 22:36:07 +02:00
|
|
|
public on(eventName: string, callback: EventCallback): void {
|
2021-09-06 14:27:54 +02:00
|
|
|
let callbacksArray: Array<EventCallback> | undefined = this.callbacks.get(eventName);
|
2020-07-27 22:36:07 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|