Phaser 4 draws closer to release with RC7. This release contains several cool new features. Originally planned for other projects, we didn't want to waste that work, so we adapted anything that made sense into Phaser itself. It also contains several fixes, thanks to community feedback.

Tint Overhaul

Tint on sprites was overhauled. In Phaser 3, tint and tintFill were different modes, and you could accidentally swap between them with color-setting commands. In Phaser 4, color and mode are separated, and there are 6 possible modes: MULTIPLY, FILL, ADD, SCREEN, OVERLAY and HARD_LIGHT. The setTint() method is now solely responsible for colors. The setTintFill() method now does nothing. The new setTintMode() method sets the tint mode.

Phaser 4 doesn't like breaking changes, but this one was necessary. It reminds the developer that this code behaves differently, and, we hope, more reliably.

There is no loss in capabilities with this change. In fact, we fixed FILL mode to work better with partially transparent pixels.

Conversion tip: foo.setTintFill(color) becomes foo.setTint(color).setTintMode(Phaser.TintModes.FILL).

Return of the Lost FX

When we unified FX and Masks into the new Filters system, we made the decision to cut a few. They were generally too specialized or limited in their use, and we figured our limited time was better spent elsewhere. Then a lot of time passed and we reconsidered.

As a result, all the lost FX have now been re-implemented. Some are Filters; others found better homes elsewhere.

  • Bloom is now available as Phaser.Actions.AddEffectBloom(). It creates a Bloom effect using a mix of other filters, so everything works the same way.
  • Circle is now available as Phaser.Actions.AddMaskShape(), with extra options.
  • Gradient is now a game object - see below.
  • Shine is now available as Phaser.Actions.AddEffectShine(). It uses a Gradient to create a texture, giving you all the power of gradients, and lets you control the highlight effect with a tween.
  • Vignette is now a Filter, and you can now set the border color. In Phaser 3, it just erased the border.
  • Wipe is now a Filter, and you can set it to wipe between two textures. It also offers helper methods to set various directions and modes.

New Game Objects

We created several new game objects. These all extend the Shader game object, so you can use methods such as setRenderToTexture to use them as resources.

  • Gradient: Create gradients using highly configurable bands of color, in a variety of shapes and patterns.
    • To support this, Display.ColorBand and Display.ColorRamp were added. You can use these on their own to manage ranges of colors, from straightforward blends between two colors in your chosen color space, to million-color insanity.
  • Noise: Create random static.
  • NoiseCell2D, NoiseCell3D, and NoiseCell4D: Create and animate cellular noise (aka Worley Noise or Voronoi Cells). Great for naturalistic patterns with strong divisions.
  • NoiseSimplex2D and NoiseSimplex3D: Create and animate simplex noise. Great for naturalistic patterns with smooth transitions.

