Change Log - What's new?
- Feature: In-game CONTROLS mapping menu added (pause → CONTROLS) to remap keyboard and gamepad buttons for all logical
BTN_* inputs.
- Bindings save in the browser and apply across every game on that device.
- Update: UX improvement to the menu system to make it more consistent and easier to use.
- Update: Quit option removed as it had no functionality.
- Fix: Fixed bug where Restart did nothing.
- Feature:
time() / t() — returns seconds since the game booted - continues when the menu is open.
- Feature:
gameTime() — returns seconds since the game started - pauses when the menu is open.
Overhaul of the Sprite Editor Paste functionality.
- Update: Sprite Editors - Big overhaul of paste functionality - Thanks TheLastRobot.
- Update: Sprite Editor - Pasted and selections stay floating until you press Enter or click outside. Escape cancels a paste.
- Update: Sprite Editor - Can now paste from system clipboard or sprite editor.
- Update: Sprite Editor - Resize with corner and edge handles (hold Shift to keep the aspect ratio).
- Update: Sprite Editor - Choice of resizing algorithm when resizing.
- Fix: Sprite Editor - Fixed bug where pasting a selection from the sprite editor would cause transparent pixels to change colour during selection.
- Fix: Level Editor - Undo was not working on the node layers.
- Fix: Can now draw in all sprite rows
Gamepad support, multiple sprite sheets, and several editor and billing fixes.
- Feature: Gamepad support added. Keyboard and standard controllers both drive the same
BTN_* buttons (D-pad or left stick, A/B/X/Y, shoulders).
- Start opens the pause menu, the same as Escape.
- Feature: Multiple sprite sheets. Each sheet is now fixed at 16 columns × 16 rows (256 sprites).
- Paid plans can have up to 8 sprite sheets (2048 sprites).
- Free Tier has 1 sheet (256 sprites).
drawSprite still uses global 1-based IDs (sheet 0 is 1–256, sheet 1 is 257–512, and so on).
- Existing carts load as they did before; extra-tall sheets split into 16-row chunks.
- Fix: This should resolve the performance issues seen with excessive number of rows - Thanks AndyH.
- Update: Added confirmations to Switch Tier modal - Thanks AndyH.
- Update: Added confirmation statement about feature limits when switching to Free Tier.
- Update: Documentation now returns to last page and position when navigating back to it - Thanks AndyH.
- Fix: Resolving payment after past-due, now restores tier paid for - Thanks Garlic Bread Boi.
- Fix: Added, very generous map, size limit to prevent crashes - Thanks AndyH.
- Paid maps are limited to 65,536 tiles (for example 4096×16 or 256×256)
- Optimised editor performance by only painting the visible area, so very wide maps no longer crash or show a blank canvas.
- New maps now start with default size of 16×16.
- Fix:
print() now uses Lua __tostring and default type formatting, so class instances and tables no longer show as <value> - Thanks TheLastRobot.
- Fix: Code editor no longer flags tables made callable with
__call as undefined functions.

