0
# Asset Loading System
1
2
Phaser's loader system provides comprehensive asset loading capabilities supporting multiple file types, loading strategies, and progress monitoring. The system handles caching, parallel downloads, and various asset formats automatically.
3
4
## Loader Plugin
5
6
### Basic Loading
7
Each scene has its own loader accessible via `this.load`:
8
9
```javascript { .api }
10
class LoadingScene extends Phaser.Scene {
11
preload() {
12
// Basic asset loading
13
this.load.image('logo', 'assets/logo.png');
14
this.load.audio('music', 'assets/music.mp3');
15
this.load.json('gameData', 'assets/data.json');
16
17
// Load with key and URL
18
this.load.image('background', 'assets/images/bg.jpg');
19
20
// Load with configuration
21
this.load.image('sprite', 'assets/sprite.png', {
22
frameConfig: {
23
frameWidth: 32,
24
frameHeight: 32
25
}
26
});
27
28
// Start loading (automatic in preload)
29
this.load.start();
30
}
31
32
create() {
33
// Assets are now available
34
this.add.image(400, 300, 'logo');
35
this.sound.add('music').play();
36
}
37
}
38
```
39
40
### Loader Configuration
41
Configure global loader settings:
42
43
```javascript { .api }
44
class ConfiguredLoadingScene extends Phaser.Scene {
45
init() {
46
// Configure loader settings
47
this.load.setBaseURL('https://cdn.example.com/');
48
this.load.setPath('assets/');
49
this.load.setPrefix('game_');
50
51
// Cross-origin settings
52
this.load.setCORS('anonymous');
53
54
// Parallel loading
55
this.load.maxParallelDownloads = 4; // Default: 32
56
57
// Response type for XHR
58
this.load.setXHRSettings({
59
responseType: 'arraybuffer',
60
timeout: 10000,
61
headers: {
62
'Custom-Header': 'value'
63
}
64
});
65
}
66
67
preload() {
68
// URLs will be: https://cdn.example.com/assets/game_logo.png
69
this.load.image('logo', 'logo.png');
70
71
// Override settings for specific file
72
this.load.image('special', 'special.png', {
73
xhrSettings: {
74
responseType: 'blob',
75
timeout: 5000
76
}
77
});
78
}
79
}
80
```
81
82
## File Types
83
84
### Images
85
Load various image formats and configurations:
86
87
```javascript { .api }
88
class ImageLoadingScene extends Phaser.Scene {
89
preload() {
90
// Basic image
91
this.load.image('logo', 'assets/logo.png');
92
93
// Spritesheet
94
this.load.spritesheet('player', 'assets/player.png', {
95
frameWidth: 32,
96
frameHeight: 48,
97
startFrame: 0,
98
endFrame: 7
99
});
100
101
// Texture atlas (JSON)
102
this.load.atlas('characters', 'assets/characters.png', 'assets/characters.json');
103
104
// Texture atlas (XML)
105
this.load.atlasXML('ui', 'assets/ui.png', 'assets/ui.xml');
106
107
// Multi-atlas (multiple texture sheets)
108
this.load.multiatlas('game', 'assets/game.json');
109
110
// Unity atlas
111
this.load.unityAtlas('unity', 'assets/unity.png', 'assets/unity.txt');
112
113
// SVG images
114
this.load.svg('vector', 'assets/vector.svg', { width: 300, height: 300 });
115
116
// Base64 images
117
this.load.image('base64', 'data:image/png;base64,iVBORw0KGgoAAAANS...');
118
119
// HTML as texture
120
this.load.htmlTexture('htmlText', 'assets/text.html', 512, 256);
121
}
122
}
123
```
124
125
### Audio Files
126
Load audio with various formats and configurations:
127
128
```javascript { .api }
129
class AudioLoadingScene extends Phaser.Scene {
130
preload() {
131
// Basic audio
132
this.load.audio('bgm', 'assets/music.mp3');
133
134
// Multiple formats (browser chooses best)
135
this.load.audio('sfx', [
136
'assets/sound.ogg',
137
'assets/sound.mp3',
138
'assets/sound.wav'
139
]);
140
141
// Audio with instances for overlapping playback
142
this.load.audio('explosion', 'assets/explosion.wav', {
143
instances: 5
144
});
145
146
// Audio sprite
147
this.load.audioSprite('gamesfx', 'assets/gamesfx.json', [
148
'assets/gamesfx.ogg',
149
'assets/gamesfx.mp3'
150
]);
151
152
// Streaming audio (not cached)
153
this.load.audio('stream', 'assets/longtrack.mp3', {
154
stream: true
155
});
156
}
157
}
158
```
159
160
### Data Files
161
Load various data formats:
162
163
```javascript { .api }
164
class DataLoadingScene extends Phaser.Scene {
165
preload() {
166
// JSON data
167
this.load.json('gameConfig', 'assets/config.json');
168
169
// XML data
170
this.load.xml('levelData', 'assets/level.xml');
171
172
// Plain text
173
this.load.text('story', 'assets/story.txt');
174
175
// CSV data
176
this.load.text('scores', 'assets/scores.csv');
177
178
// Binary data
179
this.load.binary('saveFile', 'assets/save.dat');
180
181
// CSS files
182
this.load.css('styles', 'assets/game.css');
183
184
// HTML files
185
this.load.html('template', 'assets/template.html');
186
187
// JavaScript files
188
this.load.script('external', 'assets/external.js');
189
}
190
191
create() {
192
// Access loaded data
193
const config = this.cache.json.get('gameConfig');
194
const levelData = this.cache.xml.get('levelData');
195
const story = this.cache.text.get('story');
196
197
console.log('Game config:', config);
198
console.log('Level data:', levelData);
199
console.log('Story text:', story);
200
}
201
}
202
```
203
204
### Fonts and Textures
205
Load bitmap fonts and special textures:
206
207
```javascript { .api }
208
class FontLoadingScene extends Phaser.Scene {
209
preload() {
210
// Bitmap font
211
this.load.bitmapFont('pixel', 'assets/fonts/pixel.png', 'assets/fonts/pixel.xml');
212
213
// Bitmap font (JSON format)
214
this.load.bitmapFont('arcade', 'assets/fonts/arcade.png', 'assets/fonts/arcade.json');
215
216
// Google Fonts (Web Font Loader required)
217
this.load.script('webfont', 'https://ajax.googleapis.com/ajax/libs/webfont/1.6.26/webfont.js');
218
219
// Texture from canvas
220
const canvas = document.createElement('canvas');
221
canvas.width = 64;
222
canvas.height = 64;
223
const ctx = canvas.getContext('2d');
224
ctx.fillStyle = '#ff0000';
225
ctx.fillRect(0, 0, 64, 64);
226
227
this.textures.addCanvas('redSquare', canvas);
228
}
229
230
create() {
231
// Use bitmap font
232
this.add.bitmapText(100, 100, 'pixel', 'Hello World');
233
234
// Use generated texture
235
this.add.image(200, 200, 'redSquare');
236
237
// Load Google Fonts dynamically
238
if (window.WebFont) {
239
WebFont.load({
240
google: {
241
families: ['Orbitron']
242
},
243
active: () => {
244
this.add.text(300, 300, 'Google Font', {
245
fontFamily: 'Orbitron',
246
fontSize: '24px'
247
});
248
}
249
});
250
}
251
}
252
}
253
```
254
255
### 3D and Advanced Assets
256
Load 3D models and shaders:
257
258
```javascript { .api }
259
class Advanced3DLoadingScene extends Phaser.Scene {
260
preload() {
261
// OBJ 3D model
262
this.load.obj('model', 'assets/model.obj', 'assets/model.mtl');
263
264
// GLSL shaders
265
this.load.glsl('vertexShader', 'assets/vertex.glsl');
266
this.load.glsl('fragmentShader', 'assets/fragment.glsl');
267
268
// Video files
269
this.load.video('intro', 'assets/intro.mp4');
270
this.load.video('background', [
271
'assets/bg.webm',
272
'assets/bg.mp4'
273
]);
274
275
// Compressed textures (WebGL)
276
this.load.texture('compressed', {
277
ETC1: 'assets/texture.etc1',
278
PVRTC: 'assets/texture.pvr',
279
S3TC: 'assets/texture.dxt'
280
});
281
}
282
283
create() {
284
// Use loaded assets
285
if (this.renderer.type === Phaser.WEBGL) {
286
// Create shader
287
const shader = this.add.shader('fragmentShader', 100, 100, 200, 200);
288
289
// Play video
290
const video = this.add.video(400, 300, 'intro');
291
video.play();
292
}
293
}
294
}
295
```
296
297
## Loading Progress and Events
298
299
### Progress Monitoring
300
Track loading progress with detailed feedback:
301
302
```javascript { .api }
303
class ProgressLoadingScene extends Phaser.Scene {
304
preload() {
305
// Create progress UI
306
this.createProgressBar();
307
308
// Loading events
309
this.load.on('start', () => {
310
console.log('Loading started');
311
this.progressText.setText('Loading...');
312
});
313
314
this.load.on('progress', (percent) => {
315
console.log('Loading progress:', percent);
316
this.updateProgressBar(percent);
317
this.progressText.setText(`Loading: ${Math.round(percent * 100)}%`);
318
});
319
320
this.load.on('fileprogress', (file, percent) => {
321
console.log(`File ${file.key}: ${Math.round(percent * 100)}%`);
322
this.fileText.setText(`Loading: ${file.key}`);
323
});
324
325
this.load.on('complete', () => {
326
console.log('Loading complete');
327
this.progressText.setText('Complete!');
328
this.time.delayedCall(1000, () => {
329
this.scene.start('GameScene');
330
});
331
});
332
333
// File-specific events
334
this.load.on('filecomplete', (key, type, data) => {
335
console.log(`Loaded ${type}: ${key}`);
336
});
337
338
this.load.on('filecomplete-image-logo', (key, type, data) => {
339
console.log('Logo loaded!');
340
});
341
342
// Error handling
343
this.load.on('loaderror', (file) => {
344
console.error('Failed to load:', file.key);
345
this.errorText.setText(`Error loading: ${file.key}`);
346
});
347
348
// Load assets
349
this.loadGameAssets();
350
}
351
352
createProgressBar() {
353
// Progress bar background
354
this.progressBox = this.add.graphics();
355
this.progressBox.fillStyle(0x222222);
356
this.progressBox.fillRect(240, 270, 320, 50);
357
358
// Progress bar fill
359
this.progressBar = this.add.graphics();
360
361
// Progress text
362
this.progressText = this.add.text(400, 240, 'Loading...', {
363
fontSize: '20px',
364
fill: '#ffffff'
365
}).setOrigin(0.5);
366
367
// Current file text
368
this.fileText = this.add.text(400, 330, '', {
369
fontSize: '16px',
370
fill: '#ffffff'
371
}).setOrigin(0.5);
372
373
// Error text
374
this.errorText = this.add.text(400, 360, '', {
375
fontSize: '16px',
376
fill: '#ff0000'
377
}).setOrigin(0.5);
378
}
379
380
updateProgressBar(percent) {
381
this.progressBar.clear();
382
this.progressBar.fillStyle(0xffffff);
383
this.progressBar.fillRect(250, 280, 300 * percent, 30);
384
}
385
386
loadGameAssets() {
387
// Load multiple assets
388
this.load.image('background', 'assets/bg.jpg');
389
this.load.spritesheet('player', 'assets/player.png', {
390
frameWidth: 32, frameHeight: 48
391
});
392
this.load.atlas('ui', 'assets/ui.png', 'assets/ui.json');
393
this.load.audio('music', ['assets/music.ogg', 'assets/music.mp3']);
394
this.load.audio('sfx', 'assets/sfx.wav');
395
this.load.json('levels', 'assets/levels.json');
396
// Add more assets...
397
}
398
}
399
```
400
401
### Asset Packs
402
Organize assets into reusable packs:
403
404
```javascript { .api }
405
class AssetPackScene extends Phaser.Scene {
406
preload() {
407
// Define asset pack
408
const assetPack = {
409
"section1": {
410
"files": [
411
{
412
"type": "image",
413
"key": "logo",
414
"url": "assets/logo.png"
415
},
416
{
417
"type": "image",
418
"key": "background",
419
"url": "assets/bg.jpg"
420
},
421
{
422
"type": "spritesheet",
423
"key": "player",
424
"url": "assets/player.png",
425
"frameConfig": {
426
"frameWidth": 32,
427
"frameHeight": 48
428
}
429
},
430
{
431
"type": "audio",
432
"key": "music",
433
"urls": ["assets/music.ogg", "assets/music.mp3"],
434
"config": {
435
"loop": true,
436
"volume": 0.8
437
}
438
}
439
]
440
},
441
"section2": {
442
"files": [
443
{
444
"type": "atlas",
445
"key": "sprites",
446
"textureURL": "assets/sprites.png",
447
"atlasURL": "assets/sprites.json"
448
},
449
{
450
"type": "bitmapFont",
451
"key": "font",
452
"textureURL": "assets/font.png",
453
"fontDataURL": "assets/font.xml"
454
}
455
]
456
}
457
};
458
459
// Load from pack object
460
this.load.pack("gameAssets", assetPack);
461
462
// Load from external pack file
463
this.load.pack("uiAssets", "assets/ui-pack.json");
464
465
// Load specific pack section
466
this.load.pack("levelAssets", "assets/levels-pack.json", "level1");
467
}
468
}
469
```
470
471
## Advanced Loading Techniques
472
473
### Dynamic Loading
474
Load assets at runtime based on game state:
475
476
```javascript { .api }
477
class DynamicLoadingScene extends Phaser.Scene {
478
create() {
479
this.currentLevel = 1;
480
this.loadingQueue = [];
481
this.isLoading = false;
482
}
483
484
loadLevel(levelNumber) {
485
if (this.isLoading) {
486
this.loadingQueue.push(levelNumber);
487
return;
488
}
489
490
this.isLoading = true;
491
492
// Create temporary loader
493
const loader = new Phaser.Loader.LoaderPlugin(this);
494
495
// Configure for this level
496
loader.setPath(`assets/levels/${levelNumber}/`);
497
498
// Load level-specific assets
499
loader.image('background', 'bg.jpg');
500
loader.json('data', 'data.json');
501
loader.atlas('enemies', 'enemies.png', 'enemies.json');
502
503
// Progress tracking
504
loader.on('progress', (percent) => {
505
this.showLoadingProgress(percent);
506
});
507
508
loader.once('complete', () => {
509
this.isLoading = false;
510
this.hideLoadingProgress();
511
this.startLevel(levelNumber);
512
513
// Process queue
514
if (this.loadingQueue.length > 0) {
515
const nextLevel = this.loadingQueue.shift();
516
this.loadLevel(nextLevel);
517
}
518
});
519
520
// Start loading
521
loader.start();
522
}
523
524
preloadNextLevel() {
525
// Preload next level assets in background
526
const nextLevel = this.currentLevel + 1;
527
528
// Check if already loaded
529
if (this.textures.exists(`level${nextLevel}_bg`)) {
530
return;
531
}
532
533
// Background loading without blocking current gameplay
534
const backgroundLoader = new Phaser.Loader.LoaderPlugin(this);
535
backgroundLoader.setPath(`assets/levels/${nextLevel}/`);
536
backgroundLoader.image(`level${nextLevel}_bg`, 'bg.jpg');
537
backgroundLoader.json(`level${nextLevel}_data`, 'data.json');
538
539
backgroundLoader.once('complete', () => {
540
console.log(`Level ${nextLevel} preloaded`);
541
});
542
543
backgroundLoader.start();
544
}
545
546
showLoadingProgress(percent) {
547
if (!this.loadingOverlay) {
548
this.loadingOverlay = this.add.graphics();
549
this.loadingText = this.add.text(400, 300, '', {
550
fontSize: '24px',
551
fill: '#ffffff'
552
}).setOrigin(0.5);
553
}
554
555
this.loadingOverlay.clear();
556
this.loadingOverlay.fillStyle(0x000000, 0.8);
557
this.loadingOverlay.fillRect(0, 0, 800, 600);
558
559
this.loadingText.setText(`Loading: ${Math.round(percent * 100)}%`);
560
}
561
562
hideLoadingProgress() {
563
if (this.loadingOverlay) {
564
this.loadingOverlay.destroy();
565
this.loadingText.destroy();
566
this.loadingOverlay = null;
567
this.loadingText = null;
568
}
569
}
570
}
571
```
572
573
### Asset Streaming
574
Stream large assets progressively:
575
576
```javascript { .api }
577
class StreamingScene extends Phaser.Scene {
578
preload() {
579
// Stream large audio files
580
this.load.audio('backgroundMusic', 'assets/long-track.mp3', {
581
stream: true
582
});
583
584
// Progressive texture loading
585
this.loadTexturesProgressively([
586
'texture1', 'texture2', 'texture3', 'texture4'
587
]);
588
}
589
590
loadTexturesProgressively(textureKeys) {
591
let currentIndex = 0;
592
const batchSize = 2; // Load 2 textures at a time
593
594
const loadBatch = () => {
595
if (currentIndex >= textureKeys.length) {
596
return;
597
}
598
599
const batch = textureKeys.slice(currentIndex, currentIndex + batchSize);
600
const batchLoader = new Phaser.Loader.LoaderPlugin(this);
601
602
batch.forEach(key => {
603
batchLoader.image(key, `assets/${key}.png`);
604
});
605
606
batchLoader.once('complete', () => {
607
currentIndex += batchSize;
608
this.time.delayedCall(100, loadBatch); // Small delay between batches
609
});
610
611
batchLoader.start();
612
};
613
614
loadBatch();
615
}
616
}
617
```
618
619
### Memory Management
620
Efficiently manage loaded assets:
621
622
```javascript { .api }
623
class MemoryManagementScene extends Phaser.Scene {
624
create() {
625
this.loadedAssets = new Set();
626
}
627
628
loadAssets(assetList, callback) {
629
const loader = new Phaser.Loader.LoaderPlugin(this);
630
631
assetList.forEach(asset => {
632
if (!this.loadedAssets.has(asset.key)) {
633
loader[asset.type](asset.key, asset.url, asset.config);
634
this.loadedAssets.add(asset.key);
635
}
636
});
637
638
if (loader.list.size > 0) {
639
loader.once('complete', callback);
640
loader.start();
641
} else {
642
callback(); // All assets already loaded
643
}
644
}
645
646
unloadUnusedAssets() {
647
// Remove textures not used in current scene
648
const textureKeys = this.textures.getTextureKeys();
649
650
textureKeys.forEach(key => {
651
if (!this.isAssetInUse(key)) {
652
this.textures.remove(key);
653
this.loadedAssets.delete(key);
654
console.log('Unloaded texture:', key);
655
}
656
});
657
658
// Remove sounds not playing
659
this.sound.sounds.forEach(sound => {
660
if (!sound.isPlaying && sound.key !== 'backgroundMusic') {
661
sound.destroy();
662
}
663
});
664
665
// Clear cache entries
666
this.cache.json.entries.clear();
667
this.cache.xml.entries.clear();
668
}
669
670
isAssetInUse(key) {
671
// Check if any game object is using this asset
672
return this.children.exists((child) => {
673
return child.texture && child.texture.key === key;
674
});
675
}
676
677
getMemoryUsage() {
678
const textureMemory = this.textures.getTextureKeys().length;
679
const audioMemory = this.sound.sounds.length;
680
const cacheMemory = Object.keys(this.cache.json.entries).length +
681
Object.keys(this.cache.xml.entries).length;
682
683
return {
684
textures: textureMemory,
685
audio: audioMemory,
686
cache: cacheMemory,
687
total: textureMemory + audioMemory + cacheMemory
688
};
689
}
690
691
shutdown() {
692
// Clean up when scene shuts down
693
this.unloadUnusedAssets();
694
}
695
}
696
```
697
698
This comprehensive loading system provides all the tools needed to efficiently manage assets throughout a game's lifecycle, from initial loading screens to dynamic runtime asset management.