added enums for event type and added an emitter class

This commit is contained in:
Joe Weaver 2020-09-19 20:18:39 -04:00
parent d452678344
commit a67521ea26
13 changed files with 135 additions and 72 deletions

20
src/Events/Emitter.ts Normal file
View File

@ -0,0 +1,20 @@
import Map from "../DataTypes/Map";
import EventQueue from "./EventQueue";
import GameEvent from "./GameEvent";
export default class Emitter {
private eventQueue: EventQueue;
constructor(){
this.eventQueue = EventQueue.getInstance();
}
/**
* Emit and event of type eventType with the data packet data
* @param eventType
* @param data
*/
fireEvent(eventType: string, data: Map<any> | Record<string, any> = null): void {
this.eventQueue.addEvent(new GameEvent(eventType, data));
}
}

View File

@ -2,6 +2,7 @@ import Queue from "../DataTypes/Queue";
import Map from "../DataTypes/Map";
import GameEvent from "./GameEvent";
import Receiver from "./Receiver";
import { GameEventType } from "./GameEventType";
export default class EventQueue {
private static instance: EventQueue = null;
@ -65,8 +66,8 @@ export default class EventQueue {
}
// If a receiver is subscribed to all events, send it the event
if(this.receivers.has("all")){
for(let receiver of this.receivers.get("all")){
if(this.receivers.has(GameEventType.ALL)){
for(let receiver of this.receivers.get(GameEventType.ALL)){
receiver.receive(event);
}
}

View File

@ -0,0 +1,59 @@
export enum GameEventType {
/**
* Mouse Down event. Has data: {position: Vec2 - Mouse Position}
*/
MOUSE_DOWN = "mouse_down",
/**
* Mouse Up event. Has data: {position: Vec2 - Mouse Position}
*/
MOUSE_UP = "mouse_up",
/**
* Mouse Move event. Has data: {position: Vec2 - Mouse Position}
*/
MOUSE_MOVE = "mouse_move",
/**
* Key Down event. Has data: {key: string - The key that is down}
*/
KEY_DOWN = "key_down",
/**
* Key Up event. Has data: {key: string - The key that is up}
*/
KEY_UP = "key_up",
/**
* Canvas Blur event. Has data: {}
*/
CANVAS_BLUR = "canvas_blur",
/**
* Start Recording event. Has data: {}
*/
START_RECORDING = "start_recording",
/**
* Stop Recording event. Has data: {}
*/
STOP_RECORDING = "stop_recording",
/**
* Play Recording event. Has data: {}
*/
PLAY_RECORDING = "play_recording",
/**
* Play Sound event. Has data: {key: string, loop: boolean, holdReference: boolean }
*/
PLAY_SOUND = "play_sound",
/**
* Play Sound event. Has data: {key: string}
*/
STOP_SOUND = "stop_sound",
/**
* Encompasses all event types. Used for receivers only.
*/
ALL = "all",
}

View File

@ -1,6 +1,7 @@
import EventQueue from "../Events/EventQueue";
import Vec2 from "../DataTypes/Vec2";
import GameEvent from "../Events/GameEvent";
import { GameEventType } from "../Events/GameEventType";
/**
* Handles communication with the web browser to receive asynchronous events and send them to the event queue
@ -23,36 +24,36 @@ export default class InputHandler{
private handleMouseDown = (event: MouseEvent, canvas: HTMLCanvasElement): void => {
let pos = this.getMousePosition(event, canvas);
let gameEvent = new GameEvent("mouse_down", {position: pos});
let gameEvent = new GameEvent(GameEventType.MOUSE_DOWN, {position: pos});
this.eventQueue.addEvent(gameEvent);
}
private handleMouseUp = (event: MouseEvent, canvas: HTMLCanvasElement): void => {
let pos = this.getMousePosition(event, canvas);
let gameEvent = new GameEvent("mouse_up", {position: pos});
let gameEvent = new GameEvent(GameEventType.MOUSE_UP, {position: pos});
this.eventQueue.addEvent(gameEvent);
}
private handleMouseMove = (event: MouseEvent, canvas: HTMLCanvasElement): void => {
let pos = this.getMousePosition(event, canvas);
let gameEvent = new GameEvent("mouse_move", {position: pos});
let gameEvent = new GameEvent(GameEventType.MOUSE_MOVE, {position: pos});
this.eventQueue.addEvent(gameEvent);
}
private handleKeyDown = (event: KeyboardEvent): void => {
let key = this.getKey(event);
let gameEvent = new GameEvent("key_down", {key: key});
let gameEvent = new GameEvent(GameEventType.KEY_DOWN, {key: key});
this.eventQueue.addEvent(gameEvent);
}
private handleKeyUp = (event: KeyboardEvent): void => {
let key = this.getKey(event);
let gameEvent = new GameEvent("key_up", {key: key});
let gameEvent = new GameEvent(GameEventType.KEY_UP, {key: key});
this.eventQueue.addEvent(gameEvent);
}
private handleBlur = (event: Event): void => {
let gameEvent = new GameEvent("canvas_blur", {});
let gameEvent = new GameEvent(GameEventType.CANVAS_BLUR, {});
this.eventQueue.addEvent(gameEvent);
}

View File

@ -3,6 +3,8 @@ import Map from "../DataTypes/Map";
import Vec2 from "../DataTypes/Vec2";
import EventQueue from "../Events/EventQueue";
import Viewport from "../SceneGraph/Viewport";
import GameEvent from "../Events/GameEvent";
import { GameEventType } from "../Events/GameEventType";
/**
* Receives input events from the event queue and allows for easy access of information about input
@ -31,7 +33,8 @@ export default class InputReceiver{
this.eventQueue = EventQueue.getInstance();
// Subscribe to all input events
this.eventQueue.subscribe(this.receiver, ["mouse_down", "mouse_up", "mouse_move", "key_down", "key_up", "canvas_blur"]);
this.eventQueue.subscribe(this.receiver, [GameEventType.MOUSE_DOWN, GameEventType.MOUSE_UP, GameEventType.MOUSE_MOVE,
GameEventType.KEY_DOWN, GameEventType.KEY_UP, GameEventType.CANVAS_BLUR]);
}
static getInstance(): InputReceiver{
@ -50,21 +53,21 @@ export default class InputReceiver{
let event = this.receiver.getNextEvent();
// Handle each event type
if(event.type === "mouse_down"){
if(event.type === GameEventType.MOUSE_DOWN){
this.mouseJustPressed = true;
this.mousePressed = true;
this.mousePressPosition = event.data.get("position");
}
if(event.type === "mouse_up"){
if(event.type === GameEventType.MOUSE_UP){
this.mousePressed = false;
}
if(event.type === "mouse_move"){
if(event.type === GameEventType.MOUSE_MOVE){
this.mousePosition = event.data.get("position");
}
if(event.type === "key_down"){
if(event.type === GameEventType.KEY_DOWN){
let key = event.data.get("key")
if(!this.keyPressed.get(key)){
this.keyJustPressed.set(key, true);
@ -72,12 +75,12 @@ export default class InputReceiver{
}
}
if(event.type === "key_up"){
if(event.type === GameEventType.KEY_UP){
let key = event.data.get("key")
this.keyPressed.set(key, false);
}
if(event.type === "canvas_blur"){
if(event.type === GameEventType.CANVAS_BLUR){
this.clearKeyPresses()
}
}

View File

@ -8,7 +8,7 @@ import UIElement from "./Nodes/UIElement";
import Button from "./Nodes/UIElements/Button";
import Layer from "./Scene/Layer";
import SecondScene from "./SecondScene";
import GameEvent from "./Events/GameEvent";
import { GameEventType } from "./Events/GameEventType";
export default class MainScene extends Scene {
@ -42,7 +42,7 @@ export default class MainScene extends Scene {
backgroundTilemap.getLayer().setAlpha(0.5);
// Add the music and start playing it on a loop
this.emit("play_sound", {key: "level_music", loop: true, holdReference: true});
this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "level_music", loop: true, holdReference: true});
// Add the tilemap
this.add.tilemap("platformer", OrthogonalTilemap);
@ -65,19 +65,19 @@ export default class MainScene extends Scene {
recordButton.setSize(100, 50);
recordButton.setText("Record");
recordButton.setPosition(400, 30);
recordButton.onClickEventId = "record_button_press";
recordButton.onClickEventId = GameEventType.START_RECORDING;
let stopButton = this.add.uiElement(Button, uiLayer);
stopButton.setSize(100, 50);
stopButton.setText("Stop");
stopButton.setPosition(550, 30);
stopButton.onClickEventId = "stop_button_press";
stopButton.onClickEventId = GameEventType.STOP_RECORDING;
let playButton = this.add.uiElement(Button, uiLayer);
playButton.setSize(100, 50);
playButton.setText("Play");
playButton.setPosition(700, 30);
playButton.onClickEventId = "play_button_press";
playButton.onClickEventId = GameEventType.PLAY_RECORDING;
let cycleFramerateButton = this.add.uiElement(Button, uiLayer);
cycleFramerateButton.setSize(150, 50);
@ -123,7 +123,7 @@ export default class MainScene extends Scene {
switchButton.setText("Change Scene");
switchButton.setPosition(340, 190);
switchButton.onClick = () => {
this.emit("stop_sound", {key: "level_music"});
this.emitter.fireEvent(GameEventType.STOP_SOUND, {key: "level_music"});
this.sceneManager.changeScene(SecondScene);
}
}

View File

@ -1,9 +1,8 @@
import EventQueue from "../Events/EventQueue";
import InputReceiver from "../Input/InputReceiver";
import Vec2 from "../DataTypes/Vec2";
import Map from "../DataTypes/Map";
import Receiver from "../Events/Receiver";
import GameEvent from "../Events/GameEvent";
import Emitter from "../Events/Emitter";
import Scene from "../Scene/Scene";
import Layer from "../Scene/Layer";
@ -11,17 +10,18 @@ import Layer from "../Scene/Layer";
* The representation of an object in the game world
*/
export default abstract class GameNode {
private eventQueue: EventQueue;
protected input: InputReceiver;
protected position: Vec2;
private receiver: Receiver;
protected receiver: Receiver;
protected emitter: Emitter;
protected scene: Scene;
protected layer: Layer;
constructor(){
this.eventQueue = EventQueue.getInstance();
this.input = InputReceiver.getInstance();
this.position = new Vec2(0, 0);
this.receiver = new Receiver();
this.emitter = new Emitter();
}
setScene(scene: Scene): void {
@ -52,24 +52,6 @@ export default abstract class GameNode{
}
}
/**
* Subscribe this object's receiver to the specified event type
* @param eventType
*/
subscribe(eventType: string): void {
this.eventQueue.subscribe(this.receiver, eventType);
}
/**
* Emit and event of type eventType with the data packet data
* @param eventType
* @param data
*/
emit(eventType: string, data: Map<any> | Record<string, any> = null): void {
let event = new GameEvent(eventType, data);
this.eventQueue.addEvent(event);
}
// TODO - This doesn't seem ideal. Is there a better way to do this?
protected getViewportOriginWithParallax(): Vec2 {
return this.scene.getViewport().getPosition().clone().mult(this.layer.getParallax());

View File

@ -82,7 +82,7 @@ export default class UIElement extends CanvasNode{
}
if(this.onClickEventId !== null){
let data = {};
this.emit(this.onClickEventId, data);
this.emitter.fireEvent(this.onClickEventId, data);
}
}
}
@ -104,7 +104,7 @@ export default class UIElement extends CanvasNode{
}
if(this.onEnterEventId !== null){
let data = {};
this.emit(this.onEnterEventId, data);
this.emitter.fireEvent(this.onEnterEventId, data);
}
} else if(this.isEntered) {
@ -115,7 +115,7 @@ export default class UIElement extends CanvasNode{
}
if(this.onLeaveEventId !== null){
let data = {};
this.emit(this.onLeaveEventId, data);
this.emitter.fireEvent(this.onLeaveEventId, data);
}
} else if(this.isClicked) {
// If mouse is dragged off of element while down, it is not clicked anymore

View File

@ -2,6 +2,7 @@ import Queue from "../DataTypes/Queue";
import Receiver from "../Events/Receiver";
import GameEvent from "../Events/GameEvent";
import EventQueue from "../Events/EventQueue";
import { GameEventType } from "../Events/GameEventType";
export default class Recorder{
private receiver: Receiver;
@ -53,7 +54,7 @@ export default class Recorder{
while(this.receiver.hasNextEvent()){
let event = this.receiver.getNextEvent();
if(event.type === "stop_button_press"){
if(event.type === GameEventType.STOP_RECORDING){
this.recording = false;
}
@ -61,13 +62,13 @@ export default class Recorder{
this.log.enqueue(new LogItem(this.frame, deltaT, event));
}
if(event.type === "record_button_press"){
if(event.type === GameEventType.START_RECORDING){
this.log.clear();
this.recording = true;
this.frame = 0
}
if(event.type === "play_button_press"){
if(event.type === GameEventType.PLAY_RECORDING){
this.frame = 0;
this.recording = false;
this.playing = true;

View File

@ -3,6 +3,7 @@ import Vec2 from "./DataTypes/Vec2";
import Debug from "./Debug/Debug";
import AABB from "./Physics/Colliders/AABB";
import CanvasNode from "./Nodes/CanvasNode";
import { GameEventType } from "./Events/GameEventType";
export default class Player extends PhysicsNode {
velocity: Vec2;
@ -83,7 +84,7 @@ export default class Player extends PhysicsNode {
if(this.grounded){
if(dir.y === -1){
// Jumping
this.emit("play_sound", {key: "player_jump"});
this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "player_jump"});
}
vel.y = dir.y*1800;
}

View File

@ -10,9 +10,8 @@ import Tilemap from "../Nodes/Tilemap";
import ResourceManager from "../ResourceManager/ResourceManager";
import GameLoop from "../Loop/GameLoop";
import SceneManager from "./SceneManager";
import EventQueue from "../Events/EventQueue";
import GameEvent from "../Events/GameEvent";
import Map from "../DataTypes/Map";
import Receiver from "../Events/Receiver";
import Emitter from "../Events/Emitter";
export default class Scene{
protected layers: Stack<Layer>;
@ -21,6 +20,8 @@ export default class Scene{
protected running: boolean;
protected game: GameLoop;
protected sceneManager: SceneManager;
protected receiver: Receiver;
protected emitter: Emitter;
protected tilemaps: Array<Tilemap>;
@ -48,6 +49,8 @@ export default class Scene{
this.running = false;
this.game = game;
this.sceneManager = sceneManager;
this.receiver = new Receiver();
this.emitter = new Emitter();
this.tilemaps = new Array();
this.sceneGraph = new SceneGraphArray(this.viewport, this);
@ -146,14 +149,4 @@ export default class Scene{
getViewport(): Viewport {
return this.viewport;
}
/**
* Emit and event of type eventType with the data packet data
* @param eventType
* @param data
*/
emit(eventType: string, data: Map<any> | Record<string, any> = null): void {
let event = new GameEvent(eventType, data);
EventQueue.getInstance().addEvent(event);
}
}

View File

@ -7,6 +7,7 @@ import Vec2 from "./DataTypes/Vec2";
import UIElement from "./Nodes/UIElement";
import Button from "./Nodes/UIElements/Button";
import Layer from "./Scene/Layer";
import { GameEventType } from "./Events/GameEventType";
export default class SecondScene extends Scene {
@ -40,7 +41,7 @@ export default class SecondScene extends Scene {
backgroundTilemap.getLayer().setAlpha(0.2);
// Add the music and start playing it on a loop
this.emit("play_sound", {key: "level_music", loop: true, holdReference: true});
this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: "level_music", loop: true, holdReference: true});
// Add the tilemap
this.add.tilemap("level2", OrthogonalTilemap);
@ -63,19 +64,19 @@ export default class SecondScene extends Scene {
recordButton.setSize(100, 50);
recordButton.setText("Record");
recordButton.setPosition(400, 30);
recordButton.onClickEventId = "record_button_press";
recordButton.onClickEventId = GameEventType.START_RECORDING;
let stopButton = this.add.uiElement(Button, uiLayer);
stopButton.setSize(100, 50);
stopButton.setText("Stop");
stopButton.setPosition(550, 30);
stopButton.onClickEventId = "stop_button_press";
stopButton.onClickEventId = GameEventType.STOP_RECORDING;
let playButton = this.add.uiElement(Button, uiLayer);
playButton.setSize(100, 50);
playButton.setText("Play");
playButton.setPosition(700, 30);
playButton.onClickEventId = "play_button_press";
playButton.onClickEventId = GameEventType.PLAY_RECORDING;
let cycleFramerateButton = this.add.uiElement(Button, uiLayer);
cycleFramerateButton.setSize(150, 50);

View File

@ -1,6 +1,7 @@
import Map from "../DataTypes/Map";
import Receiver from "../Events/Receiver";
import ResourceManager from "../ResourceManager/ResourceManager";
import { GameEventType } from "../Events/GameEventType";
export default class AudioManager {
private static instance: AudioManager;
@ -12,7 +13,7 @@ export default class AudioManager {
private constructor(){
this.initAudio();
this.receiver = new Receiver();
this.receiver.subscribe(["play_sound", "stop_sound"]);
this.receiver.subscribe([GameEventType.PLAY_SOUND, GameEventType.STOP_SOUND]);
this.currentSounds = new Map();
}
@ -117,14 +118,14 @@ export default class AudioManager {
// TODO - Add logic to merge sounds if there are multiple of the same key
while(this.receiver.hasNextEvent()){
let event = this.receiver.getNextEvent();
if(event.type === "play_sound"){
if(event.type === GameEventType.PLAY_SOUND){
let soundKey = event.data.get("key");
let loop = event.data.get("loop");
let holdReference = event.data.get("holdReference");
this.playSound(soundKey, loop, holdReference);
}
if(event.type === "stop_sound"){
if(event.type === GameEventType.STOP_SOUND){
let soundKey = event.data.get("key");
this.stopSound(soundKey);
}