Published on 30th August 2024
Welcome to Phaser World Issue 195
The service we have used for years to send Phaser World is closing down tomorrow. So this will be the final issue of Phaser World in this style, sent from this account. We haven't fully decided where to migrate the newsletter yet. There are a few options, and they all have pros and cons. What we will do is export the current active subscriber list (i.e. you guys!) and import it to the new service. We hope you'll stick around because we've a lot to release in the coming months. If not, unsubscribing is just a single click. With that said, let's get on with the final 'old school' issue of Phaser World :)
Game of the Week
V and N Pizza Cooking Game
Experience the ultimate virtual pizza-making adventure with the V And N Pizza Cooking Game!
Pixcale
A Game Maker's Toolkit Jam entry made in Phaser.
Runner's Grave
Try not to get lost in this Phaser made maze runner!
Gloomyvania
Classic arcade pixel platformer Metroidvania-style, run and shoot to destroy enemies through five stages and a boss.
Spanish language Phaser tutorial
Spanish language creator MiduDev teaches Phaser on Youtube.
Ariel Roffé's personal website
Code for my Pokémon-style personal website, made with Phaser 3.
Texture Packer for VS Code
Easily create texture atlases for Phaser, Pixi, and more by grouping images into a folder.
Build a highly customizable mobile friendly HTML5 level selection screen controllable by tap and swipe written in TypeScript and powered by Phaser
Now it’s time to move to TypeScript so I built a new prototype, allowing even more space for customization and using classes for a better code reusability.
Rich: This week I've mostly been working on Phaser v3.85 and the documentation for it. This feels like an almost endless task, but there does appear to be light at the end of the tunnel - and we're inching ever closer to it. Documentation is a complicated subject. I've always been careful to ensure that the API is documented, even all the internal and private stuff (because that really helps guide those looking to help fix bugs, for example). But documentation means a lot of different things to different people.
These days, it's quite common to expect that the documentation is actually not really docs at all but tutorials, guides, and learning resources explaining the concepts and systems behind how the framework, err.. works. The issue is that because all of our docs are built from JSDocs directly authored in the source code of Phaser, there was never a clean and easy way to add all of these supplementary guides. The same is true of code snippets as well.
Suffice to say, as Zeke and I have been pouring through and editing literally thousands upon thousands of lines of docs, I've also been trying to figure out how we display this content on our new website. We're not quite there yet, truth be told, but there are some promising options out there so next week will be all about investigating those. All we know is that we don't want to have to 'home grow' our docs system again (like we did with the current one) and we don't want to have to store all of the snippets and guides and so on in the Phaser repository. But, of course, we still want to use JSDoc! It's a surprisingly complex problem to solve when you've an API as wide as Phaser has.
Arian: Hello! This week we have completed the development of the Trial mode of the desktop version of the editor. Now what remains to be done is all the work to publish a new release. While we were testing this new mode, I dedicated myself to working a little on one of my games. This is something I like to do from time to time because I always find details that can be improved, such as the following button:
As it is, its function is to execute the "Go To Scene" command, which opens a dialog with all the scenes in the project.
I was also able to detect some bugs and fix them. Sometimes I feel like dedicating a couple of months just to making games and polishing rough details that are still in the editor, and optimizing some workflows, but in Phaser Studio we are at full speed and with new and powerful features planned for the very near future.
Ben: 2024-08-30
I spent most of this week rearranging shader components to support the things we want to do with accelerated tile rendering. It's complex stuff that sometimes makes me want to pull my hair out, but it's all in the name of making everything work as best it can.
Bleed Clamping
One thing I tested was "bleed clamping". This turned out to be a solution which is sometimes worse than the problem it solves, and led to plenty of revisions.
First, the problem. Bleeding is an issue with linear texture filtering, where the linear filter naturally blends into texels from just outside the border of a frame. GPU hardware isn't specialized in frames within a texture atlas; it's designed for contiguous meshes where textures should blend across polygon boundaries. Unfortunately, when you use that for sprites and tiles and other 2D tasks, it can mean ugly blurred seams along borders.
Bleed clamping restricts the possible range of texture coordinates. The coordinates are just clamped to 0.5 texels inside the border, so linear filtering never wants to sample outside.
The problem is, this requires the shader to know about the frame. It's not part of our default quad rendering data, so we would need to add the frame to every vertex. This adds 4 values to a 7-value vertex attribute array, and in practice, this turns out to be too expensive to justify for every game object.
For most game objects, bleed clamping is the wrong fix. Instead, you should make sure your textures are set up properly. Use texture extrusion to make sure that the texels just outside the frame are the ones you want. There are three main cases:
Empty margins give your sprite soft edges. Extruded margins (copying the edge pixels across the margin) pull color right to the edge, good for sprites intended to line up with each other. * Wrapped margins are like extruded margins, but flipped (vertically and horizontally). These are good for sprites intended to repeat.
If you follow this best practice, you get the same effect as bleed clamping, but for free!
However, there is one place where bleed clamping is necessary: tiles. Tiles can intersect in all sorts of ways, so managing borders in the texture may be impractical.
As a result, I changed tiles from using the Quad shader to the TileSprite shader, which already includes frame information. Using the new shader additions system, the renderer can be reconfigured to handle texture coordinates however we want. TileSprites do frame wrapping, while tiles do frame clamping. And they can both benefit from other additions, like lighting and smooth pixel art.
Smooth Pixel Art
Oh yeah, I implemented a smooth pixel art option. (Thanks again, flay!) This uses the OES_standard_derivatives WebGL extension to do clever things with texture coordinates, allowing sprite art to benefit from antialiasing while still keeping pixels crisp. This will probably be the new standard for sprite art; it makes scaling and rotation much cleaner.
Multi Texturing Made Simple
While I was at it, I changed the way we handle multi-texturing. Previously, the shader needed to compile a monolithic list of checks: if texId < 0.5 { texture = texture2D(uMainSampler[0], texCoord); } else if outTexId < 1.5 ... repeated as many times as the system has texture units. (Usually 8 or 16.) This made big shader code, and big functions for dynamically generating that monolithic switch.
But while rearranging shader components, I discovered that our new emphasis on preprocessor use can make this much simpler. See, we can replicate the whole thing with a for loop:
For those unacquainted with GLSL, you can't ordinarily use for loops. They need a constant length. But with a preprocessor directive #define TEXTURE_COUNT 1, it gets that constant length, and the code is allowed to run.
And the result is actually exactly the same! The loop gets unrolled by the compiler, repeating its contents the fixed number of times and filling out i, so it's just like that big monolith of if...else cases. Except we never have to read it, and the code we ship is much lighter.
(Why can't we just say texture2D(uMainSampler[texId]))? At least in WebGL 1, that's illegal. The shader needs to run validity checks on every sampler it uses, so it needs those sampler accesses to be constant at compile time. Thus we have to step through them until we find the right one. It's annoying, but shaders are extremely fast so it works out.)
Fracturing Fractions
The new shader composition system got an overhaul, as I got more comfortable with its capabilities. In particular, I started splitting things up more.
Previously, we might have a lighting addition which adds a function that does lighting. You pass it the surface color, and it looks up the normal map, does lighting calculations, and combines it all into a lit surface color.
But this was impractical for all purposes. For example, what if we want to do lighting on Graphics objects, which don't have textures at all?
Well, we could add a shader feature for flat objects, and add more preprocessor code to the lighting function to decide between a flat normal and a texture map normal. But now the function is getting complex and difficult to read, and it's still not going to work if we invent a different use case.
So I split the function up into a range of related additions, which we can mix and match to get the results we need. Now the core lighting function just takes a normal, and other additions tell the shader how to generate that normal, and when to apply lighting. This allows us to continue using common additions across shaders, but doesn't lock us into one way of using them.
Next Week
Right now I'm working on an advanced tile layer. It encodes layer data into textures, so the whole thing can be computed in the shader, instead of uploading every tile individually. It works already, but only for a limited range of shader options. When it's done, this will be much faster than regular tile layers, and hopefully offer some features for truly perfect rendering. None of the bleeding or sharp edges inherent to other forms of tiles!
Wish me luck.
Phaser Releases
Phaser 3.85.0 Beta 2 released 23rd July 2024.
Phaser Editor 4.2 released 7th August 2024.
Phaser CE 2.20.0 released 13th December 2022.
Have some news you'd like published? Email support@phaser.io or tweet us.
Missed an issue? Check out the Back Issues page.
©2024 Phaser Studio Inc | 548 Market St PMB 90114, San Francisco CA 94104