Welcome to Pulp, a friendly tool for making tiny but visually and narratively rich games for Playdate. Pulp has a few parts:
- An Editor, where you create your game in the browser
- A Web Player, where you can preview the game in the browser
- A Playdate game that plays on the hardware
There are two ways to make games with Pulp. The easiest is using the default, simple behaviors of Sprites, Items, and Exits. For example: when a player starts your game, it will say (print onscreen) the name of the game. When the player bumps into a Sprite or walks over an Item it can say something. Exits can connect one room to another or say a parting message before ending the game.
For the more adventurous there’s PulpScript, a terse but powerful scripting language that gives you more control over how the player and your game interact. You can learn more about that in the PulpScript documentation.
Finally, at the end of this document you’ll find a list of editor key commands and a few tips for publishing your Pulp game.
The Pulp editor has six modes:
Regardless of how you will approach making your game, you’ll start in Game mode. Under Games, click the New button and enter a filename for your game. From there you can change your game’s display name, author, version, and build number; add some introductory text; choose a background color; or jump right into editing PulpScript.
Your next stop is Font mode. If you expect your game to have a lot of text, you might want to change from the default full-width font to the half-width version . You can customize or completely redraw the font, individual characters, and UI tiles.
You’ll probably spend most of your time in Room mode. Here you can create the rooms for your game. Each room is composed of tiles. This is also where you create tiles! There are four types of tiles:
- Player. The character or object the player controls; there’s only one of these in the game.
- Sprite. Anything interactive, like a door, a button, or another character. (If a tile is solid, the player can’t pass through it. Sprites are always solid.)
- Item. Something the player can collect. (Items are never solid and disappear from the room when collected, replaced by the tile chosen as the game’s background color.)
- World. The floor, walls, furniture etc. that make up the game’s world. (World tiles can be solid or not solid.)
All tiles can have multiple frames for simple animation. The Player, Sprite, and Item tiles support simple or scripted behavior. You can connect rooms or present an ending with Exits.
Then there’s Song mode. Here you can compose music for your game using five different voices: Sine, Square, Sawtooth, Triangle, and Noise. Noodle around with musical typing then draw your notes with a familiar piano roll interface. Split and join parts or drag them between voices to arrange the final composition. The Game and Room modes allow you to start a song looping when the game starts, upon entering a room, or when presenting an ending.
Sound mode is very similar to the Notes section of Song mode. Here you can create individual sound effects to use in your game using one of the same five voices and familiar piano roll interface. The Room mode lets you assign sounds to Items and Sprites that are played when collected or interacted with.
Which brings us to our final mode, Script. While you can create short scripts for individual tiles in Room mode, Script mode provides access to every script in your game in one place and offers a little more breathing room for editing. The main game and individual room scripts can only be edited in Script mode.
Pulp supports a 100-step undo/redo history, and common key commands for those actions, as well as saving. Holding the mouse over most icons and inputs will show a tooltip with the feature name and its keyboard shortcut if available.
Here you can set your game’s Name, Author, Version and Build number, Intro text, Fill tile, and start Looping a song, as well as open existing games and create new ones. Note the Script button in the corner; it will take you to Script mode where you can edit the main game script. You can also choose a room to use as your game’s card in the Playdate launcher and download individual assets collected from all over the Pulp editor.
You can choose between the default “white” and “black” World tiles for your game’s default Fill color. When you create a new room it will be filled with this tile. This tile is also automatically swapped in when collecting an Item tile without a custom
collect event handler declared.
Version and Build
These are important only if you plan to distribute your game to users. The version string can be anything you want; it’s displayed to the user when they view your game in their device’s settings. The build number starts at 1 and should be incremented for each new release. This informs Playdate’s game installation system that the higher-numbered copy should replace the lower-numbered one.
Choose between full-width and half-width fonts . You can clear or invert the entire font and UI tiles. Redraw individual characters or UI tiles. Preview the font with alphanumerics, a familiar pangram, or your own custom text. You can also import and export Pulp format fonts to simplify sharing between projects. (But note that each game only supports a single font which includes the UI tiles.)
The meatiest mode. You’ll probably spend most of your time here, drawing and animating tiles, then using them to layout your rooms. You can toggle the display of the tile and pixel grids and a red overlay for solid tiles. In the room you have selected as your card, you can toggle an overlay showing how the room will be cropped for the card.
Hold shift to activate the eyedropper then click on the room to select the tile under the cursor. Hold alt to activate flood fill then click to fill either the room with the active tile or the tile with the opposite color. Hold command to activate dragging to shift your tile or room around. Tiles can also be inverted, flipped horizontally or vertically, and rotated counter-clockwise.
There are four tile types, each with their own unique use. You can reorder tiles within their Layer and frames within their tile. You can change the type of most tiles, the only exceptions being the two default “white” and “black” World tiles, the default “player” Player tile, and the last remaining Sprite and Item tiles.
The majority of your rooms tiles will be World tiles. A World tile can be solid or allow the Player to pass through. Sprite tiles are always solid. Item tiles can always be passed over.
World tiles do not support simple or scripted behavior. Both Sprites and Items can say something when bumped into or collected or define more advance behavior with PulpScript.
By default, when a Player overlaps an Item tile it will be swapped with the Fill tile and a variable matching the plural form of the tile’s name will be incremented (eg. an Item tile named “dot” will increment a variable named
dots when collected). But once you declare your own
collect event handler for an Item tile you become responsible for tracking the amount collected and swapping out a different tile upon collection.
All types of tiles can have multiple frames. By default all instances of a tile will loop continuously at the specified fps (frames per second), but using PulpScript you can tell specific instances of a tile in a room to play once or set their fps to 0 and control which frame to display manually.
The Player tile is unique. Only the primary Player tile can be placed in a room and only one room which then becomes the starting room. Only Player tiles can contain transparent pixels. Only the primary Player tile can define behavior. Additional Player tiles can be created and swapped in for different animations based on movement direction or context. Unlike other tiles, when swapped, only the Player’s representation is swapped. This way all Player behavior lives in one place, on the primary Player tile.
Exits can connect a single tile in one room to a single tile in another room, connect the edges of two rooms, or display an ending.
Single tile Exit connections are one-way. To connect two rooms to each other, you must place an exit in each room pointing to the other room. First place an exit in the current room, then in the Exits palette to the right, select the room to connect to and place the exit outlet. Then open the connected room and create a reciprocal exit. Related exits and targets should be placed next to each other, not on top of each other. Exits can be placed on solid World tiles and still be interacted with unless covered by a Sprite. This allows you to create door Sprites that require key Items to unlock and clear to access the Exits below.
Edge Exits automatically create a reciprocal exit in the target room. Place the edge exit in the current room, then in the Exits palette to the right, select the room to connect to, and place the exit outlet. That’s it, the rooms now have a two way connection. Despite their name, Edge exits don’t have to be placed at the edge of a room. They can be inset from the edge as much as you like which is useful if you want to have square rooms and use the remaining space for a HUD.
Fin Exits display some text and reload the game when dismissed.
Song & Sound
The two audio modes have a lot of overlap. A little music theory will help here but just like you don’t need to be an illustrator to use the Tile editor, with a little experimentation and practice, you’ll be hammering out little opuses (opera?) in no time.
The middle row of keys on the keyboard (ASDFGHJKL;’) map to the white keys (or naturals) on a musical keyboard, from C4 to F5 by default. Select keys in the row above (WE TYU OP) map to the black keys (or sharps/flats). Z lowers the octave of the musical typing keyboard while X raises it.
Writing about sound is like dancing about houses but we’re doing this.
- Sine wave is probably the smoothest, roundest sound.
- Square wave has a brighter and boxier sound.
- Sawtooth wave is a little buzzy?
- Triangle wave is a nice middleground between sine and square, not too round, not too boxy. Naturally.
- Noise is just noise, perfect for percussion.
Each voice has different characteristics in different octave ranges and at different durations. Experiment until you find a sound you like. Then do it again!
Each voice has a customizable envelope (plus volume) that applies to all notes played by that voice. For the uninitiated, an envelope describes how a note changes over time. Let’s break it down:
- Attack: the time in seconds it takes a note to go from zero to full volume
- Decay: the time in seconds it takes a note to go from full volume to its sustain volume
- Sustain: the volume a note will hold after the attack and decay volume changes and up until it is released
- Release: the time in seconds it takes for a note go from the sustain volume back to zero
A long attack and short decay and release makes notes sound backwards. A long release lets the waveform mingle with subsequent notes simulating reverb and, if the tones are close enough together, can create an unsettling vibrato. The different waveforms naturally have different volumes and that volume can vary depending on the octave. Lower octaves are usually lower volume while higher octaves may be ear piercing at the same volume level. Experimentation is again key to finding unique sounds.
While Sounds are limited to four bars of a single voice, Songs can be up to 32 bars long and make use of all five voices simultaneously. A song can have an intro of arbitrary length that plays once, after which the remaining bars of the song can be looped. Parts can be split, joined, deleted, duplicated, relocated, and even moved between the different voices. Hold shift to select multiple parts in the same Voice. Hold option while dragging to duplicate one or more selected parts. Press the delete key to delete one or more selected parts. Moving the melody to a different voice with a unique envelope is a great way to keep your loops feeling fresh and may inspire other variations.
When creating Tiles you have the pixel grid, when creating Songs or Sound you have the piano roll. In a piano roll rows denote pitch and columns denote the 16th note interval the note starts and ends on. While only an octave and a half is visible, by selecting one or more notes you can change the note, octave, and hold (duration) relative to each note’s current values. When a note jumps to a higher or lower octave than the previous note, the left edge is angled to reflect the direction of the octave change.
You can select multiple notes by holding shift and dragging within the Notes piano roll. You can move one or more by dragging from a selected note. You can also duplicate one or more selected notes by holding option while dragging.
In addition to looping the entire arrangement in the editor, you can also loop just the visible Notes (eg. if you’d rather work on just a few bars at a time).
The script editor is fairly fully featured. It supports PulpScript syntax highlighting, auto-indenting, auto-pairing of most control structures, and snippets for most functions (try pressing tab after typing
tell and experiment to find others).
The PulpScript parser validates your code as you type, highlighting compilation errors below the editor. The editor will not save code that does not compile. If you switch away from a script before fixing its errors, when you return the code will be in its last working state—which may be an empty editor. Take care to address any issues as they arise.
Check out the PulpScript documentation to learn more about PulpScript.
The Pulp editor supports a number of keyboard shortcuts to make editing your game faster.
- Command/Control+S: Saves the game
- Command/Control+Z: Undo
- Command/Control+Shift+Z or Command/Control+Y: Redo
- Command/Control+B: Run your game in the Web Player
- 1…6: Change editing mode (Game, Font, Room…)
- Command/Control+F and Command/Control+? Find
- Command/Control+G or Command/Control+Shift+G Find next or previous
- - and =: Cycle through rooms, songs, sounds, or scripts (Note the dropdown in the top-right corner.)
- Up and Down arrows: Cycle through tile layers
- Left and Right arrows: Cycle through tiles
- [ and ]: Cycle through tile animation frames
- I: Invert the colors of the current tile
- H: Flip the current tile horizontally
- V: Flip the current tile vertically
- R: Rotate the current tile 90° counter-clockwise
- Shift+R: Rotate the current tile 90° clockwise
- Option+R: Create 3 copies of the current tile, each rotated 90° relative to the last
- D: Duplicate the current tile
- Shift+D: Duplicate the current frame
Song and Sound
- Spacebar: Play/pause the current song or sound
- Return: Returns playhead to the beginning of the song or sound
- R: Toggle looped playback in editor
With one or more notes selected:
- Up and Down arrows: Raise or lower pitch of the selected notes, hold Shift to raise or lower their octave
- Left and Right arrows: Offset position of selected notes relative to the beat, hold Shift to reduce or extend the duration
- Shift+R: Toggle looped playback of the visible bars in the Notes editor
- V: Split part at playhead position
- B: Join selected parts
- M: Set loop point at playhead position
With no notes selected:
- Up and Down arrows: Cycle through song voices
With no notes selected:
- Left and Right arrows: Cycle through sound voices
The PulpScript code editor uses Ace which has its own predefined keyboard shortcuts.
- Up/Down/Left/Right arrows: dpad, move player
- S: A Button, confirm
- A: B button, cancel
- Command/Control+B: open the game in the Editor
- Space: toggle execution
- F: enter fullscreen
- Esc: exit fullscreen
- Shift-click on a button that normally requires confirmation to skip the confirmation dialog, eg. deleting a room, tile, frame, etc or importing a game and replacing the currently open one.
- Shift-click on a tile in the room: “sample” the tile; that is, load it up in the tile editor.
- Option/Alt-click in the room: fill the area with the current tile. (A fast way to paint a lot of floor space, for instance.)
- Option/Alt-click in the tile editor: fill the area with the opposite of the current color.
- Command/Control-drag in a room or in the tile editor: move the whole room or tile.
- Shift-click and drag on a Player tile in the Tile editor to erase and add transparency.
- Option/Alt-click in the char editor: fill the area with the opposite of the current color.
- Command/Control-drag in the char/UI editor: move the char, window tile, or cursor.
- Command/Control+Shift-drag in the char/UI editor: move all chars, window tiles, or cursors.
Publishing a Pulp Game
When you download your game as a pdx, it’s just like any other game on the platform except you built it with Pulp instead of with Lua or C. While Pulp allows you to design a card image for your game, Playdate games support additional metadata including different states (and even animation) for the card image, launch sound effects, and a custom wrapping paper pattern. You could create these assets, put them in an empty Lua game and compile them into a pdx with the Playdate SDK and then move the compiled assets from the empty Lua game’s pdx bundle into your Pulp game’s pdx bundle for a little extra polish.
Another thing to consider before publishing, to safeguard against data loss, every Pulp pdx includes a zipped copy of the game’s json data. This can be deleted from the bundle without affecting the game if you don’t want to share your source.
Finally, Pulp (and especially PulpScript) was built with tiny ambitions but nothing is stopping you from dreaming big. If you find you’re pushing Pulp and it can’t keep up you might be able to squeeze out more performance using the third-party Pulp-to-Lua transpiler Pulp Mill.