LEARN PICO8 GAMEDEV
Learn PICO-8 Game Development: From Zero to Fantasy Console Dev
Goal: To master game development in the PICO-8 fantasy console. You will learn how to embrace its creative constraints to build and finish fun, tiny games, covering everything from basic movement and graphics to sound, music, and game structure.
Why Learn PICO-8?
In a world of complex game engines and endless asset stores, PICO-8 is a breath of fresh air. It provides a focused, all-in-one environment where the goal is not to get bogged down in technology, but to actually finish a game. Its limitations are its greatest strength, forcing you to focus on the core of what makes a game fun: gameplay, clever design, and charm.
After completing these projects, you will:
- Master the PICO-8 API for drawing, input, sound, and music.
- Understand the fundamentals of game loops, state management, and collision detection.
- Be able to create your own pixel art sprites and tile-based maps.
- Have a portfolio of small, complete, and shareable games.
- Rediscover the joy of making games in a simple, contained, and creative environment.
Core Concept Analysis
(Please see the detailed conceptual overview provided in the previous response for a breakdown of PICO-8’s constraints and the _init, _update, and _draw game loop).
The most important PICO-8 functions you will use constantly are:
- Drawing:
cls(): Clears the screen. Usually the first call in_draw().spr(n, x, y): Draws spritenfrom your sprite sheet at screen position(x, y).map(cx, cy, sx, sy, w, h): Draws a region of your game map onto the screen.rectfill(x0, y0, x1, y1, c): Draws a filled rectangle of colorc.print(str, x, y, c): Prints text on the screen.
- Input:
btn(i): Returnstrueif buttoniis currently held down. (e.g.,btn(0)is left).btnp(i): Returnstrueonly on the frame buttoniis first pressed. This is better for “jump” or “shoot” actions.
- Sound:
sfx(n): Plays the sound effectnyou created in the sound editor.
- Data:
- Everything in Lua is a table. You will use tables for everything: player objects, lists of enemies, particles, etc.
player = {x=64, y=64, health=3}.
- Everything in Lua is a table. You will use tables for everything: player objects, lists of enemies, particles, etc.
Project List
These projects are designed as a step-by-step introduction to PICO-8 game development, with each one building on the concepts of the last. You will need to own a copy of PICO-8 to get started.
Project 1: Pong
- File: LEARN_PICO8_GAMEDEV.md
- Main Programming Language: Lua (PICO-8 dialect)
- Alternative Programming Languages: N/A
- Coolness Level: Level 2: Practical but Forgettable
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 1: Beginner
- Knowledge Area: Game Dev Fundamentals / Input / Collision
- Software or Tool: PICO-8
- Main Book: The PICO-8 Zines (available on the PICO-8 website) and the PICO-8 Wiki are your bibles.
What you’ll build: The original arcade classic. Two paddles, one ball, first to score a few points wins.
Why it teaches PICO-8: This is the “Hello, World!” of game development. It teaches the absolute essentials in the simplest possible context: the game loop, drawing primitive shapes, handling player input, basic movement, and simple collision detection against the screen boundaries.
Core challenges you’ll face:
- Setting up the game state → maps to creating tables for the ball and paddles in
_init() - Drawing the game elements → maps to using
rectfill()for the paddles and ball in_draw() - Moving a paddle with input → maps to checking
btn()for up/down in_update()and changing the paddle’syvalue - Making the ball bounce → maps to checking the ball’s position against screen edges and reversing its velocity
- Handling scoring and resets → maps to detecting when the ball goes off-screen and resetting its position
Key Concepts:
- The Game Loop: The relationship between
_init,_update, and_draw. - State Management: Storing and modifying coordinates in Lua tables.
- Input Handling: The
btn()function. - AABB Collision Detection: Simple Axis-Aligned Bounding Box checks for paddle/ball collision.
Difficulty: Beginner Time estimate: A few hours. Prerequisites: None. This is the place to start.
Real world outcome:
A complete, playable game of Pong. You will have a .p8.png “cartridge” file that you can share with anyone who has PICO-8, or export to a web version.
Implementation Hints:
- In
_init(), create tables for your game objects.player1 = {x=5, y=60, w=4, h=20}.ball = {x=64, y=64, w=4, h=4, dx=1, dy=1}.dxanddyare the velocity. - In
_update(), checkif btn(2) then player1.y -= 1 end. Do this for both players. - Update the ball’s position:
ball.x += ball.dx. - Check for collisions:
if ball.y < 0 or ball.y > 124 then ball.dy = -ball.dy end. - Check for paddle collision by checking if the rectangles of the ball and paddle overlap. If they do, reverse the ball’s
dx.
Learning milestones:
- You have a paddle that moves → You understand input and state.
- The ball moves and bounces off the top and bottom walls → You understand movement and boundary checks.
- The ball bounces off the paddles → You understand basic object collision.
- The game keeps score and resets → You have a complete game loop with win/loss states.
Project 2: Top-Down Shooter (Space Invaders Clone)
- File: LEARN_PICO8_GAMEDEV.md
- Main Programming Language: Lua
- Alternative Programming Languages: N/A
- Coolness Level: Level 3: Genuinely Clever
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 2: Intermediate
- Knowledge Area: Entity Management / Sprites / Sound
- Software or Tool: PICO-8
- Main Book: Check out the “Lazy Devs Academy” tutorials on YouTube for excellent PICO-8 patterns.
What you’ll build: A classic top-down shooter. Your player ship moves left and right at the bottom of the screen and can fire bullets upwards. A grid of enemies moves back and forth at the top, slowly descending.
Why it teaches PICO-8: This project forces you to manage collections of things (enemies, player bullets, enemy bullets). This is the perfect introduction to using Lua tables as lists and learning the common patterns for creating, deleting, and iterating over game objects in PICO-8. It also gets you using the sprite and sound editors.
Core challenges you’ll face:
- Drawing sprites → maps to using the PICO-8 sprite editor and the
spr()function - Managing lists of objects → maps to using tables to store bullets and enemies
- Spawning objects → maps to using
add(bullets, new_bullet)when the player shoots - Deleting objects → maps to using
del(bullets, bullet)when a bullet goes off-screen or hits something - Collision between two groups of objects → maps to looping through all player bullets and all enemies to check for hits
- Creating sound effects → maps to using the
sfx()function and the sound editor
Key Concepts:
- Entity Management: Using tables to manage dynamic collections of objects.
- The
add/del/allpattern: A common and efficient way to manage collections in PICO-8. - Sprite Animation: Simple animation by changing which sprite index is drawn each frame.
- Sound Design: Creating simple “pew” and “boom” sounds.
Difficulty: Intermediate Time estimate: A weekend. Prerequisites: Project 1.
Real world outcome: A fun, playable arcade shooter with graphics and sound.
Implementation Hints:
- Go to the sprite editor (press ESC and click the sprite icon) and draw a player ship, an enemy, and a bullet.
- In
_init(), create your tables:bullets = {},enemies = {}. Populate theenemiestable with a grid of enemy objects. - In
_update(), check for fire button press (btnp(5)). If pressed, create a new bullet table{x=player.x, y=player.y, ...}andadd(bullets, new_bullet). - Use
for b in all(bullets) do ... endto loop through and update all bullets. Inside the loop, check for collisions. If a bullet hits an enemy, delete both the bullet and the enemy. - Use
sfx(0)to play your laser sound andsfx(1)for the explosion sound.
Learning milestones:
- Your player ship is drawn from the sprite sheet and moves → You can use the graphics editor.
- You can fire bullets → You understand how to spawn new game objects dynamically.
- Enemies are destroyed when hit → You understand collision detection between groups and how to delete objects.
- The game has sound effects for shooting and explosions → You have integrated audio into your game.
Project 3: Top-Down Adventure (Zelda-like)
- File: LEARN_PICO8_GAMEDEV.md
- Main Programming Language: Lua
- Alternative Programming Languages: N/A
- Coolness Level: Level 4: Hardcore Tech Flex
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 2: Intermediate
- Knowledge Area: World Maps / Camera Control / Tile-based-logic
- Software or Tool: PICO-8
- Main Book: The PICO-8 Wiki’s section on the Map Editor.
What you’ll build: The start of a top-down adventure game. Your character can walk around a large world that scrolls with the player. The world will be built using PICO-8’s map editor.
Why it teaches PICO-8: This project is all about the map. You will learn how to design a world visually and then use the map() function to draw it. It introduces camera control and the concept of a game world that is larger than a single screen, which is fundamental to many genres.
Core challenges you’ll face:
- Using the map editor → maps to placing sprites from your sprite sheet onto the map grid
- Drawing the map to the screen → maps to calling the
map()function in_draw() - Implementing a scrolling camera → maps to using
camera(x, y)to keep the player centered - Tile-based collision → maps to checking map data to prevent the player from walking through walls
Key Concepts:
- Map Editor: PICO-8’s tool for building game levels.
camera(): The function that controls the screen’s viewpoint.mget(x, y): “Map Get”. A function to get the ID of the sprite at a specific map coordinate. This is used for collision.fget(n)andfset(n, flag, val): “Flag Get/Set”. Getting and setting flags on sprites, used to mark certain tiles as “solid” or “dangerous”.
Difficulty: Intermediate Time estimate: A weekend. Prerequisites: Project 2.
Real world outcome: A character walking around a scrolling world. It feels like the beginning of a real adventure game.
Implementation Hints:
- Draw some basic tiles in your sprite sheet (e.g., grass, wall, water).
- Go to the map editor and “paint” a small world using these tiles.
- In the sprite editor, select your wall tile and toggle its “flag” (e.g., flag 0). This marks all tiles of this type as solid.
- In
_draw(), you’ll callcamera(player.x - 64, player.y - 64)to keep the player in the center of the screen, and thenmap(0,0,0,0,128,32)to draw the whole map. - In
_update(), before you move the player, check the destination. For example, if the player wants to move right:- Calculate the target map coordinate:
future_x = player.x + 1,future_y = player.y. - Get the tile at that location:
tile_id = mget(future_x / 8, future_y / 8). - Check if that tile is solid:
is_solid = fget(tile_id, 0). - Only update
player.xifis_solidisfalse.
- Calculate the target map coordinate:
Learning milestones:
- You have a static map drawn on the screen → You can use the map editor and
map()function. - The player sprite can move around the screen → Basic movement is implemented.
- The camera follows the player, revealing a larger world → You understand
camera(). - The player collides with walls you painted on the map → You understand tile-based collision with
mgetandfget.
Project 4: Celeste-style Platformer
- File: LEARN_PICO8_GAMEDEV.md
- Main Programming Language: Lua
- Alternative Programming Languages: N/A
- Coolness Level: Level 5: Pure Magic (Super Cool)
- Business Potential: 1. The “Resume Gold”
- Difficulty: Level 3: Advanced
- Knowledge Area: Game Physics / Platforming Logic / Level Design
- Software or Tool: PICO-8
- Main Book: “Game Programming Patterns” by Robert Nistrom (for physics concepts).
What you’ll build: A single-screen precision platformer, in the style of Celeste (which was originally a PICO-8 game!). Your character will be able to run, jump, and interact with walls.
Why it teaches PICO-8: This project teaches the “feel” of game development. You’ll implement physics (gravity, friction, acceleration) and fine-tune variables to make the movement feel tight and responsive. It combines the tile-based collision from the adventure game project with more complex movement logic.
Core challenges you’ll face:
- Implementing gravity → maps to adding a value to the player’s vertical velocity each frame
- Implementing jumping → maps to setting a negative vertical velocity when the jump button is pressed and the player is on the ground
- Fine-tuning player physics → maps to tweaking variables for acceleration, friction, and jump height until it feels good
- Writing robust tile-based collision → maps to a collision function that can handle colliding with the floor, ceiling, and walls correctly
Key Concepts:
- Game Feel: The intangible quality that makes a game satisfying to control.
- Physics Engine: A simple one, with velocity, acceleration, and gravity.
- State Machines: Managing player state (e.g.,
standing,jumping,falling).
Difficulty: Advanced Time estimate: 1-2 weeks. Prerequisites: Project 3.
Real world outcome: A playable, challenging platformer level. Getting the jump to feel “just right” is a huge accomplishment.
Implementation Hints:
- Your player object will need more physics properties:
p = {x, y, dx, dy, on_ground=false}.dxanddyare velocities. - In
_update(), apply gravity:p.dy += gravity. - Apply velocity to position:
p.x += p.dx,p.y += p.dy. - After moving, check for collisions with the map tiles. This is the hardest part. You need a function that checks if the player’s bounding box overlaps any solid tiles.
- If a vertical collision with the floor is detected, set
p.yto be on top of the tile, setp.dy = 0, and setp.on_ground = true. - If a horizontal collision with a wall is detected, set
p.xto be next to the wall and setp.dx = 0. - The jump logic in
_update()should look like:if btnp(5) and p.on_ground then p.dy = -jump_power; p.on_ground = false end.
Learning milestones:
- Your character is affected by gravity and falls → You have a basic physics loop.
- Your character can jump and land on platforms → You have implemented vertical collision.
- Your character cannot walk through walls → You have implemented horizontal collision.
- The movement feels responsive and fun → You have spent time tuning your physics variables and have learned the art of game feel.
Summary
| Project | Main Language | Difficulty | Key PICO-8 Concept Taught | |—|—|—|—| | Pong | Lua | Beginner | The Game Loop, Input, Basic Collision | | Top-Down Shooter | Lua | Intermediate | Entity Management, Sprites, Sound | | Top-Down Adventure| Lua | Intermediate | Map Editor, Camera, Tile Collision | | Celeste-style Platformer| Lua | Advanced | Physics, Game Feel, Advanced Collision | (This list gives a solid foundation. From here, you could explore other genres like “Roguelikes” (turn-based logic), “Flappy Bird” (procedural generation), or even non-game “Tools” like a music sequencer.)