Unlock the full potential of PICO-8 game development with this comprehensive cheat sheet, your essential guide to mastering the intricacies of this unique fantasy console. From sprite creation to code optimization, this cheat sheet puts a wealth of tips, tricks, and shortcuts at your fingertips, simplifying your creative process. Whether you're a seasoned developer or a hobbyist, this resource is your stepping stone to crafting engaging 8-bit classics.
Basics
Specifications
- Display: 128x128, 16 colors
- Input: 6-Button controllers
- Carts: 32K data enc. PNG files
- Sound: 4-channel, 64 chip blerps
- Code: Lua subset (Max 8192 code tokens)
- CPU: 8MHz, 4M Lua vm insts/sec
- Sprite: 1 bank of 128 8x8 SPR's (+ 128 shared)
- Map: 128x32 Tilemap (+ 128x32 shared)
Controls
Button | P1 | P2 | Pause |
---|---|---|---|
0 | Left Arrow | S | |
1 | Right Arrow | F | |
2 | Up Arrow | E | |
3 | Down Arrow | D | |
4 | Z | LShift / A | |
5 | X | C / V / N / M | P / Enter |
- API:
BTN(i)
,BTN(p)
- Player:
BTN(i,p)
Command Line
- HELP
- SAVE
<FILENAME>.P8
/.PNG
- LOAD
<FILENAME>.P8
- RUN
[PARAM]
- IMPORT
S.PNG
- EXPORT
X.BIN
/X.HTML
- SPLORE
- FOLDER
- MKDIR
<DIR_NAME>
- LS
[DIR]
- CD
- CLS
- INFO
- SHUTDOWN
- REBOOT
- SAVE/LOAD
("@CLIP")
- SAVE
("@URL")
-- P8 EDU URL - EXTCMD
(CMD_STR,[P1],[P2])
Coding
Functions
FUNCTION SUM(A,B)
-- DECLARE
RETURN A+B
-- RETURN VALUE
END
Program Structure
-
INIT()
-- 1X ON STARTUP -
UPDATE()
-- UPDATE @ 30FPS -
UPDATE60()
-- UPDATE @ 60FPS -
_DRAW()
-- 1X/VISIBLE FRAME -
#INCLUDE <FILE_NAME>.LUA
-
#INCLUDE ONETAB.P8:1
-
#INCLUDE ALLTABS.P8
COMMENTS & TYPES
-- THIS IS A COMMENT
--[[ THIS IS A MULTI- LINE COMMENT ]]
O=NIL N=23
-- GLOBAL SCOPE
LOCAL S="TEXT"
-- LOCAL SCOPE
TABLES
T={1,2,3,4}
T={A="X", B=1}
ADD(T,VAL,[I])
DEL(T,VAL)
DEL(T,[I])
PRINT(T[1])
-- 1-BASED#T/COUNT(T,VAL)
ALL(T)
PAIRS(T)
T=PACK(...)
A,B,C=UNPACK(T,[I],[J])
FOREACH(T,F)
IPAIRS(T)
FLOW CONTROL1
Goto
::LABEL::
-- LABEL
GOTO LABEL
-- JUMP
If Then Else
IF (TRUE) CLS()
-- INLINE IF
IF <CONDITION> THEN
-- IF BLOCK
ELSEIF <CONDITION> THEN
-- ELSEIF BLOCK
ELSE
-- ELSE BLOCK
END
While
WHILE <CONDITION> DO
-- WHILE BLOCK
BREAK
-- EXIT LOOP EARLY
END
FLOW CONTROL2
Repeat
REPEAT
-- REPEAT BLOCK
UNTIL <CONDITION>
For
FOR I=1,10 DO
-- COUNT UP
-- (DOWN:FOR I=10,0,-1 DO)
END
FOR V IN ALL(T) DO
-- TABLE/ARRAY
END
FOR K,V IN PAIRS(T) DO
-- TABLE: T[K]=V
END
OPERATORS
+ - * / ^ %
+= -= *= /= ^= %=
< > <= >= == ~=
#LIST "A" .. "B"
AND OR NOT
COLOR PALETTES
PAL(C0, C1, [P])
--P: 0=DRAWPAL(TABLE, [P])
--P: 1=DISP --P: 2=2ND PALPALT(COL, T)
-- TRANS(BOOL)
SCREEN
CAMERA(X, Y)
CLS([COL])
COLOR([COL])
PGET(X, Y)
PSET(X, Y, [COL])
FLIP()
CLIP([X, Y, W, H, CLIP_PREV])
SHAPES
CIRC(X, Y, R, [COL])
CIRCFILL(X, Y, R, [COL])
LINE(X0, Y0, X1, Y1, [COL])
OVAL(X0, Y0, X1, Y1, [COL])
OVALFILL(X0, Y0, X1, Y1, [COL])
RECT(X0, Y0, X1, Y1, [COL])
RECTFILL(X0, Y0, X1, Y1, [COL])
FILLP([MASK])
SPRITES
SPR(N, X, Y, [W, H, FLIP_X, FLIP_Y])
SSPR(SX, SY, SW, SH, DX, DY, [DW, DH, FLIP_X, FLIP_Y])
SGET(X, Y)
SSET(X, Y, [COL])
FGET(N, [F])
FSET(N, [F], V)
MAP
MAP(TILE_X, TILE_Y, [SX, SY], [TILE_W, TILE_H], [LAYERS])
MGET(X, Y)
MSET(X, Y, VAL)
TLINE(X0, Y0, X1, Y1, MX, MY, MDX, [MDY], [LAYERS])
AUDIO + Tracker
Audio
SFX(N, [CH], [OFFSET], [LEN])
MUSIC([N, [FADE, [MASK]]])
TRACKER
--INSTRUMENT --EFFECT
0 Triangle 0 None
1 Tilt.Saw 1 Slide
2 Saw 2 Vibrato
3 Square 3 Drop
4 Pulse 4 Fade In
5 Organ 5 Fade Out
6 Noise 6 Arp Fast
7 Phaser 7 Arp Slow
Math
- Numeric range:
-32768.0
to32767.99
MAX(X, Y)
MIN(X, Y)
MID(X, Y, Z)
FLR(X)
CEIL(X)
COS(X)
SIN(X)
ATAN2(DX, DY)
SQRT(X)
ABS(X)
RND(X)
-- 0 <= N < XSRAND(X)
-- SET RND SEEDSGN(X)
-- -1 OR 1FUNC - OPERATOR
BAND(X, Y)
--&
BOR(X, Y)
--|
BXOR(X, Y)
--^^
BNOT(X)
--~
SHL(X, N)
--<<
SHR(X, N)
-->>
LSHR(X, N)
-->>>
ROTL(X, N)
--<<
ROTR(X, N)
-->>
Strings
S="HELLO"
S=[[HELLO
MULTILINE]]
PRINT(S, [X, Y, COL])
?S, [X, Y, COL]
-- SHORTHAND#S
-- LENGTH"STR="..S
-- CONCAT
CHR(VAL0, VAL1, ...)
ORD(STR, [POS], [LEN])
SPLIT(STR, [SEP], [TO_NUM])
SUB(STR, POS0, [POS1])
TOSTR(VAL, [FLAGS])
TONUM(VAL, [FLAGS])
TYPE(VAL)
Glyphs 1
Glyphs 2
SYSTEM
COROUTINES
C=COCREATE(FUNC)
CORESUME(C, [...])
COSTATUS(C)
YIELD()
CARTRIDGE DATA
-- GAME SAVES
CARTDATA("ID")
DGET(I)
-- 0..63DSET(I, VAL)
SYSTEM FLAGS
POKE(0x5F2D,FLAGS)
-- DEVKIT MODE FLAGS:
0x1 Enable
0x2 Mouse buttons>btn()
0x4 Pointer Lock
POKE(0x5F5C, D)
-- BTNP 1X DELAYPOKE(0x5F5D, D)
-- REPEAT DELAYPOKE(0x5F34,1)
-- INT.FILLPPOKE(0x5F36, 0x8)
-- DRAW SPR 0
RAM MEMORY LAYOUT
0x0
GFX0x1000
GFX2/Map2 (Shared)0x2000
Map0x3000
GFX Flags0x3100
Song0x3200
SFX0x4300
User Data0x5600
Custom Font (If def.)0x5E00
Persistent Cart Data0x5F00
Draw State0x5F40
Hardware State0x5F80
GPIO Pins (128 Bytes)0x6000
Screen Data (8K)0x8000
User Data
MEMORY FUNCTIONS
CSTORE(DEST, SRC, LEN, [FILENAME])
MEMCPY(DEST_ADDR, SRC_ADDR, LEN)
MEMSET(DEST_ADDR, VAL, LEN)
RELOAD(DEST, SRC, LEN, [FILENAME])
POKE(ADDR, VAL1 [, VAL2, ...])
PEEK(ADDR, [N])
-- @ADDRPEEK2(ADDR)
-- %ADDRPOKE2(ADDR, VAL)
PEEK4(ADDR)
-- $ADDRPOKE4(ADDR, VAL)
SERIAL(CH, ADDR, LEN)
SYSTEM & DEBUG
TIME()/T()
ASSERT(CONDITION, [MESSAGE])
PRINTH(STR, [FILE], [O/W], [DESK])
STOP([MESSAGE])
RESUME()
--"."=Frame-by-Frame
TRACE([C], [MESSAGE], [SKIP])
STAT(X)
-- Status of X:
0 Mem Usage |
1 CPU Used |
4 Clipboard |
6 Param str |
7 Curr fps |
30 Keypressed |
31 Key char |
32, 33 Mouse X,Y |
34 Mouse btns |
36 Mouse Wheel |
38, 39 Rel.X,Y move (Req. 0x4) |
46..49 Curr SFX (CH 0..3) |
50..53 Curr Note (CH 0..3) |
54 Patt.Idx |
55 Patt.Played |
56 Patt.Ticks |
57 Music Playing |
80..85 UTC Time (Y,M,D,H,M,S) |
90..95 Local Time |
100 Breadcrumb Label |
110 Frame-by-Frame Mode |
SHORTCUTS
COMMON
ALT+ENTER
: FullscreenCTRL+R
: Reload/RunCTRL+S
: Quick-SaveCTRL+M
: Mute/UnmuteENTER/P
: Pause MenuESC
: Console/EditorCTRL+6
: Save ScreenshotCTRL+7
: Save Label ImageCTRL+8
: Start GIF/VideoCTRL+9
: Save GIF/VideoCTRL+P
: Toggle CPU Meter
CODE EDITOR
CTRL+X,C,V
: Cut, Copy, PasteCTRL+Z,Y
: Undo, RedoCTRL+F
: SearchCTRL+G
: Next ResultCTRL+H
: Next Res(all tabs)CTRL+L
: Jump to Line No.CTRL+A,V
: Jump Start, EndALT+A,V
: Prev, Next Func()CTRL+<,>
: Jump WordCTRL+W,E
: Start, End LineCTRL+D
: Duplicate LineTAB
: Indent SelectionSHIFT+TAB
: Un-indent Sel.CTRL+B
: Un/Comment BlockCTRL+U
: HELP for keywordSHIFT+▲,▼,◄,►,O,X
SPRITE/MAP EDITOR
SPACE
: Pan viewTAB
: FullscreenMousewheel
: ZoomSHIFT+,/.
: Zoom In/OutF,V
: Flip Y,XR
: Rotate▲,▼,◄,►
: MoveS
: Select
DRAW TOOL
CTRL+LMB
: Replace ColRMB
: Grab ColCTRL+G
: Toggle Gridlines
SFX/MUSIC EDITOR
SPACE
: Play/PauseSHIFT+LMB
: Set all notes◄,►
: Modify speed+, -
: Prev/Next Patterna
: Release Loop
Useful Tips + Links
Top 5 PICO-8 Coding Tips
- Keep It Simple: Start with a small project to get familiar with the PICO-8 environment and Lua syntax.
- Optimize Your Tokens: Use short variable names and consider token-saving techniques like using bitwise operations for simple math.
- Use Tables Wisely: Tables are powerful. Use them for everything from data storage to object management.
- Take Advantage of PICO-8 APIs: PICO-8 offers a variety of built-in functions. Learn them well to save time and tokens.
- Iterate and Test: Make small changes and test often to avoid introducing hard-to-track bugs.
Top 5 PICO-8 Game Design Tips
- Design Around Limitations: The constraints of PICO-8 are part of its charm. Embrace them in your game design.
- Focus on Gameplay: Graphics and sound are limited, so prioritize solid gameplay mechanics.
- Prototype Quickly: Get a playable version up as soon as possible and iterate on your design.
- Engage the Community: Share your game with the PICO-8 community for feedback and suggestions.
- Polish: Small details can make a big difference. Polish your game with screen shake, particle effects, and juicy feedback.
Top 5 PICO-8 Links
- PICO-8 Official Website
- PICO-8 Zine - A community-created magazine full of tips and tricks.
- PICO-8 BBS - The official forums for sharing games, tools, and discussions.
- PICO-8 Wiki - A comprehensive resource for all things PICO-8.
- Awesome PICO-8 - A curated list of awesome PICO-8 resources, carts, and tools.