Skip to main content

Subcameras and Sparks (April 2026 update)

· 5 min read
raysplaceinspace
Creator of Easel

Subcameras for parallax effects, TextSpark and other particles, and more! Keep reading to learn what is new with Easel this month.

info

Easel is a 2D game engine which makes your game multiplayer automatically! Intrigued? Visit our home page to learn more.

Bigger world with Incremental Physics

The biggest update this month is the new physics engine, which means Easel can now support much larger worlds, as only the parts of the world that change need to be snapshotted and rolled back as part of Easel's predictive multiplayer architecture. This is such a big topic that it deserved its own post: A Physics Engine with Incremental Rollback.

Parallax Effects with Subcameras

Parallax is a common effect found in games where the background moves slower than the foreground, creating a sense of depth. It involves creating a stack of cameras that are locked to the same position but with different zoom levels. Previously, this was difficult to do in Easel reliably because of the way its predictive multiplayer architecture works.

For example, the camera may be moved to the left based on the player's input, but when other player's inputs arrive, the camera may need to be rolled back and moved to the right instead. Instead of the camera snapping to its new position, the camera is smoothed between the predicted position and the new position (controlled by the transitionRate parameter). But because your userspace code lives only in the current timeline and has no awareness of the predicted timelines that came before it, it cannot know where to place the stack of parallax cameras so they match the main camera, which could be transitioning from any direction.

The new Subcamera function locks one camera to another at the engine level. This makes sure the parallax is always right, no matter what happens with the timelines and rollbacks.

More Kinds of Spark

In Easel, when a fireball crashes into an enemy, you can use Spark to emit a burst of particles that fly out in all directions, creating a satisfying explosion effect. The new PolygonSpark, ImageSpark, and TextSpark functions make it easy to create sparks in different shapes and styles. For example, you could use a TextSpark to flash damage numbers when slicing an enemy with a sword, or ImageSpark to create a burst of coins when breaking open a treasure chest.

While you could previously create the same effects using sprites, sparks are a lot more efficient. Why is this?

When you animate a sprite, you are changing its underlying data every frame. Everything that changes in Easel needs to be snapshotted so it can potentially be rolled back as part of the predictive multiplayer architecture. Sparks are cool because their data never changes. You declare a spark once, and then the engine calculates its position and appearance at render time based on the spark's parameters and the current time. Perhaps surprisingly, the data actually never gets snapshotted at all because it never changes. In Easel, sparks are super efficient. Spark your imagination and let it go wildfire!

Stroke Your Text, or Don't

The new stroke and strokeAlpha parameters have been added to the TextSprite function, allowing you to add a dark outline to your text, helping it stand out against bright backgrounds. Great for damage numbers, speech bubbles, or any text that needs to be easily readable.

A similar stroke parameter has been added to Span and other similar UI elements, so you can turn off the default stroke if you want your text to be blend in with the background more. Great for styling little hints or reminders next to common actions.

More styles

In addition to stroke, you can now also use crater, glare and feather on both text and image sprites and sparks.

Text culling fixed

In doing this change, we discovered that Easel was basically not culling any offscreen text. This was causing massive peformance issues on games like GTW where the labels of every star in the entire galaxy were being redrawn every single frame. Normally the text would only need to be drawn once and then it would remain on the texture atlas without needing to be redrawn, but in this particular game, each label in the star map is actually the size of a star and so when you're zoomed into one star, the labels 2048px high, and no texture atlas is big enough to hold 50 of those.

Now offscreen text gets culled correctly, meaning it does not get drawn at all. This should result in a significant performance boost for games with worlds full of text.

Do More with "With"

The with block now accepts a parameter, letting you easily assign the value of a property to a variable:

with Health myHealth {
Content { "My health is: " + myHealth }
}

The new WithEachPlayer lets you add a behavior to every player in the game, past and present, letting you create more decentralized systems:

WithEachPlayer owner {
Print { "Welcome to your doom, " + PlayerName + "!" }
}

You can delete WithEachPlayer<Id> too:

WithEachPlayer<upgradeSystem> owner {
PlayerUpgradeSystem
}
await ConcludeGame
delete WithEachPlayer<upgradeSystem>

Thanks for Being Here!

Thanks to everyone in the Easel community for your continued support. We love seeing what you're making! Speaking of games, if you haven't already, try out the new Dinosaur game made by NotAHat: https://easel.games/@notahat/dinosaur-game