1+ import { AudioPlayer } from "./audio" ;
2+ import { Game } from "./game" ;
3+ import { IAsset as IAsset , IAssets } from "./interface" ;
4+
5+ /**
6+ * AssetsLoader class for loading game assets (JSON, audio, images).
7+ * Supports asynchronous loading with progress tracking and error handling.
8+ */
9+ class AssetsLoader {
10+ private assets : IAssets ;
11+ private totalAsset : number = 0 ;
12+ private loadedAssets : number = 0 ;
13+ private onProgress : ( ( progress : number , loaded : number , total : number ) => void ) | null = null ;
14+ private onComplete : ( ( assets : IAssets ) => void ) | null = null ;
15+ private onError : ( ( error : { name : string ; url : string ; error : any } ) => void ) | null = null ;
16+ private game : Game
17+ /**
18+ * Creates an instance of AssetsLoader.
19+ * Initializes the asset storage and counters.
20+ */
21+ constructor ( game : Game ) {
22+ this . game = game
23+ this . assets = {
24+ json : { } ,
25+ audio : { } ,
26+ images : { }
27+ } ;
28+ }
29+
30+ /**
31+ * Sets the callback for loading progress updates.
32+ * @param callback - Function called with progress (0.0 to 1.0), loaded count, and total count.
33+ */
34+ setProgressCallback ( callback : ( progress : number , loaded : number , total : number ) => void ) : void {
35+ this . onProgress = callback ;
36+ }
37+
38+ /**
39+ * Sets the callback for when all assets are loaded.
40+ * @param callback - Function called with the loaded assets.
41+ */
42+ setCompleteCallback ( callback : ( assets : IAssets ) => void ) : void {
43+ this . onComplete = callback ;
44+ }
45+
46+ /**
47+ * Sets the callback for handling loading errors.
48+ * @param callback - Function called with error details (name, url, error).
49+ */
50+ setErrorCallback ( callback : ( error : { name : string ; url : string ; error : any } ) => void ) : void {
51+ this . onError = callback ;
52+ }
53+
54+ /**
55+ * Loads a JSON file asynchronously.
56+ * @param name - The unique identifier for the JSON asset.
57+ * @param url - The URL of the JSON file.
58+ */
59+ loadJson ( name : string , url : string ) : void {
60+ this . totalAsset ++ ;
61+ fetch ( url )
62+ . then ( response => response . json ( ) )
63+ . then ( data => {
64+ this . assets . json [ name ] = data ;
65+ this . assetLoaded ( ) ;
66+ } )
67+ . catch ( error => this . handleError ( name , url , error ) ) ;
68+ }
69+
70+ /**
71+ * Loads an audio file asynchronously.
72+ * @param name - The unique identifier for the audio asset.
73+ * @param url - The URL of the audio file.
74+ */
75+ loadAudio ( name : string , url : string ) : void {
76+ this . totalAsset ++ ;
77+ const audio = new Audio ( ) ;
78+ audio . src = url ;
79+ audio . oncanplaythrough = ( ) => {
80+ this . assets . audio [ name ] = new AudioPlayer ( audio , this . game . audio . audioContext ) ;
81+ this . assetLoaded ( ) ;
82+ audio . oncanplaythrough = null ; // Clear event
83+ } ;
84+ audio . onerror = ( ) => this . handleError ( name , url , 'Audio load error' ) ;
85+ }
86+
87+ /**
88+ * Loads an image file asynchronously.
89+ * @param name - The unique identifier for the image asset.
90+ * @param url - The URL of the image file.
91+ */
92+ loadImage ( name : string , url : string ) : void {
93+ this . totalAsset ++ ;
94+ const img = new Image ( ) ;
95+ img . src = url ;
96+ img . onload = ( ) => {
97+ this . assets . images [ name ] = this . game . render . texture . textureFromSource ( img ) ;
98+ this . assetLoaded ( ) ;
99+ } ;
100+ img . onerror = ( ) => this . handleError ( name , url , 'Image load error' ) ;
101+ }
102+
103+ /**
104+ * Loads multiple assets from a list.
105+ * @param assetList - Array of assets to load.
106+ */
107+ loadAssets ( assetList : IAsset [ ] ) : void {
108+ assetList . forEach ( asset => {
109+ switch ( asset . type ) {
110+ case 'json' :
111+ this . loadJson ( asset . name , asset . url ) ;
112+ break ;
113+ case 'audio' :
114+ this . loadAudio ( asset . name , asset . url ) ;
115+ break ;
116+ case 'image' :
117+ this . loadImage ( asset . name , asset . url ) ;
118+ break ;
119+ default :
120+ console . warn ( `Unknown asset type: ${ asset . type } ` ) ;
121+ }
122+ } ) ;
123+ }
124+
125+ /**
126+ * Handles the completion of an asset load.
127+ * Updates progress and triggers completion callback if all assets are loaded.
128+ */
129+ private assetLoaded ( ) : void {
130+ this . loadedAssets ++ ;
131+ if ( this . onProgress ) {
132+ const progress = this . loadedAssets / this . totalAsset ;
133+ this . onProgress ( progress , this . loadedAssets , this . totalAsset ) ;
134+ }
135+ if ( this . loadedAssets === this . totalAsset && this . onComplete ) {
136+ this . onComplete ( this . assets ) ;
137+ }
138+ }
139+
140+ /**
141+ * Handles errors during asset loading.
142+ * @param name - The name of the asset.
143+ * @param url - The URL of the asset.
144+ * @param error - The error object or message.
145+ */
146+ private handleError ( name : string , url : string , error : any ) : void {
147+ if ( this . onError ) {
148+ this . onError ( { name, url, error } ) ;
149+ } else {
150+ console . error ( `Failed to load asset ${ name } from ${ url } :` , error ) ;
151+ }
152+ }
153+
154+ /**
155+ * Retrieves a loaded asset by type and name.
156+ * @param type - The type of asset ('json', 'audio', or 'images').
157+ * @param name - The name of the asset.
158+ * @returns The loaded asset or undefined if not found.
159+ */
160+ get < T extends keyof IAssets > ( type : T , name : string ) : IAssets [ T ] [ string ] | undefined {
161+ return this . assets [ type ] ?. [ name ] ;
162+ }
163+
164+ /**
165+ * Retrieves a loaded JSON asset by name.
166+ * @param name - The name of the JSON asset.
167+ * @returns The loaded JSON data or undefined if not found.
168+ */
169+ getJSON ( name : string ) : any | undefined {
170+ return this . assets . json [ name ] ;
171+ }
172+
173+ /**
174+ * Retrieves a loaded audio asset by name.
175+ * @param name - The name of the audio asset.
176+ * @returns The loaded AudioPlayer instance or undefined if not found.
177+ */
178+ getAudio ( name : string ) : AudioPlayer | undefined {
179+ return this . assets . audio [ name ] ;
180+ }
181+
182+ /**
183+ * Retrieves a loaded texture (image) asset by name.
184+ * @param name - The name of the texture asset.
185+ * @returns The loaded texture or undefined if not found.
186+ */
187+ getTexture ( name : string ) : any | undefined {
188+ return this . assets . images [ name ] ;
189+ }
190+ }
191+
192+ export default AssetsLoader ;
0 commit comments