The noise objects also have counterparts in Phaser.Math: Hash, HashCell, and HashSimplex, designed to support deterministic pseudo-random generation in games. (Don't use them for encryption!)

New Texture Source Management

We made it easier to manage textures after game load.

  • TextureManager.addFlatColor() creates a texture with a given size and color. You can use this as a proxy while loading images elsewhere.
  • Texture.setSource() replaces a texture source. For example, you could replace a proxy with an image once the image loads.
  • TextureSource.updateSource() is the deeper function which controls this.

Note that changing a texture source doesn't change any derivatives that might already exist, e.g. object width and height. If you want to use proxies while textures load in the background, it's best to make the proxies match the final size.

New Filters

There's a whole list of new filters. The shiniest is ImageLight, a way to apply environment maps or image-based lighting to objects. Many of the new features interact well with ImageLight, e.g. using gradients to quickly sketch light coming from sky and ground, or using cellular noise to generate a normal map to simulate reflections in water.

  • CombineColorMatrix lets you remix alpha and other channels between textures.
    • Transform grayscale into transparency, or other combinations.
  • GradientMap uses a ColorRamp, just like Gradient, to recolor an image based on pixel value.
    • Because ColorRamp supports so many divisions, you could use this as a kind of palette swap. This is most straightforward if you have less than 256 colors, because that's how many grayscale brightness values there are.
  • Key removes or isolates specific colors.
    • I checked the latest research, and there's no universal solution for chroma key. This will work fine for sprites which use a single color, e.g. #ff00ff, as code for transparency, but for more complex chroma key operations you'll need to use your own judgement. In general you should already have alpha in your sprites.
  • ImageLight does environmental mapping via a normal map.
    • I started using this everywhere after it was finished. It's so cool.
    • It supports sphere mapped panoramas, and you can even rotate the perspective to change lighting angles.
    • But simpler gradients or photos can also look great. The point is to provide light from all angles at once.
  • PanoramaBlur helps you convert a sharp image into a diffuse image-based lighting texture, allowing you to use ImageLight for natural lighting effects.
  • NormalTools adjusts normal maps in various ways.
  • Quantize applies quantization and dithering to reduce the number of colors in an image.
    • Use this to get a retro palette style effect. It doesn't emulate any specific hardware, so if you have a specific target in mind, authoring your sprites to that standard will be more efficient.
    • We use high quality Interleaved Gradient Noise to dither the Quantize filter and Gradients.

New Color Operations

We updated many color functions with an option to write their output to an existing Color object. This improves efficiency when doing many color operations; creating a new Color every time takes a lot of resources!

We also added the option for HSV mode to Color.Interpolate. HSV interpolation preserves brightness and saturation during blends, avoiding the muddy tones you can get when blending RGB values directly.

Other Features and Fixes

There are plenty of other cool things in RC7 that don't fit one of these themes.

Actions.FitToRegion() is a quick way to scale an object to a space. By default it just matches the screen, which is great for quickly setting up a background. It also has applications in masks and other areas.

GameObject.isDestroyed is a useful flag. For many years, a common class of error has been 'trying to do something with an object that was destroyed'. This flag helps you avoid that.

NineSlice now has tileX and tileY properties, allowing you to repeat the slice between corners with minimal stretching. Thanks to @skhoroshavin for this contribution!

The FPS limit code was updated to run more smoothly. In general, you shouldn't need to set a frame limit, because Phaser matches the current display refresh rate; this is for emulating low refresh rates, e.g. 30fps updates on specific consoles. There were issues that would cause it to persistently underperform, though. Those have been fixed, thanks to community discussion.

Several other issues were fixed, including blend modes leaking within Containers in the new render system, DynamicTexture turning black if resized away from a power-of-two resolution, Shape not using lighting, ParseXMLBitmapFont not handling offsets correctly, and some edge cases with internal methods.

Gallery

Orbs using Image Light

Above: ImageLight demonstrates various levels of smoothness in lighting/reflection. The top left shows full hemispherical light diffusion; the bottom right shows full reflectivity.

Gradient in an image

Above: Gradient used to create a lens flare (it's the ring around the glowing eye).

Spectrum gradient quantized and dithered

Above: Gradient smoothly covering the rainbow, using HSV blending. It's quantized into 8 colors. The first quantization is discrete. The second uses dithering; it's using the same 8 colors, but by mixing the pixels up a bit, the effect is much smoother. (Dithering may create distortion patterns if not viewed at the original resolution, but hopefully you see some kind of smoothness!)

Mech reflected in water

Above: Reflections generated with cellular noise. This example uses CaptureFrame to copy the render buffer, NoiseCell4D to generate an animated normal map, and Displacement to warp the reflection by the normal map. Simple and very effective!

Simplex noise clouds

Above: Clouds rendered with simplex noise. Phaser is a 2D engine and it's not meant to render 3D volumetric effects - but I did it anyway. (And the sky is a Gradient.)

Simplex noise landscape

Above: A landscape generated using Phaser.Math.HashSimplex to create an infinite landscape using Isobox shapes and a ColorRamp to tint them. It's not a practical rendering technique (it'll slow even the latest machine down, due to all the little boxes constantly updating), but it shows just how powerful these new features can be. I'm getting flashbacks to setting sail for the Isle of Dread.

Download Now

You can download Phaser 4 RC7 from npm and GitHub, or try it out immediately in the Phaser Sandbox!

What's Next

Phaser 4 is already more powerful and more reliable than Phaser 3 ever was. Honestly, we should have given it a formal release ages ago - but things have been super busy. Maybe one day we'll tell that story. And with RC7, we've brought Phaser up to date with tools we found useful in our own development.

We encourage community feedback - it's been super valuable at every step of the process.

Fingers crossed this is it - we're keen to get this beast formally released! But I have every confidence that it already works better than ever.

Download Phaser 4 RC7