Phaser HTML5 Game Framework
repository·master·Indexed 12 days ago
https://github.com/phaserjs/phaserA fast, free, and open-source HTML5 game framework for desktop and mobile web browsers supporting WebGL and Canvas rendering. Version 4.2.1 introduces a new Render Node Architecture, a unified Filter system, SpriteGPULayer for massive sprite rendering, and an overhauled tinting and lighting system.
What's inside Phaser
- The Phaser Compact Texture Atlas (PCT) is a text-based format used to define sprite sheets and texture atlases. It is designed to be human-readable, version-control friendly, and highly compressible via Gzip. The format supports multiple atlas pages, folder hierarchies, block-based sprite grouping (for efficiency), individual frame definitions, aliases, and automatic extension handling.
Overview of the Phaser Compact Texture (PCT) format
masterThe PCT format is a compact, line-oriented, text-based descriptor for texture atlases. It is designed to be 90-95% smaller than JSON descriptors while remaining easy to parse in a single pass.
File Structure Requirements:
- Must be a plain UTF-8 text file.
- Each line represents a single record.
- Mandatory Order:
PCT:(Version header) must be on line 1.P:(Page headers) must follow.F:(Folder entries) must follow.- Frame data (interleaved
#,B:, block names, and individual frames). A:(Alias records) must be at the end of the file.
Record Types Summary:
Prefix Type Purpose PCT:Version header File identifier and format version P:Page header Declares a texture image and its dimensions F:Folder entry Declares a folder name in the dictionary #Page selector Switches subsequent frames to a different page B:Block header Declares a grid block of same-sized sprites A:Alias Maps duplicate sprites to an existing frame name|Individual frame A single sprite with explicit position names,...Block names Comma-separated names for a block PCT:1.0 P:atlas_0.png,RGBA8888,2048,512,2 F:warrior 0/idle_01 #0 B:2,2,8,64,64 0/idle#01-24 A:0/idle_01=0/idle_12Use Mesh Game Objects and Geom.Mesh utilities
masterThe
MeshGame Object allows for complex geometry rendering. It is supported by theGeom.Meshnamespace for generating vertex and face data.Core Mesh Concepts:
- Vertices & Faces: A Mesh is composed of
Geom.Mesh.Vertexinstances (position, uv, normals, color, alpha) andGeom.Mesh.Faceinstances (references to three vertices). - Data Storage: Unlike older versions,
Mesh.verticesis an array ofVertexobjects, andMesh.facesis an array ofFaceobjects. UV, color, and alpha data are now stored directly within theVertexinstances. - Transformations: Use
modelPosition,modelRotation, andmodelScale(allVector3) to transform the entire mesh geometry. - Projections: Use
setPerspectiveorsetOrthoto define the projection matrix. - Animation: Meshes include an Animation State Component, allowing for texture animations.
- Vertices & Faces: A Mesh is composed of
Handle Pointer and Input Events with stopPropagation
masterIn Phaser 3.13, the order of input event dispatching was changed to allow better control. The sequence is now:
- Game Object specific event (e.g.,
pointerdownon the object). gameobjectdownevent.- Global
pointerdownevent (via the InputPlugin).
All events now include an
eventobject. You can callevent.stopPropagation()to prevent further listeners from being invoked. For example, calling it during a Game Object'spointerdowncallback will prevent the globalpointerdownevent from firing.Updated Callback Signatures (v3.13+):
pointerdown:(pointer, x, y, event)pointerup:(pointer, x, y, event)pointermove:(pointer, x, y, event)pointerover:(pointer, x, y, event)pointerout:(pointer, x, y, event)gameobjectdown:(pointer, x, y, event)gameobjectup:(pointer, x, y, event)gameobjectmove:(pointer, x, y, event)gameobjectover:(pointer, x, y, event)gameobjectout:(pointer, x, y, event)
- Game Object specific event (e.g.,
How ScaleManager works
masterThe
ScaleManager(accessible viagame.scaleorthis.scalein a Scene) manages how the game canvas is sized and displayed. It uses three internal size components to drive calculations:gameSize: The unmodified dimensions from your config. Used for world bounds and cameras. Access viagame.scale.width/game.scale.height.baseSize: The auto-roundedgameSize. This sets the actualcanvas.widthandcanvas.heightattributes.displaySize: The CSS-scaled canvas size after applying scale mode, parent bounds, and zoom. This setscanvas.style.widthandcanvas.style.height.
Scaling is achieved by keeping the
baseSizefixed and stretching the element via CSS (displaySize), which is more performant than constant canvas resizing.Create custom pipelines using SinglePipeline
masterIf you want to create a custom WebGL pipeline but do not want to rewrite your shaders to support multiple textures, you should extend
SinglePipelineinstead of the olderTextureTintPipeline.SinglePipelineis designed to emulate the old behavior using just a single texture, making it easier to integrate existing shader code. While you can extend it, it is recommended to update your shaders for better performance if possible.// Example concept: extending SinglePipeline for custom shader logic class MyCustomPipeline extends SinglePipeline { // implementation }Use Post FX Pipelines on Layers
masterLayers allow you to apply a Post FX Pipeline to a whole range of children simultaneously. This is often more efficient than applying effects to each child individually.
Important Constraints for Layers:
- Layers have no position, size, rotation, scale, or scroll factor within a Scene.
- You cannot enable physics or input on a Layer.
- Layers have no texture, tint, origin, crop, or bounds.
Comparison with Containers:
- If you need position, size, rotation, scale, or input, use a Container instead.
- You can add Containers to Layers, but you cannot add Layers to Containers.
What you CAN set on a Layer:
AlphaBlend ModeDepthMaskVisiblestate (affects all children)
Use SpriteGPULayer for high-performance static layers
masterUse
SpriteGPULayerto render millions of objects (like parallax backgrounds or particle effects) with minimal CPU overhead. It works by uploading a large buffer of data to the GPU once and then reusing it, skipping the expensive per-frame upload required by regular Sprites.Key Characteristics:
- Performance: Runtime cost is ~1% of the vertex cost of regular sprites.
- Memory: High memory usage (approx. 168 bytes per layer member on both CPU and GPU) in exchange for speed.
- Features: Supports animations and scroll factor per-member.
Best Practice for Initialization: To avoid long initialization times (which can take seconds if creating new config objects for every member), create a single config object and edit it for each new member during the setup loop.
Understand RenderNodes and the rendering architecture
masterPhaser 4 replaces the v3
Pipelinesystem with aRenderNodegraph. Instead of one pipeline handling multiple responsibilities, eachRenderNodehandles exactly one specific rendering task via itsrun()method.Game objects use role-based maps to reference nodes. Common roles include:
Submitter: Runs other node roles for each element.Transformer: Provides vertex coordinates.Texturer: Handles textures.
You can override these roles or pass custom data to them using
setRenderNodeRole.// Override a specific render role: gameObject.setRenderNodeRole('Submitter', 'MyCustomSubmitter'); // Pass data to a render node: gameObject.setRenderNodeRole('Transformer', 'MyTransformer', { customProperty: 42 }); // Remove a custom node (falls back to default): gameObject.setRenderNodeRole('Submitter', null);How the Phaser Boot Sequence works
masterWhen you instantiate
new Phaser.Game(config), the following lifecycle occurs:- Config Parsing: The
Configconstructor resolves theGameConfigobject, applying defaults and resolving property priority (e.g.,scalesub-object properties override top-level properties). - Manager Creation: Global managers are initialized, including
AnimationManager,TextureManager,CacheManager,InputManager,SceneManager,ScaleManager,SoundManager,TimeStep, andPluginManager. - Booting: After
DOMContentLoaded, theboot()method is called. This creates the renderer, adds the canvas to the DOM, and emits theBOOTevent. - Ready State: Once the
TextureManageremitsREADY, the game emitsREADYand callsstart(). - Game Loop:
start()begins theTimeSteploop, sets up theVisibilityHandler, and executesconfig.postBoot.
Developers can hook into this process using
callbacks.preBoot(before systems are available) andcallbacks.postBoot(after all systems are ready and the loop starts).- Config Parsing: The
Understand DrawingContext for renderer internals
masterA
Phaser.Renderer.WebGL.DrawingContextis an internal object representing a localized WebGL state (camera, blend modes, framebuffer, etc.). It acts as a specific "drawing setup."Usage Rules
- Nesting: DrawingContexts are nestable. You can create a copy using
drawingContext.getClone(), modify it, and return to the previous state. - Lifecycle: When using a context, you must call
drawingContext.use()at the start anddrawingContext.release()at the end. This handles clearing the context and managing batch renders. - Framebuffers: If a
DrawingContextholds a framebuffer,drawingContext.texturerefers to that texture. Everything drawn within that context is directed to that texture.
- Nesting: DrawingContexts are nestable. You can create a copy using
How the Command Buffer works in Phaser 4
masterIn Phaser 4, drawing calls (
draw,stamp,fill,clear,erase,repeat,capture) are asynchronous. They do not execute immediately; instead, they push commands into acommandBuffer.You must call
.render()to flush and execute the buffer.Render Modes
The
renderModeproperty on aRenderTexturecontrols how it handles rendering:'render'(default): Draws texture contents to the frame each tick. You must callrender()manually when content changes.'redraw': Callsrender()automatically every frame but does NOT display itself. Useful for textures reused by other objects.'all': Callsrender()every frame AND draws itself to the frame.
Preserve Mode
By default, the command buffer clears after
render(). Callpreserve(true)to keep commands between renders, so the same drawing replays each frame automatically.// Manual rendering rt.clear(); rt.fill(0x000000); rt.draw(sprite, 128, 128); rt.render(); // REQUIRED // Preserving commands rt.preserve(true); rt.clear(); rt.draw(sprite); // On every subsequent render(), clear + draw will repeat