Phaser World Issue 201

Richard DaveyRichard Davey
15 min read

Welcome to another packed issue of Phaser World! This week, we have a new release of Phaser and Phaser CE, two awesome games (one completely made with AI), and the teams' developer Logs to digest. Lots of fun stuff! Let’s dig in …

🌟 Phaser v3.86 Released

The latest version of Phaser is now available including important GPU memory fixes.

Phaser v3.86.0 is now available for download. This release is a seamless upgrade for any project using v3.85.x and is one we strongly recommend you all take. The full change log is available on GitHub, but the headline item is a fix in the way Render Textures are resized, which was causing Phaser 3.85 games to use significantly more texture memory than they should have been, leading to out-of-memory errors on some mobile devices. This fix reduces memory usage back down to 3.80 levels.

v3.85 also had an issue where black lines could appear between tightly packed sprites or tiles when you zoomed the Camera to a float (non-integer) zoom value. Upon investigation, we also uncovered a much longer-standing issue with the canvas renderer under similar circumstances. Both of these have been fixed in v3.86. Finally, we also fixed a severe run-time crash issue with the new EXPAND scale mode should you launch the game into a container or iframe with a horizontal or vertical width of zero. Please read the full Change Log on GitHub or npm.

All of the Phaser Templates for React, Vue, Discord Activities, etc., have been updated for v3.86, along with all the Phaser Editor templates, the Phaser Sandbox, and the create-game Phaser CLI app. Although there were only minimal documentation changes, the docs site is also fully current.

Download Phaser v3.86

🎮 Spellstrife

Plants vs. Zombies meets Scrabble in this word spelling tactics rogue-like

Spell words to summon monsters in a tactically deep turn-based battle system. Roguelike runs last about an hour each--choose your upgrades carefully as you climb the Spelltower with a variety of classes.

The starting letter of your word determines which of 26 unique monsters you will summon. Uncommon letters tend to be stronger, but each monster is useful in different scenarios. The length of the word determines the monster's HP and attack power.

You can also cast spells to manipulate your letter tiles or change the battlefield in your favor. Spellstrife is available to buy now on Steam and also has a demo version available. Developer Ben Coffman has done an excellent job of using Phaser to create a really novel blend of game genres and we wish him all the best for his release.

View Spellstrife Trailer

🍉 Suika Watermelon game

Create your own chart-topping suika clone with the full Phaser source code.

Long-time Phaser developer Emanuele Feronato has released the full source code to his Suika / Watermelon Phaser game. If you haven't seen it before, Suika is a Japanese puzzle game which combines elements of falling and merging puzzlers. It rose to glory recently with a series of games and apps using the same gameplay mechanic.

For $5 you get the full source code of the complete HTML5 "Watermelon Game" created using the Phaser 3.80.1 framework and Box2D physics engine powered by Planck.js, all written in TypeScript.

From the experience of more than 500 tutorials about Phaser framework, here is a complete Watermelon game which will make you learn game development using Phaser and TypeScript.

Read more about the source bundle

🌟 Phaser CE v2.20.1 Released

The Community Edition of Phaser gets a new point release.

Today, we released Phaser CE v2.20.1. Phaser CE is the 'Community Edition' of Phaser 2. It is no longer fully maintained by Phaser Studio but instead is looked after by the community.

