Here's a Breakout clone that fits in a single tweet (this version is three two characters shorter than the original). Use the mouse to control the paddle. The game will start right after loading/resetting so be ready to catch the ball. The game is made for PICO-8. See below the original and the commented version of the source code and follow me on Twitter to see more similar things.

1
2
3
4
5
b,a={64,99},{.5,-1}poke(24365,1)memset(0,153,9215)::_::for z=0,5 do
cls()map()rect(0,0,127,128)p=stat(32)rect(p-8,126,p+8,127)i=z%2+1y=b[i]
b[i]+=a[i]if(pget(b[1],b[2])>0)mset(b[1]/8,b[2]/8,0)a[i]*=-1 b[i],a[i-1]=y,b[2]>119 and(b[1]-p)/8 or a[1]
end
pset(b[1],b[2])flip()goto _

And here is the annotated version:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
-- set up ball position (b) and velocity vector (a)
-- start game with the ball moving up-right
b,a={64,99},{.5,-1}
-- enable mouse controls
poke(24365,1)
-- fill sprite data and the top part of the map with 153
-- the sprite data starts at address 0 and the map is right
-- after it. this makes all the sprites orange (one byte encodes
-- two pixels in a sprite, 153 -> 0x99 in hex -> 9 is the index
-- for the orange color) and the map is filled with tile 153. as
-- long as the map has nonzero tiles this will work as all the
-- sprites/tiles are now full orange.
memset(0,153,9215)
-- loop label for game logic start
::_::
-- loop six times per displayed frame so the gameplay is faster
-- this needs to be a number divisible by two (see below why)
-- the real multiplier for speed is actually three (see below)
for z=0,5 do
  cls()
  -- just draw the whole map - only the top part was filled above
  map()
  -- draw playfield borders
  rect(0,0,127,128)
  -- take paddle positio (p) n from mouse x coordinate
  p=stat(32)
  -- draw 16 pixel wide paddle at paddle position on bottom of the
  -- screen
  rect(p-8,126,p+8,127)
  -- build an index counter (i) from the frame loop counter (z)
  -- the index counter can now be used to access both of the ball
  -- position and velocity components (x and y, 1 and 2) with the
  -- same code -- it first moves the ball horizontally and then
  -- vertically on the next frame loop. effectively there is no
  -- diagonal movement (it does look like that, though)
  i=z%2+1
  -- store the previous value of the current position component
  y=b[i]
  -- move ball along the current axis using the velocity vector
  b[i]+=a[i]
  -- check for collision (pixel value under the ball is non-zero)
  if pget(b[1],b[2])>0 then
    -- the if-statement uses a pico8 preprocessor shorthand that
    -- allows for shorter code. here it is written using the standard
    -- if-then-end structure instead of the if(x) structure

    -- zero the map tile under the ball (each tile is 8x8 so we
    -- need to divide the ball coordinate by 8 to access the correct
    -- tile)
    mset(b[1]/8,b[2]/8,0)
    -- the grouped assignments are written in long form here.
    -- put the stored previous value back in the coordinate (the ball
    -- hit something so move it back outside whatever it hit)
    b[i]=y
    -- reverse the velocity component -- bounce! note that this could
    -- also be written like a[i]*=-1 (a[i] = -1 * a[i]) but this can't
    -- be done
    a[i]=-a[i]
    -- this is sneaky: the [i-1] is used to access the x component
    -- of the velocity vector (a) when we are processing the y
    -- component (i == 2, i-1 == 1): it will set index zero when
    -- processing x (i == 1, i-1 == 0) but that is never used. this
    -- sets the x component of the velocity vector based on the
    -- paddle position. the more to the left of the paddle hits, the
    -- more left motion the velocity will have and vice versa.
    -- if the position y component (b[2]) is over 119 (we know all
    -- hits will be a hit with the paddle instead of the top
    -- wall/bricks) -- otherwise it just reassigns the original
    -- value (a[1] == velocity x).
    --
    -- this could be written as follows (but it's two chars longer):
    --
    -- if b[2]>119 then
    --  a[i-1]=(b[1]-p)/8
    -- end
    a[i-1]=b[2]>119 and(b[1]-p)/8 or a[1]
    -- end of collision logic
  end
  -- end of frame loop
end
-- draw the ball at the ball position
pset(b[1],b[2])
-- flip the frame
flip()
-- loop to beginning of game logic
goto _
Updated 15 days ago
StatusReleased
PlatformsHTML5
Authorkometbomb
GenreAction
Made withPICO-8
TagsBreakout, PICO-8, tweetjam
LicenseMIT License
Average sessionA few seconds
InputsMouse
AccessibilityColor-blind friendly, Textless

Leave a comment

Log in with itch.io to leave a comment.