made sounds play via EventQueue and flagged vars in ResourceManager
This commit is contained in:
parent
3a57a1acab
commit
90996115f1
|
@ -55,6 +55,14 @@ export default class Map<T> implements Collection {
|
||||||
Object.keys(this.map).forEach(key => func(key));
|
Object.keys(this.map).forEach(key => func(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes an item associated with a key
|
||||||
|
* @param key The key at which to delete an item
|
||||||
|
*/
|
||||||
|
delete(key: string): void {
|
||||||
|
delete this.map[key];
|
||||||
|
}
|
||||||
|
|
||||||
clear(): void {
|
clear(): void {
|
||||||
this.forEach(key => delete this.map[key]);
|
this.forEach(key => delete this.map[key]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import Queue from "../DataTypes/Queue";
|
import Queue from "../DataTypes/Queue";
|
||||||
|
import EventQueue from "./EventQueue";
|
||||||
import GameEvent from "./GameEvent";
|
import GameEvent from "./GameEvent";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,6 +14,14 @@ export default class Receiver{
|
||||||
this.q = new Queue(this.MAX_SIZE);
|
this.q = new Queue(this.MAX_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds these types of events to this receiver's queue every update.
|
||||||
|
* @param eventTypes The types of events this receiver will be subscribed to
|
||||||
|
*/
|
||||||
|
subscribe(eventTypes: string | Array<string>): void {
|
||||||
|
EventQueue.getInstance().subscribe(this, eventTypes);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an event to the queue of this reciever
|
* Adds an event to the queue of this reciever
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -196,6 +196,9 @@ export default class GameLoop{
|
||||||
// Update all scenes
|
// Update all scenes
|
||||||
this.sceneManager.update(deltaT);
|
this.sceneManager.update(deltaT);
|
||||||
|
|
||||||
|
// Update all sounds
|
||||||
|
this.audioManager.update(deltaT);
|
||||||
|
|
||||||
// Load or unload any resources if needed
|
// Load or unload any resources if needed
|
||||||
this.resourceManager.update(deltaT);
|
this.resourceManager.update(deltaT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import UIElement from "./Nodes/UIElement";
|
||||||
import Button from "./Nodes/UIElements/Button";
|
import Button from "./Nodes/UIElements/Button";
|
||||||
import Layer from "./Scene/Layer";
|
import Layer from "./Scene/Layer";
|
||||||
import SecondScene from "./SecondScene";
|
import SecondScene from "./SecondScene";
|
||||||
|
import GameEvent from "./Events/GameEvent";
|
||||||
|
|
||||||
export default class MainScene extends Scene {
|
export default class MainScene extends Scene {
|
||||||
|
|
||||||
|
@ -41,8 +42,7 @@ export default class MainScene extends Scene {
|
||||||
backgroundTilemap.getLayer().setAlpha(0.5);
|
backgroundTilemap.getLayer().setAlpha(0.5);
|
||||||
|
|
||||||
// Add the music and start playing it on a loop
|
// Add the music and start playing it on a loop
|
||||||
let music = this.add.audio("level_music");
|
this.emit("play_sound", {key: "level_music", loop: true, holdReference: true});
|
||||||
music.play(true);
|
|
||||||
|
|
||||||
// Add the tilemap
|
// Add the tilemap
|
||||||
this.add.tilemap("platformer", OrthogonalTilemap);
|
this.add.tilemap("platformer", OrthogonalTilemap);
|
||||||
|
@ -55,10 +55,6 @@ export default class MainScene extends Scene {
|
||||||
let playerSprite = this.add.sprite("player", mainLayer)
|
let playerSprite = this.add.sprite("player", mainLayer)
|
||||||
player.setSprite(playerSprite);
|
player.setSprite(playerSprite);
|
||||||
|
|
||||||
// TODO - Should sound playing be handled with events?
|
|
||||||
let playerJumpSound = this.add.audio("player_jump");
|
|
||||||
player.jumpSound = playerJumpSound;
|
|
||||||
|
|
||||||
this.viewport.follow(player);
|
this.viewport.follow(player);
|
||||||
|
|
||||||
// Initialize UI
|
// Initialize UI
|
||||||
|
@ -127,7 +123,7 @@ export default class MainScene extends Scene {
|
||||||
switchButton.setText("Change Scene");
|
switchButton.setText("Change Scene");
|
||||||
switchButton.setPosition(340, 190);
|
switchButton.setPosition(340, 190);
|
||||||
switchButton.onClick = () => {
|
switchButton.onClick = () => {
|
||||||
music.stop();
|
this.emit("stop_sound", {key: "level_music"});
|
||||||
this.sceneManager.changeScene(SecondScene);
|
this.sceneManager.changeScene(SecondScene);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ import Vec2 from "./DataTypes/Vec2";
|
||||||
import Debug from "./Debug/Debug";
|
import Debug from "./Debug/Debug";
|
||||||
import AABB from "./Physics/Colliders/AABB";
|
import AABB from "./Physics/Colliders/AABB";
|
||||||
import CanvasNode from "./Nodes/CanvasNode";
|
import CanvasNode from "./Nodes/CanvasNode";
|
||||||
import Audio from "./Sound/Audio";
|
|
||||||
|
|
||||||
export default class Player extends PhysicsNode {
|
export default class Player extends PhysicsNode {
|
||||||
velocity: Vec2;
|
velocity: Vec2;
|
||||||
|
@ -12,7 +11,6 @@ export default class Player extends PhysicsNode {
|
||||||
size: Vec2;
|
size: Vec2;
|
||||||
gravity: number = 7000;
|
gravity: number = 7000;
|
||||||
type: string;
|
type: string;
|
||||||
jumpSound: Audio;
|
|
||||||
|
|
||||||
constructor(type: string){
|
constructor(type: string){
|
||||||
super();
|
super();
|
||||||
|
@ -85,7 +83,7 @@ export default class Player extends PhysicsNode {
|
||||||
if(this.grounded){
|
if(this.grounded){
|
||||||
if(dir.y === -1){
|
if(dir.y === -1){
|
||||||
// Jumping
|
// Jumping
|
||||||
this.jumpSound.play();
|
this.emit("play_sound", {key: "player_jump"});
|
||||||
}
|
}
|
||||||
vel.y = dir.y*1800;
|
vel.y = dir.y*1800;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,15 +21,15 @@ export default class ResourceManager {
|
||||||
/**
|
/**
|
||||||
* Number to keep track of how many images need to be loaded
|
* Number to keep track of how many images need to be loaded
|
||||||
*/
|
*/
|
||||||
private imagesLoaded: number;
|
private loadonly_imagesLoaded: number;
|
||||||
/**
|
/**
|
||||||
* Number to keep track of how many images are loaded
|
* Number to keep track of how many images are loaded
|
||||||
*/
|
*/
|
||||||
private imagesToLoad: number;
|
private loadonly_imagesToLoad: number;
|
||||||
/**
|
/**
|
||||||
* The queue of images we must load
|
* The queue of images we must load
|
||||||
*/
|
*/
|
||||||
private imageLoadingQueue: Queue<{key: string, path: string}>;
|
private loadonly_imageLoadingQueue: Queue<{key: string, path: string}>;
|
||||||
/**
|
/**
|
||||||
* A map of the images that are currently loaded and (presumably) being used by the scene
|
* A map of the images that are currently loaded and (presumably) being used by the scene
|
||||||
*/
|
*/
|
||||||
|
@ -38,15 +38,15 @@ export default class ResourceManager {
|
||||||
/**
|
/**
|
||||||
* Number to keep track of how many tilemaps need to be loaded
|
* Number to keep track of how many tilemaps need to be loaded
|
||||||
*/
|
*/
|
||||||
private tilemapsLoaded: number;
|
private loadonly_tilemapsLoaded: number;
|
||||||
/**
|
/**
|
||||||
* Number to keep track of how many tilemaps are loaded
|
* Number to keep track of how many tilemaps are loaded
|
||||||
*/
|
*/
|
||||||
private tilemapsToLoad: number;
|
private loadonly_tilemapsToLoad: number;
|
||||||
/**
|
/**
|
||||||
* The queue of tilemaps we must load
|
* The queue of tilemaps we must load
|
||||||
*/
|
*/
|
||||||
private tilemapLoadingQueue: Queue<{key: string, path: string}>;
|
private loadonly_tilemapLoadingQueue: Queue<{key: string, path: string}>;
|
||||||
/**
|
/**
|
||||||
* A map of the tilemaps that are currently loaded and (presumably) being used by the scene
|
* A map of the tilemaps that are currently loaded and (presumably) being used by the scene
|
||||||
*/
|
*/
|
||||||
|
@ -55,15 +55,15 @@ export default class ResourceManager {
|
||||||
/**
|
/**
|
||||||
* Number to keep track of how many sounds need to be loaded
|
* Number to keep track of how many sounds need to be loaded
|
||||||
*/
|
*/
|
||||||
private audioLoaded: number;
|
private loadonly_audioLoaded: number;
|
||||||
/**
|
/**
|
||||||
* Number to keep track of how many sounds are loaded
|
* Number to keep track of how many sounds are loaded
|
||||||
*/
|
*/
|
||||||
private audioToLoad: number;
|
private loadonly_audioToLoad: number;
|
||||||
/**
|
/**
|
||||||
* The queue of sounds we must load
|
* The queue of sounds we must load
|
||||||
*/
|
*/
|
||||||
private audioLoadingQueue: Queue<{key: string, path: string}>;
|
private loadonly_audioLoadingQueue: Queue<{key: string, path: string}>;
|
||||||
/**
|
/**
|
||||||
* A map of the sounds that are currently loaded and (presumably) being used by the scene
|
* A map of the sounds that are currently loaded and (presumably) being used by the scene
|
||||||
*/
|
*/
|
||||||
|
@ -72,25 +72,25 @@ export default class ResourceManager {
|
||||||
/**
|
/**
|
||||||
* The total number of "types" of things that need to be loaded (i.e. images and tilemaps)
|
* The total number of "types" of things that need to be loaded (i.e. images and tilemaps)
|
||||||
*/
|
*/
|
||||||
private typesToLoad: number;
|
private loadonly_typesToLoad: number;
|
||||||
|
|
||||||
private constructor(){
|
private constructor(){
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.justLoaded = false;
|
this.justLoaded = false;
|
||||||
|
|
||||||
this.imagesLoaded = 0;
|
this.loadonly_imagesLoaded = 0;
|
||||||
this.imagesToLoad = 0;
|
this.loadonly_imagesToLoad = 0;
|
||||||
this.imageLoadingQueue = new Queue();
|
this.loadonly_imageLoadingQueue = new Queue();
|
||||||
this.images = new Map();
|
this.images = new Map();
|
||||||
|
|
||||||
this.tilemapsLoaded = 0;
|
this.loadonly_tilemapsLoaded = 0;
|
||||||
this.tilemapsToLoad = 0;
|
this.loadonly_tilemapsToLoad = 0;
|
||||||
this.tilemapLoadingQueue = new Queue();
|
this.loadonly_tilemapLoadingQueue = new Queue();
|
||||||
this.tilemaps = new Map();
|
this.tilemaps = new Map();
|
||||||
|
|
||||||
this.audioLoaded = 0;
|
this.loadonly_audioLoaded = 0;
|
||||||
this.audioToLoad = 0;
|
this.loadonly_audioToLoad = 0;
|
||||||
this.audioLoadingQueue = new Queue();
|
this.loadonly_audioLoadingQueue = new Queue();
|
||||||
this.audioBuffers = new Map();
|
this.audioBuffers = new Map();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ export default class ResourceManager {
|
||||||
* @param path The path to the image to load
|
* @param path The path to the image to load
|
||||||
*/
|
*/
|
||||||
public image(key: string, path: string): void {
|
public image(key: string, path: string): void {
|
||||||
this.imageLoadingQueue.enqueue({key: key, path: path});
|
this.loadonly_imageLoadingQueue.enqueue({key: key, path: path});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -132,7 +132,7 @@ export default class ResourceManager {
|
||||||
* @param path
|
* @param path
|
||||||
*/
|
*/
|
||||||
public audio(key: string, path: string): void {
|
public audio(key: string, path: string): void {
|
||||||
this.audioLoadingQueue.enqueue({key: key, path: path});
|
this.loadonly_audioLoadingQueue.enqueue({key: key, path: path});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -149,7 +149,7 @@ export default class ResourceManager {
|
||||||
* @param path
|
* @param path
|
||||||
*/
|
*/
|
||||||
public tilemap(key: string, path: string): void {
|
public tilemap(key: string, path: string): void {
|
||||||
this.tilemapLoadingQueue.enqueue({key: key, path: path});
|
this.loadonly_tilemapLoadingQueue.enqueue({key: key, path: path});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,7 +166,7 @@ export default class ResourceManager {
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
loadResourcesFromQueue(callback: Function): void {
|
loadResourcesFromQueue(callback: Function): void {
|
||||||
this.typesToLoad = 3;
|
this.loadonly_typesToLoad = 3;
|
||||||
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
||||||
|
@ -191,16 +191,16 @@ export default class ResourceManager {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.justLoaded = false;
|
this.justLoaded = false;
|
||||||
|
|
||||||
this.imagesLoaded = 0;
|
this.loadonly_imagesLoaded = 0;
|
||||||
this.imagesToLoad = 0;
|
this.loadonly_imagesToLoad = 0;
|
||||||
this.images.clear();
|
this.images.clear();
|
||||||
|
|
||||||
this.tilemapsLoaded = 0;
|
this.loadonly_tilemapsLoaded = 0;
|
||||||
this.tilemapsToLoad = 0;
|
this.loadonly_tilemapsToLoad = 0;
|
||||||
this.tilemaps.clear();
|
this.tilemaps.clear();
|
||||||
|
|
||||||
this.audioLoaded = 0;
|
this.loadonly_audioLoaded = 0;
|
||||||
this.audioToLoad = 0;
|
this.loadonly_audioToLoad = 0;
|
||||||
this.audioBuffers.clear();
|
this.audioBuffers.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,11 +209,11 @@ export default class ResourceManager {
|
||||||
* @param onFinishLoading
|
* @param onFinishLoading
|
||||||
*/
|
*/
|
||||||
private loadTilemapsFromQueue(onFinishLoading: Function): void {
|
private loadTilemapsFromQueue(onFinishLoading: Function): void {
|
||||||
this.tilemapsToLoad = this.tilemapLoadingQueue.getSize();
|
this.loadonly_tilemapsToLoad = this.loadonly_tilemapLoadingQueue.getSize();
|
||||||
this.tilemapsLoaded = 0;
|
this.loadonly_tilemapsLoaded = 0;
|
||||||
|
|
||||||
while(this.tilemapLoadingQueue.hasItems()){
|
while(this.loadonly_tilemapLoadingQueue.hasItems()){
|
||||||
let tilemap = this.tilemapLoadingQueue.dequeue();
|
let tilemap = this.loadonly_tilemapLoadingQueue.dequeue();
|
||||||
this.loadTilemap(tilemap.key, tilemap.path, onFinishLoading);
|
this.loadTilemap(tilemap.key, tilemap.path, onFinishLoading);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ export default class ResourceManager {
|
||||||
for(let tileset of tilemapObject.tilesets){
|
for(let tileset of tilemapObject.tilesets){
|
||||||
let key = tileset.image;
|
let key = tileset.image;
|
||||||
let path = StringUtils.getPathFromFilePath(pathToTilemapJSON) + key;
|
let path = StringUtils.getPathFromFilePath(pathToTilemapJSON) + key;
|
||||||
this.imageLoadingQueue.enqueue({key: key, path: path});
|
this.loadonly_imageLoadingQueue.enqueue({key: key, path: path});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish loading
|
// Finish loading
|
||||||
|
@ -248,9 +248,9 @@ export default class ResourceManager {
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
private finishLoadingTilemap(callback: Function): void {
|
private finishLoadingTilemap(callback: Function): void {
|
||||||
this.tilemapsLoaded += 1;
|
this.loadonly_tilemapsLoaded += 1;
|
||||||
|
|
||||||
if(this.tilemapsLoaded === this.tilemapsToLoad){
|
if(this.loadonly_tilemapsLoaded === this.loadonly_tilemapsToLoad){
|
||||||
// We're done loading tilemaps
|
// We're done loading tilemaps
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
@ -261,11 +261,11 @@ export default class ResourceManager {
|
||||||
* @param onFinishLoading
|
* @param onFinishLoading
|
||||||
*/
|
*/
|
||||||
private loadImagesFromQueue(onFinishLoading: Function): void {
|
private loadImagesFromQueue(onFinishLoading: Function): void {
|
||||||
this.imagesToLoad = this.imageLoadingQueue.getSize();
|
this.loadonly_imagesToLoad = this.loadonly_imageLoadingQueue.getSize();
|
||||||
this.imagesLoaded = 0;
|
this.loadonly_imagesLoaded = 0;
|
||||||
|
|
||||||
while(this.imageLoadingQueue.hasItems()){
|
while(this.loadonly_imageLoadingQueue.hasItems()){
|
||||||
let image = this.imageLoadingQueue.dequeue();
|
let image = this.loadonly_imageLoadingQueue.dequeue();
|
||||||
this.loadImage(image.key, image.path, onFinishLoading);
|
this.loadImage(image.key, image.path, onFinishLoading);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,9 +295,9 @@ export default class ResourceManager {
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
private finishLoadingImage(callback: Function): void {
|
private finishLoadingImage(callback: Function): void {
|
||||||
this.imagesLoaded += 1;
|
this.loadonly_imagesLoaded += 1;
|
||||||
|
|
||||||
if(this.imagesLoaded === this.imagesToLoad ){
|
if(this.loadonly_imagesLoaded === this.loadonly_imagesToLoad ){
|
||||||
// We're done loading images
|
// We're done loading images
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
@ -308,11 +308,11 @@ export default class ResourceManager {
|
||||||
* @param onFinishLoading
|
* @param onFinishLoading
|
||||||
*/
|
*/
|
||||||
private loadAudioFromQueue(onFinishLoading: Function){
|
private loadAudioFromQueue(onFinishLoading: Function){
|
||||||
this.audioToLoad = this.audioLoadingQueue.getSize();
|
this.loadonly_audioToLoad = this.loadonly_audioLoadingQueue.getSize();
|
||||||
this.audioLoaded = 0;
|
this.loadonly_audioLoaded = 0;
|
||||||
|
|
||||||
while(this.audioLoadingQueue.hasItems()){
|
while(this.loadonly_audioLoadingQueue.hasItems()){
|
||||||
let audio = this.audioLoadingQueue.dequeue();
|
let audio = this.loadonly_audioLoadingQueue.dequeue();
|
||||||
this.loadAudio(audio.key, audio.path, onFinishLoading);
|
this.loadAudio(audio.key, audio.path, onFinishLoading);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,9 +349,9 @@ export default class ResourceManager {
|
||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
private finishLoadingAudio(callback: Function): void {
|
private finishLoadingAudio(callback: Function): void {
|
||||||
this.audioLoaded += 1;
|
this.loadonly_audioLoaded += 1;
|
||||||
|
|
||||||
if(this.audioLoaded === this.audioToLoad){
|
if(this.loadonly_audioLoaded === this.loadonly_audioToLoad){
|
||||||
// We're done loading audio
|
// We're done loading audio
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
@ -370,10 +370,10 @@ export default class ResourceManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getLoadPercent(): number {
|
private getLoadPercent(): number {
|
||||||
return (this.tilemapsLoaded/this.tilemapsToLoad
|
return (this.loadonly_tilemapsLoaded/this.loadonly_tilemapsToLoad
|
||||||
+ this.imagesLoaded/this.imagesToLoad
|
+ this.loadonly_imagesLoaded/this.loadonly_imagesToLoad
|
||||||
+ this.audioLoaded/this.audioToLoad)
|
+ this.loadonly_audioLoaded/this.loadonly_audioToLoad)
|
||||||
/ this.typesToLoad;
|
/ this.loadonly_typesToLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(deltaT: number): void {
|
public update(deltaT: number): void {
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import ResourceManager from "../../ResourceManager/ResourceManager";
|
|
||||||
import AudioManager from "../../Sound/AudioManager";
|
|
||||||
import Scene from "../Scene";
|
|
||||||
import Audio from "../../Sound/Audio";
|
|
||||||
|
|
||||||
export default class AudioFactory {
|
|
||||||
private scene: Scene;
|
|
||||||
private resourceManager: ResourceManager;
|
|
||||||
private audioManager: AudioManager;
|
|
||||||
|
|
||||||
init(scene: Scene){
|
|
||||||
this.scene = scene;
|
|
||||||
this.resourceManager = ResourceManager.getInstance();
|
|
||||||
this.audioManager = AudioManager.getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns an audio element created using the previously loaded audio file specified by the key.
|
|
||||||
* @param key The key of the loaded audio file
|
|
||||||
*/
|
|
||||||
addAudio = (key: string): Audio => {
|
|
||||||
let audio = new Audio(key);
|
|
||||||
return audio;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@ import Scene from "../Scene";
|
||||||
import PhysicsNodeFactory from "./PhysicsNodeFactory";
|
import PhysicsNodeFactory from "./PhysicsNodeFactory";
|
||||||
import CanvasNodeFactory from "./CanvasNodeFactory";
|
import CanvasNodeFactory from "./CanvasNodeFactory";
|
||||||
import TilemapFactory from "./TilemapFactory";
|
import TilemapFactory from "./TilemapFactory";
|
||||||
import AudioFactory from "./AudioFactory";
|
|
||||||
import PhysicsManager from "../../Physics/PhysicsManager";
|
import PhysicsManager from "../../Physics/PhysicsManager";
|
||||||
import SceneGraph from "../../SceneGraph/SceneGraph";
|
import SceneGraph from "../../SceneGraph/SceneGraph";
|
||||||
import Tilemap from "../../Nodes/Tilemap";
|
import Tilemap from "../../Nodes/Tilemap";
|
||||||
|
@ -13,13 +12,11 @@ export default class FactoryManager {
|
||||||
private canvasNodeFactory: CanvasNodeFactory = new CanvasNodeFactory();
|
private canvasNodeFactory: CanvasNodeFactory = new CanvasNodeFactory();
|
||||||
private physicsNodeFactory: PhysicsNodeFactory = new PhysicsNodeFactory();
|
private physicsNodeFactory: PhysicsNodeFactory = new PhysicsNodeFactory();
|
||||||
private tilemapFactory: TilemapFactory = new TilemapFactory();
|
private tilemapFactory: TilemapFactory = new TilemapFactory();
|
||||||
private audioFactory: AudioFactory = new AudioFactory();
|
|
||||||
|
|
||||||
constructor(scene: Scene, sceneGraph: SceneGraph, physicsManager: PhysicsManager, tilemaps: Array<Tilemap>){
|
constructor(scene: Scene, sceneGraph: SceneGraph, physicsManager: PhysicsManager, tilemaps: Array<Tilemap>){
|
||||||
this.canvasNodeFactory.init(scene, sceneGraph);
|
this.canvasNodeFactory.init(scene, sceneGraph);
|
||||||
this.physicsNodeFactory.init(scene, physicsManager);
|
this.physicsNodeFactory.init(scene, physicsManager);
|
||||||
this.tilemapFactory.init(scene, tilemaps, physicsManager);
|
this.tilemapFactory.init(scene, tilemaps, physicsManager);
|
||||||
this.audioFactory.init(scene);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expose all of the factories through the factory manager
|
// Expose all of the factories through the factory manager
|
||||||
|
@ -28,5 +25,4 @@ export default class FactoryManager {
|
||||||
graphic = this.canvasNodeFactory.addGraphic;
|
graphic = this.canvasNodeFactory.addGraphic;
|
||||||
physics = this.physicsNodeFactory.add;
|
physics = this.physicsNodeFactory.add;
|
||||||
tilemap = this.tilemapFactory.add;
|
tilemap = this.tilemapFactory.add;
|
||||||
audio = this.audioFactory.addAudio;
|
|
||||||
}
|
}
|
|
@ -10,6 +10,9 @@ import Tilemap from "../Nodes/Tilemap";
|
||||||
import ResourceManager from "../ResourceManager/ResourceManager";
|
import ResourceManager from "../ResourceManager/ResourceManager";
|
||||||
import GameLoop from "../Loop/GameLoop";
|
import GameLoop from "../Loop/GameLoop";
|
||||||
import SceneManager from "./SceneManager";
|
import SceneManager from "./SceneManager";
|
||||||
|
import EventQueue from "../Events/EventQueue";
|
||||||
|
import GameEvent from "../Events/GameEvent";
|
||||||
|
import Map from "../DataTypes/Map";
|
||||||
|
|
||||||
export default class Scene{
|
export default class Scene{
|
||||||
protected layers: Stack<Layer>;
|
protected layers: Stack<Layer>;
|
||||||
|
@ -143,4 +146,14 @@ export default class Scene{
|
||||||
getViewport(): Viewport {
|
getViewport(): Viewport {
|
||||||
return this.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);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -40,7 +40,7 @@ export default class SecondScene extends Scene {
|
||||||
backgroundTilemap.getLayer().setAlpha(0.2);
|
backgroundTilemap.getLayer().setAlpha(0.2);
|
||||||
|
|
||||||
// Add the music and start playing it on a loop
|
// Add the music and start playing it on a loop
|
||||||
this.add.audio("level_music").play(true);
|
this.emit("play_sound", {key: "level_music", loop: true, holdReference: true});
|
||||||
|
|
||||||
// Add the tilemap
|
// Add the tilemap
|
||||||
this.add.tilemap("level2", OrthogonalTilemap);
|
this.add.tilemap("level2", OrthogonalTilemap);
|
||||||
|
@ -53,10 +53,6 @@ export default class SecondScene extends Scene {
|
||||||
let playerSprite = this.add.sprite("player", mainLayer);
|
let playerSprite = this.add.sprite("player", mainLayer);
|
||||||
player.setSprite(playerSprite);
|
player.setSprite(playerSprite);
|
||||||
|
|
||||||
// TODO - Should sound playing be handled with events?
|
|
||||||
let playerJumpSound = this.add.audio("player_jump");
|
|
||||||
player.jumpSound = playerJumpSound;
|
|
||||||
|
|
||||||
this.viewport.follow(player);
|
this.viewport.follow(player);
|
||||||
|
|
||||||
// Initialize UI
|
// Initialize UI
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
import AudioManager from "./AudioManager";
|
|
||||||
|
|
||||||
export default class Audio {
|
|
||||||
private key: string;
|
|
||||||
private sound: AudioBufferSourceNode;
|
|
||||||
|
|
||||||
constructor(key: string){
|
|
||||||
this.key = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Play the sound this audio represents
|
|
||||||
* @param loop A boolean for whether or not to loop the sound
|
|
||||||
*/
|
|
||||||
play(loop?: boolean): void {
|
|
||||||
this.sound = AudioManager.getInstance().createSound(this.key);
|
|
||||||
|
|
||||||
if(loop){
|
|
||||||
this.sound.loop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sound.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop the sound this audio represents
|
|
||||||
*/
|
|
||||||
stop(): void {
|
|
||||||
if(this.sound){
|
|
||||||
this.sound.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,19 @@
|
||||||
|
import Map from "../DataTypes/Map";
|
||||||
|
import Receiver from "../Events/Receiver";
|
||||||
import ResourceManager from "../ResourceManager/ResourceManager";
|
import ResourceManager from "../ResourceManager/ResourceManager";
|
||||||
|
|
||||||
export default class AudioManager {
|
export default class AudioManager {
|
||||||
private static instance: AudioManager;
|
private static instance: AudioManager;
|
||||||
|
private receiver: Receiver;
|
||||||
|
private currentSounds: Map<AudioBufferSourceNode>;
|
||||||
|
|
||||||
private audioCtx: AudioContext;
|
private audioCtx: AudioContext;
|
||||||
|
|
||||||
private constructor(){
|
private constructor(){
|
||||||
this.initAudio();
|
this.initAudio();
|
||||||
|
this.receiver = new Receiver();
|
||||||
|
this.receiver.subscribe(["play_sound", "stop_sound"]);
|
||||||
|
this.currentSounds = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,7 +50,17 @@ export default class AudioManager {
|
||||||
* Creates a new sound from the key of a loaded audio file
|
* Creates a new sound from the key of a loaded audio file
|
||||||
* @param key The key of the loaded audio file to create a new sound for
|
* @param key The key of the loaded audio file to create a new sound for
|
||||||
*/
|
*/
|
||||||
createSound(key: string): AudioBufferSourceNode {
|
/*
|
||||||
|
According to the MDN, create a new sound for every call:
|
||||||
|
|
||||||
|
An AudioBufferSourceNode can only be played once; after each call to start(), you have to create a new node
|
||||||
|
if you want to play the same sound again. Fortunately, these nodes are very inexpensive to create, and the
|
||||||
|
actual AudioBuffers can be reused for multiple plays of the sound. Indeed, you can use these nodes in a
|
||||||
|
"fire and forget" manner: create the node, call start() to begin playing the sound, and don't even bother to
|
||||||
|
hold a reference to it. It will automatically be garbage-collected at an appropriate time, which won't be
|
||||||
|
until sometime after the sound has finished playing.
|
||||||
|
*/
|
||||||
|
protected createSound(key: string): AudioBufferSourceNode {
|
||||||
// Get audio buffer
|
// Get audio buffer
|
||||||
let buffer = ResourceManager.getInstance().getAudio(key);
|
let buffer = ResourceManager.getInstance().getAudio(key);
|
||||||
|
|
||||||
|
@ -57,6 +74,60 @@ export default class AudioManager {
|
||||||
source.connect(this.audioCtx.destination);
|
source.connect(this.audioCtx.destination);
|
||||||
|
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play the sound specified by the key
|
||||||
|
* @param key The key of the sound to play
|
||||||
|
* @param loop A boolean for whether or not to loop the sound
|
||||||
|
* @param holdReference A boolean for whether or not we want to hold on to a reference of the audio node. This is good for playing music on a loop that will eventually need to be stopped.
|
||||||
|
*/
|
||||||
|
protected playSound(key: string, loop: boolean, holdReference: boolean): void {
|
||||||
|
let sound = this.createSound(key);
|
||||||
|
|
||||||
|
if(loop){
|
||||||
|
sound.loop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a reference of the new sound to a map. This will allow us to stop a looping or long sound at a later time
|
||||||
|
if(holdReference){
|
||||||
|
this.currentSounds.add(key, sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
sound.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the sound specified by the key
|
||||||
|
*/
|
||||||
|
protected stopSound(key: string): void {
|
||||||
|
let sound = this.currentSounds.get(key);
|
||||||
|
if(sound){
|
||||||
|
sound.stop();
|
||||||
|
this.currentSounds.delete(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the AudioManager
|
||||||
|
* @param deltaT
|
||||||
|
*/
|
||||||
|
update(deltaT: number): void {
|
||||||
|
// Play each audio clip requested
|
||||||
|
// 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"){
|
||||||
|
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"){
|
||||||
|
let soundKey = event.data.get("key");
|
||||||
|
this.stopSound(soundKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user