Created
September 9, 2024 18:44
-
-
Save rostok/299929640e6ea08ba5e386c76a719d39 to your computer and use it in GitHub Desktop.
heat signature pico1k 2024 jam game source
This file contains hidden or 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 42 | |
__lua__ | |
-- "Heat signature" | |
-- You hide behind the rubble and watch the kid, who listens for drones. Vigilant, focused, and obedient; not curious or joyful like kids used to be. Was it worth it, leaving a broken homeland? The border is close, just one more push. Just avoid the machines. | |
-- | |
-- game by rostok / @von_rostok / rostok.itch.io | |
-- | |
-- O all objects, | |
-- x,y pos | |
-- u,v movement | |
-- r random shift, 2 for characters, 3 and more when dead which is semi progression in blow up animation | |
-- w width | |
-- d half diameter of drone targetting area | |
-- P player O[1] | |
-- Q kid O[2] | |
-- D drawable objects in proper order, up to down | |
-- B border's x, value hardcoded to conserve space | |
-- T table of drone's targets | |
-- L previous frame's T count | |
srand(5) -- initialize random, 5 gives nice map with 3 separating ways, and only one going to the border | |
D={{x=0,y=0}} -- for initialization this will hold relative objects we derive new positions from | |
P={x=46,y=-32,r=2,w=0} -- player | |
Q={x=41,y=-32,r=2,w=2} -- kid | |
O={P,Q} -- all objects | |
L=0 -- last target table | |
while#O<75do -- loop till there are 75 houses, game is oppressive enough | |
o=deli(D,1) -- remove from temp table, and create a new object in the next line, x,y are not far from last one | |
o=add(O,{x=o.x+(20+#O\2)*rnd{2,3},y=o.y+11*rnd{2,3,-2,-3},w=rnd{30,35,40,45},r=rnd()}) -- ,d=64 but if charactes start behind house this can be skipped | |
if(rnd()<.05)add(D,O[#O\4+1]) -- on rare ocasions add extra objects to fork paths | |
add(D,o) -- make path | |
end | |
-- calculate map size and index of rightmost house | |
-- l=9999 r=0 t=0 b=0 rightmost_index=nil for i,o in pairs(O) do l=min(o.x,l) if o.x > r then r=o.x rightmost_index=i end t=min(o.y,t) b=max(o.y,b) end cls() stop(" left:"..l.."\n right:"..r.."\n top:"..t.."\n bottom:"..b.."\n border:"..(r+128).."\n rightmost index:"..(rightmost_index or "none")) | |
-- B=2400 -- border x was hardcoded | |
-- P.x=O[#O].x P.y=O[#O].y-8 Q.x=O[#O].x-5 Q.y=O[#O].y-8 -- check last house before border | |
-- B=2400 P.x=B+10 Q.x=B+20 -- check happy ending | |
for i=1,128do add(O,{x=i*16,y=rnd(-1)>>7,r=-rnd()})end -- add some trees | |
while 1 do -- while compresses better than label/goto | |
---------------------------------- | |
----- SCREEN SNOW AND STATUS ----- | |
---------------------------------- | |
-- if(P.x>B and Q.x>B)do ?"¹a peace & ptsd⁶1⁶c1⁶!5f1033⬅️33?5",P.x-64,P.y-64,7 -- if both passed border print status for happy ending and change palette | |
if(P.x>2400 and Q.x>2400)do ?"¹a peace & ptsd⁶1⁶c1⁶!5f113⬅️33?3",P.x-64,P.y-64 -- if both passed border print status for happy ending and change palette | |
else for i=24576,32767do if(rnd()<.2)poke(i,@i+1)end | |
?"⁶1⁶c1⁶!5f11█🐱░49:" -- otherwise snow screen and set heat signature pal | |
end | |
P.u=@24396\2%2*2-@24396%2*2 -- left/right arrows correspond to -2,2 assigned to u | |
P.v=@24396\8%2-@24396\4%2 -- and so are up/down but -1,1 | |
Q.u=@24396\16%2*sgn(P.x-Q.x-6)*2 -- kid follows player if z is pressed, will stand beside | |
Q.v=@24396\16%2*sgn(P.y-Q.y) | |
D={} -- drawable objetcs | |
T={} -- targets | |
-------------------- | |
---- RENDER MAP ---- | |
-------------------- | |
-- if(btn(4,1)or mapIndex) then | |
-- xi=O[1].x | |
-- xx=O[1].x | |
-- yi=O[1].y | |
-- yx=O[1].y | |
-- for i=2,#O do | |
-- xi=min(xi,O[i].x-256) | |
-- xx=max(xx,O[i].x+256) | |
-- yi=min(yi,O[i].y-256) | |
-- yx=max(yx,O[i].y+256) | |
-- end | |
-- width=xx-xi | |
-- height=yx-yi | |
-- h_blocks=width\128+1 | |
-- v_blocks=height\128+1 | |
-- mapIndex=(mapIndex or -1)+1 | |
-- local current_block_x=mapIndex%h_blocks | |
-- local current_block_y=mapIndex\h_blocks | |
-- d=xi+current_block_x*128 | |
-- e=yi+current_block_y*128 | |
-- savedPx = P.x | |
-- savedPy = P.y | |
-- P.x,P.y = d,e | |
-- end | |
for o in all(O)do | |
if max(abs(o.y-P.y),abs(o.x-P.x))<128do -- first filter stuff outside of screen, 128 instead of 64 as drawing part has movement logic | |
j=1 | |
while j<=#D and o.y>D[j].y do j+=1 end -- sort it by y coord | |
add(D,o,j) -- insert object into D and | |
if(o.r==2)add(T,o) -- visible alive characters are automatically targetted | |
for p in all({P,Q})do | |
if(o.r<1 and o.w and abs(p.x-o.x+p.u)<o.w\2+2 and abs(p.y-o.y)<2)p.u=0 -- simple collisions | |
if(o.r<1 and o.w and abs(p.x-o.x)<o.w\2+2 and abs(p.y-o.y+p.v)<2)p.v=0 -- and simple sliding | |
-- if(o.r<1 and o.w and (abs(p.x-o.x)<o.w\2+2 and abs(p.y-o.y+5)<6) or p.x>B)p.d=66del(T,p) -- hidden behind house or across border, target is nil, diameter is big | |
if(o.r<1 and o.w and (abs(p.x-o.x)<o.w\2+2 and abs(p.y-o.y+5)<6) or p.x>2400)p.d=66del(T,p) -- hidden behind house or across border, target is nil, diameter is big | |
end | |
end | |
end | |
--------------------- | |
------ DRAWING ------ | |
--------------------- | |
srand(5) | |
camera(P.x-64,P.y-64) -- fix on player | |
----------------------- | |
-- GROUND AND BORDER -- | |
----------------------- | |
for i=1,128do | |
?"\"",P.x-64+(rnd(128)-P.x)%128,P.y-64+(i-P.y)%128,2 -- draw some grass | |
-- ?".",B-rnd(64),P.y-64+(i-P.y)%128,5 -- draw the border | |
?".",2400-rnd(64),P.y-64+(i-P.y)%128,5 -- draw the border | |
end | |
-------------------- | |
---- RENDER MAP ---- | |
-------------------- | |
-- if(btn(4,1)or mapIndex) then P.x,P.y = savedPx,savedPy end | |
srand(t()) | |
for x,o in ipairs(D)do -- draw all visible objects | |
if(o.r>2)do -- draw dead characters | |
o.r=min(o.r+1,31) -- character exploded, o.r is a animation progress | |
for i=-8,8 do | |
?rnd{",","."},o.x+o.r/i/4,o.y-3+sin((o.r+i/3)/64)*12-i/o.r,5 -- randomize body parts as dot and comma | |
end | |
?"¹a death & despair",P.x-64,P.y-64 -- sad ending | |
elseif(o.r==2)do -- draw live characters | |
rect(o.x-1,o.y-4,1+o.x,o.y+o.w-9,5) -- body | |
rect(o.x,o.y-4,o.x,o.y+o.w-11) -- head and spine | |
for i=1,-1,-2do line(i+o.x,o.y-3,i+o.x+o.u*i*sin(t()*3),o.y+o.v*2*i*sin(t()*3))end -- legs | |
o.x+=o.u -- apply movement | |
o.y+=o.v -- if kid is too far he cant be called to follow | |
-- if(rnd()<.5)add(O,{x=o.x+o.y%2*2,y=o.y,r=0}) -- add heat signature for footsteps | |
elseif(o.r<=0)do -- draw trees | |
-- ?"⁶:1010105438109254\n⁶:3810925438101010",o.x-4,o.y-16,3 | |
-- ?"⁶:1010105438101054\n⁶:3810105438101010",o.x-4,o.y-16,3 | |
?"⁶. そp そ\n⁶.p そp ",o.x-4,o.y-16,3 | |
-- draw heat fading footsteps, dropped from the release | |
-- o.r-=1 | |
-- if(o.r<-20)del(O,o) | |
-- ?".",o.x-2,o.y-4,6+o.r/4 | |
else -- draw ruined houses | |
for x=-o.w\2,o.w\2,2do -- step by 2 as this takes some cpu cycles | |
k=16-sin(o.r+x/32+sin(x/8)/16)*6 -- wobbly semi random sine to limit front wall max height | |
-- houses are made of 5px horizontal blocks: wall, window, doors | |
-- each block is defined as up to 3 starting vertical positions 0,5,10 starting from house y | |
-- then and goes typically by 5 pixels or more if this is last segment and roof should be drawn | |
-- door (10..roof) | |
-- window: (0..5) + door | |
-- wall (5..10) + window + door | |
-- so single table {10,0,5} holds starting positions and number of iterations determines type of segment | |
-- however this table can be converted into expression i%3*5 assuming i starts from 2 | |
-- h, below, returns house table index, which is be wall for first/last segment, doors in the middle, and windows otherwise (more or less) | |
-- btw, initially this was a table H={{10},{10,0},{10,0,5}} | |
h=5-(x+o.w\2+1)\5%2-((x+o.w\2+1)\5==o.w\9 and 2 or 1) | |
for i=2,h do | |
-- the min section below also limits top max heigt so houses have gaping holes AND inclined roof at the edges | |
rect(o.x+x,o.y-i%3*5,1+o.x+x,o.y-min(5+i%3*5+i%3\2*min(5,o.w\2-abs(x)),k),3) | |
end | |
if(h>3)?"-",o.x+x,o.y-o.x*o.y%k,2 -- finally, a pseudo random bullet holes only on walls | |
end | |
end | |
end | |
-------------------- | |
---- RENDER MAP ---- | |
-------------------- | |
-- if(btn(4,1)or mapIndex)do | |
-- if(mapIndex>=h_blocks*v_blocks) then | |
-- cls() | |
-- color(7) | |
-- stop("blocks: "..h_blocks.."x"..v_blocks.."\nwidth height:"..width.." "..height .."\n".."bounds:"..xi.." "..yi.." "..xx.." "..yx.."\n") | |
-- else | |
-- mi = tostr(mapIndex) | |
-- if(#mi<4)mi="0"..mi | |
-- if(#mi<4)mi="0"..mi | |
-- if(#mi<4)mi="0"..mi | |
-- extcmd('set_filename','map-'.. mi) | |
-- extcmd('screen') | |
-- end | |
-- end | |
----------------------- | |
----- TARGET RECT ----- | |
----------------------- | |
for o in all(T)do -- for all characters are targetted | |
if(L==1 and #T>1)o.d+=24 -- if a new target is in view the drone is disoriented and has larger diameter for a moment | |
o.d=min(o.d-1.2,66) -- make the targetting diameter smaller, run you fools! | |
rect(o.x-o.d,o.y-5-o.d,o.x+o.d,o.y-5+o.d,8) -- target rectangle | |
-- ?"⁷x0v1i3s0c",0,0 -- play buzzing sound strange slowdown at 3561 -69 | |
?"⁷s000",0,128 -- play buzzing sound strange slowdown at 3561 -69 | |
if(o.d<9)o.r=3?"⁷x5v6i6c<c<c<c<c<c" -- explode player or kid and shake the screen | |
end | |
L=#T | |
--------------------- | |
---- RESET DRONE ---- | |
--------------------- | |
-- if(btn(5)and T)o.d=60 | |
-------------------- | |
----- MINI MAP ----- | |
-------------------- | |
-- if(btn(5,1))do | |
-- camera() | |
-- xi=O[1].x | |
-- xx=O[1].x | |
-- yi=O[1].y | |
-- yx=O[1].y | |
-- for i=2,#O do xi=min(xi,O[i].x)xx=max(xx,O[i].x)yi=min(yi,O[i].y)yx=max(yx,O[i].y)end | |
-- rh=8+((yx-yi)/(xx-xi))*127 | |
-- rectfill(0,0,127,rh,0) | |
-- for i=#O,1,-1 do | |
-- local x,y | |
-- x=(O[i].x-xi)/(xx-xi)*127 | |
-- y=(O[i].y-yi)/(yx-yi)*rh | |
-- c=8 | |
-- if(O[i].r>1)c=10 | |
-- if(O[i].r<0)c=11 | |
-- pset(x,y,c) | |
-- end | |
-- ?P.x.." "..P.y,0,0,7 | |
-- ?xx\1,0,rh-6,13 | |
-- end | |
end -- keep those poor bastards here for eternity or until user graciously closes the application |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment