diff --git a/Ideas.md b/Ideas.md new file mode 100644 index 0000000..b9641a7 --- /dev/null +++ b/Ideas.md @@ -0,0 +1,207 @@ +# Ideas + +## Table of Contents + +* [File Formats](#file-formats) +* [Text Console](#text-console) +* [Doodads](#doodads) + +# File Formats + +* The file formats should eventually have a **Protocol Buffers** binary + representation before we go live. JSON support shall remain, but the + production application will not _write_ JSON files, only read them. + (This way we can ship drawings in the git repo as text files). + +## Common Drawing Files + +* A common base format should be shared between Levels and Doodads. You should + be able to use the Editor mode and draw a map *or* draw a doodad like a + button. The drawing data should be a common structure between Level and + Doodad files. +* The drawing is separated between a **Palette** and the **Pixels** + themselves. The Pixels reference the Palette values and their X,Y + coordinate. +* The _color_ and the _behavior_ of the palette are decoupled. + * In the base game, all the solid lines you draw may be black and red + lines are fire, but these aren't hard and fast rules. You could hack a + custom map file that makes black lines fire and red lines water if + you wanted. + * The Palette in the map file stores the attributes and colors of each + distinct type of pixel used in the map. Here it says "color 0 is + black and is solid", "color 1 is red and is fire and is not solid", + etc. + * A mod tool could be written to produce a full-color pixel art level + that still behaves and follows the normal rules of the Doodle game + with regards to geometry and collisions. +* Ideas for pixel attributes: + * Brush: what shape brush to draw the pixel with. + * Solid: can't collide with other solid pixels. + * Fire: applies fire damage to doodads that intersect with it. + * Water: If a doodad passes through a blue pixel, they toggle their + underwater physics. This way pools can be entered from ANY side (top, + bottom, sides) and the physics should toggle on and off. + * Slippery: when a doodad is standing on a slippery pixel, do some extra + checks to find a slope and slide the doodad down it. Makes the pixels + act like ice. +* Standard palette: + * The base game's map editor will tend toward hand-drawn style, at least + at first. + * Black lines are solid. + * Dashed black lines are slippery. + * Red lines are fire. + * Blue lines are water. + * Light grey lines are decoration (non solid, background geometry) + * May make it possible to choose arbitrary colors separately from the + type of pixel. A palette manager UX would be great. + +## Level Files + +* In the level file, store the `pixelHistory` as the definitive source + of pixels rather than the grid of pixels. Let the grid be populated when + the level is being inflated. The grid should have `json:"-"` so it doesn't + serialize to the JSON. + * This makes it possible to animate levels as they load -- by + fast-tracing the original lines that the mapper drew, watching them draw + the map before you play it. + * Makes the file _slightly_ lighter weight because a lot of lines will have + delta positions in the pixelHistory so we don't need to store the middle + pixels. +* It should have space to store copies of any custom Doodads that the user + wants to export with the level file itself, for easy sharing. +* It should have space to store a custom background image. + +# Text Console + +* Create a rudimentary dev console for entering text commands in-game. It + will be helpful until we get a proper UI developed. + * The `~` key would open the console. + * Draw the console on the bottom of the screen. Show maybe 6 lines of + output history (a `[]string` slice) and the command prompt on the + bottom. +* Ideas for console commands: + * `save ` to save the drawing to disk. + * `open ` + * `clear` to clear the drawing. +* Make the console scriptable so it can be used as a prompt, in the mean + time before we get a UI. + * Example: the key binding `Ctrl-S` would be used to save the current + drawing, and we want to ask the user for a file name. There is no UI + toolkit yet to draw a popup window or anything. + * It could be like `console.Prompt("Filename:")` and it would force open + the text console (if it wasn't already open) and the command prompt would + have that question... and have a callback command to run, like + `save ` using their answer. + +# Doodads + +Doodads will be the draggable, droppable, scriptable assets that make the +mazes interactive. + +* They'll need to store multiple frames, for animations or varying states. + Example: door opening, button being pressed, switch toggled on or off. +* They'll need a scripting engine to make them interactive. Authoring the + scripts can be done externally of the game itself. +* The built-in doodads should be scripted the same way as custom doodads, + dogfooding the system. +* Custom doodads will be allowed to bundle with a level file for easy + shipping. + * Installing new doodads from a level file could be possible too. +* Doodads within a level file all have a unique ID, probably just an + integer. Could be just their array index even. + +Some ideas for doodad attributes: + +* Name (string) +* Frames (drawings, like levels) + +Doodad instances in level files would have these attributes: + +* ID (int) +* X,Y coordinates +* Target (optional int; doodad ID): + * For buttons and switches and things. The target would be another + doodad that can be interacted with. + * Self-contained doodads, like trapdoors, won't have a Target. +* Powered (bool) + * Default `false` and most things won't care. + * A Button would be default `false` until pressed, then it's `true` + * A Switch is `true` if On or `false` if Off + * A Door is `true` if Open and `false` if Closed + * So when a switch is turned on and it opens a door by pushing a `true` + state to the door... this is the underlying system. + +## Scripting + +* Probably use Otto for a pure Go JavaScript runtime, to avoid a whole world + of hurt. +* Be able to register basic event callbacks like: + * On load (to initialize any state if needed) + * On visible (for when we support scrolling levels) + * On collision with another doodad or the player character + * On interaction (player hits a "Use" button, as if to toggle a switch) +* Doodads should be able to pass each other messages by ID. + * Example: a Button should be able to tell a Door to open because the + button has been pressed by another doodad or the player character. + +Some ideas for API features that should be available to scripts: + +* Change the direction and strength of gravity (i.e. Antigravity Boots). +* Teleport the player doodad to an absolute or relative coordinate. +* Summon additional doodads at some coordinate. +* Add and remove items from the player's inventory. + +## Ideas for Doodads + +Some specific ideas for doodads that should be in the maze game, and what +sorts of scripting features they might need: + +* Items (class) + * A class of doodad that is "picked up" when touched by the player + character and placed into their inventory. + * Scriptable hooks can still apply, callback ideas: + * On enter inventory + * On leave inventory + * Example: Gravity Boots could be scripted to invert the global gravity + when the item enters your inventory until you drop the boots. + * Some attribute ideas: + * Undroppable: player can't remove the item from their inventory. + * Item ideas to start with: + * Keys to open doors (these would just be mere collectables) + * Antigravity Boots (scripted to mess with gravity) +* Buttons + * At least 2 frames: pressed and not pressed. + * Needs to associate with a door or something that works with buttons. + * On collision with a doodad or player character: send a notification to + its associated Door that it should open. (`Powered: true`) + * When collision ends, button and its door become unpowered. +* Sticky Buttons + * Buttons that only become `true` once. They stick "On" when activated + for the first time. + * Once pressed they can't be unpressed. However, there's nothing stopping + a switch from targeting a sticky button, so when the switch is turned off + the sticky button turns off too. +* Switches + * Like a button. On=`true` and Off=`false` + * 2 frames for the On and Off position. + * On "use" by the player, toggle the switch and notify the door of the new + boolean value. + * It would invert the value of the target, not just make it match the + value of the switch. i.e. if the switch is `false` and the door is + already open (`true`), making the switch `true` closes the door. +* Powered Doors + * Can only be opened when powered. + * 2 frames of animation: open and closed. + * A switch or button must target the door as a way to open/close it. +* Locked Doors + * Requires a key item to be in the player's inventory. + * On collision with the player: if they have the key, the door toggles to + its `true` powered state (open) and stays open. + * The door takes the key from the player's inventory when opened. +* Trapdoors + * One-way doors that close behind you. + * Can be placed horizontally: a doodad falling from above should cause + the door to swing open (provided it's a downward-only door) and fall + through. + * Can be placed vertically and acts as a one-way door. + * Needs several frames of animation.