Releases / v0.69.0
v0.69.0 Flat Out
2026-08-19 Engine Latest
A release about making 2D games. A sprite node that knows what a pixel is, sorting that puts a character in front of the table they are standing at, sprite animation whose frames can come from anywhere, and a camera that follows.
A sprite is a node now
✚ New ▸ ▦ 2D ▸ ▫ Sprite.
You could always build one out of a Plane and a Material, and every 2D project did — each of them working out the same three things: that the plane is 1.4 units across and not one, that flipping means a negative scale, and that the sheet cell lives on the Material. A Sprite answers all three once, and carries two things a Plane cannot:
- A size in pixels.
pixels per unitmeasures one cell, not the sheet, so slicing a sheet finer does not resize every sprite on it. - A pivot. The origin defaults to the middle; the feet button puts it at the bottom, which is what a Y-sorted character wants.
Lower on the screen draws in front
Set a node's sorting layer to Y, and nodes level on layer and order sort by how far down the screen they are. Walk behind a table and you are behind it; walk in front and you are in front.
The order is sorting layer, then order, then Y. Y is the tiebreak, not a replacement — a drop shadow on order −1 stays under a Y-sorted crowd, and a lantern on order 1 stays in front of whoever is carrying it.
Two things to know:
- A node's sorting layer and its collision layer are different things. They were both labelled "layer"; they are not any more. (Nor is the third one, the layers a 2D light reaches.)
- A Y-sorting layer holds about 64 nodes before two of them tie — that is measured, not estimated. Split crowded scenes across sorting layers.
Backgrounds that move less than the world
parallax is a per-axis scroll factor: 1 moves with the world, 0 pins to the
camera, 0.3 is a distant range of hills.
A factor rather than a distance, because the other way of getting parallax — putting a layer further back — only works under a perspective camera, and a flat game wants an orthographic one so its pixels hold still.
Sorting and parallax move the picture. Colliders stay where you put them and
node.x reads back what you set.
Sprite animation, from any sheet
A frame names its own art, so one animation can use frames from different sheets and from plain PNGs that were never on a sheet at all.
Three ways in:
- Right-click a sliced texture in Assets ▸ ▦ New sprite animation — one frame per cell, ready to cut down.
- Right-click an Aseprite
.json▸ ▦ Import Aseprite sheet — the tags become clips, the grid slices the image, and per-frame timing is kept. - ⏱ Animating ▸ ✚ Property ▸ Sprite ▸ frame — a lane beside position and rotation, for when the sprite is only part of what is animated.
A sprite animation is an ordinary clip: drop it in a controller and it crossfades, layers, carries events and plays from Lua like anything else.
// hero_walk.spriteanim.ron
(
fps: 12,
loop: true,
cols: 8, rows: 4,
texture: "art/hero.png",
frames: [
(cell: 0),
(cell: 1),
(texture: "art/hero_extra.png", cols: 4, rows: 4, cell: 9),
(cell: 2, hold: 3.0),
],
)
Record picks up what you actually changed
● Record used to notice numbers and nothing else, so changing a material's texture with record on wrote no key — which is the one gesture sprite animation is for. It writes one now.
Materials also gained the rest of their surface: opacity, base colour, emissive, specular, rim, roughness, metallic and the rest are all keyable, so fading something out is a lane rather than a script.
The ✚ Property menu is grouped by component, with the fields people reach for at the top.
A camera that follows
Tick 2D camera on an orthographic Camera:
| follow | the name of a node to chase |
| dead zone | how far it may move before the camera moves at all |
| smoothing | seconds to close the gap — the same at 30 fps and at 144 |
| limits | a rectangle the camera stays inside |
With no follow target the camera's position is left to whatever else is moving it — a script, a cutscene, your own placement — and only the limits and the shake are applied. So you can drive the camera by hand and still shake it.
node:setCamera2D{ follow = "Player", smoothing = 0.12, deadZoneX = 1.5 }
node:shake(0.4, 0.25)
Shake is added to what is drawn and never fed back into the follow, so it composes with the chase and with the limits instead of fighting them. Calling it again takes the louder amplitude and the longer time, each independently — a bang during a rumble does not cut the rumble short.
All of this applies to an orthographic camera and to nothing else.
Menus that stay short
✚ New is grouped — ▦ 2D, ■ 3D, ▦ Model shape, ● Lighting, Δ World, ⬚ Navigation, 🖼 UI — so adding a node is a glance rather than a scroll.
Panels fit however thin you drag them
Every form panel now shrinks, then wraps, then stacks. Drag the Model, Tiles, Inspector or Settings panel as narrow as you like and nothing goes past the edge.
Smaller things you will notice
- Drag a
.pnginto the Scene view and you get a Sprite wearing it. It used to do nothing at all. - Sorting, parallax and 2D light settings follow a multi-selection, so putting forty tiles on a background layer is one edit.
- Greyed-out menu entries now say why they are greyed out. They had the explanation written and could not show it.
- The ✚ Property menu in the Animating tab is grouped by component, and a material's texture and opacity sit at the top rather than in a wall of surface maps.
- Duplicating or pasting a node keeps its sorting layer, parallax and 2D camera. It used to drop them.
For package authors
json.array(t)/json.isArray(v).{}is both an empty list and an empty object and encodes as an object, so there was no way to send[]at all.json.decodenow marks the arrays it builds, so reading a body, emptying a list and sending it back keeps it a list.ed.copy(text)puts a string on the clipboard, so a panel can have a copy button. Write only — nothing can read the clipboard — and the editor shows how much was copied.
Upgrading
Nothing to do. Everything here is opt-in: a scene that does not use sorting layers, parallax, sprites or a 2D camera saves exactly the file it saved before.
Floptle Hub
Engine
The binaries are not signed yet. On macOS, right-click the app and pick Open the first time. On Windows, if SmartScreen appears, pick More info then Run anyway.