Created
September 8, 2022 17:43
-
-
Save rostok/85f3673b696e44e10da7d954d27564b4 to your computer and use it in GitHub Desktop.
source code for dehydrated - a pico8 game under 1kb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pico-8 cartridge // http://www.pico-8.com | |
version 37 | |
__lua__ | |
-- Dehydrated - a Pico1k 2022 jam entry by https://rostok.itch.io/ @von_rostock | |
-- as the original code was heavily compressed here is the unpacked source with a brief description of what's going on | |
D={}E={} -- D E tables hold x and y global position values for wind dust particles, there are 129 dust particles in total | |
K={} -- K L M tables store map data, they are linear with total length of 128x310 it's hard to explain how they are organized | |
-- since tiles are of isometric shape. however basic address is expression is v+310*u with u/v being cell coordinates | |
-- K table hold compacted tile information | |
-- bits 1-4 represent height (value range 0..15), with 0 being water, and 1+ being sand | |
-- 5th bit means tile will be picked random (value 32) or not (for shadow effect darkest/leftmost tile is used) | |
-- 6th bit means water under sand (value 64) | |
-- 7th bit if set indicates tree on a tile | |
L={} -- L table holds tile/sprite number for each cell as row number (0, 64, 128) and sprite number, these are | |
-- calculated only once | |
N={} -- hold general random 0..31 used for trees | |
c=0 -- temp var for cell elevation | |
p=0q=0 -- p q represent player position in global space (or rather screen left right corner) | |
w=~0 -- w is a bit mask used for both marking place with hidden water and revealing it | |
z=0 -- z holds random altitude for cells/tiles used for seismic quake | |
T="T" -- T is used for drawing tool player can find and once obtained being empty | |
m="\^!5f1149♥" -- sets palette on first frame (black, brown, orange, light yellow), notice skipping first byte | |
-- later m is used for final info text | |
for u=0,128do -- initialize all the tiles, apparently hardcoding constants allows for better code compression | |
for v=0,310do -- note that the vertical loop is inner, this is to calculate dunes shadow | |
d=c&15 -- d stores last cell elevation, or the one that has lower v coordinate | |
E[u]=0D[u]=0 -- initialize dust particle x and y to 0 | |
e=0 -- e will store elevation using the quasi Gardner texture result, spanning from approx. -1 to 1 | |
c=(u\16+u\8+rnd())%3+u/128+1 -- pick color for iso cube lower sides, it is color number 1 for left, 2 for right with slight variation | |
-- there will be total of 32 iso cubes with dimensions of 16x32 | |
-- the ones further to right seem a little lighter | |
-- last 8 sprites are water and their side color is irrelevant | |
-- sprites are 16 pixels wide, with top being 4 pixel tall, each tile is approx 24 pixels tall in total | |
if(v%24+abs(u%16-8)<8)c=2+rnd(1+u/310/2) -- change the color for cube top side | |
sset(u,v%24+abs(u%16-8)/2+v\24*32,c+v\72*10.3) -- set pixel in sprite memory, v\72*10.3 will change the colors to blue shades (pico's default 12 and 13) | |
for i=1,4do -- very simple Gardner cloud texture generator with 4 iterations | |
g=4^i*.001e+=.4^i*(sin(g*u*2+sin(g*v)/2)+sin(g*v*2+sin(g*u)/5)) | |
end -- for Gardner texture see Computers Graphics: Principle & Practice 2e, ch 20.8.2 | |
c=1+12*abs(e)*min(1,10*sin(u/128/2)*sin(v/310/2)) | |
-- now c holds value from 1 to 10, this is a elevation of the tile on map | |
-- elevation is damped on the edges with vertival and horizontal sin functions | |
-- note that sin in pico is negative for the first half but multiplying both negative results yields val > 0 | |
if(d<=c)c|=32 -- comparing current elevation with previous one can create semi shadow effect | |
-- shadow is realy simple - it's the first column of tile sprites which are darkest | |
if(rnd()^-1.5>(u-75)^2+(v-160)^2)c|=128 | |
-- this creates trees on the map by setting 7th bit | |
-- cell at 75/160 is the center where most of the trees are located | |
I=v+u*310 -- I holds cell index from u/v coords | |
K[I]=c -- store elecation, random bit, water being hidden and tree information | |
L[I]=rnd(3)\1*64+rnd(c&32) -- store sprite tile number | |
N[I]=rnd(32) -- and general random value for that tile | |
end | |
end -- ok, initialization is complete, to view sprite sheet use memcpy(0x6000,0,8192) | |
::_:: -- main game loop stars here | |
z*=.8 -- z is being damped with every frame | |
z&=3.75 -- and this ensures there is a cut off (without it rnd(z) may yield large values on very low z) | |
g=t()/2%5 -- g will hold growing radius with 10 sec period | |
I=(g*cos(t())+75)\1*310+(g*sin(t())+160)\1 -- calculate cell index I based on radius and angle aroiund 75/160 cell | |
K[I]=K[I]&w|64 -- store it but with w mask | |
-- remember that w is ~0 so it is all ones | |
-- when player finds the water this will become 192 which will flatten the height but leave the trees and water | |
e=(@24396&2)-@24396%2*2 -- read buttons | |
f=@24396\8%2-@24396\4%2 -- e is horizontal direction -2, 0 or 2, -- f is vertical direction -1, 0 or 1 | |
?"\^1" -- flip() | |
p+=e -- adjust player position | |
q+=f | |
for y=0,168,4do -- draw the screen by paring 430 sprites with iso cubes, first line is ommited for performance reasons | |
X=y\8+q\8-p\16+y\4%2 -- this transforms screen location to U,V map coordinates | |
Y=y\8+q\8+p\16 -- X Y wont be changed in horizontal loop | |
for x=0,9do -- we draw sprite from top to bottom overwriting previous ones with higher tiles | |
a=2+rnd(z) -- a is height multiplier for elevation stored in K table, it is 2px minimally and in case z is set it may be more | |
U=Y+x -- U V cell coordinates are calculated | |
V=X-x | |
I=V%310+U%128*310 -- I is cell index trimmed with modulo | |
b=K[I] -- b is value with height and extra bits info | |
if(U!=U%128or V%310!=V)b=1a=1 -- if this cell is outside both the elevation and heigth multiplier are set to 1 - meaning flat earth and no trees | |
g=b&15 -- g is just elevation (leftmost 4 bits) | |
k=L[I]&~31 -- k is sprite index (or row multipied by 64) | |
n=L[I] -- n chooses one of 8 sprites in this row (it will be trimmed later) | |
if(g<1)n+=t()k=192 -- in case elevation is 0 this is water tile, then sprites will change with time and only the last row will be used | |
h=y-a*g-q%8 -- screen y position | |
g=x*16-p%16 -- g temp x position shifted for every second line (y is increased by 4 so y&4 is either 0 or 4) | |
spr(k+(n&14),g-(y&4)*2,h,2,2) -- draws sprite, the horizontal index is trimmed with &14, last bit is forced to 0 so only odd sprites are used | |
if(b>127)g-=N[I]\4for i=0,N[I]\8do line(g,h,g,h-3,0)line(g-3+i%2*6,h-5)h-=4g+=sin(t()/4+N[I])end | |
-- if 7th bit is set draw random swaying tree with branczes | |
end | |
end -- so far so good | |
?T,382-p,879-q,0 -- draws the seismic tool for player to pick up | |
if(p\8==40and q\4==207)T="" -- if player stumbles on it hide it by setting T to "" | |
b=K[(q+36-p/2)\8%310+(q+92+p/2)\8%128*310] -- b is cell elevation value for current player position | |
o=a*(b&15) -- o is a slight upward shift depending on elevation | |
if(o<1)o=-1m="well done" -- and if player is in water (o==0) then shift him down a little and set success notification | |
?"▮\+cd-\b|\#7\^jc7"..m,63,57-o -- draw player head, torso and success message | |
if(o>0)for i=-1,1,2do line(64+i,62-o,64+i+e*i*sin(t()*3),65-o+2*f*i*sin(t()*3))end | |
-- this draws player legs using e,f direction variables and time | |
if(btn(4)and#T<1)z=1 -- check if z is pressed and if player has tool use it by setting z to 1 (quake tiles) | |
if(btn(4)and#T>0)?"\#7\^jc7find my tool" -- if player has no tool show info to make him find one | |
if(b&64<z)?"\#7\^jc7just sand\as000" -- if there is just sand (6th bit not set) play sound and display info | |
if(b&64>64-z)w=192 -- if there is actually water underneath set w to 192 so water will be shown | |
-- this looks strange but if the button is not pressed z is zero and condition will be false | |
?"\f3" -- set color for dust particles | |
J=4+sin(t()/8) -- just a temp var with oscilating value | |
for i=0,128do -- draw dust particles dancing through the wind | |
x=D[i]-p -- D E holds global position so adjust for screen | |
y=E[i]-q | |
r=K[(E[i]%310+D[i]%128*310)\1]&15 -- is is radius for bifurcation based on cell for this particle | |
if(x>127or y%128!=y)E[i]=64+sin(t()/4)*32+q+q%64D[i]=p-r | |
-- once particle is off the screen set its new position on the left edge | |
D[i]+=r/2*cos(y/J/32)+rnd(4) -- twirl and swirl these little pixels to mesmerize the player | |
E[i]+=r/4*sin(x/J/32) -- note that D is pushed right slighltly harder | |
pset(x,y) | |
end | |
goto _ -- game loop ends making player to endlessly seek water on this deserted hell |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pico-8 cartridge // http://www.pico-8.com | |
version 37 | |
__lua__ | |
D={}E={}K={}L={}N={}c=0p=0q=0w=~0z=0T="T"m="\^!5f1149♥"for u=0,128do | |
for v=0,310do | |
d=c&15E[u]=0D[u]=0e=0c=(u\16+u\8+rnd())%3+u/128+1if(v%24+abs(u%16-8)<8)c=2+rnd(1+u/310/2) | |
sset(u,v%24+abs(u%16-8)/2+v\24*32,c+v\72*10.3)for i=1,4do g=4^i*.001e+=.4^i*(sin(g*u*2+sin(g*v)/2)+sin(g*v*2+sin(g*u)/5))end | |
c=1+12*abs(e)*min(1,10*sin(u/128/2)*sin(v/310/2))if(d<=c)c|=32 | |
if(rnd()^-1.5>(u-75)^2+(v-160)^2)c|=128 | |
I=v+u*310K[I]=c | |
L[I]=rnd(3)\1*64+rnd(c&32)N[I]=rnd(32)end | |
end::_::z*=.8z&=3.75g=t()/2%5I=(g*cos(t())+75)\1*310+(g*sin(t())+160)\1K[I]=K[I]&w|64e=(@24396&2)-@24396%2*2f=@24396\8%2-@24396\4%2?"\^1" | |
p+=e | |
q+=f | |
for y=0,168,4do | |
X=y\8+q\8-p\16+y\4%2Y=y\8+q\8+p\16for x=0,9do | |
a=2+rnd(z)U=Y+x | |
V=X-x | |
I=V%310+U%128*310b=K[I]if(U!=U%128or V%310!=V)b=1a=1 | |
g=b&15k=L[I]&~31n=L[I]if(g<1)n+=t()k=192 | |
h=y-a*g-q%8g=x*16-p%16spr(k+(n&14),g-(y&4)*2,h,2,2)if(b>127)g-=N[I]\4for i=0,N[I]\8do line(g,h,g,h-3,0)line(g-3+i%2*6,h-5)h-=4g+=sin(t()/4+N[I])end | |
end | |
end?T,382-p,879-q,0 | |
if(p\8==40and q\4==207)T="" | |
b=K[(q+36-p/2)\8%310+(q+92+p/2)\8%128*310]o=a*(b&15)if(o<1)o=-1m="well done" | |
?"▮\+cd-\b|\#7\^jc7"..m,63,57-o | |
if(o>0)for i=-1,1,2do line(64+i,62-o,64+i+e*i*sin(t()*3),65-o+2*f*i*sin(t()*3))end | |
if(btn(4)and#T<1)z=1 | |
if(btn(4)and#T>0)?"\#7\^jc7find my tool" | |
if(b&64<z)?"\#7\^jc7just sand\as000" | |
if(b&64>64-z)w=192 | |
?"\f3" | |
J=4+sin(t()/8)for i=0,128do | |
x=D[i]-p | |
y=E[i]-q | |
r=K[(E[i]%310+D[i]%128*310)\1]&15if(x>127or y%128!=y)E[i]=64+sin(t()/4)*32+q+q%64D[i]=p-r | |
D[i]+=r/2*cos(y/J/32)+rnd(4)E[i]+=r/4*sin(x/J/32)pset(x,y)end | |
goto _ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment