slippery-boxes

  • v0.10 - Gamepad Support

    Added gamepad controller support! The game now detects connected gamepads and maps the d-pad and buttons to movement and restart actions. The first button press on a gamepad “claims” it as the active controller.

    Refactored the input handling into a clean Controller abstraction with separate KeyboardController and GamepadController implementations. Both implement the same callback interface for movement and actions, making it easy to add more input methods later.

  • v0.9.1 - Storage Fallback and UI Fixes

    Added a storage abstraction layer that gracefully falls back to an in-memory cache when localStorage isn’t available. This fixes issues for users in private browsing mode or with strict browser privacy settings where localStorage throws exceptions.

    Also fixed a few UI issues: the level selector and editor dialogs now have proper heights, the canvas centers correctly in the viewport, and the win animation state resets properly between levels.

  • v0.9 - Drag and Drop Editor

    Major editor improvements today. Added drag and drop support for repositioning players and goals - much more intuitive than the previous click-to-place workflow. You can now grab any node or goal and drag it to a new position on the grid.

    Implemented a “move cells” feature that lets you shift chunks of the level around, which is super helpful when you need to recenter a puzzle or make room for new elements. Also added query string support so you can link directly to edit mode with ?edit=true.

    The level selector now shows completion progress with visual indicators. Fixed several bugs including issues with goal rendering and editor state management. Added a bunch of new levels across different difficulties including “Radio Masts”, “Hooks”, and “Lids”.

  • v0.8 - Delete Level Feature

    Added the ability to delete custom levels from the editor. The delete button only appears for user-created levels, not the built-in ones - don’t want anyone accidentally wiping out the tutorial levels.

    Fixed a bug where levels would appear twice after being added to the source code - the localStorage version was conflicting with the hardcoded one. Also disabled fullscreen mode when the game is embedded on atqu.in to prevent layout issues.

  • v0.7.1 - Level File Organization

    Extracted all the level definitions from the monolithic levels.ts into separate files organized by difficulty: tutorials.ts, easy.ts, medium.ts, hard.ts, and veryHard.ts. This makes it much easier to find and edit specific levels without scrolling through 500+ lines.

    Added several new puzzles including “Creeping” and a few more medium and hard levels to round out the collection.

  • v0.7 - Analytics and CI/CD Pipeline

    Set up Google Analytics to track how players interact with the game. The Analytics.ts module wraps screen view tracking for Editor, Level Select, and Game screens, plus events for game wins (including level ID and completion time), restarts, and editor actions.

    Also built out a CI/CD pipeline using GitHub Actions. On push to main, it builds the project and syncs the dist folder to an S3 bucket, then purges the Cloudflare cache so changes go live immediately. Took a few commits to get the workflow syntax right but it’s working now.

  • v0.6 - Clipboard Support and Loading Screen

    Added a useCopyToClipboard hook that wraps the clipboard API with status feedback - it shows “Copied!” or “Failed to copy” messages that auto-dismiss after a timeout. The export level dialog now uses this to let players copy level JSON directly to their clipboard instead of manually selecting and copying text.

    Also embedded a loading spinner directly in the HTML so there’s visual feedback while the JavaScript bundle loads. Fixed some canvas scaling issues and added a menu toggle shortcut for quicker access during gameplay.

  • v0.5.1 - Level State Refactoring

    Refactored how level state is managed to separate concerns better. The editor now has cleaner separation between runtime state and saved level data, which makes it easier to add features like “New (Copy)” that duplicates an existing level as a starting point.

    Fixed a bug in edit mode and changed the localStorage key for completed levels to avoid conflicts. Also added two new puzzle levels: “Pockets” and “Rolly”.

  • v0.5 - Level Editor Implementation

    Big feature day - built out a proper level editor. The LevelEditor component provides buttons for export, import, creating new levels, and saving/loading player positions. I also added a placement mode system so you can click on the grid to place different cell types like walls and goals.

    Added a bunch of tutorial levels to help new players learn the mechanics, plus a new “ladders” level. The editor now supports placing red goals and the whole Edit tab in the level menu is functional. This was done on a separate branch and merged back to main once it was working.

  • v0.4 - Level Completion Tracking

    Added level completion tracking using localStorage. When you finish a level, the game now records the completion date and how long it took you using Luxon for time calculations. This sets up the foundation for showing completion stats and possibly a leaderboard later.

    I also built a LevelMenu component with tabbed navigation for switching between Play and Edit modes. The level selector now groups levels and shows completion status with checkmarks. Keyboard handling got some fixes too - making sure inputs don’t interfere with gameplay when dialogs are open.

  • v0.3 - Level Selector Dialog

    Added a proper level selector dialog using MUI’s Dialog and Chip components. When you complete a level, the selector automatically pops up so you can pick the next challenge. Completed levels show with a filled chip style while unselected ones remain outlined.

    Fixed a few bugs along the way: player spawn positions weren’t calculating correctly, wall goals had rendering issues, and users could accidentally delete goal cells in the level editor. Now goal cells are protected from deletion to prevent breaking levels mid-edit.

  • v0.2.1 - Constants Extraction and Level Migration

    Quick refactoring session. I extracted magic numbers like PLAYER_SIZE, GRID_RESOLUTION, and BACKGROUND_COLOR into a dedicated Constants.ts file so they’re easier to tweak and reuse across the codebase.

    Also added a level migration system that automatically pads smaller levels with empty cells when the game grid size changes. This was needed because I bumped the grid width from 18 to 19 columns, and existing levels needed to gracefully handle the size difference without breaking.

  • v0.2 - Win Condition and Animation

    Big day of progress on the game. I implemented win condition detection - the game now checks when all players have reached their matching goal positions. Once a win is detected, a satisfying animation plays using GSAP where the players slide to the center of their goals and squish down into nothing.

    I added several new levels including an “EasyMode” tutorial level and refactored the level system to use unique IDs. The import/export code got extracted into separate importLevel.ts and validateLevel.ts modules to keep things tidy.

    Also added a coordinate toggle in the debug GUI that overlays x,y positions on the grid cells - super helpful for designing new levels and debugging player positioning issues.

  • v0.1 - Slippery Boxes Initial Setup

    Started a new puzzle game project called Slippery Boxes using PixiJS and React with Vite. The game features a platformer-style grid where players navigate to goal positions, with support for multiple “frozen” players that need to reach their own goals.

    I built out a level editor using react-dat-gui for tweaking game parameters in real-time - things like grid visibility, player positions, and level dimensions. The editor stores level progress in localStorage and lets you switch between different levels on the fly.

    Later in the day I added level import/export functionality with schema validation using Yup. Players can now copy level data as JSON and share it with others, or paste in level data from elsewhere. The validation ensures imported levels have the correct structure before loading them into the game.