Skip to content

Instantly share code, notes, and snippets.

@Powersaurus
Created September 21, 2022 22:19
Show Gist options
  • Save Powersaurus/3a30cf19134327742804f5ca1239674f to your computer and use it in GitHub Desktop.
Save Powersaurus/3a30cf19134327742804f5ca1239674f to your computer and use it in GitHub Desktop.
BEARS STOLE YOUR PICNIC, but with comments
-- set nearly my "usual" palette, ready for drawing the sprites
cls()pal(split"1,141,3,4,5,6,7,137,9,10,138,12,13,131,133",1)
-- draw 4 trees, 4 items and a bear. A lot of overdraw here, the 150
-- is chosen because it is a number I duplicate later to appease
-- the compressor, and because it ensures scattering foliage
-- gives the impression of a bushy tree
for i=0,150do
-- draw the trunks using a mix of symbols and p8scii control codes
-- every sprite is created by using the ? print shorthand to draw
-- to the screen
?"\^t\f5✽\-6\ff ✽\b\^w\f1\|e𝘷",rnd(i%5)+i%4*32+8,24+i/9
-- vertically scatter the foliage in a triangular pattern
-- as y increases, the x range increases too
y=rnd(26)
?"\^t\f3★\-b★\b\fe░\-9\f1ˇ",i%4*32+rnd(y)+6-y/4,y
-- p8scii for the items. Each item uses two symbols laid on top of
-- each other to add 'detail', the bear is a bit more complicated.
-- Moving the cursor is a pain
?"\f3●\b\|f\fb●\b /\f8█\b\f9ˇ\fb█\b\f7⧗\f4█\fa\-9▒\f4\-a█\f1█1\b\b\b\f4m🐱",1,54
end
-- copy screen mem to sprite sheet mem
memcpy(0,0x6000,0x2000)
-- set 'restart' label, used for win and lose conditions and
-- (re)initialise a load of variables
::x::t,h,j,c,n,a,m,l={},8,8,0,0,0,split"apple,crisps,lemonade,sandwich"
-- scatter 80 trees in the 16x16 environment. Every object lives
-- in the t array and has a type, an optional colour, x,y,z coords and
-- a width and height. Some objects have more info
for i=0,80do
add(t,{t=0,c=rnd(3)\1,x=rnd(16),y=160,z=rnd(16),w=23,h=33})
end
-- scatter 80 shrunk trees to act as 'fallen leaves on the ground'
-- note the tiny width+height values
for i=0,80do
add(t,{t=0,c=rnd(3)\1,x=rnd(16),y=-30,z=rnd(16),w=.5,h=.5})
end
-- create borders for the game environment - too uniform, but
-- no space left!
for i=0,16,16do
for v=0,16do
add(t,{t=0,c=rnd(3)\1,x=i,y=160,z=v,w=23,h=33})
add(t,{t=0,c=rnd(3)\1,x=v,y=160,z=i,w=23,h=33})
end
end
-- scatter the 4 collectible objects. These objects have
-- spritesheet info (i = width/height, p = spritesheet x,
-- s = spritesheet y)
for i=0,3do
add(t,{t=1+i,x=1+rnd(14),y=-30,z=1+rnd(14),w=2,h=2,i=8,p=8*i,s=51})
end
-- p8scii to play a sad trombone sound at the start of the
-- game
?"\asfe1.a#0"
-- game loop label and
-- initialising the player's x + z values - this is to save
-- space, only initialised the 'new position variables'.
-- A lot of stuff happens in an odd order in this game for space
-- reasons. It is not update - draw, it is update - draw - update!
::i::x,z=h,j
-- read input, left and right rotation, followed by forward and
-- backwards
if(btn(0))a-=.007
if(btn(1))a+=.007
-- h and j store the new position, and are used to update if the
-- move does not leave the play area
if(btn(2))h,j=x+cos(a)*.05,z+sin(a)*.05
if(btn(3))h,j=x-cos(a)*.05,z-sin(a)*.05
-- if the game is over (c has been set to less than zero)
-- then check if the player pressed x to restart the game - use
-- goto to jump to the initialise step just after the sprite creation
if(btn(5)and c<0)goto x
-- check x and z boundaries for the player's new position. Update
-- each of these values if the move is within the boundaries
if(h<1or h>15)h=x
if(j<1or j>15)j=z
-- clear the screen with the light grey/blue colour for a daytime
-- sky
cls(13)
-- draw the floor in green, followed by some dithering for a
distance effect
fillp()rectfill(0,40,128,128,3)
fillp(0x4010)rectfill(0,83,128,90,83)
-- overlap both the sky and the ground with this dither, works
-- with both
fillp(▒)rectfill(0,32,128,82,5)
fillp(0x5a5a)rectfill(0,56,128,68,19)
-- rotate every object into '3d' space. Note the use of i
-- as the loop variable everywhere - the duplication saves
-- space
for i in all(t)do
u,v=i.x-x,i.z-z i.u,i.v=sin(a)*u-cos(a)*v,cos(a)*u+sin(a)*v
end
-- i love/hate this. Using lua's scoping / heinous name
-- shadowing to save space, since I don't actually need
-- the loop variable from the outer loop. Double i!
-- the loops are repeating a bubble sort for depth
for i=0,3do
for i=1,#t-1do
-- test two items depths from the player
if(t[i].v<=t[i+1].v)t[i],t[i+1]=t[i+1],t[i]
end
end
-- originally this loop was just for drawing objects,
-- but now does several different things
for i in all(t)do
-- bears (t==5) change to a new random direction
-- every 3 seconds
if(i.t==5and c%90==0)i.f=rnd()-.5i.g=rnd()-.5
-- bears move based on their velocity f (x vel) and g (z vel)
if(i.t==5)i.x+=i.f or 0i.z+=i.g or 0
-- check whether the player collided with a bear, and
-- if so, go to the start of the game (x label)
if(i.t==5and abs(i.x-x)<1and abs(i.z-z)<1)goto x
-- check all other object collisions. If it is a collision
-- then remove the object, increase the 'score', set the
-- hud message for which item the player got, and play a little
-- sound effect
if(i.t>0and abs(i.x-x)<1and abs(i.z-z)<1)del(t,i)n+=1l=m[i.t]?"\ace-g"
-- draw objects. This has to handle trees, items and bears, so has
-- a lot of 'this object might not have this value, so we need a
-- default'. i.v is the screen depth value for an object, so objects
-- behind the player/camera
-- the palette for the dark green colour is switched - this is only
-- used for trees, everything
if(i.v>0)pal(3,1+(i.c or 0))sspr(i.p or i.c*32,i.s or 0,i.i or 32,i.i or 48,64+i.u*64/i.v,64-i.y/i.v,i.w*6/i.v,i.h*6/i.v)
end
-- every 3 seconds add a bear at random location
if(c%90==0)add(t,{t=5,x=rnd(16),y=40,z=rnd(16),w=30,h=30,i=12,p=36,s=51})
-- reset the dark green colour for drawing things the next time round
pal(3,3)
-- if any item has been collected, draw the hud message
if(l)?"\f7found "..l
-- if the player finds all 4 items, save the time it took them,
-- set c to a negative number to indicate 'game end' and play a
-- tune by printing some p8scii control codes
if(n==4)n,c=c,-999?"\a..d..d..d..ccc..ddd"
-- title screen for three seconds when the game starts
-- note: the game is running in the background and this causes
-- problems if the player spawns at the same location as the bear
-- game restarts immediately and screen flickers
if(c<90)cls()?"bears stole your picnic",20,60
-- game end screen - shows time player took to win, and a prompt
-- to return to the start of the game. c < 0 == game is over
if(c<0)cls()?"found your picnic\nin "..(n\30).." secs!\npress ❎",20,60
-- increase c, the game timer, flip the screen buffers and then goto
-- the i label. Using i for the label since it is used as a loop
-- variable elsewhere so it is slightly cheaper.
c+=1flip()goto i
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment