Skip to content
This repository has been archived by the owner on Nov 13, 2023. It is now read-only.

Commit

Permalink
Merge branch bugfix/infinite-asset-loading-loop into main (#102)
Browse files Browse the repository at this point in the history
* Fix infinite asset loading

- Implement events for asset loading in AssetLoader
- Adapt main game class to new AssetLoader events.
  • Loading branch information
Kitt3120 committed Jun 19, 2023
1 parent 1675794 commit 7772a0c
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 40 deletions.
107 changes: 90 additions & 17 deletions src/ts/engine/assets/assetloader.ts
Original file line number Diff line number Diff line change
@@ -1,78 +1,122 @@
import EngineEvent from "../event/engineevent.js";
import EngineEventHandler from "../event/engineventhandler.js";
import AssetVerifier from "./assetverifier.js";

class AssetLoader {
private _images: Map<string, HTMLImageElement>;
private _audio: Map<string, HTMLAudioElement>;

constructor() {
private _imagesLoadedEvent: EngineEventHandler<boolean, EngineEvent<boolean>>;
private _audiosLoadedEvent: EngineEventHandler<boolean, EngineEvent<boolean>>;
private _assetsLoadedEvent: EngineEventHandler<boolean, EngineEvent<boolean>>;

private _imageLoadTrackerTask: number | undefined;
private _audioLoadTrackerTask: number | undefined;
private _assetLoadTrackerTask: number | undefined;

public get imagesLoadedEvent(): EngineEventHandler<
boolean,
EngineEvent<boolean>
> {
return this._imagesLoadedEvent;
}

public get audiosLoadedEvent(): EngineEventHandler<
boolean,
EngineEvent<boolean>
> {
return this._audiosLoadedEvent;
}

public get assetsLoadedEvent(): EngineEventHandler<
boolean,
EngineEvent<boolean>
> {
return this._assetsLoadedEvent;
}

public constructor() {
this._images = new Map<string, HTMLImageElement>();
this._audio = new Map<string, HTMLAudioElement>();
}

hasImage(key: string): boolean {
this._imagesLoadedEvent = new EngineEventHandler<
boolean,
EngineEvent<boolean>
>();
this._audiosLoadedEvent = new EngineEventHandler<
boolean,
EngineEvent<boolean>
>();
this._assetsLoadedEvent = new EngineEventHandler<
boolean,
EngineEvent<boolean>
>();
}

public hasImage(key: string): boolean {
return this._images.has(key);
}

getImage(key: string): HTMLImageElement {
public getImage(key: string): HTMLImageElement {
if (!this.hasImage(key)) {
throw new Error(`Image with key ${key} does not exist!`);
}

return this._images.get(key) as HTMLImageElement;
}

getImagesCount(): number {
public getImagesCount(): number {
return this._images.size;
}

getImagesReadyCount(): number {
public getImagesReadyCount(): number {
return Array.from(this._images.values())
.map((image) => AssetVerifier.verifyImage(image))
.filter((status) => status === true).length;
}

areImagesReady(): boolean {
public areImagesReady(): boolean {
return this.getImagesCount() === this.getImagesReadyCount();
}

hasAudio(key: string): boolean {
public hasAudio(key: string): boolean {
return this._audio.has(key);
}

getAudio(key: string): HTMLAudioElement {
public getAudio(key: string): HTMLAudioElement {
if (!this.hasAudio(key)) {
throw new Error(`Audio with key ${key} does not exist!`);
}
return this._audio.get(key) as HTMLAudioElement;
}

getAudiosCount(): number {
public getAudiosCount(): number {
return this._audio.size;
}

getAudiosReadyCount(): number {
public getAudiosReadyCount(): number {
return Array.from(this._audio.values())
.map((audio) => AssetVerifier.verifyAudio(audio))
.filter((status) => status === true).length;
}

areAudiosReady(): boolean {
public areAudiosReady(): boolean {
return this.getAudiosCount() === this.getAudiosReadyCount();
}

getAssetsCount(): number {
public getAssetsCount(): number {
return this.getImagesCount() + this.getAudiosCount();
}

getAssetsReadyCount(): number {
public getAssetsReadyCount(): number {
return this.getImagesReadyCount() + this.getAudiosReadyCount();
}

areAssetsReady(): boolean {
public areAssetsReady(): boolean {
return this.getAssetsCount() === this.getAssetsReadyCount();
}

registerImages(className: string) {
public registerImages(className: string) {
let images = document.getElementsByClassName(className);
if (images.length == 0) {
console.warn(`No images found for class ${className}`);
Expand All @@ -92,7 +136,7 @@ class AssetLoader {
}
}

registerAudios(className: string) {
public registerAudios(className: string) {
let audio = document.getElementsByClassName(className);
if (audio.length == 0) {
console.warn(`No audios found for class ${className}`);
Expand All @@ -111,6 +155,35 @@ class AssetLoader {
this._audio.set(audioElement.id, audioElement);
}
}

public startTracking() {
this._imageLoadTrackerTask = setInterval(() => {
let imagesReady = this.areImagesReady();
this._imagesLoadedEvent.dispatch(new EngineEvent<boolean>(imagesReady));

if (imagesReady) {
clearInterval(this._imageLoadTrackerTask);
}
}, 500);

this._audioLoadTrackerTask = setInterval(() => {
let audiosReady = this.areAudiosReady();
this._audiosLoadedEvent.dispatch(new EngineEvent<boolean>(audiosReady));

if (audiosReady) {
clearInterval(this._audioLoadTrackerTask);
}
}, 500);

this._assetLoadTrackerTask = setInterval(() => {
let assetsReady = this.areAssetsReady();
this._assetsLoadedEvent.dispatch(new EngineEvent<boolean>(assetsReady));

if (assetsReady) {
clearInterval(this._assetLoadTrackerTask);
}
}, 500);
}
}

export default AssetLoader;
41 changes: 24 additions & 17 deletions src/ts/engine/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import CookieManager from "./cookies/cookiemanager.js";
import Services from "./dependencyinjection/services.js";
import EngineSetup from "./enginesetup.js";
import EntityManager from "./entitiy/entitymanager.js";
import EngineEvent from "./event/engineevent.js";
import InputHandler from "./input/inputhandler.js";
import LevelManager from "./level/levelmanager.js";
import Compositor from "./renderer/compositor.js";
Expand Down Expand Up @@ -93,25 +94,31 @@ class Game {
this._levelManager
);

while (!this._assetLoader.areAssetsReady()) {
console.log("Loading assets...");
}

engineSetup.registerTextures(
this._assetLoader,
this._assetManager,
this._entityManager,
this._levelManager
);

engineSetup.registerLevels(
this._assetLoader,
this._assetManager,
this._entityManager,
this._levelManager
this._assetLoader.assetsLoadedEvent.subscribe(
(engineEvent: EngineEvent<boolean>) => {
if (!engineEvent.eventData) {
console.log("Loading assets...");
} else {
engineSetup.registerTextures(
this._assetLoader,
this._assetManager,
this._entityManager,
this._levelManager
);

engineSetup.registerLevels(
this._assetLoader,
this._assetManager,
this._entityManager,
this._levelManager
);

engineSetup.registerScenes(this._sceneManager);
}
}
);

engineSetup.registerScenes(this._sceneManager);
this._assetLoader.startTracking();
}

public startUpdateLoop(): void {
Expand Down
24 changes: 21 additions & 3 deletions src/ts/game/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import SpriteSheet from "../engine/assets/texture/spritesheet.js";
import Cookie from "../engine/cookies/cookie.js";
import CookieManager from "../engine/cookies/cookiemanager.js";
import Services from "../engine/dependencyinjection/services.js";
import EngineEvent from "../engine/event/engineevent.js";
import Game from "../engine/game.js";
import InputHandler from "../engine/input/inputhandler.js";
import LevelManager from "../engine/level/levelmanager.js";
Expand All @@ -28,17 +29,34 @@ function getGameCanvas(): HTMLCanvasElement {
return canvas;
}

function start(): void {
function init(): void {
let htmlCanvasElement: HTMLCanvasElement = getGameCanvas();
let game: Game = new Game(htmlCanvasElement, new GameSetup());

window.addEventListener("beforeunload", game.stopGame.bind(game));

let inputHandler: InputHandler =
Services.resolve<InputHandler>("InputHandler");
inputHandler.addWhiteListedKeys(["F5", "F11", "F12", "Alt"]);

game.startGame();
let assetLoader = Services.resolve<AssetLoader>("AssetLoader");

if (!assetLoader.areAssetsReady()) {
assetLoader.assetsLoadedEvent.subscribe(
(engineEvent: EngineEvent<boolean>) => {
if (engineEvent.eventData) {
start(game);
}
}
);
} else {
start(game);
}
}

function start(game: Game): void {
Services.resolve<SceneManager>("SceneManager").switch("mainmenu");
game.startGame();
}

window.addEventListener("DOMContentLoaded", start);
window.addEventListener("DOMContentLoaded", init);
2 changes: 1 addition & 1 deletion src/ts/game/scenes/leveloverview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class LevelOverview extends Base {

private _backToMainMenu: Button;
private _reset: Button;
_audioPlayer: AudioPlayer;
private _audioPlayer: AudioPlayer;

public constructor() {
super(
Expand Down
3 changes: 1 addition & 2 deletions src/ts/game/scenes/mainmenu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,8 @@ class MainMenu extends Base {

public open(): void {
super.open();
console.log(this._audioPlayer.currentMusic);
if (
this._audioPlayer.currentMusic === null ||
!this._audioPlayer.currentMusic ||
this._audioPlayer.currentMusic.id !== "track4"
) {
this._audioPlayer.play(
Expand Down

0 comments on commit 7772a0c

Please sign in to comment.