PIXELFALLS is here — our first official release!
Jump in, make something weird, and share it with the world.
v0.0.18
- Feature: Delete account option added to Account Settings
- Fix: Removed unnecessary URL calls when logging in
- Update: Cleaner Console Log: Only user
print() and errors will be logged to the console by default.
v0.0.17
- Feature: Share Game; branded QR code for the play link.
v0.0.16
- Update: Additional game buttons added and remapped (
BTN_UP/DOWN/LEFT/RIGHT, BTN_A–BTN_D, BTN_L/BTN_R). Games poll buttonDown/buttonPressed with these IDs; default keyboard binds are Z/X/A/S/Q/W + arrows. Existing carts migrate KEY_Z→BTN_A, KEY_X→BTN_B, KEY_M→BTN_C, and direction KEY_*→BTN_* on load.
- Update: Mobile Virtual Pad layout improved for better touch interaction.
v0.0.15
- Feature: Share Game; Share your game with the world.
v0.0.14
- Feature: SFX Editor; playSFX() function now working in the engine.
- Feature: SFX Editor; playSFX() support sound name as a string parameter instead of index.
playSFX("jump")
- Update: Engine;
drawText now supports \n in the text string to start a new line. 
- Fix: Fixed ticket #35 - Bleed through when using Show Colliders in Play mode.
- Fix: Fixed ticket #42 - Game instructions are not updated when changing between carts
- Fix: Fixed ticket #39 - Editor switching Tabs loses position
v0.0.13
- Update: SFX Editor; Removed multi column note style change
- Update: SFX Editor; Mouse cursor row and column highlighting.
- Update: App wide; removed browser default context menu.
v0.0.12
- Update: More changes to the SFX Editor
v0.0.11
- Feature: SFX editor added to the IDE
- Feature: Code Editor; spotlight appears when switching back to a code tab. Can be turned off in IDE Settings.
- Fix: Code Editor; Cursor and Scroll position of each tab now remembered.
- Update: Solution Explorer; Folder and File context menus now use PF modal prompts.
- Update: Solution Explorer; Folder state now remembered and expanded/collapsed.
- Update: Solution Explorer; Right Click Context Menu added for Folder and File.
- Update: Solution Explorer; UX improvement by simplifying solution explorer items.
- Update: Solution Explorer is now resizeable.
v0.0.10
- Feature: Subscription integration with Stripe
- Feature: Cloud storage integration
- Feature: Font trim options added to Game Settings
- Feature: New viewport overlay in the Level Editor to help level design within the game screen bounds

- Feature: Customizable grid and viewport color in Home → IDE — one setting for all grids

- Update: Home section added for Projects, IDE, Account, and About (Therefore removed Settings section)
- Update: Styling updated for consistency across the app.
- Update: Tidy up of NavBar lower buttons.
- Update: Improved code suggestions with Node method referencing.
- Update: Added collidersEnabled(boolean) function to nodes.
- Update: Added Changelog images and GIFs support.
- Update: Improved Node and Prop Palette to show more items and improved layout

