Phaser HTML5 Game Framework

repository·master·Indexed 12 days ago

https://github.com/phaserjs/phaser

A 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.

Tokens
294.4K
Snippets
840
Records
1.4K
Agent score
94%

What's inside Phaser

  1. Phaser Compact Texture Atlas (PCT) Format Specification

    master
    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.
  2. Overview of the Phaser Compact Texture (PCT) format

    master

    The 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:
      1. PCT: (Version header) must be on line 1.
      2. P: (Page headers) must follow.
      3. F: (Folder entries) must follow.
      4. Frame data (interleaved #, B:, block names, and individual frames).
      5. A: (Alias records) must be at the end of the file.

    Record Types Summary:

    PrefixTypePurpose
    PCT:Version headerFile identifier and format version
    P:Page headerDeclares a texture image and its dimensions
    F:Folder entryDeclares a folder name in the dictionary
    #Page selectorSwitches subsequent frames to a different page
    B:Block headerDeclares a grid block of same-sized sprites
    A:AliasMaps duplicate sprites to an existing frame
    name|Individual frameA single sprite with explicit position
    names,...Block namesComma-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_12
  3. Use Mesh Game Objects and Geom.Mesh utilities

    master

    The Mesh Game Object allows for complex geometry rendering. It is supported by the Geom.Mesh namespace for generating vertex and face data.

    Core Mesh Concepts:

    • Vertices & Faces: A Mesh is composed of Geom.Mesh.Vertex instances (position, uv, normals, color, alpha) and Geom.Mesh.Face instances (references to three vertices).
    • Data Storage: Unlike older versions, Mesh.vertices is an array of Vertex objects, and Mesh.faces is an array of Face objects. UV, color, and alpha data are now stored directly within the Vertex instances.
    • Transformations: Use modelPosition, modelRotation, and modelScale (all Vector3) to transform the entire mesh geometry.
    • Projections: Use setPerspective or setOrtho to define the projection matrix.
    • Animation: Meshes include an Animation State Component, allowing for texture animations.
  4. Handle Pointer and Input Events with stopPropagation

    master

    In Phaser 3.13, the order of input event dispatching was changed to allow better control. The sequence is now:

    1. Game Object specific event (e.g., pointerdown on the object).
    2. gameobjectdown event.
    3. Global pointerdown event (via the InputPlugin).

    All events now include an event object. You can call event.stopPropagation() to prevent further listeners from being invoked. For example, calling it during a Game Object's pointerdown callback will prevent the global pointerdown event 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)
  5. How ScaleManager works

    master

    The ScaleManager (accessible via game.scale or this.scale in 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 via game.scale.width / game.scale.height.
    • baseSize: The auto-rounded gameSize. This sets the actual canvas.width and canvas.height attributes.
    • displaySize: The CSS-scaled canvas size after applying scale mode, parent bounds, and zoom. This sets canvas.style.width and canvas.style.height.

    Scaling is achieved by keeping the baseSize fixed and stretching the element via CSS (displaySize), which is more performant than constant canvas resizing.

  6. Create custom pipelines using SinglePipeline

    master

    If you want to create a custom WebGL pipeline but do not want to rewrite your shaders to support multiple textures, you should extend SinglePipeline instead of the older TextureTintPipeline. SinglePipeline is 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
    }
  7. Use Post FX Pipelines on Layers

    master

    Layers 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:

    • Alpha
    • Blend Mode
    • Depth
    • Mask
    • Visible state (affects all children)
  8. Use SpriteGPULayer for high-performance static layers

    master

    Use SpriteGPULayer to 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.

  9. Understand RenderNodes and the rendering architecture

    master

    Phaser 4 replaces the v3 Pipeline system with a RenderNode graph. Instead of one pipeline handling multiple responsibilities, each RenderNode handles exactly one specific rendering task via its run() 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);
  10. How the Phaser Boot Sequence works

    master

    When you instantiate new Phaser.Game(config), the following lifecycle occurs:

    1. Config Parsing: The Config constructor resolves the GameConfig object, applying defaults and resolving property priority (e.g., scale sub-object properties override top-level properties).
    2. Manager Creation: Global managers are initialized, including AnimationManager, TextureManager, CacheManager, InputManager, SceneManager, ScaleManager, SoundManager, TimeStep, and PluginManager.
    3. Booting: After DOMContentLoaded, the boot() method is called. This creates the renderer, adds the canvas to the DOM, and emits the BOOT event.
    4. Ready State: Once the TextureManager emits READY, the game emits READY and calls start().
    5. Game Loop: start() begins the TimeStep loop, sets up the VisibilityHandler, and executes config.postBoot.

    Developers can hook into this process using callbacks.preBoot (before systems are available) and callbacks.postBoot (after all systems are ready and the loop starts).

  11. Understand DrawingContext for renderer internals

    master

    A Phaser.Renderer.WebGL.DrawingContext is 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 and drawingContext.release() at the end. This handles clearing the context and managing batch renders.
    • Framebuffers: If a DrawingContext holds a framebuffer, drawingContext.texture refers to that texture. Everything drawn within that context is directed to that texture.
  12. How the Command Buffer works in Phaser 4

    master

    In Phaser 4, drawing calls (draw, stamp, fill, clear, erase, repeat, capture) are asynchronous. They do not execute immediately; instead, they push commands into a commandBuffer.

    You must call .render() to flush and execute the buffer.

    Render Modes

    The renderMode property on a RenderTexture controls how it handles rendering:

    • 'render' (default): Draws texture contents to the frame each tick. You must call render() manually when content changes.
    • 'redraw': Calls render() automatically every frame but does NOT display itself. Useful for textures reused by other objects.
    • 'all': Calls render() every frame AND draws itself to the frame.

    Preserve Mode

    By default, the command buffer clears after render(). Call preserve(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