0
# Rendering and Display Systems
1
2
Phaser's rendering system provides flexible WebGL and Canvas rendering with comprehensive texture management, visual effects, and display utilities. The system automatically chooses the best available renderer while providing fine-grained control over rendering operations.
3
4
## Renderer System
5
6
### Renderer Types and Configuration
7
Phaser supports multiple rendering backends:
8
9
```javascript { .api }
10
// Game configuration with renderer settings
11
const config = {
12
type: Phaser.AUTO, // Auto-detect best renderer
13
// type: Phaser.WEBGL, // Force WebGL
14
// type: Phaser.CANVAS, // Force Canvas
15
// type: Phaser.HEADLESS, // No rendering (testing)
16
17
width: 800,
18
height: 600,
19
20
render: {
21
antialias: true, // Enable anti-aliasing
22
pixelArt: false, // Optimize for pixel art
23
autoResize: true, // Auto-resize canvas
24
roundPixels: true, // Round pixel positions
25
transparent: false, // Transparent canvas background
26
clearBeforeRender: true, // Clear canvas each frame
27
preserveDrawingBuffer: false, // Keep drawing buffer (screenshots)
28
failIfMajorPerformanceCaveat: false, // Fail on poor performance
29
powerPreference: 'default', // 'high-performance' or 'low-power'
30
batchSize: 4096, // WebGL batch size
31
maxLights: 10, // Maximum point lights
32
maxTextures: -1, // Maximum texture units (-1 = auto)
33
mipmapFilter: 'LINEAR' // Mipmap filtering
34
},
35
36
backgroundColor: '#2c3e50', // Canvas background color
37
38
canvas: document.getElementById('game-canvas'), // Existing canvas
39
canvasStyle: 'width: 100%; height: 100%;', // Canvas CSS
40
41
scene: RenderingScene
42
};
43
44
class RenderingScene extends Phaser.Scene {
45
create() {
46
// Access renderer information
47
const renderer = this.renderer;
48
49
console.log('Renderer type:', renderer.type);
50
console.log('WebGL:', renderer.type === Phaser.WEBGL);
51
console.log('Canvas size:', renderer.width, renderer.height);
52
console.log('Max texture size:', renderer.maxTextureSize);
53
54
if (renderer.gl) {
55
console.log('WebGL context:', renderer.gl);
56
console.log('Extensions:', renderer.extensions);
57
console.log('Max textures:', renderer.maxTextures);
58
}
59
}
60
}
61
```
62
63
### WebGL Renderer Features
64
Advanced WebGL-specific rendering capabilities:
65
66
```javascript { .api }
67
class WebGLRenderingScene extends Phaser.Scene {
68
create() {
69
if (this.renderer.type === Phaser.WEBGL) {
70
const gl = this.renderer.gl;
71
const renderer = this.renderer;
72
73
// WebGL state management
74
renderer.setBlendMode(Phaser.BlendModes.ADD);
75
renderer.pushScissor(100, 100, 200, 150); // Clip region
76
renderer.popScissor(); // Restore previous clip
77
78
// Texture binding
79
renderer.setTexture2D(this.textures.get('myTexture'), 0);
80
renderer.resetTextures();
81
82
// Batch management
83
renderer.flush(); // Force render current batch
84
85
// Framebuffer operations
86
const framebuffer = renderer.createFramebuffer(256, 256, null, false);
87
renderer.setFramebuffer(framebuffer);
88
renderer.setFramebuffer(null); // Back to main framebuffer
89
90
// Custom WebGL operations
91
this.setupCustomWebGL();
92
}
93
}
94
95
setupCustomWebGL() {
96
const gl = this.renderer.gl;
97
98
// Create custom shader program
99
const vertexShaderSource = `
100
attribute vec2 a_position;
101
attribute vec2 a_texCoord;
102
uniform mat3 u_matrix;
103
varying vec2 v_texCoord;
104
105
void main() {
106
vec3 position = u_matrix * vec3(a_position, 1.0);
107
gl_Position = vec4(position, 1.0);
108
v_texCoord = a_texCoord;
109
}
110
`;
111
112
const fragmentShaderSource = `
113
precision mediump float;
114
varying vec2 v_texCoord;
115
uniform sampler2D u_texture;
116
uniform float u_time;
117
118
void main() {
119
vec4 color = texture2D(u_texture, v_texCoord);
120
color.rgb *= 0.5 + 0.5 * sin(u_time);
121
gl_FragColor = color;
122
}
123
`;
124
125
// Compile shaders (simplified - use Phaser's shader system in practice)
126
this.customShader = this.createShaderProgram(vertexShaderSource, fragmentShaderSource);
127
}
128
}
129
```
130
131
## Texture Management
132
133
### Texture System
134
Comprehensive texture loading and management:
135
136
```javascript { .api }
137
class TextureManagementScene extends Phaser.Scene {
138
preload() {
139
// Load various texture types
140
this.load.image('logo', 'assets/logo.png');
141
this.load.atlas('sprites', 'assets/sprites.png', 'assets/sprites.json');
142
this.load.spritesheet('tiles', 'assets/tiles.png', {
143
frameWidth: 32,
144
frameHeight: 32
145
});
146
}
147
148
create() {
149
// Access texture manager
150
const textures = this.textures;
151
152
// Texture operations
153
console.log('Texture exists:', textures.exists('logo'));
154
console.log('All texture keys:', textures.getTextureKeys());
155
156
// Get texture and frame
157
const logoTexture = textures.get('logo');
158
const spriteFrame = textures.getFrame('sprites', 'character.png');
159
160
// Create runtime textures
161
this.createRuntimeTextures();
162
163
// Texture manipulation
164
this.manipulateTextures();
165
166
// Generate textures procedurally
167
this.generateTextures();
168
}
169
170
createRuntimeTextures() {
171
// Canvas texture
172
const canvas = document.createElement('canvas');
173
canvas.width = 128;
174
canvas.height = 128;
175
const ctx = canvas.getContext('2d');
176
177
// Draw on canvas
178
ctx.fillStyle = '#ff0000';
179
ctx.fillRect(0, 0, 64, 64);
180
ctx.fillStyle = '#00ff00';
181
ctx.fillRect(64, 0, 64, 64);
182
ctx.fillStyle = '#0000ff';
183
ctx.fillRect(0, 64, 64, 64);
184
ctx.fillStyle = '#ffff00';
185
ctx.fillRect(64, 64, 64, 64);
186
187
// Add to texture manager
188
this.textures.addCanvas('colorGrid', canvas);
189
190
// Base64 texture
191
this.textures.addBase64('base64Texture', 'data:image/png;base64,iVBORw0KGgoAAAANSUh...');
192
193
// Create from ImageData
194
const imageData = ctx.getImageData(0, 0, 128, 128);
195
this.textures.addImage('imageData', imageData);
196
197
// Use created textures
198
this.add.image(100, 100, 'colorGrid');
199
}
200
201
manipulateTextures() {
202
// Clone texture frame
203
const clonedFrame = this.textures.cloneFrame('logo', '__BASE');
204
205
// Get pixel color
206
const pixelColor = this.textures.getPixel(50, 50, 'logo');
207
console.log('Pixel color:', pixelColor);
208
209
// Get pixel alpha
210
const pixelAlpha = this.textures.getPixelAlpha(50, 50, 'logo');
211
console.log('Pixel alpha:', pixelAlpha);
212
213
// Texture as base64
214
const base64 = this.textures.getBase64('logo');
215
console.log('Texture as base64 length:', base64.length);
216
217
// Set texture filter
218
this.textures.setFilter('logo', 1); // 0 = nearest, 1 = linear
219
}
220
221
generateTextures() {
222
// Procedural noise texture
223
const noiseTexture = this.textures.createCanvas('noise', 256, 256);
224
const ctx = noiseTexture.getContext('2d');
225
const imageData = ctx.getImageData(0, 0, 256, 256);
226
const data = imageData.data;
227
228
for (let i = 0; i < data.length; i += 4) {
229
const noise = Math.random() * 255;
230
data[i] = noise; // Red
231
data[i + 1] = noise; // Green
232
data[i + 2] = noise; // Blue
233
data[i + 3] = 255; // Alpha
234
}
235
236
ctx.putImageData(imageData, 0, 0);
237
noiseTexture.refresh();
238
239
// Gradient texture
240
const gradientTexture = this.textures.createCanvas('gradient', 256, 64);
241
const gradCtx = gradientTexture.getContext('2d');
242
const gradient = gradCtx.createLinearGradient(0, 0, 256, 0);
243
gradient.addColorStop(0, '#ff0000');
244
gradient.addColorStop(0.5, '#00ff00');
245
gradient.addColorStop(1, '#0000ff');
246
247
gradCtx.fillStyle = gradient;
248
gradCtx.fillRect(0, 0, 256, 64);
249
gradientTexture.refresh();
250
251
// Use generated textures
252
this.add.image(300, 200, 'noise');
253
this.add.image(300, 300, 'gradient');
254
}
255
}
256
```
257
258
### Render Textures
259
Dynamic textures for rendering operations:
260
261
```javascript { .api }
262
class RenderTextureScene extends Phaser.Scene {
263
create() {
264
// Create render texture
265
this.renderTexture = this.add.renderTexture(400, 300, 400, 300);
266
267
// Create objects to draw
268
const sprite = this.add.sprite(0, 0, 'player');
269
const graphics = this.add.graphics();
270
graphics.fillStyle(0xff0000);
271
graphics.fillCircle(50, 50, 30);
272
273
// Draw to render texture
274
this.renderTexture.draw(sprite, 100, 100);
275
this.renderTexture.draw(graphics, 200, 150);
276
277
// Draw texture frame
278
this.renderTexture.drawFrame('atlas', 'frame1', 50, 200);
279
280
// Batch drawing
281
const objects = [sprite, graphics];
282
objects.forEach((obj, index) => {
283
this.renderTexture.draw(obj, index * 100, 50);
284
});
285
286
// Render texture operations
287
this.renderTexture.clear(); // Clear contents
288
this.renderTexture.fill(0x00ff00); // Fill with color
289
this.renderTexture.stamp('logo', 10, 10); // Stamp texture
290
291
// Save render texture
292
this.renderTexture.snapshot((image) => {
293
console.log('Render texture saved as image');
294
// Could save to server or local storage
295
});
296
297
// Use render texture on other objects
298
const resultSprite = this.add.sprite(600, 400, this.renderTexture.texture);
299
300
// Dynamic painting system
301
this.setupDynamicPainting();
302
}
303
304
setupDynamicPainting() {
305
// Create painting canvas
306
this.paintTexture = this.add.renderTexture(100, 100, 300, 300);
307
this.paintTexture.fill(0xffffff); // White background
308
309
// Brush settings
310
this.brushSize = 5;
311
this.brushColor = 0x000000;
312
this.isDrawing = false;
313
314
// Mouse/touch painting
315
this.input.on('pointerdown', (pointer) => {
316
if (this.isPointerOverPaintArea(pointer)) {
317
this.isDrawing = true;
318
this.lastPaintPoint = { x: pointer.x - 100, y: pointer.y - 100 };
319
}
320
});
321
322
this.input.on('pointermove', (pointer) => {
323
if (this.isDrawing && this.isPointerOverPaintArea(pointer)) {
324
const currentPoint = { x: pointer.x - 100, y: pointer.y - 100 };
325
this.paintBrushStroke(this.lastPaintPoint, currentPoint);
326
this.lastPaintPoint = currentPoint;
327
}
328
});
329
330
this.input.on('pointerup', () => {
331
this.isDrawing = false;
332
});
333
334
// Brush size controls
335
this.input.keyboard.on('keydown-ONE', () => { this.brushSize = 2; });
336
this.input.keyboard.on('keydown-TWO', () => { this.brushSize = 5; });
337
this.input.keyboard.on('keydown-THREE', () => { this.brushSize = 10; });
338
339
// Color controls
340
this.input.keyboard.on('keydown-R', () => { this.brushColor = 0xff0000; });
341
this.input.keyboard.on('keydown-G', () => { this.brushColor = 0x00ff00; });
342
this.input.keyboard.on('keydown-B', () => { this.brushColor = 0x0000ff; });
343
}
344
345
paintBrushStroke(from, to) {
346
// Create brush graphics
347
const brush = this.add.graphics();
348
brush.fillStyle(this.brushColor);
349
350
// Draw line between points
351
const distance = Phaser.Math.Distance.Between(from.x, from.y, to.x, to.y);
352
const steps = Math.max(1, Math.floor(distance / (this.brushSize / 2)));
353
354
for (let i = 0; i <= steps; i++) {
355
const t = i / steps;
356
const x = Phaser.Math.Linear(from.x, to.x, t);
357
const y = Phaser.Math.Linear(from.y, to.y, t);
358
359
brush.fillCircle(x, y, this.brushSize);
360
}
361
362
// Draw to paint texture
363
this.paintTexture.draw(brush, 0, 0);
364
brush.destroy();
365
}
366
367
isPointerOverPaintArea(pointer) {
368
return pointer.x >= 100 && pointer.x <= 400 &&
369
pointer.y >= 100 && pointer.y <= 400;
370
}
371
}
372
```
373
374
## Blend Modes and Visual Effects
375
376
### Blend Modes
377
Control how objects are composited:
378
379
```javascript { .api }
380
class BlendModeScene extends Phaser.Scene {
381
create() {
382
// Create base objects
383
const background = this.add.rectangle(400, 300, 200, 200, 0x888888);
384
385
// Demonstrate different blend modes
386
const blendModes = [
387
{ mode: Phaser.BlendModes.NORMAL, name: 'Normal' },
388
{ mode: Phaser.BlendModes.ADD, name: 'Add' },
389
{ mode: Phaser.BlendModes.MULTIPLY, name: 'Multiply' },
390
{ mode: Phaser.BlendModes.SCREEN, name: 'Screen' },
391
{ mode: Phaser.BlendModes.OVERLAY, name: 'Overlay' },
392
{ mode: Phaser.BlendModes.DARKEN, name: 'Darken' },
393
{ mode: Phaser.BlendModes.LIGHTEN, name: 'Lighten' },
394
{ mode: Phaser.BlendModes.COLOR_DODGE, name: 'Color Dodge' },
395
{ mode: Phaser.BlendModes.COLOR_BURN, name: 'Color Burn' },
396
{ mode: Phaser.BlendModes.HARD_LIGHT, name: 'Hard Light' },
397
{ mode: Phaser.BlendModes.SOFT_LIGHT, name: 'Soft Light' },
398
{ mode: Phaser.BlendModes.DIFFERENCE, name: 'Difference' },
399
{ mode: Phaser.BlendModes.EXCLUSION, name: 'Exclusion' },
400
{ mode: Phaser.BlendModes.ERASE, name: 'Erase' }
401
];
402
403
blendModes.forEach((blend, index) => {
404
const x = 100 + (index % 4) * 150;
405
const y = 100 + Math.floor(index / 4) * 120;
406
407
// Background circle
408
this.add.circle(x, y, 40, 0xff0000, 0.8);
409
410
// Overlapping circle with blend mode
411
const blendedCircle = this.add.circle(x + 25, y + 25, 40, 0x0000ff, 0.8);
412
blendedCircle.setBlendMode(blend.mode);
413
414
// Label
415
this.add.text(x - 30, y + 60, blend.name, {
416
fontSize: '10px',
417
fill: '#ffffff'
418
});
419
});
420
421
// Interactive blend mode demo
422
this.setupInteractiveBlending();
423
}
424
425
setupInteractiveBlending() {
426
// Create interactive objects
427
this.baseLayer = this.add.circle(600, 300, 60, 0xff6600);
428
this.blendLayer = this.add.circle(650, 330, 60, 0x0066ff);
429
430
let currentBlendIndex = 0;
431
const blendModesList = Object.values(Phaser.BlendModes).filter(mode => typeof mode === 'number');
432
433
this.blendLayer.setBlendMode(blendModesList[currentBlendIndex]);
434
435
// Cycle through blend modes on click
436
this.blendLayer.setInteractive();
437
this.blendLayer.on('pointerdown', () => {
438
currentBlendIndex = (currentBlendIndex + 1) % blendModesList.length;
439
this.blendLayer.setBlendMode(blendModesList[currentBlendIndex]);
440
441
console.log('Blend mode:', Object.keys(Phaser.BlendModes)[currentBlendIndex]);
442
});
443
444
// Animate blend layer
445
this.tweens.add({
446
targets: this.blendLayer,
447
x: 550,
448
duration: 2000,
449
yoyo: true,
450
repeat: -1
451
});
452
}
453
}
454
```
455
456
### Visual Effects and Filters
457
Apply visual effects to game objects:
458
459
```javascript { .api }
460
class VisualEffectsScene extends Phaser.Scene {
461
create() {
462
// Tint effects
463
const redTintedSprite = this.add.sprite(100, 100, 'logo');
464
redTintedSprite.setTint(0xff0000);
465
466
// Multiple tints (corners)
467
const multiTintSprite = this.add.sprite(200, 100, 'logo');
468
multiTintSprite.setTint(0xff0000, 0x00ff00, 0x0000ff, 0xffff00);
469
470
// Alpha effects
471
const alphaSprite = this.add.sprite(300, 100, 'logo');
472
alphaSprite.setAlpha(0.5);
473
474
// Scale effects
475
const scaledSprite = this.add.sprite(400, 100, 'logo');
476
scaledSprite.setScale(2, 0.5);
477
478
// Rotation effects
479
const rotatedSprite = this.add.sprite(500, 100, 'logo');
480
rotatedSprite.setRotation(Math.PI / 4);
481
482
// Flip effects
483
const flippedSprite = this.add.sprite(600, 100, 'logo');
484
flippedSprite.setFlipX(true);
485
flippedSprite.setFlipY(true);
486
487
// Origin effects
488
const originSprite = this.add.sprite(700, 100, 'logo');
489
originSprite.setOrigin(0, 0); // Top-left corner
490
491
// Mask effects
492
this.setupMaskEffects();
493
494
// Shader effects (WebGL only)
495
if (this.renderer.type === Phaser.WEBGL) {
496
this.setupShaderEffects();
497
}
498
499
// Animation effects
500
this.setupAnimationEffects();
501
}
502
503
setupMaskEffects() {
504
// Geometry mask
505
const maskShape = this.add.graphics();
506
maskShape.fillStyle(0xffffff);
507
maskShape.fillCircle(200, 300, 80);
508
509
const geometryMask = maskShape.createGeometryMask();
510
511
const maskedImage = this.add.image(200, 300, 'logo');
512
maskedImage.setMask(geometryMask);
513
514
// Bitmap mask
515
const maskTexture = this.add.image(400, 300, 'maskTexture');
516
const bitmapMask = maskTexture.createBitmapMask();
517
518
const bitmapMaskedImage = this.add.image(400, 300, 'logo');
519
bitmapMaskedImage.setMask(bitmapMask);
520
521
// Animated mask
522
this.tweens.add({
523
targets: maskShape,
524
scaleX: 1.5,
525
scaleY: 1.5,
526
duration: 2000,
527
yoyo: true,
528
repeat: -1
529
});
530
}
531
532
setupShaderEffects() {
533
// Load and create shader
534
this.load.glsl('waveShader', 'assets/shaders/wave.frag');
535
536
this.load.once('complete', () => {
537
const shader = this.add.shader('waveShader', 600, 300, 200, 200);
538
539
// Animate shader uniforms
540
shader.setUniform('time.value', 0);
541
542
this.tweens.add({
543
targets: shader,
544
'uniforms.time.value': 10,
545
duration: 5000,
546
repeat: -1
547
});
548
});
549
550
this.load.start();
551
}
552
553
setupAnimationEffects() {
554
// Pulsing effect
555
const pulsingSprite = this.add.sprite(100, 400, 'logo');
556
this.tweens.add({
557
targets: pulsingSprite,
558
scaleX: 1.2,
559
scaleY: 1.2,
560
duration: 1000,
561
yoyo: true,
562
repeat: -1,
563
ease: 'Sine.easeInOut'
564
});
565
566
// Glowing effect
567
const glowSprite = this.add.sprite(300, 400, 'logo');
568
this.tweens.add({
569
targets: glowSprite,
570
alpha: 0.3,
571
duration: 800,
572
yoyo: true,
573
repeat: -1
574
});
575
576
// Color cycling effect
577
const colorSprite = this.add.sprite(500, 400, 'logo');
578
let hue = 0;
579
580
this.time.addEvent({
581
delay: 50,
582
repeat: -1,
583
callback: () => {
584
hue = (hue + 5) % 360;
585
const color = Phaser.Display.Color.HSVToRGB(hue / 360, 1, 1);
586
colorSprite.setTint(color.color);
587
}
588
});
589
590
// Particle trail effect
591
this.setupParticleTrail();
592
}
593
594
setupParticleTrail() {
595
const trailSprite = this.add.sprite(700, 400, 'logo');
596
597
// Create particle emitter for trail
598
const particles = this.add.particles(0, 0, 'particle', {
599
follow: trailSprite,
600
quantity: 2,
601
scale: { start: 0.3, end: 0 },
602
alpha: { start: 0.8, end: 0 },
603
lifespan: 500,
604
tint: 0x00ff88
605
});
606
607
// Move sprite in circle
608
this.tweens.add({
609
targets: trailSprite,
610
x: 700 + Math.cos(0) * 100,
611
y: 400 + Math.sin(0) * 100,
612
duration: 0
613
});
614
615
let angle = 0;
616
this.time.addEvent({
617
delay: 16,
618
repeat: -1,
619
callback: () => {
620
angle += 0.05;
621
trailSprite.x = 700 + Math.cos(angle) * 100;
622
trailSprite.y = 400 + Math.sin(angle) * 50;
623
}
624
});
625
}
626
}
627
```
628
629
## Display Utilities
630
631
### Alignment and Layout
632
Position and align objects systematically:
633
634
```javascript { .api }
635
class DisplayUtilitiesScene extends Phaser.Scene {
636
create() {
637
// Create container for alignment demo
638
const container = this.add.rectangle(400, 300, 300, 200, 0x333333, 0.5);
639
640
// Create objects to align
641
const objects = [];
642
for (let i = 0; i < 9; i++) {
643
const obj = this.add.circle(0, 0, 15, Phaser.Display.Color.HSVToRGB(i / 9, 1, 1).color);
644
objects.push(obj);
645
}
646
647
// Alignment using Display.Align
648
const alignPositions = [
649
Phaser.Display.Align.TOP_LEFT,
650
Phaser.Display.Align.TOP_CENTER,
651
Phaser.Display.Align.TOP_RIGHT,
652
Phaser.Display.Align.LEFT_CENTER,
653
Phaser.Display.Align.CENTER,
654
Phaser.Display.Align.RIGHT_CENTER,
655
Phaser.Display.Align.BOTTOM_LEFT,
656
Phaser.Display.Align.BOTTOM_CENTER,
657
Phaser.Display.Align.BOTTOM_RIGHT
658
];
659
660
objects.forEach((obj, index) => {
661
Phaser.Display.Align.In.QuickSet(obj, container, alignPositions[index]);
662
});
663
664
// Grid layout
665
this.createGridLayout();
666
667
// Bounds utilities
668
this.demonstrateBounds();
669
670
// Color utilities
671
this.demonstrateColors();
672
}
673
674
createGridLayout() {
675
// Create grid of objects
676
const gridObjects = [];
677
for (let i = 0; i < 20; i++) {
678
const obj = this.add.rectangle(0, 0, 30, 30, 0xff6600);
679
gridObjects.push(obj);
680
}
681
682
// Arrange in grid
683
Phaser.Actions.GridAlign(gridObjects, {
684
width: 5,
685
height: 4,
686
cellWidth: 40,
687
cellHeight: 40,
688
x: 50,
689
y: 50
690
});
691
692
// Circular arrangement
693
const circleObjects = [];
694
for (let i = 0; i < 12; i++) {
695
const obj = this.add.circle(0, 0, 8, 0x00ff88);
696
circleObjects.push(obj);
697
}
698
699
const circle = new Phaser.Geom.Circle(600, 200, 80);
700
Phaser.Actions.PlaceOnCircle(circleObjects, circle);
701
702
// Line arrangement
703
const lineObjects = [];
704
for (let i = 0; i < 10; i++) {
705
const obj = this.add.triangle(0, 0, 0, 10, 10, 10, 5, 0, 0x8800ff);
706
lineObjects.push(obj);
707
}
708
709
const line = new Phaser.Geom.Line(100, 500, 300, 450);
710
Phaser.Actions.PlaceOnLine(lineObjects, line);
711
}
712
713
demonstrateBounds() {
714
const sprite = this.add.sprite(500, 500, 'logo');
715
sprite.setScale(0.5);
716
717
// Get bounds information
718
const bounds = sprite.getBounds();
719
console.log('Sprite bounds:', bounds);
720
721
// Bounds utilities
722
const left = Phaser.Display.Bounds.GetLeft(sprite);
723
const right = Phaser.Display.Bounds.GetRight(sprite);
724
const top = Phaser.Display.Bounds.GetTop(sprite);
725
const bottom = Phaser.Display.Bounds.GetBottom(sprite);
726
const centerX = Phaser.Display.Bounds.GetCenterX(sprite);
727
const centerY = Phaser.Display.Bounds.GetCenterY(sprite);
728
729
console.log('Bounds - Left:', left, 'Right:', right, 'Top:', top, 'Bottom:', bottom);
730
console.log('Center:', centerX, centerY);
731
732
// Set bounds positions
733
const boundSprite = this.add.sprite(0, 0, 'logo');
734
Phaser.Display.Bounds.SetLeft(boundSprite, 100);
735
Phaser.Display.Bounds.SetTop(boundSprite, 100);
736
737
// Center object
738
Phaser.Display.Bounds.CenterOn(boundSprite, 400, 100);
739
740
// Visualize bounds
741
const graphics = this.add.graphics();
742
graphics.lineStyle(2, 0xff0000);
743
graphics.strokeRectShape(bounds);
744
}
745
746
demonstrateColors() {
747
// Color class usage
748
const color1 = new Phaser.Display.Color(255, 128, 64);
749
const color2 = new Phaser.Display.Color();
750
751
// Color operations
752
color2.setFromRGB({ r: 128, g: 255, b: 192 });
753
754
console.log('Color 1 hex:', color1.color32);
755
console.log('Color 2 HSV:', color2.h, color2.s, color2.v);
756
757
// Color manipulation
758
color1.brighten(20);
759
color1.saturate(10);
760
color2.desaturate(15);
761
762
// Color interpolation
763
const interpolated = Phaser.Display.Color.Interpolate.ColorWithColor(
764
color1, color2, 10, 5
765
);
766
767
// Random colors
768
const randomColor = Phaser.Display.Color.RandomRGB();
769
770
// HSV color wheel
771
const colorWheel = Phaser.Display.Color.HSVColorWheel(1, 1);
772
773
// Display color examples
774
colorWheel.forEach((color, index) => {
775
const x = 50 + (index % 16) * 25;
776
const y = 550 + Math.floor(index / 16) * 25;
777
this.add.circle(x, y, 10, color.color);
778
});
779
}
780
}
781
```
782
783
## Performance Optimization
784
785
### Rendering Optimization
786
Techniques for optimal rendering performance:
787
788
```javascript { .api }
789
class RenderingOptimizationScene extends Phaser.Scene {
790
create() {
791
// Object pooling for frequently created/destroyed objects
792
this.bulletPool = this.add.group({
793
classType: Phaser.GameObjects.Image,
794
key: 'bullet',
795
frame: 0,
796
active: false,
797
visible: false,
798
maxSize: 100
799
});
800
801
// Texture atlasing to reduce draw calls
802
this.createAtlasedSprites();
803
804
// Culling optimization
805
this.setupCulling();
806
807
// Batch rendering
808
this.setupBatchRendering();
809
810
// Level-of-detail (LOD) system
811
this.setupLOD();
812
}
813
814
createAtlasedSprites() {
815
// Use texture atlas instead of individual images
816
const atlasSprites = [];
817
const frames = ['sprite1', 'sprite2', 'sprite3', 'sprite4'];
818
819
for (let i = 0; i < 100; i++) {
820
const frame = Phaser.Utils.Array.GetRandom(frames);
821
const sprite = this.add.sprite(
822
Phaser.Math.Between(0, 800),
823
Phaser.Math.Between(0, 600),
824
'gameAtlas',
825
frame
826
);
827
atlasSprites.push(sprite);
828
}
829
}
830
831
setupCulling() {
832
// Manual culling for large number of objects
833
this.objects = [];
834
835
for (let i = 0; i < 500; i++) {
836
const obj = this.add.rectangle(
837
Phaser.Math.Between(0, 2000),
838
Phaser.Math.Between(0, 2000),
839
20, 20,
840
Phaser.Math.Between(0x000000, 0xffffff)
841
);
842
this.objects.push(obj);
843
}
844
845
// Culling update
846
this.cullObjects();
847
}
848
849
cullObjects() {
850
const camera = this.cameras.main;
851
const worldView = camera.worldView;
852
853
this.objects.forEach(obj => {
854
// Check if object is within camera bounds
855
const inView = Phaser.Geom.Rectangle.Overlaps(worldView, obj.getBounds());
856
obj.setVisible(inView);
857
858
// Disable expensive operations for off-screen objects
859
if (!inView && obj.body) {
860
obj.body.enable = false;
861
} else if (inView && obj.body) {
862
obj.body.enable = true;
863
}
864
});
865
}
866
867
setupBatchRendering() {
868
// Use Graphics object for batched drawing
869
this.batchGraphics = this.add.graphics();
870
871
// Draw many shapes in single batch
872
this.batchGraphics.fillStyle(0xff0000);
873
for (let i = 0; i < 100; i++) {
874
this.batchGraphics.fillCircle(
875
Phaser.Math.Between(0, 800),
876
Phaser.Math.Between(0, 600),
877
Phaser.Math.Between(5, 15)
878
);
879
}
880
881
// Use Blitter for many similar sprites
882
this.blitter = this.add.blitter(0, 0, 'particle');
883
884
for (let i = 0; i < 200; i++) {
885
this.blitter.create(
886
Phaser.Math.Between(0, 800),
887
Phaser.Math.Between(0, 600)
888
);
889
}
890
}
891
892
setupLOD() {
893
// Level-of-detail based on distance from camera
894
this.lodObjects = [];
895
896
for (let i = 0; i < 50; i++) {
897
const obj = {
898
x: Phaser.Math.Between(0, 2000),
899
y: Phaser.Math.Between(0, 2000),
900
highDetail: this.add.sprite(0, 0, 'highDetailSprite'),
901
mediumDetail: this.add.sprite(0, 0, 'mediumDetailSprite'),
902
lowDetail: this.add.sprite(0, 0, 'lowDetailSprite')
903
};
904
905
obj.highDetail.setPosition(obj.x, obj.y);
906
obj.mediumDetail.setPosition(obj.x, obj.y);
907
obj.lowDetail.setPosition(obj.x, obj.y);
908
909
this.lodObjects.push(obj);
910
}
911
912
this.updateLOD();
913
}
914
915
updateLOD() {
916
const camera = this.cameras.main;
917
const cameraCenter = new Phaser.Math.Vector2(
918
camera.scrollX + camera.width / 2,
919
camera.scrollY + camera.height / 2
920
);
921
922
this.lodObjects.forEach(obj => {
923
const distance = Phaser.Math.Distance.Between(
924
cameraCenter.x, cameraCenter.y, obj.x, obj.y
925
);
926
927
// Show different detail levels based on distance
928
obj.highDetail.setVisible(distance < 200);
929
obj.mediumDetail.setVisible(distance >= 200 && distance < 500);
930
obj.lowDetail.setVisible(distance >= 500);
931
});
932
}
933
934
update() {
935
// Update optimization systems
936
this.cullObjects();
937
this.updateLOD();
938
939
// Performance monitoring
940
if (this.time.now % 1000 < 16) { // Once per second
941
console.log('FPS:', this.game.loop.actualFps);
942
console.log('Visible objects:', this.children.list.filter(child => child.visible).length);
943
}
944
}
945
}
946
```
947
948
This comprehensive rendering system provides all the tools needed to create visually stunning games with optimal performance across different devices and rendering contexts.