This version includes the following changes:

  • The canvases used for device capability checks and input hit testing are now created with willReadFrequently: true.

  • Fixed an error when a video loaded after the game was destroyed (#742).

  • Set forceSingleUpdate to false for better consistency in physics calculations.

If you still use Phaser CE for legacy reasons, then be sure to upgrade to this new point release.

Download v2.20.1

🎮 Setris

This AI created game mixes the classic Tetris and crumbles it all into sand.

Setris, or Sand Tetris, is a new twist on the classic original. As the Tetris blocks fall from the top, you can move and rotate them, but when they land, they turn into sand and crumble to pieces.

The sand falls convincingly down, and as more and more blocks crumble onto the playfield, it creates a glorious mess of sandy colors. If you can get a solid stretch of color touch from side to side, it will vanish - just like getting a whole row in Tetris does, causing the sand above it to slip into place and netting you some valuable points.

This is a fun and clever game. Even more remarkable is that it was created entirely using Rosebud AI. That's right. It was "prompted" together using their smart conversational game-making system, with Phaser powering it under the hood. Rosebud AI has recently left private beta, so anyone can register and try making games of their own. If you create something extraordinary, please let us know!

Play Setris

💰 Let us publish your Phaser Games

Got a Phaser game you’d like published? Get in touch!

At Phaser Studio, we’re all about empowering developers to create great games. By focusing on the framework and tools to allow this, we’ve seen thousands of games released over the years, many of which went on to critical and commercial success.

And we’ve noticed the publishing landscape is changing yet again. New platforms are opening up that introduce keen opportunities for the right games. And it’s something we’re deeply invested in.

So - if you’ve developed a Phaser game you feel would benefit from wider distribution to exciting new platforms, then we’d love to hear from you. Please email a link to your game or games portfolio to bizdev@phaser.io , and we’ll be in touch.


Phaser Studio Developer Logs

👨‍💻 Rich

Welcome to another update! This week has been a nice mixture of tasks for me, but the main thing I focused on is getting Phaser v3.86 released. This version contains some important fixes, making it essential for anyone using 3.85.

It was an interesting task tracking down the causes of the issues and brought home just how poor the debugging tools we have available as web game developers really are. Dev Tools does its best, but it really isn’t geared towards long-running or frequently updating processes. Given it was built for web devs making web sites, this isn’t really surprising, but it does highlight a truly massive hole in the market.

Team progress across all fronts continues at speed. Box2D is nearing completion, our Discord Activities tools are nearing a first release, Phaser Beam is very close to the end of its dev cycle, Phaser Editor is about to start venturing into tilemap territory, Phaser Launcher has nearly completed its R&D stage, the docs site is very close to release, and of course the new website continues to be updated every day, with new features and fixes here and there. We’re also well into the development of our publishing system, which will allow you to easily host your games on our site via a simple drag-and-drop.

Also, thank you to those of you who responded last week to my call-out about having your Phaser games published by Phaser Studio. We’ve already started working with a small group of developers and are keen to see where this partnership takes us. If this is something you’re interested in, then drop me a line (rich at phaser.io), and we can talk more about it.

Finally, I took a little time one evening to play with Deno 2. If you haven’t seen the announcement video for it, then I strongly recommend it! The first 3 minutes are just golden 😀

The product itself is outstanding and great fun to use. What with this, VoidZero and Bun on the market, things are starting to get really interesting.

👨‍💻 Pete - Box2D

Optimization and Performance Improvements in the Box2D Plugin

  • Continued the "Great GC Clean-up" (GGCC) to reduce object allocations and improve performance.

  • Reduced b2Vec2 allocations from 240,000 to less than 500 per world step for a 1000-object tumbler demo.

  • Eliminated b2Sweep object allocations by converting to a single constant at program start.

  • Modified b2Manifold and b2ManifoldPoint usage to avoid allocation.

  • Replaced b2StackAllocator with faster JS arrays.

  • Optimized time-critical code chunks using Claude AI and manual refinement.

  • Improved performance of the 750-object tumbler demo to run stably at 139-144 FPS in Chrome and 70 FPS in Firefox.

  • Achieved 1000-object simulation running at 139-144 FPS in Chrome desktop (the monitor refresh rate).

Memory Management

  • Investigated potential memory leaks and explored tracking methods like WeakSet, though with limited success.

Documentation and Helper Functions

  • Created documentation for Box2D 3.0 JS and helper functions.

  • Developed an example project demonstrating the library's capabilities.

  • Moved demo code from main.js into separate, more accessible files like fun_stuff.js.

  • Wrapped and documented toy features such as Guns, Spinners, and a Ragdoll class.

Simulation Behavior Improvements

  • Modified the world step mechanism to prevent FPS cascading failures during overload situations.

  • Implemented a new approach allowing FPS to drop when overworked, avoiding permanent catch-up scenarios.

Ongoing Optimization Efforts

  • Identified and optimized frequently called one-line functions like b2ContainsKey and b2AABB_Overlaps.

  • Reordered conditionals to reduce function call frequency in critical paths.

  • Optimized callback usage in inner loops, particularly for b2PairQueryCallback.

  • Restructured a central function to avoid an inefficient callback and optimised it for the most common case.

  • Created a reproducible test case: 1000 steps of a tumbler with 1000 objects.

Next Steps

  • Continue documentation efforts.

  • Prepare for team exploration and contribution in the coming week.

  • Consider further performance profiling and optimization techniques.

Wins for the Week

  • Dynamic memory allocation is sufficiently low that the GC time is almost irrelevant.

  • Tumbler 1000 execution time decreased from 12500 to 8500ms.

  • Improved understanding of systems in Box2D will help with further optimisations in the JS version.


👨‍💻 Francisco - Phaser Launcher

Hello everyone,

This week I’ve been working on the Phaser Launcher tool and managed to add several new features. Now, you can open files, switch between tabs, focus on the editor, and even save the files you’re editing.

The editor now has full context of the selected file. Additionally, in the file view, files are automatically selected when the editor gains focus.

Creating files, creating folders, and minimizing everything works as expected. It’s incredible how many small tasks come with building an editor like this. Tasks such as selecting a file, checking its type, creating the corresponding tab, getting the language, fetching its content, displaying it in the editor with its own context—it all adds up. And if a tab is closed, the editor needs to check if it was in focus, select the next tab in line, and repeat the process all over again.

Step by step, our Phaser Launcher editor is growing into a tool that will become extremely useful for anyone who wants a fast and easy way to work with Phaser.

👨‍💻 Can - Discord Activities

This week, I made solid progress on our Phaser Discord Activity Launcher! The core features are now complete, allowing us to jump into the development server with just one click.

I started by running npm commands (make sure npm is installed on your system) and dynamically adjusting them based on the user's operating system. Thankfully, Tauri made this part a breeze, utilizing the "os" package and executing shell commands under the hood.

Next, I tackled command output handling essential for real-time feedback. Now, we can read every output buffer from npm, making it easy to filter relevant data on the fly. Regex came in clutch here (gotta love that dark magic), and it's working like a charm!

For the UI, I added a CSS loader to keep users entertained while all the heavy lifting happens behind the scenes. A bit more polishing is needed, without a doubt.

I’m hyped to finish this up and get it into your hands soon - can’t wait to see what you’ll build with it!


Takes from the Pixel Mines

October 14th 2024, Ben Richards

This week, I got a thing working! But what is that thing? Well, I don't know what to call it. Let me explain, and maybe you'll see where I'm coming from.

How It Started

Originally, we called these things FX. They handle post-processing effects like blurs, pixelation, displacement, etc.

In previous weeks, I explained that I want to put these into a single wrapper around game objects, to improve clarity. It's good to know where the framebuffers are in your scene, because they can affect performance. I originally called this wrapper Box, but that was too generic. So I switched to calling it RenderFX.

How many framebuffers is too many? In one way, I can't tell you, because of another way in which I can tell you.

I tested nesting RenderFX objects, one inside the other. Somewhere above 1024 nested levels, Chrome gave up and gave me RangeError: Maximum call stack size exceeded. This means there are just too many things inside each other for the JavaScript engine to handle. While it's possible to set browsers to have a larger call stack size, that's no good for games that are supposed to run on any device. So 1024 nested levels seems like a good "soft limit" for nesting.

This was not a WebGL error. Every object requires a new framebuffer, and an extra draw call. Performance did not drop under 60 frames per second during testing. Thus, we don't really know how this nesting affected GPU performance, because on my machine it is actually impossible to stress the GPU in this way. The CPU gives up before the GPU reaches its full potential.

I did do some performance profiling, though, and both CPU and GPU utilization were around 60% when the stack size was exceeded. Most of the GPU cost is probably spent on waiting for draw calls to be sent, rather than actually executing them. Overall, even though we can't reach full GPU utilization, it looks like drawing 1024 framebuffers is close to the limits of performance.

How It's Going

This week, I made several discoveries and decisions. Nothing changes my objectives, but it does change the way I think about them.

First, I decided that the things called FX should instead be called Filters. Post-processing effects are analogous to filters that you'd use in Photoshop, right? And "effects" extends to more than just filters - things like particles aren't filters, but would be called effects. So Filters seems best to me.

Then I took a long, hard look at the Camera. I realized two things: the Camera doesn't have enough transform power, and the Camera is where all filters live.

What kind of transform power does the Camera need? Ideally, it should have full transforms for internal and external sides. The internal transform dictates where in the world the camera is looking; more precisely, it is applied to anything rendering through that camera. The external transform dictates where the camera is placed in its parent context; this usually means "where it is drawn on the game canvas". Right now, Camera doesn't have a complete transform for either. Its position is external; its rotation is internal, and it has scroll and zoom properties for internal position and scale.

I'm not going to redefine the whole camera paradigm right now. But I do have some ideas for incremental upgrades. In addition, putting a Camera inside a RenderFX object provides it with a full external transform. This means that a camera can be drawn rotated at last.

Why should filters live only on the Camera? Because a camera is always involved in rendering. There's a camera inside a RenderTexture, and there's a camera inside my RenderFX implementation. Additionally, cameras in Phaser 3 can use FX. It's just a natural place for filters to reside.

After all this, I concluded that the RenderFX object was mostly just a wrapper around a Camera and a child (the game object you want to put filters over). It's necessary... but is it still a RenderFX if it doesn't even handle FX?

So after a week with RenderFX, I think I want to rename it to RenderFilters. I considered naming it after the camera, but that buries its main role: handling filters. However, it can be used to render cameras in new ways, such as rotating them.

Do the new names, Filter and RenderFilters, make sense?

A New Quandary

So with all that sorted out, I implemented a system for rendering filters. And it works! I have a minimal implementation which can apply the Pixelate filter.

There's just one problem: I overestimated the old FX system, and now my system does something different.

Here's how Phaser 3 renders a certain test, with a rotating image, using PreFX:

And here's how Phaser Beam renders the same rotating image test:

You can see that Beam has aligned the pixelation filter to the rotation of the image. But Phaser 3 has not.

Now, both of these are set to apply the FX/filter "internally", supposedly in the context of the texture/object rather than that of the world. To me, that means the axis of the filter should follow the camera view used to render the filter. If we instead applied the filter "externally", it should follow the main camera, as Phaser 3 has done.

Further, this is how I'm going to apply masks in Phaser Beam. A mask is just a filter which removes material. When it's "external", the mask will be applied in screen space; this is how masks currently work. When it's "internal", the mask will match the object's transformations; this is a much-requested feature, and in the Beam paradigm, it just works.

So I'm going to continue in this way. Does that make sense?

Coming Up

We're planning one final Technical Preview to test filters, or whatever they're called. Now that I'm actually implementing the filters, we're extremely close to completion. After that, it's time to integrate Beam with updates made to Phaser over the last year, and move forward with a full release. Very exciting! I'm looking forward to finally getting Beam, and all its enhancements to performance and quality and flexibility, into your hands.


Send us your stuff!

Created a game, tutorial, sandbox entry, video, or anything you feel Phaser World readers would like? Then please send it to us!

Until the next issue, happy coding!

1
Subscribe to my newsletter

Read articles from Richard Davey directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Richard Davey
Richard Davey