- Fix: Enhanced code suggestions with Node method referencing and properties.
- Fix: Code spawned node instances now have colliders
- Fix: Font now has complete character set
- Fix: Local/Cloud timestamp check performed to ensure use is in sync with the latest changes.
v0.0.9
IDE
- Fix: Sprite editor now correctly renders palette color index
0 as the default background color..0
- Feature: Tags are now enums. Add/Remove tags in Game Settings, then use them in code by typing tag. and it will list available tags.
- Update: After confirming Start New Game, the IDE now automatically switches to Game Settings.
- Update: Cleaned up the Node Settings modal.
- Update: Improved Level Editor Collider Show visuals
- Fix: Map node/prop
visible now only affects rendering. Collision participation now depends on enabled, so invisible-but-enabled instances still collide.
- Feature: Collide checkbox on map node/prop instances (
enableCollisions, default on): turn off to exclude a placement from hasCollided* while keeping it enabled and visible.
- Update: Clean up and styling update to Game Settings screen
- Feature: Multiple selected entities can now be move/copied/pasted/delete together.
- Feature: Function names are background highlighted for easier visual scanning (togging on/off in settings > IDE)
API
- Feature:
buttonDown() and buttonPressed() now support no-argument calls to query whether any tracked key is currently held or was pressed this frame.
- Update: Map-node collision participation uses
enabled and per-instance enableCollisions (default true). visible controls rendering only.
- Feature:
getAllEntities(tag) returns live instances with overloads for no arg (all), type query (path/class/instance), and tag id (e.g. tag.wall).
- Feature: Added built-in global
state table as a shared data namespace between main.lua and nodes/props.
- Fix: DrawText now correctly uses the setColor value if drawText colour parameter is omitted. Ticket #20
- Feature: Added runtime map-entity loading APIs:
loadMapEntities(mapIndex), loadMapLayerEntities(mapIndex, layerIndexOrName), unloadMapEntities, and unloadMapLayerEntities — always restart-style (reset engine entities and tiles for that scope, then spawn).
- Feature: Default behaviour to loadMapEntities(0) automatically on first run can be turned off in Game Settings:
Auto-load first map entities on startup
- Feature:
saveSnapshot([replaceSnapshotId]), loadSnapshot(snapshotId), deleteSnapshot(snapshotId) — engine checkpoints for the current logical level (tracks last loadMapEntities / loadMapLayerEntities); console logs approximate snapshot sizes.
v0.0.8
API
- Feature:
instance:getCollidedEntities() or getCollidedEntities(instance) — for a node placed on the map, returns a list of the other instances overlapping it this frame (pickups, doors, hazards, etc.). See the collision docs for examples.
- Feature:
instance:isType(NodeName) or isType(instance, NodeName) - Check if an instances if of a type.
IDE — Creating classes
- Update: New Node (+N) and New Prop (+P) in Solution Explorer now open the full Create Node / Create Prop dialog.
- Feature: Creating a node or prop class prevents create if the name would clash with an existing node or prop type.
IDE — Sprite & level editors
- Feature: Eyedropper tool in the Sprite Editor (shortcut I or Right-Click anytime) to sample pixels from the sheet.
- Update: Draw tool hover tips use a clearer label + shortcut style.
v0.0.7
Engine
- Update: 30 FPS is now game default, option to change to 60 in game settings. Older carts will be set to 60 FPS to run as they were.
- Update: Delta time now passed to
update(dt). Existing carts that use update() with no args are unchanged.
- Update: Fixed issue with just a few nodes causing slowdown.
IDE
- Update: Added FPS stats current / min / max / Avg30s when playing the game.
- Update: Loading Game screen while game loads
v0.0.6
** Switch a node to a prop and visa versa has not been tested - suggest avoid doing this for now **
API
- Fixed: Renamed 'mapGetTile' to 'getMapTile' and added level and layer index to parameters.
- API is now 'getMapTile(levelIndex, layerIndex, tileX, tileY)'
- Feature: Added 'setMapTile(levelIndex, layerIndex, tileX, tileY, spriteIndex)'
- Feature: Initial work for collisions with the following APIs
- 'hasCollided(instance, instance)'
- 'hasCollided(tag, instance)'
- 'hasCollided(instance, tag)'
- 'hasCollided(tag, tag)'
- 'self.Collided(instance)'
- 'self.Collided(tag)'
Node/Prop Settings
- Update: Unified origin and colliders in UI
- Feature: Add tag field
Level Editor
- Feature: Now able to select multiple sprites in Sprite Palette, with Click-Drag, and then draw them with the brush tool.
- Feature: Easily create Nodes/Props by right clicking a sprite(s) in the Sprite Palette
- Feature: Added Node/Prop Ghost when adding to Node Layer
- Feature: In Node Layer, hold Shift to 'Snap' nodes/props to grid
Code Editor
- Feature: Added code formatter button
v0.0.5
IDE
- Added migration scripts to automatic upgrade carts going forward
- Migration: drawText to swap last 2 parameters (now colour then size, both optional)
- Migration: enabled is now enable
- Added 'About' tab in the settings model
- API documentation re-organised
- Reduced font and control sizes to be more inline with typical online apps, giving more real-estate
Node system
- Feature: PIXELFALLS Lua Sugar — Added compile-time sugar support for
x++, x-- (postfix), and compound assignment operators (+=, -=, *=, /=, %=).
- Feature: Lifecycle callbacks — Nodes can define
onEnabled(self), onDisabled(self), onShown(self), and onHidden(self).
- Breaking:
enabled renamed to enable — The built-in property is now enable (and visible unchanged). Existing carts that use enabled continue to work; the runtime treats enabled as an alias for backward compatibility.
- Feature:
spawn() options — You can pass an options table as the last argument: spawn(node, x, y, ...args, { enable = false, visible = true, z = 0, scale = 1 }). Or use a single config object: spawn(node, { x = 10, y = 20, enable = false }). All other arguments are still passed through to init(self, ...).
- Fix: Node
init parameters — spawn(node, x, y, a, b, c) now passes all arguments to init(self, x, y, a, b, c); previously only the first three were passed, which broke nodes like pixel that take extra parameters (e.g. colour, speed, y_stop).
- Fix: Deferred init order — When a node is first enabled (e.g.
play1.enable = true), init(self, ...) now runs before onEnabled(self), so refs you set in init (e.g. bucket1 = spawn(bucket)) exist when onEnabled runs.
Code editor
- Feature: Right-click context menu (node files) now includes Insert Lifecycle: onEnabled, onDisabled, onShown, and onHidden alongside the existing init/update/draw/drawUI/destroy options.
API
- Breaking:
drawText parameter order changed to drawText(text, x, y [, colorIndex [, size]]) and size as optional, defaulting to 1 when omitted.
Level editor
- Feature: Layered maps — Maps are now composed of ordered tile and node layers; the engine draws layers from bottom-up.
- Feature:
drawMap(levelIndex, x, y) — Now treats the first argument as a logical level index and draws all tile layers for that level in order.
- Feature:
drawMapLayer(levelIndex, layerIndex, x, y) — Draw a single tile layer of a level (e.g. for custom parallax or drawing sprites between layers).
- Feature:
drawMapLayerRange(levelIndex, firstLayerIndex, lastLayerIndex, x, y) — Draw a contiguous range of tile layers for a level.
- Feature: Map layers panel — Add, remove, reorder, show/hide, lock, and rename tile and node layers; drag-and-drop reorder; single-click to select a layer, double-click to rename.
- Feature: Multiple tile layers render in the editor in the same order as at runtime (bottom layer first, transparent pixels reveal lower layers).
- Update: Selected tool icon is shown next to the cursor when over the map canvas.
- Update: Sprite Editor also: Draw Tools now have groupings (Shapes, AutoTile & Transform)
- Feature: Added outline draw tools for Rectangle and Ellipse
- Feature: Shift/Ctrl can now be used to select/deselect areas
- Feature: Drag select multiple sprites and draw them for quicker level creation
- Update: Moved Maps settings into top Right maps drop-down
- Fix: Stopped Sprite Palette overlapping other control cards
Sprite editor
- Feature: Selected tool icon is shown next to the cursor when over the sprite canvas.
- Update: Zoom level of sprite editor changed to zoom out more
- Feature: TileSet rows are highlighted and tooltip warning
- Feature: Shift/Ctrl can now be used to select/deselect areas
- Works with double-click too for whole tile selection
- Phase can now be used to paste multiple copies
Engine
- Update: Flow order changed to improve input responsiveness
v0.0.4
Play Console Error Improvements
- General improvements to more clearly show lua errors
- File and Line numbers shown for most errors
- Errors with File and Line number are clickable to take you straight to the problem
- First error instance shown in the Error Bar at the top of the console.
Documentation
- First pass as improved API Reference documents
- First pass at explaining Nodes, with examples.
- Simple content added to Overview, Quick Start and Core sections
v0.0.3
Authentication
- Forgotten password implementation added
v0.0.2
Authentication & Access
- Feature: Replaced password protection with true Authentication
- Feature: Settings > Account tab with password change and sign out
Node System Updates
- Feature:
spawn(nodeClass, ...) now accepts arguments to pass to init() function
- Example:
spawn(enemy, 10, 20) passes 10, 20 to the node's init(self, 10, 20) function
- Update: Node
update function now properly handles missing implementations
v0.0.1
Code Editor Updates
- Feature: Virtual Files and Folders added
- Feature: Files can be marked as a Node - Meaning they can have their own Life cycle methods
- Feature: ToDo List - start a comment with
-- todo and whatever follows is added as an Item in the ToDo List
- Feature: Hover mouse over PIXELFALLS & Lua methods to popup explanation
- Feature: Right click for Insert Lifecycle methods (context aware i.e. node and non-node)
- Feature: F2 to rename selected Method and all references will be renamed too
- Feature: Code search - Ctrl + Shift + F, or Magnifying Glass button, to search across all code files
- Update: IDE Settings > Suggestion Insert can now be Tab or Enter
- Fix: Select Sprite popup, when using drawSprite, now all 16 columns should be visible
Node Specific
- Feature:
spawn(node name) to create an instance of that specific node
- Feature:
destroy(mode instance) remove the specific node instance
- Feature: All nodes have the following built in (so far):
- x & y: coordinate values
- z: draw order - Lower numbers drawn first
- destroy(): - removes itself
Other Updates
- Update: New NavBar Icons
- Feature: This 'What's New' component 😁