Code Examples

Learn by example — from Hello World to full games.

1. Hello World & Moving Text

Beginner

The simplest game: move a text label around the screen with the arrow keys. Demonstrates cls, print, btn.

lua
function _init()
  x, y = 64, 120
end

function _update()
  if btn(0) then x -= 2 end
  if btn(1) then x += 2 end
  if btn(2) then y -= 2 end
  if btn(3) then y += 2 end

  -- clamp to screen
  x = mid(0, x, 190)
  y = mid(0, y, 248)
end

function _draw()
  cls(1)
  print("HELLO PLUTO-8!", x, y, 7)
  print("USE ARROWS", 88, 240, 6)
end

2. Bouncing Ball

Beginner

A ball bouncing off all four walls with velocity. Demonstrates physics-style movement, boundary collision, and circfill.

lua
function _init()
  x, y   = 128, 128
  vx, vy = 2, 1.5
  r      = 6        -- ball radius
  col    = 10       -- yellow
end

function _update()
  x += vx
  y += vy

  -- bounce off left/right walls
  if x < r then
    x = r; vx = abs(vx)
    sfx(0)
  elseif x > 256-r then
    x = 256-r; vx = -abs(vx)
    sfx(0)
  end

  -- bounce off top/bottom walls
  if y < r then
    y = r; vy = abs(vy)
    sfx(0)
  elseif y > 256-r then
    y = 256-r; vy = -abs(vy)
    sfx(0)
  end

  -- change color on bounce
  col = flr(rnd(14)) + 1
end

function _draw()
  cls(0)
  -- trail effect: draw faded circles
  circ(x-vx*3, y-vy*3, r, 5)
  circ(x-vx*2, y-vy*2, r, 5)
  circfill(x, y, r, col)
end

3. Parallax Starfield

Intermediate

60 stars split into three depth layers, each scrolling at a different speed. Demonstrates table initialisation, modular arithmetic for wrapping, and layered rendering.

lua
function _init()
  stars = {}
  for i = 1, 60 do
    add(stars, {
      x     = rnd(256),
      y     = rnd(256),
      layer = flr(rnd(3)),   -- 0=far 1=mid 2=near
    })
  end
end

local speeds = {0.2, 0.6, 1.5}   -- pixels/frame per layer
local colors = {5,   6,   7  }   -- dark→light
local sizes  = {0,   0,   1  }   -- radius (0=pixel, 1=small circ)

function _update()
  for s in all(stars) do
    s.y += speeds[s.layer + 1]
    if s.y > 256 then
      s.y = 0
      s.x = rnd(256)
    end
  end
end

function _draw()
  cls(0)
  for s in all(stars) do
    local l = s.layer + 1
    if sizes[l] == 0 then
      pset(flr(s.x), flr(s.y), colors[l])
    else
      circfill(flr(s.x), flr(s.y), sizes[l], colors[l])
    end
  end
  print("PLUTO-8", 96, 120, 7)
  print("PARALLAX DEMO", 72, 132, 6)
end

4. Snake Game

Intermediate

Classic Snake with growing tail, food spawning, wall and self-collision. Shows a state machine (title / playing / game-over), grid-based movement and table manipulation.

lua
local GRID = 8       -- tile size in pixels
local W, H = 32, 32  -- grid dimensions

function _init()
  state = "title"
end

function start_game()
  snake  = {{x=16, y=16}}
  dir    = {x=1, y=0}
  next_d = {x=1, y=0}
  score  = 0
  timer  = 0
  spawn_food()
  state  = "play"
end

function spawn_food()
  food = {x=flr(rnd(W)), y=flr(rnd(H))}
end

function _update()
  if state == "title" then
    if btnp(4) then start_game() end
    return
  end
  if state == "over" then
    if btnp(4) then state = "title" end
    return
  end

  -- read input (don't allow 180° reverse)
  if btn(0) and dir.x ~= 1  then next_d={x=-1,y=0} end
  if btn(1) and dir.x ~= -1 then next_d={x=1,y=0}  end
  if btn(2) and dir.y ~= 1  then next_d={x=0,y=-1} end
  if btn(3) and dir.y ~= -1 then next_d={x=0,y=1}  end

  timer += 1
  if timer < 6 then return end  -- move every 6 ticks (5 moves/sec)
  timer = 0
  dir = next_d

  -- new head position
  local head = snake[1]
  local nx = (head.x + dir.x) % W
  local ny = (head.y + dir.y) % H

  -- check self-collision
  for s in all(snake) do
    if s.x == nx and s.y == ny then
      sfx(1); state = "over"; return
    end
  end

  -- grow or trim tail
  local ate = (nx == food.x and ny == food.y)
  table.insert(snake, 1, {x=nx, y=ny})
  if ate then
    score += 10; sfx(0); spawn_food()
  else
    table.remove(snake)
  end
end

function _draw()
  cls(0)
  if state == "title" then
    print("SNAKE",      104, 110, 11)
    print("PRESS Z",    96,  130, 7)
    return
  end

  -- food
  rectfill(food.x*GRID, food.y*GRID, GRID, GRID, 8)

  -- snake body
  for i, s in ipairs(snake) do
    local c = (i == 1) and 11 or 3
    rectfill(s.x*GRID+1, s.y*GRID+1, GRID-2, GRID-2, c)
  end

  -- HUD
  print("SCORE:"..score, 2, 2, 7)

  if state == "over" then
    rectfill(70, 108, 116, 40, 0)
    rect(    70, 108, 116, 40, 8)
    print("GAME OVER", 88,  118, 8)
    print("PRESS Z",  96,  132, 7)
  end
end

5. Sprite Animation & Flip

Beginner

Walk-cycle animation using sprite frames, with horizontal flipping for left/right direction. Shows how to combine movement, timers and spr() flags.

lua
-- Assumes sprites 1-4 are a 4-frame walk cycle
local WALK_FRAMES = {1, 2, 3, 4}
local ANIM_SPEED  = 6     -- ticks per frame

function _init()
  px, py     = 120, 120
  facing     = 1          -- 1=right, -1=left
  anim_t     = 0
  anim_frame = 1
  moving     = false
end

function _update()
  moving = false

  if btn(0) then
    px -= 2; facing = -1; moving = true
  end
  if btn(1) then
    px += 2; facing =  1; moving = true
  end
  if btn(2) then py -= 2; moving = true end
  if btn(3) then py += 2; moving = true end

  -- advance animation only when moving
  if moving then
    anim_t += 1
    if anim_t >= ANIM_SPEED then
      anim_t = 0
      anim_frame = (anim_frame % #WALK_FRAMES) + 1
    end
  else
    anim_frame = 1   -- idle = frame 1
    anim_t = 0
  end
end

function _draw()
  cls(3)
  -- ground
  rectfill(0, 200, 256, 56, 4)

  local sprite_n = WALK_FRAMES[anim_frame]
  local flip_x   = (facing == -1)   -- flip left

  spr(sprite_n, px, py, 1, 1, flip_x)

  print("MOVE: ARROWS", 74, 8, 7)
end