Skip to content

Instantly share code, notes, and snippets.

@egordorichev
Created April 22, 2018 17:31
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save egordorichev/0ebdc9ed75f7702280370d01c571b667 to your computer and use it in GitHub Desktop.
Rythm is Lava
pico-8 cartridge // http://www.pico-8.com
version 16
__lua__
-- main
-- todo
-- music
-- sfx
-- fx
-- ideas
-- platforms
-- music boss
music(0,1)
function _init()
g_time,state,g_index,shk=
0,ingame,10,0
restart_level()
end
function _update60()
local nt=stat(21)
if(nt~=lastnt) nt_time+=1
lastnt=nt
e_update_all()
do_movement()
do_collisions()
do_supports()
state.update()
g_time+=1
end
function _draw()
if shk>0 then
shk-=0.5
local a=shk/2
camera(rnd(shk)-a,rnd(shk)-a)
end
if(state~=menu) cls(12)
--cls(stat(20)%2==0 and 1 or 0)
state.draw()
end
function restart_level()
reload(0x2000,0x2000,0x1000)
entity_reset()
collision_reset()
nt_time=0
g_hp=6
g_bdown=false
lastnt=0
g_lost=false
e_add(level({
base=v(g_index%8*16,flr(g_index/8)*16),
size=v(16,16)
}))
end
-->8
-- oop
function deep_copy(obj)
if (type(obj)~="table") return obj
local cpy={}
setmetatable(cpy,getmetatable(obj))
for k,v in pairs(obj) do
cpy[k]=deep_copy(v)
end
return cpy
end
function index_add(idx,prop,elem)
if (not idx[prop]) idx[prop]={}
add(idx[prop],elem)
end
function event(e,evt,p1,p2)
local fn=e[evt]
if fn then
return fn(e,p1,p2)
end
end
function state_dependent(e,prop)
local p=e[prop]
if (not p) return nil
if type(p)=="table" and p[e.state] then
p=p[e.state]
end
if type(p)=="table" and p[1] then
p=p[1]
end
return p
end
function round(x)
return flr(x+0.5)
end
-------------------------------
-- objects
-------------------------------
object={}
function object:extend(kob)
-- printh(type(kob))
if (kob and type(kob)=="string") kob=parse(kob)
kob=kob or {}
kob.extends=self
return setmetatable(kob,{
__index=self,
__call=function(self,ob)
ob=setmetatable(ob or {},{__index=kob})
local ko,init_fn=kob
while ko do
if ko.init and ko.init~=init_fn then
init_fn=ko.init
init_fn(ob)
end
ko=ko.extends
end
return ob
end
})
end
-------------------------------
-- vectors
-------------------------------
vector={}
vector.__index=vector
function vector:__add(b)
return v(self.x+b.x,self.y+b.y)
end
function vector:__sub(b)
return v(self.x-b.x,self.y-b.y)
end
function vector:__mul(m)
return v(self.x*m,self.y*m)
end
function vector:__div(d)
return v(self.x/d,self.y/d)
end
function vector:__unm()
return v(-self.x,-self.y)
end
function vector:dot(v2)
return self.x*v2.x+self.y*v2.y
end
function vector:norm()
return self/sqrt(#self)
end
function vector:len()
return sqrt(#self)
end
function vector:__len()
return self.x^2+self.y^2
end
function vector:str()
return self.x..","..self.y
end
function v(x,y)
return setmetatable({
x=x,y=y
},vector)
end
-------------------------------
-- collision boxes
-------------------------------
cbox=object:extend()
function cbox:translate(v)
return cbox({
xl=self.xl+v.x,
yt=self.yt+v.y,
xr=self.xr+v.x,
yb=self.yb+v.y
})
end
function cbox:overlaps(b)
return
self.xr>b.xl and
b.xr>self.xl and
self.yb>b.yt and
b.yb>self.yt
end
function cbox:sepv(b,allowed)
local candidates={
v(b.xl-self.xr,0),
v(b.xr-self.xl,0),
v(0,b.yt-self.yb),
v(0,b.yb-self.yt)
}
if type(allowed)~="table" then
allowed={true,true,true,true}
end
local ml,mv=32767
for d,v in pairs(candidates) do
if allowed[d] and #v<ml then
ml,mv=#v,v
end
end
return mv
end
function cbox:str()
return self.xl..","..self.yt..":"..self.xr..","..self.yb
end
function box(xl,yt,xr,yb)
return cbox({
xl=min(xl,xr),xr=max(xl,xr),
yt=min(yt,yb),yb=max(yt,yb)
})
end
function vbox(v1,v2)
return box(v1.x,v1.y,v2.x,v2.y)
end
-------------------------------
-- entities
-------------------------------
entity=object:extend({
state="idle",t=0,
last_state="idle",
dynamic=true,
spawns={}
})
function entity:init()
if self.sprite then
self.sprite=deep_copy(self.sprite)
if not self.render then
self.render=spr_render
end
end
end
function entity:become(state)
if state~=self.state then
self.last_state=self.state
self.state,self.t=state,0
end
end
function entity:is_a(tag)
if (not self.tags) return false
for i=1,#self.tags do
if (self.tags[i]==tag) return true
end
return false
end
function entity:spawns_from(...)
for tile in all({...}) do
entity.spawns[tile]=self
end
end
static=entity:extend({
dynamic=false
})
function spr_render(e)
local s,p=e.sprite,e.pos
function s_get(prop,dflt)
local st=s[e.state]
if (st~=nil and st[prop]~=nil) return st[prop]
if (s[prop]~=nil) return s[prop]
return dflt
end
local sp=p+s_get("offset",v(0,0))
local w,h=
s.width or 1,s.height or 1
local flip_x=false
local frames=s[e.state] or s.idle
local delay=frames.delay or 1
if s.turns and type(frames[1])~="number" then
if e.facing=="up" then
frames=frames.u
elseif e.facing=="down" then
frames=frames.d
else
frames=frames.r
end
flip_x=(e.facing=="left")
end
if s_get("flips") then
flip_x=e.flipped
end
if (type(frames)~="table") frames={frames}
local frm_index=flr(e.t/delay) % #frames + 1
local frm=frames[frm_index]
local f=e.bold and ospr or spr
f(e.exr_sprite or frm,
(sp.x),(sp.y),w,h,flip_x)
return frm_index
end
function ospr(s,x,y,...)
for i=0,15 do pal(i,0) end
spr(s,x-1,y,...)
spr(s,x+1,y,...)
spr(s,x,y-1,...)
spr(s,x,y+1,...)
r_reset()
spr(s,x,y,...)
end
-------------------------------
-- entity registry
-------------------------------
function entity_reset()
entities,entities_with,
entities_tagged={},{},{}
end
function e_add(e)
add(entities,e)
for p in all(indexed_properties) do
if (e[p]) index_add(entities_with,p,e)
end
if e.tags then
for t in all(e.tags) do
index_add(entities_tagged,t,e)
end
c_update_bucket(e)
end
return e
end
function e_remove(e)
del(entities,e)
for p in all(indexed_properties) do
if (e[p]) del(entities_with[p],e)
end
if e.tags then
for t in all(e.tags) do
del(entities_tagged[t],e)
if e.bkt then
del(c_bucket(t,e.bkt.x,e.bkt.y),e)
end
end
end
e.bkt=nil
end
indexed_properties={
"dynamic",
"render","render_hud",
"vel",
"collides_with",
"feetbox"
}
-- systems
-------------------------------
-- update system
-------------------------------
function e_update_all()
for ent in all(entities_with.dynamic) do
local state=ent.state
if ent[state] then
ent[state](ent,ent.t)
end
if ent.done then
e_remove(ent)
elseif state~=ent.state then
ent.t=0
else
ent.t+=1
end
end
end
function schedule(fn)
scheduled=fn
end
-------------------------------
-- render system
-------------------------------
function r_render_all(prop)
local drawables={}
for ent in all(entities_with[prop]) do
local order=ent.draw_order or 0
if not drawables[order] then
drawables[order]={}
end
add(drawables[order],ent)
end
for o=0,15 do
for ent in all(drawables[o]) do
r_reset(prop)
if not ent.done then ent[prop](ent,ent.pos) end
end
end
end
function r_reset(prop)
pal()
palt(0,false)
palt(12,true)
if (prop~="render_hud" and g_cam) g_cam:set()
end
-------------------------------
-- movement system
-------------------------------
function do_movement()
for ent in all(entities_with.vel) do
local ev=ent.vel
ent.pos+=ev
if ev.x~=0 then
ent.flipped=ev.x<0
end
if ev.x~=0 and abs(ev.x)>abs(ev.y) then
ent.facing=
ev.x>0 and "right" or "left"
elseif ev.y~=0 then
ent.facing=
ev.y>0 and "down" or "up"
end
if (ent.weight) then
local w=state_dependent(ent,"weight")
ent.vel+=v(0,w)
end
end
end
-------------------------------
-- collision
-------------------------------
function c_bkt_coords(e)
local p=e.pos
return flr(shr(p.x,4)),flr(shr(p.y,4))
end
function c_bucket(t,x,y)
local key=t..":"..x..","..y
if not c_buckets[key] then
c_buckets[key]={}
end
return c_buckets[key]
end
function c_update_buckets()
for e in all(entities_with.dynamic) do
c_update_bucket(e)
end
end
function c_update_bucket(e)
if (not e.pos or not e.tags) return
local bx,by=c_bkt_coords(e)
if not e.bkt or e.bkt.x~=bx or e.bkt.y~=by then
if e.bkt then
for t in all(e.tags) do
local old=c_bucket(t,e.bkt.x,e.bkt.y)
del(old,e)
end
end
e.bkt=v(bx,by)
for t in all(e.tags) do
add(c_bucket(t,bx,by),e)
end
end
end
function c_potentials(e,tag)
local cx,cy=c_bkt_coords(e)
local bx,by=cx-2,cy-1
local bkt,nbkt,bi={},0,1
return function()
while bi>nbkt do
bx+=1
if (bx>cx+1) bx,by=cx-1,by+1
if (by>cy+1) return nil
bkt=c_bucket(tag,bx,by)
nbkt,bi=#bkt,1
end
local e=bkt[bi]
bi+=1
return e
end
end
function collision_reset()
c_buckets={}
end
function do_collisions()
c_update_buckets()
for e in all(entities_with.collides_with) do
for tag in all(e.collides_with) do
if entities_tagged[tag] then
local nothers=
#entities_tagged[tag]
if nothers>4 then
for o in c_potentials(e,tag) do
if o~=e and not e.nocol and not o.nocol then
local ec,oc=
c_collider(e),c_collider(o)
if ec and oc then
c_one_collision(ec,oc,e,o)
end
end
end
else
for oi=1,nothers do
local o=entities_tagged[tag][oi]
local dx,dy=
abs(e.pos.x-o.pos.x),
abs(e.pos.y-o.pos.y)
if dx<=20 and dy<=20 then
local ec,oc=
c_collider(e),c_collider(o)
if ec and oc then
c_one_collision(ec,oc,e,o)
end
end
end
end
end
end
end
end
function c_check(box,tags)
local fake_e={pos=v(box.xl,box.yt)}
for tag in all(tags) do
for o in c_potentials(fake_e,tag) do
local oc=c_collider(o)
if oc and not o.nocol and box:overlaps(oc.b) then
return oc.e
end
end
end
return nil
end
function c_one_collision(ec,oc,e,o)
if ec.b:overlaps(oc.b) then
c_reaction(ec,oc,e,o)
c_reaction(oc,ec,e,o)
end
end
function c_reaction(ec,oc,e,o)
local reaction,param=
event(ec.e,"collide",oc.e)
if type(reaction)=="function" then
reaction(ec,oc,param,e,o)
end
end
function c_collider(ent)
if ent.collider then
if ent.coll_ts==g_time or not ent.dynamic then
return ent.collider
end
end
local hb=state_dependent(ent,"hitbox")
if (not hb) return nil
local coll={
b=hb:translate(ent.pos),
e=ent
}
ent.collider,ent.coll_ts=
coll,g_time
return coll
end
function c_push_out(oc,ec,allowed_dirs,e,o)
local sepv=ec.b:sepv(oc.b,allowed_dirs)
ec.e.pos+=sepv
if ec.e.vel then
local vdot=ec.e.vel:dot(sepv)
if vdot<0 then
if (sepv.y~=0) ec.e.vel.y=0
if (sepv.x~=0) ec.e.vel.x=0
end
end
ec.b=ec.b:translate(sepv)
end
function c_move_out(oc,ec,allowed)
return c_push_out(ec,oc,allowed)
end
-------------------------------
-- support
-------------------------------
function do_supports()
for e in all(entities_with.feetbox) do
local fb=e.feetbox
if fb then
fb=fb:translate(e.pos)
local support=c_check(fb,{"walls"})
-- ) support=nil
e.supported_by=support
if support and support.vel then
e.pos+=support.vel
end
end
end
end
local a="0000000000000000000000000000000000000000000000000000000000000000000000000000000000055555555550000000000000000000005555555555550000000000000000000555155555555500000000000000000005551555555555000000000000000000055555555555550000000000000000000555555555555500000000000000000005555555555555000000008888888800055555550000000000000008888888880555555500000000000000008880008888555555555500000000000080000000558888000000000000005000000000005555558000000000000050000000005555555500000000000000550000005555555555555000000000005550000555555555550050000000000055550055555555555500500000000000555555555555555555000000000000005555555555555555550000000000000005555555555555555500000000000000055555555555555550000000000000000055555555555555500000000000000000055555555555550000000000000000000055555555555000000000000000000000055555555500000000000000000000000055550555000000000000000000000000555000550000000000000000000000005500000500000000000000000000000050000005000000000000000000000000555000055500000000000000000000000000000000000000000000"
function b(y,xx,yy)
for c=0,31 do
for d=1,31 do
local e=d+c*32
local m=tonum(sub(a,e,e))
if (m~=0) pset(d+48+xx,c-48+y+yy,m)
end
end
end
function oprint(s,x,y,...)
s=smallcaps(s)
prnt(s,x,y,...)
end
function coprint(s,y,c,m,n)
s=smallcaps(s)
prnt(s,64-#s*2+(m or 0),y,c,nil,n)
end
function prnt(s,x,y,c,o,n)
if(not o) o=sget(97,c)
for xx=x-1,x+1 do
for yy=y-1,y+2 do
print(s,xx,yy,n or 0)
end
end
print(s,x,y+1,o)
print(s,x,y,c)
end
local gt=0
function f(e)
cls()
gt=min(0.5,gt+0.03)
local y=96+cos(gt)*5
for xx=-1,1 do
for yy=-1,1 do
if abs(xx)+abs(yy)==1 then
coprint("^rexellent ^games",
y+yy,0,xx,7)
end
end
end
coprint("^rexellent ^games",
y,7)
for i=0,15 do pal(i,l[e][6]) end
for xx=-1,1 do
for yy=-1,1 do
if(abs(xx)+abs(yy)==1)b(y,xx,yy)
end
end
pl(e)
b(y,0,0)
flip()
end
function g(h,i,j)
for e=h,i,j do
for m=1,5 do
pl(e)
f(e)
end
end
end
function pl(e)
local k=l[e]
pal()
pal(8,k[1])
pal(1,k[2])
pal(5,k[3])
pal(7,k[4])
pal(13,k[5])
end
l={
{0,0,0,0,0,1},
{2,0,1,1,1,5},
{4,0,1,5,13,5},
{4,1,5,6,13,6},
{8,1,5,7,13,7}
}
function m()
g(1,#l,1)
g(#l,1,-1)
pal()
fade()
end
function smallcaps(s)
s=s..""
local d=""
local c
for i=1,#s do
local a=sub(s,i,i)
if a!="^" then
if not c then
for j=1,26 do
if a==sub("abcdefghijklmnopqrstuvwxyz",j,j) then
a=sub("\65\66\67\68\69\70\71\72\73\74\75\76\77\78\79\80\81\82\83\84\85\86\87\88\89\90\91\92",j,j)
end
end
end
d=d..a
c=true
end
c=not c
end
return d
end
function oline(x1,y1,x2,y2,c)
for x=-1,1 do
for y=-1,1 do
line(x1+x,y1+y,x2+x,y2+y,c)
end
end
end
function noprint(s,x,y,c)
s=smallcaps(s)
prnt(s,x+4-#s*2,y,c)
end
plt={7,6,5,1,0}
function fade()
shk=20
for i=1,#plt do
cls(plt[i])
flip() flip()
end
end
-->8
-- level
function block_type(blk)
if (fget(blk,0)) return solid
if (fget(blk,1)) return support
if (fget(blk,2)) return ice
end
level=entity:extend({
draw_order=2
})
function level:init()
local b,s=self.base,self.size
for x=0,s.x-1 do
for y=0,s.y-1 do
local blk=mget(b.x+x,b.y+y)
local cl=entity.spawns[blk]
if cl then
mset(b.x+x,b.y+y,0)
local e=cl({
pos=v(x,y)*8,
map_pos=b+v(x,y),
tile=blk
})
e_add(e)
blk=0
end
local bt=block_type(blk)
if bt then
bl=bt({
pos=v(x,y)*8,
map_pos=b+v(x,y),
tile=blk,
typ=bt
})
if (bl.needed) e_add(bl)
end
end
end
end
function level:render()
pal(15,3)
map(self.base.x,self.base.y,
0,0,self.size.x,self.size.y)
end
solid=static:extend({
tags={"walls"},
hitbox=box(0,0,8,8),
draw_order=3
})
function solid:bad()
return self.lava and
(flr(nt_time/4)
+self.pos.x/8
+self.pos.y/8)%7==0
end
function solid:render()
if self:bad() then
self.t+=1
pal(8,11-min(3,self.t/8))
spr(6,self.pos.x,self.pos.y)
else
if self.t>0 then
pal(8,11-min(2,self.t/12))
pal(0,1)
spr(6,self.pos.x,self.pos.y)
end
self.t=max(0,self.t-4)
end
end
function solid:init()
self.t=0
local dirs={v(-1,0),v(1,0),v(0,-1),v(0,1)}
local allowed={}
self.lava=fget(self.tile,3)
local needed=self.lava
for i=1,4 do
local np=self.map_pos+dirs[i]
allowed[i]=
block_type(mget(np.x,np.y))
~=solid
needed=needed or allowed[i]
end
self.allowed=allowed
self.needed=needed
end
function solid:collide(e)
if e:is_a("guy")
and self:bad() and self.t>=24 then
e:die()
end
return c_push_out,self.allowed
end
support=solid:extend({
hitbox=box(0,0,8,1)
})
function support:collide(e)
if (not e.vel) return
local dy,vy=e.pos.y-self.pos.y,e.vel.y
if vy>0 and dy<=vy+1 then
return c_push_out,{false,false,true,false}
end
end
ice=solid:extend({ice=true})
-->8
-- guy
guy=entity:extend({
hitbox=box(-3,-3,3,4),
feetbox=box(-3,-3,3,4.1),
sprite={
offset=v(-4,-4),
idle={64,65,delay=30},
move={66,67,68,67,delay=8},
fly={66},
flips=true
},
draw_order=5,
tags={"guy"},
collides_with={"walls","guy"},
weight={up=0,0.1}
})
guy:spawns_from(64)
function guy:render()
if self.invt>0 then
self.invt-=1
if (self.invt%15>7) for i=1,15 do pal(i,7) end
end
spr_render(self)
end
function guy:die(f)
if(self.invt>0 and not f or self.nocol) return
if g_hp==0 or f then
self:death(f)
else
g_hp-=1
sfx(32)
if(g_hp==0) self:death(f)
end
for g in all(entities_tagged["guy"]) do
g.invt=60
end
end
function guy:death(f)
parts(self.pos.x,self.pos.y,5,5,6)
self.nocol=true
g_lost=true
fade()
sfx(33)
end
function guy:collide(o)
if o:is_a("guy") and o.zomb and o~=self then
self:die(true)
end
end
function guy:init()
self:become("up")
self.vel=v(0,0)
self.pos.x+=4
self.start=self.pos.y+4
self.pos.y=128
self.nocol=true
self.s=1
self.t=rnd(128)
self.invt=0
end
function guy:up()
self.s+=0.1
self.pos.y-=self.s
if(self.pos.y<=self.start) self.nocol=false self.pos.y=self.start self:become("idle")
end
function guy:idle()
self.onice=(self.supported_by and self.supported_by.ice)
self.vel.x*=(self.onice and 0.8 or 0.2)
local s=0.7
if(btn(⬅️)) self.vel.x-=s
if(btn(➡️)) self.vel.x+=s
if(btnp(⬆️) and not g_lost and self.supported_by) self.vel.y-=1.8 parts(self.pos.x,self.pos.y,3,4,7)
if abs(self.vel.x)>0.1 or self.vel.y<0 then
self:become(self.supported_by and "move" or "fly")
elseif self.supported_by then
if(self.state~="idle") parts(self.pos.x,self.pos.y,3,4,5)
self:become("idle")
end
if (self.pos.x>=132) g_index+=1 restart_level()
if (self.pos.x<=-4) g_index-=1 restart_level()
if self.pos.y>=132 then
if self.nocol then
fade()
restart_level()
else g_index+=8 restart_level() end
end
if (g_lost) self.vel.x=0
if (self.pos.y<=-4) g_index-=8 restart_level()
end
guy.move=guy.idle
guy.fly=guy.idle
-->8
-- zombie
zombie=guy:extend({
sprite={
offset=v(-4,-4),
idle={80,81,delay=30},
move={82,83,84,83,delay=8},
fly={82},
flips=true
},
zomb=true
})
zombie:spawns_from(80)
-->8
-- entities
door_top=entity:extend({
hitbox=box(0,0,8,8),
tags={"walls","door"},
vy=-1
})
function door_top:clamp()
if(abs(self.pos.y-self.start)<9) self.pos.y+=self.vy/5
end
function door_top:idle()
if(abs(self.pos.y-self.start)>0.1) self.pos.y-=self.vy/5
end
door_top:spawns_from(78)
function door_top:init()
self.start=self.pos.y
self.sprite={idle={self.tile}}
end
function door_top:collide()
return c_push_out
end
door_bottom=door_top:extend({
vy=1
})
door_bottom:spawns_from(94)
button=entity:extend({
sprite={
idle={79},
down={95}
},
hitbox=box(0,6,8,8),
collides_with={"guy"}
})
button:spawns_from(79)
function button:collide(o)
-- if(self.state~="idle") return
if(self.state~="down") sfx(34)
self:become("down")
self.t=0
self:use()
end
function button:use()
self:open()
end
function button:open()
for d in all(entities_tagged["door"]) do
d:become("clamp")
end
end
function button:down()
if self.t>3 and not g_bdown and not self.blue then
sfx(35)
for d in all(entities_tagged["door"]) do
d:become("idle")
end
self:become("idle")
end
end
blue_button=button:extend({
sprite={
idle={77},
down={93}
},
tags={"blue"}
})
blue_button:spawns_from(77)
function blue_button:use()
for b in all(entities_tagged["blue"]) do
if (b.state~="down") return
end
for b in all(entities_tagged["blue"]) do
b.blue=true
end
g_bdown=true
self:open()
end
snk=entity:extend({
sprite={
idle={96},
closed={97}
},
hitbox=box(1,1,7,7),
tags={"snk","walls"}
})
snk:spawns_from(96,97)
function snk:collide(o)
if(self.state=="idle") return c_push_out,{false,false,true,false},4
end
function snk:init()
if (self.tile==97) self:become("closed")
if (self.tile==96) self.main=true
end
function snk:closed() self.nocol=true end
function snk:idle()
self.nocol=false
if (self.state~="idle") return
if self.main and self.t%20==19 then
local m,s=16
for e in all(entities_tagged["snk"]) do
if e~=self and e.state~="idle" then
local d=(e.pos-self.pos):len()
if d<m then
m,s=d,e
end
end
end
if s~=nil then
s:become("idle")
s.main=true
self.main=false
end
end
if self.t==80 then
self:become("closed")
end
end
-->8
-- fx
part=entity:extend({
draw_order=10
})
function part:idle()
self.r-=0.1
self.vel*=0.9
if self.r<0 then
self.done=true
end
end
function part:render()
circfill(self.pos.x,self.pos.y,self.r,0)
end
function part:render_hud()
circfill(self.pos.x,self.pos.y,self.r-1,self.c)
end
function parts(x,y,a,r,c)
for i=1,a do
e_add(part({
pos=v(x,y),
vel=v(rnd(2)-1,rnd()),
r=r,
c=rnd()>0.7 and c or sget(97,c)
}))
end
end
water=entity:extend({
sprite={idle={9,25,41,57,delay=15}}
})
water:spawns_from(9)
fly=entity:extend({
draw_order=10,
sprite={idle={99,100,delay=10}}
})
fly:spawns_from(99)
function fly:init()
self.t=rnd(128)
end
function fly:idle(t)
t/=10
self.pos=self.pos+v(
cos(t/32)*sin(t/105),
sin(t/17)*sin(t/9)
)/2
end
-->8
-- states
ingame={}
function ingame.update()
end
function ingame.draw()
r_render_all("render")
r_render_all("render_hud")
r_reset()
oprint(g_hp.." hp",2,2,8)
end
menu={}
function menu.update()
if btnp(❎) then
state=ingame
sfx(36)
fade()
end
if g_time>=30 and
not g_showed then
g_showed=true
sfx(37)
shk=20
end
if(not g_showed) return
if g_time>=60 and not
g_musplayed then
g_musplayed=true
music(0,1000,1)
end
end
pll={0,0,1,2,4,9,4,2,1,0}
function menu.draw()
local t=g_time/400
for i=1,700 do
local x,y=rnd(128),rnd(128)
local c=3
local xx,yy=x/100,y/100
c+=cos(x/80)-sin(y/100)
c+=cos(x/40-t)*sin(y/40-t)
c+=cos(x/80)*sin(y/80-t)
c+=cos(x/200+t/2)*sin(y/80+t)
circ(x,y,1,pll[flr(c*3)%#pll])
end
if (not g_showed) return
r_reset()
sspr(10,60,110,64,9,24)
oprint("^by @egordorichev",48,86,6)
coprint("^press ❎ to start ",110+cos(g_time/200)*3.5,7)
end
-- splash
-- m()
__gfx__
00000000c0000000000000000000000cc000000ccccccccc000000000000000000000000cc060ccccccccccc0000000001000000222222222222222222222222
000000000ab3bb33b3bbb3bb3bb3bb300ab3bb30cccccccc088888800904040220404020cc0d0ccccccccccc000000001000000022c222222222222222222222
007007000b33333233333333323333100b333310cccccccc088888800000020000002000cc0d0ccccccc0000000000002100000022222c222222222222cccc22
0007700003332224223322332422331003333310cccccccc08888880cccc000cccc000cccc0d0cccccc065dd0000000031000000222222222222222222cccc22
000770000b32444444224422444423300b333330cccccccc08888880ccccccccccccccccccc060cccc0d511100000000420000002cc2c2222222222222cccc22
007007000b32422444444444444423100b332210cccccccc08888880ccccccccccccccccccc0d0cccc05100000000000510000002cc222222222222222cccc22
0000000003224224444444442444423003224230cccccccc08888880ccccccccccccccccccc0d0cccc0d10cc0000000065000000222222222222222222222222
0000000002444444444444444444442002444420cccccccc00000000ccccccccccccccccccc0d0cccc0000cc000000007d000000222222222222222222222222
44444440094444444444444444444420044444200000000000000000c03030cc0301030cccc0d0cc00000000111111118200000000000000ccccccc22ccccccc
444443bb094444444444444444444420094444400000000009040420c03030cc0300030cccc0d0cc77777777111111119400000000000000cccccc2222cccccc
44444233044444444444444444444440094444200000000000000440c03030cc030030cccc060cccdddddddd11111111a900000000000000ccccc222222ccccc
444444230944444444444444444444400444442000000000cccc0000c010030c010030cccc0d0ccc1111111111111111b300000000000000cccc22222222cccc
444444420944444444444444444444200944444000000000cccccccccc0c030cc0c010cccc0d0ccc1111111111111111c100000000000000ccc2222222222ccc
444444440444444444444444444444400944442000000000cccccccccccc010ccccc0ccccc0d0ccc1111111111111111d500000000000000cc222222222222cc
444444440944444444444444444444200444444000000000ccccccccccccc0ccccccccccccc060cc1111111111111111e200000000000000c22222222222222c
444444440444444444444444444444200944442000000000ccccccccccccccccccccccccccc0d0cc1111111111111111f0000000000000002222222222222222
04444444094444444444444444444420094444200000000000000000ccccccccccccccccccc060cc000000000000000000000000000000002222222222222222
bb344444094444444444444444442440094444400000000000000000ccccccccccccccccccc0d0cc00000000000000000000000000000000c22222222222222c
33244444044244444444444422444420044444200000000000000000ccccccccccccccccccc0d0cc00000000000000000000000000000000cc222222222222cc
32444444094444444444444422444420094444200000000000000000c0ccccccc0cc0cccccc0d0cc00000000000000000000000000000000ccc2222222222ccc
244444440444444444444444444444400444444000000000000000000b0c0ccc0b00b0cccc060ccc00000000000000000000000000000000cccc22222222cccc
444444440944444444444444444444200944442000000000000000000b00b00c0b0b0c0ccc0d0ccc00000000000000000000000000000000ccccc222222ccccc
44444444042424222242244242224210042242100000000000000000c0b0b0b00b0b00b0cc0d0ccc00000000000000000000000000000000cccccc2222cccccc
44444444c0000000000000000000000cc000000c0000000000000000c030303003030030cc0d0ccc00000000000000000000000000000000ccccccc22ccccccc
00000000c0000000000000000000000cc000000c00000000000000000000000000000000cc0d0ccc000000000000000000000000000000000000000000000000
000000000ab3bb33b3bbb3bb3bb3bb300ab3bb3000000000000000000000000000000000cc0d0ccc000000000000000000000000000000000000000000000000
000000000b33333233333333323333100b33331000000000000000000000000000000000ccc060cc000000000000000000000000000000000000000000000000
000000000333222422332233242233100333331000000000000000000000000000000000ccc0d0cc000000000000000000000000000000000000000000000000
000000000b32444444224422444423300b33333000000000000000000000000000000000ccc0d0cc000000000000000000000000000000000000000000000000
000000000b32444444444444444423100b33221000000000000000000000000000000000ccc0d0cc000000000000000000000000000000000000000000000000
000000000324224222422242242242300322423000000000000000000000000000000000cc060ccc000000000000000000000000000000000000000000000000
00000000c0000000000000000000000cc000000c00000000000000000000000000000000cc0d0ccc000000000000000000000000000000000000000000000000
ccccccccccccccccccccccccccccccccccccccccc0000000000000000000000cdddddd70c0000000000000000000000c076dd10ccccccccc06d55510cccccccc
ccc00cccccccccccccc00cccccc00cccccc00ccc077777777777777777777770dddddd7707777777777777777777777006d6d50ccccccccc0d5d5510cccccccc
cc0940ccccc00ccccc0940cccc0940cccc09400c077777777777777777777760dddddd77077cccccccccccccccccc770c07d10cccccccccc06d55510cccccccc
cc04f0cccc0940ccc004f0cccc04f00ccc04f0f0077777777777777777777770ddddddd707cccccccccccccccccccc70c06d50cccccccccc0d5d5510cccccccc
c07e810cc074f10c0f7e810cc07e81f0c07e810c077777777777777777777760dddddddd07cccccccccccccccccccc70cc070ccccccccccc06d55510cccccccc
c0e8920cc0e8920cc0e8920c0fe8920cc0f8920c077dddddddddddddddddd770dddddddd07cccccccccccccccccccc70cc060ccccc0000cc0d5d5510cc0000cc
c04f54f0c0f15f0cc04554f0c045540cc045540c07dddddddddddddddddddd60dddddddd07cccccccccccccccccccc70cc060cccc07dd10c05111100c07ee80c
c0d0010cc0d0010cc0d00010cc0d10ccc0d0001007dddddddddddddddddddd60dddddddd07cccccccccccccccccccc70ccc0ccccc0d1100c00000000c0e8820c
cccccccccccccccccccccccccccccccccccccccc06dddddddddddddddddddd5007dddddd07cccccccccccccccccccc7006dddd50cccccccc05111150cccccccc
ccc00cccccccccccccc00cccccc00cccccc00ccc06dddddddddddddddddddd5077dddddd07cccccccccccccccccccc7006ddddd0cccccccc0d5d5510cccccccc
cc0ab0ccccc00ccccc0ab0cccc0ab0cccc0ab00c0dddddddddddddddddddddd077dddddd07cccccccccccccccccccc700ddddd50cccccccc06d55510cccccccc
cc0b30cccc0ab0ccc00b30cccc0b300ccc0b303006dddddddddddddddddddd507ddddddd07cccccccccccccccccccc7006dddd50cccccccc0d5d5510cccccccc
c0ae120cc0ab320c03ae120cc0ae1230c0a1520c0dddddddddddddddddddddd0dddddddd07cccccccccccccccccccc700dddddd0cccccccc06d55510cccccccc
c0b3850cc0b3810cc0b3850c03b3850cc03b850c06dddddddddddddddddddd50dddddddd07cccccccccccccccccccc7006dddd50cccccccc0d5d5510cccccccc
c0e15130c031530cc0e55430c0b5340cc0b3540c06dddddddddddddddddddd50dddddddd07cccccccccccccccccccc700d55d510cc0000cc06d55510cc0000cc
c0b0010cc0b0010cc0b00010cc0b10ccc0b0001006ddddddddddddddddddddd0dddddddd07cccccccccccccccccccc70c000000cc0d1100c0d555510c0e8820c
cccccccccccccccc00000000ccccccccc0cccc0c06dddddddddddddddddddd50c000000c07cccccccccccccccccccc70c0000000000000000000000c06dddd50
cc0000cccccccccc00000000cc0000cc0700007006dddddddddddddddddddd500777777007cccccccccccccccccccc7007777777777777777777777006ddddd0
c077770cccc00ccc00000000c076560cc076560c0dddddddddddddddddddddd00777777007cccccccccccccccccccc700777777777777777777777600ddddd50
c07cc70ccc0670cc0000000007051070cc0510cc06dddddddddddddddddddd500777777007cccccccccccccccccccc7007777777777777777777777006dddd50
c07cc70ccc0760cc00000000c0c00c0cccc00ccc0dddddddddddddddddddddd00777777007cccccccccccccccccccc700777777777777777777777600ddddd50
c077770cccc00ccc00000000cccccccccccccccc06dddddddddddddddddddd50077dd770077cccccccccccccccccc770077dddddddddddddddddd77006ddddd0
cc0000cccccccccc00000000cccccccccccccccc0d55d5d5d55d5d5555d5d51007dddd7007777777777777777777777007dddddddddddddddddddd6006dddd50
cccccccccccccccc00000000ccccccccccccccccc0000000000000000000000c07dddd70c0000000000000000000000cc0000000000000000000000c06dddd50
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccc1111cccccccccccccccccccc11cccccccccccccccccccccccccccccccccccccccccccccccccccccc1111111ccccccccccccccccccc
cccccccccccc00cccc0000011111ccccccccccccccc0000011ccccccc00011ccccccccccccccccccccccccccccccccccccc00000001111cccccccccccccccccc
ccccccccccc077000077777001111ccccccccccccc077666011ccccc0766011ccccccccccccccccccccccccccccccccccc0dddddd50111cccccccccccccccccc
cccccccccc07777777777777701111ccccccccccc07777666011ccc077766011ccccccccccccccccccccccccccccccccc0dddddd5550111ccccccccccccccccc
cccccccccc077777777777777601111cccccccccc0777776660111c0777766011ccccccccccccccccccccccccccccccc0dddddddd555011ccccccccccccccccc
cccccccccc077777776777776660111ccccccccccc0777777660111c0777766011cccccccccccccccccccccccccccccc0dddddddd555011ccccccccccccccccc
cccccccccc077777766007777666011cccccccccccc000077766011cc077776011ccccccccccccccccccccccccccccccc0dddddd5550111ccccccccccccccccc
cccccccccc077777760110777766011cccccccccccccccc077760111c0777760111ccccccccccccccc11cccccccccccccc00ddd55001111cccc11ccccccccccc
ccccccccccc0777776011077777601ccccccccc11cccc00077760011c0777760001cccccccccc11cc1111cccccccccccccc0ddd55011111c000111cccccccccc
cccccccccccc007776011077776601cccccccc1111cc077777776601c07776606601cccccc000011000011ccccccccccccc0ddd5501111c0dd50111ccccccccc
ccccccccccccc07776010077776601c0001ccc00011c0777777776601077777666601cccc07660106666011cccccccccccc0ddd55011cc0ddd550111cccccccc
ccccccccccccc0777600777776601c076601c0776011c0777766666010777777666601cc0776600776666011ccccccccccc0ddd55011c0ddd5555011cccccccc
ccccccccccccc077770067770001c0776601107666011c077666660110777777776601107776667777766601ccccccccccc0ddd550110ddddd550111cccccccc
ccccccccccccc077777677770111c0776601107766011c077660001110777777777660007777677777776601ccccccccccc0ddd55010ddddd0001111cccccccc
ccccccccccccc077777777770011c0776601107766011c07766011ccc0777770077760077777777777776601ccccccccccc0ddd55010dddd0001111ccccccccc
ccccccccccccc07777777777601110776601107766011c077601111cc0777701077760077777077700776601ccccccccccc0ddd550110dddd55011cccccccccc
ccccccccccccc07777000776601110777601107766011c0777011111c0777701077760077777007700776601ccccccccccc0ddd5501110dddd55011ccccccccc
ccccccccccc0007776010777601110777601077766011c0777600011107777010776601077770100c0776601ccccccccccc0ddd550111100dddd5011cccccccc
cccccccccc07707766010777760000777760777766011c077666660110777701077660107777011cc0776601ccccccccccc0ddd55011001100dd5501cccccccc
ccccccccc077777766010777766600777777777766011c077766666010777701077660107777011cc0776601ccccccccccc0ddd55010dd0000dd5501cccccccc
ccccccccc077777766010777776660777777777766011c0777777760c0777701077660107777011cc0776601cccccccccc0ddddd5500dddddddd5501cccccccc
cccccccccc07777766007777777660007777777766011cc07777760cc0777701077660c07777011cc077660cccccccccc0ddddddd550dddddddd5011cccccccc
ccccccccccc077766600777777770cc07777707766011ccc077770cccc07770107760ccc0777011cc07760ccccccccccc0dddddd55500ddddd550111cccccccc
ccccccccccc07766601c07777700cccc0000007766011cccc0000cccccc000ccc000ccccc00011cccc000ccccccccccccc0ddddd550110000000111ccccccccc
cccccccccccc06600cccc07770cccccc0011007766011cccccccccccccccccccccccccccccccccccccccccccccccccccccc0000000c11ccccccccccccccccccc
ccccccccccccc00ccccccc000cccccc07700107766011ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccc077777007766011ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccc07777777766601ccccccccccccc111cccccccccccccccccccccccccccccccccccccccc11111111cccccccccccccccccccc
ccccccccccccccccccccccccccccccc07777777660ccccc000000000000111cccccccccc111ccccccc1111ccccccccc00000000000011ccccccccccccccccccc
ccccccccccccccccccccccccccc111cc0776766660cccc0777aa99988890111ccccccc000111ccc00000111ccccccc07aa888888888011cccccccccccccccccc
cccccccccccccccccc0000000000111cc00666660cccc09777aaa98888890111cccc00998011100999990111ccccc0777aa888822899011ccccccccccccccccc
ccccccccccccccccc022888997770111ccc00000cccc09a777aaa88228889011ccc0799888010999888990111ccc099777a888224229701ccccccccccccccccc
ccccccccccccccccc022288899777011ccccccccccc099aa7aaa982222289901cc077788888009942288990111c088887a98882444277701cccccccccccccccc
ccccccccccccccccc022428889977011ccccccccccc0999aa999982222228901cc077788888009444228890111c0888888998882422277011ccccccccccccccc
ccccccccccccccccc024442888970111ccccccccccc099999990000222222801cc0777822880102422288aa011c0888888800008222889011ccccccccccccccc
cccccccccccccccccc02444888901111ccccccccccc0889999011cc022222801cc097822228011022288aaa011c084428801ccc0888888011ccccccccccccccc
ccccccccccccccccccc044428801111cccccccccccc08888990111c088228801ccc09822228011c02888aaa01cc044442801ccc0888888011ccccccccccccccc
ccccccccccccccccccc02472280111ccccccccccccc08822890111c088822801ccc0982242011cc02288aaa01cc084422801ccc0888822011ccccccccccccccc
ccccccccccccccccccc02777280111ccccccccccccc08222280111c088222201ccc0882444011cc02288aa01ccc082222801ccc0888222011ccccccccccccccc
ccccccccccccccccccc02272280111ccccccccccccc08222280111c088222201ccc0824442011cc02228aa01ccc099228801ccc0882222011ccccccccccccccc
ccccccccccccccccccc02222280111ccccccccccccc08222280111c099222201ccc0822428011cc022288a01ccc099988801ccc0822222011ccccccccccccccc
ccccccccccccccccccc02222220111ccccccccccccc022222801111099222201ccc0822228011cc022228801ccc099988801ccc0222228011ccccccccccccccc
ccccccccccccccccccc02222220111ccccccccccccc022228801111092242201ccc0822228011cc022228801ccc0998888011cc0242288011ccccccccccccccc
ccccccccccccccccccc08222220111ccccccccccccc022222880110992444801ccc0822228011cc082288801ccc0988888801c02444288011ccccccccccccccc
ccccccccccccccccccc08822220111ccccccccccccc022242288009992244401ccc0822228011cc088822801ccc0988888880092444888011ccccccccccccccc
ccccccccccccccccccc08882220111ccccccccccccc082444288888998244401ccc0882288011cc088222201ccc0842888889992242888011ccccccccccccccc
ccccccccccccccccccc09888880111ccccccccccccc088444288888998224201ccc08888aa011cc088222201ccc0444288889982222888011ccccccccccccccc
ccccccccccccccccccc0a788880111ccccccccccccc082242288888992222201ccc0888aaa011cc098422201ccc0244488889882222288011ccccccccccccccc
ccccccccccccccccccc07778880111ccccccccccccc022222888888aa2222801ccc088aaaa011cc094444201ccc0244448888888222288011ccccccccccccccc
ccccccccccccccccccc0777a880111cccccc11ccccc02222288800aaaa228801ccc09a7a7a011cc099444401ccc0224422880022222288011ccccccccccccccc
ccccccccccccccccccc07777a80111ccccc1111cccc08222228800aaaaa88801ccc0977777011cc099244201ccc0822222880022227889011ccccccccccccccc
ccccccccccccccccccc0777aa80111ccc0000111ccc0882222801c0aaaa999011cc0997778011cc099222201ccc098822880cc02277799011ccccccccccccccc
ccccccccccccccccccc087aa980111cc0aaa90111cc0888228011cc0aaa999011cc0998788011c0999222011ccc0988888011cc0277798011ccccccccccccccc
ccccccccccccccccccc0888899011110a77aa9011cc08888880111c0aa7a99011cc0988888011c0998222011ccc09aa888011cc0997988011ccccccccccccccc
ccccccccccccccccccc088888901111077777a011cc08888890111c0a777a90111c09888880110888222011cccc0aaaa88011cc09998880111cccccccccccccc
ccccccccccccccccccc0288888900100877777011cc09888990111c0a777790111c0988882010888822011ccccc0aa7a7901ccc09988880111cccccccccccccc
cccccccccccccccccc0222288889908889977a011c099979990111c0aa77799011c0a7a82220442222011ccccc0aa7777701ccc09888888011cccccccccccccc
ccccccccccccccccc022222228888422889aaa01cc099777990111c0aaa7aa901110777a222444422011cccccc0aaa777a01ccc0988888801ccccccccccccccc
cccccccccccccccc0822442222224442288aa0ccc0aa77779a0111c09aaaaaa90110777782224422011cccccc0aaa9a7aa01ccc0988888880ccccccccccccccc
cccccccccccccccc08844442222224442888a0ccc0aaa7777a0111c099aaaaa90110a777aa22222011ccccccc09999aaaa0cccc0988888880ccccccccccccccc
ccccccccccccccccc08844442222224288800cccc0aaaaa7a0c11ccc099aaa99011c0a7aaaa9800cccccccccc099999aa0cccccc088888880ccccccccccccccc
cccccccccccccccccc00000000000000000ccccccc0000000cccccccc000000011ccc00000000ccccccccccccc0000000cccccccc0000000cccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
__gff__
000909090901010202000000000000000101010101000200000000000000000001010101010000000000000000000000000909090900000000000000000000000000000000090909010c0c0c00000000000000000001010101040404010000000000000000010101090404040909090100000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
__map__
1212121212121212121212121212121200090000000000630011121212121212121212121222221212222222222222121212121212121212121212121212121212121212121212121212121212222212121212121212121212121212121212121222222222222212122222222222221212121212121212121212121212121212
121212121212121212121222121212120009006300000000001112121212121212121212231e0e21230e2e0e001700211212121212121212121212121212121212121212121212122212121223181e211222222222222222221212121212121213000017000e1e11130018000017002122221212121212121212121212121212
12121212121212121222230e212212120009000000000000011212121212121212121223180e0e00180e1e0e00000000121212121212122222222212121212121212121212121223001112231e0e0e0e131e0e0e1f17000000112222222222222340010232330011130005050505004e0e0e2122121212121212121212121212
12121222222222222363000e1f0021121a1a1a1a1a1a01022022222222222222121213001e0e0e63270e0e1e27280000121212121212231718000e2112121212121212121212130000212300000e2f00130e4f010300002700141f180000004e0007111300002711130005050000005e400d180e212222221212222222221212
12122300170e2f0018001e0e0e0e17111b1b1b1b1b011222231e0e1f4e0017001212131f0e0e1f0102020202020202021212121222231e1f002e0e0021221212122222221212230000634e0027010202100202201002020300140e010300005e00001122330031121300050505160501080e1f0e0e0e1700212300171e0e1112
1213001e2f0e0e00001e0e0d0e2f0e111b1b1b1b1b111318000f0e0e5e2800001212130e0e0f011222222212121212121212122317002e0e1f0e1e00181711121317001e21230e0028005e0001121212122222222222222307140d111307310202322318001e1811130505006300001102032e0e0e0e0063004e002e0e271112
1213630000001f0e0e0e0e2f000000111b1b1b1b0112230000042700010202021212130707072123001700212222221212121300000e0e002e0e1f0000002112130e0d0e000e0f0e0102020220222212130063001800280000140e111300001113630000040e0e1113000016051600111213004f272f4d00285e1e0f00011212
1213004000001e0d0e2f0e00005000111b1b0102201300000711020220121212121213002e00000000000d1f171800111212134f01030063000e0d1f001e0d1113002e04002e0e0e1112222223180011130701323232323232230e11120307111328041e11020220130005000505051112100202020202020202030e0e111212
1213070708000e0f0e2f006307070711020220121223630000111212122222121212100202020308001e0103080000111222100220100308002e0e0e0e0e0e11130800140863000721230e0e0e006311130014001e0e0f0e0e0e0e1112130011123223001112121213050516050505111212121212121212121212032f111212
121300000000000e0e0e0e0000000011121212222300000007111212130e0a1112121212121210020202201363000011130e2122222223000000000f0e1e501113004d140000000017000000044d00111307140731323232031e2f21222307111300002711221212130000000505051112222222222212121222222300211212
12131e0e1f0e1e0e2f2f0e0e0e0e0e212222231700004f00001112121203091112222222222222222222222308000711230f1f001817000707080e0e2f6307212232322307080000000007072132321213001400001800001463270017000011131e3132230021121300050505000511131f0e0d180011122300001800182112
12130e0f0e000e0e2f00000e0e2f000000000d0e1f0004070721222212130911134000000017001e180f0e1f0000501100400e0e1f0027001e1e2f2e0e00004e0018180000000000270000000000001113072132323203071102323232020220130e0e00186317111300000000000011130e0e1f006321231700000000001e21
12130000000000000000000000000000270040000e1f140000502e0e111309111308000000001e0e0e0e0e0d0e000711001600282e010202020300280e00005e00000040001e01020202030000500011130000170000140011130e1f001112121232323232330011130505050505001113500e2f28004e0000000000282e0f0e
12130707070707070707070707070708030707080807240708070707212309111300000027002e2e1f0e280e0e1f001102020202022012121210020202020202020203082e0e11121212132800070112223232323307140721231e04072122121300002800000011135000000000001113080e0103005e00004d0001031e0e2e
12131a1a1a1a1a1a1a1a1a1a1a1a1a1a131a1a1a1a1a1a1a1a1a1a1a1a1a1a111002020202020202020202020202022012121212121212121212121212121212121210020202201212121002020220120040002800001400171800140000501113004f0400010220131627052805051110020220100202020202022010020202
12131b1b1b1b1b1b1b1b1b1b1b1b1b1b131b1b1b1b1b1b1b1b1b1b1b1b1b1b11121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212030701020202120202020212020307111002021202201212100202020202022012121212121212121212121212121212
5656565656565656565656565656565656565656565656565656566666666666666666666666665656565656566666661212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212
565656565656565656565656565656565666666666666666666667000f0e1f4e000000004c00005556666666670e4e001200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
565656666656565656565656565656566700000000004c00000000004547005e00400000000000555700000e0d0e5e001200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
5656571f0e655656566666666666666600616161616161616161616155484646466d6d6d6d6e005557076c6d6d6d6d581200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
6666670e0e0e6566670e0f0e4e004c004061630000001e0e1f0000005556565657004c000000005557001e0e4c0e2f551200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
4c001e0d0f1f0e2e0e2e0e005e6300004761001f0e2f0e0e0e0e1f005556565657000000006c6d58486d6d6d6d6e08551200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
0040000e0e0e0e0045464646464646465760000e2e0e0d0e0e0e2f0e55565656570000000063005557000063000e0e551200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
4708002e2e0000455866666666565656484646464646464646464646585656565700000045470e5557076c6d6d6d6d581200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
484700000e1f076567004e2e2f55565666666666666666666666666656565656486d6d6d66670e555700000e1f0000551200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
56576300500e002e1f005e2f005556560000004c0000001e1f000000555656565700000e0f0e0e55566d6d6d6d6e08551200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
56570007080e00494a4a45474d55565600506161616161616161616155565656570000000e0d00555700001e0e0000551200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
56574d1e0e0e07696a6a654846585656464761001e0000000045470055565656576345464646465857076c6d6d6d6d581200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
5648470e2e2e00000e0e4c5556565656565761000e2e0e0e0e5557005556565657006566666666566700001e004c1f551200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
565648470e00494a4b4700656666666656576000000e0e0f0e55574f55565656570000004c00006f0007082e0e0f0e551200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
565656484646595a5b574f595a5a5a5a564846464646464646584846585656565700000000164f6f500000002e0e2f551200000000000000000000000000001212000000000000000000000000000012120000000000000000000000000000121200000000000000000000000000001212000000000000000000000000000012
565656565656595a5b574a595a5a5a5a56565656565656565656565656565656484646464646465646464646464646581212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212
__sfx__
01200000113241132211322113250f3240f3220f3220f325163241632216322163251f3241f3221f3221f3250c3240c3220c3220c3250a3240a3220a3220a3251632416322163221632503324033220332203325
012000200c0730c575246130c5750c0730c57524613246130c0730a5750a5750f073246130a5750f0730a5750f0731157524613115750c0731157524613115750c07307575246130f07307575075750c07324613
00200020163351b3351d3351d3351b3351633513335163351b335183351b335163350f3351b33516335183351d3351f3352233527335223351d3351b33518335163351d3351333511335133351b3351833513335
00200000113221132505322053250f3220f325033220332516322163250a3220a3251f3221f32518322183250c3220c32505322053250732207325033220332513322133250c3220c32503322033250132201325
01100000113241130405324053040f3240f304033240330416324163040a3240a3041f3241f30418324183040c3240c30405324053040732407304033240330413324133040c3240c30403324033040132401304
0010002018023185253061318525180231852530613306131802316525165251b02330613165251b023165251b0231d525306131d515180231d525306131d5251802313525306131b02313525135251802330613
012000001d33522332243322433224335223321d3321b3321833516332163321b3321f335223321d3321b33218335163321333211332113351133213332163321833518332183321833216335183321d33222332
011000000c33300003000030c3330c3330c333000030c3330c30000000000000c3000c3000c30000000000000c33300003000030c3330c3330c333000000c3330000000000000000000000000000000000000000
01100000133301b3301d3301d3301b330163300f3302233003325033250332503325033250332503325033250a33013330163301b3301d33013330113300f3300a330163301833016330133300f3300733005330
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000600002b250222401d2201d2001d200002000020000200002000020000200002000020000200002000020000200002000020000200002000020000200002000020000200002000020000200002000020000200
001000002b350223501b35016350113500c3500335000300003000030000300003000030000300003000030000300003000030000300003000030000300003000030000300003000030000300003000030000300
010500000066500005006450000500615000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005000050000500005
010d00000015400104001040010400104001040010400104001040010400104001040010400104001040010400104001040010400104001040010400104001040010400104001040010400104001040010400104
001200001d355223551b3551635513355163551b3550f30511305183051b3051b3051d30500305003050030500305003050030500305003050030500305003050030500305003050030500305003050030500305
011000000037304323043030030000300003000030000300003000030000300003000030000300003000030000300003000030000300003000030000300003000030000300003000030000300003000030000300
__music__
01 40014344
01 00014344
00 03014344
00 04054344
00 02054344
00 06054344
02 07084344
pico-8 cartridge // http://www.pico-8.com
version 16
__lua__
-- rythm is lava
-- by @egordorichev
-- todo
-- fx
-- trailer
menuitem(1,"reset progress",function()
for i=0,63 do
dset(i,0)
end
_init()
end)
cartdata("ril")
poke(0x5f2d,1)
pat={
0b1111111111111111.1,
0b0111111111111111.1,
0b0111111111011111.1,
0b0101111111011111.1,
0b0101111101011111.1,
0b0101101101011111.1,
0b0101101101011110.1,
0b0101101001011110.1,
0b0101101001011010.1,
0b0001101001011010.1,
0b0001101001001010.1,
0b0000101001001010.1,
0b0000101000001010.1,
0b0000001000001010.1,
0b0000001000001000.1
}
omusic=music
osfx=sfx
function music(...)
if (not g_mmusic) omusic(...)
end
function sfx(...)
if (not g_msfx) osfx(...)
end
function chk(i)
return dget(i) or 0
end
function _init()
cls()
g_dith=0
g_money=dget(0)
g_sec=chk(34)
g_min=chk(35)
g_hour=chk(36)
g_pr=chk(37)
g_deaths=chk(38)
g_mmusic=(dget(39)==1)
g_msfx=(dget(40)==1)
g_time,state,g_index,shk=
0,menu,chk(42),0
nt_time=0
--music(8)
reload(0x0800,0x0800,0x1800,"bkp.p8")
g_lost=true
--restart_level()
end
function _update60()
g_lindex=g_index
local nt=stat(20)
if(nt~=lastnt) nt_time+=1
lastnt=nt
state.update()
g_time+=1
end
-- brb
function _draw()
if shk>0 then
shk-=1
local a=shk/2
camera(rnd(shk)-a,rnd(shk)-a)
end
-- cls(flr(nt_time/4)%2==0 and 1 or 0)
state.draw()
end
function restart_level()
dset(42,g_index)
g_dith=16
g_red=false
g_index=mid(0,g_index,31)
if not g_lost then
dset(38,g_deaths)
if dget(1+g_index)<2 then
g_pr+=1
dset(1+g_index,dget(1+g_index)+2)
dset(37,g_pr)
end
else
g_deaths+=1
end
if entities~=nil then
for i=1,16 do
fillp(pat[i])
rectfill(0,0,127,127,0)
flip()
end
end
fillp()
reload(0x2000,0x2000,0x1000)
reload(0x1000,0x1000,0x1000)
entity_reset()
collision_reset()
nt_time=0
if g_selt==0 then
g_hp=9
elseif g_selt==1 then
g_hp=6
elseif g_selt==2 then
g_hp=4
elseif g_selt==3 then
g_hp=2
end
g_bdown=false
lastnt=0
g_lost=false
e_add(level({
base=v(g_index%8*16,flr(g_index/8)*16),
size=v(16,16)
}))
local i=chk(41)
if i~=0 then
for p in all(pts) do
if p.id==i then
g_pet=e_add(p())
break
end
end
end
end
-->8
-- oop
function deep_copy(obj)
if (type(obj)~="table") return obj
local cpy={}
setmetatable(cpy,getmetatable(obj))
for k,v in pairs(obj) do
cpy[k]=deep_copy(v)
end
return cpy
end
function index_add(idx,prop,elem)
if (not idx[prop]) idx[prop]={}
add(idx[prop],elem)
end
function event(e,evt,p1,p2)
local fn=e[evt]
if fn then
return fn(e,p1,p2)
end
end
function state_dependent(e,prop)
local p=e[prop]
if (not p) return nil
if type(p)=="table" and p[e.state] then
p=p[e.state]
end
if type(p)=="table" and p[1] then
p=p[1]
end
return p
end
function round(x)
return flr(x+0.5)
end
-------------------------------
-- objects
-------------------------------
object={}
function object:extend(kob)
-- printh(type(kob))
if (kob and type(kob)=="string") kob=parse(kob)
kob=kob or {}
kob.extends=self
return setmetatable(kob,{
__index=self,
__call=function(self,ob)
ob=setmetatable(ob or {},{__index=kob})
local ko,init_fn=kob
while ko do
if ko.init and ko.init~=init_fn then
init_fn=ko.init
init_fn(ob)
end
ko=ko.extends
end
return ob
end
})
end
-------------------------------
-- vectors
-------------------------------
vector={}
vector.__index=vector
function vector:__add(b)
return v(self.x+b.x,self.y+b.y)
end
function vector:__sub(b)
return v(self.x-b.x,self.y-b.y)
end
function vector:__mul(m)
return v(self.x*m,self.y*m)
end
function vector:__div(d)
return v(self.x/d,self.y/d)
end
function vector:__unm()
return v(-self.x,-self.y)
end
function vector:dot(v2)
return self.x*v2.x+self.y*v2.y
end
function vector:norm()
return self/sqrt(#self)
end
function vector:len()
return sqrt(#self)
end
function vector:__len()
return self.x^2+self.y^2
end
function vector:str()
return self.x..","..self.y
end
function v(x,y)
return setmetatable({
x=x,y=y
},vector)
end
-------------------------------
-- collision boxes
-------------------------------
cbox=object:extend()
function cbox:translate(v)
return cbox({
xl=self.xl+v.x,
yt=self.yt+v.y,
xr=self.xr+v.x,
yb=self.yb+v.y
})
end
function cbox:overlaps(b)
return
self.xr>b.xl and
b.xr>self.xl and
self.yb>b.yt and
b.yb>self.yt
end
function cbox:sepv(b,allowed)
local candidates={
v(b.xl-self.xr,0),
v(b.xr-self.xl,0),
v(0,b.yt-self.yb),
v(0,b.yb-self.yt)
}
if type(allowed)~="table" then
allowed={true,true,true,true}
end
local ml,mv=32767
for d,v in pairs(candidates) do
if allowed[d] and #v<ml then
ml,mv=#v,v
end
end
return mv
end
function cbox:str()
return self.xl..","..self.yt..":"..self.xr..","..self.yb
end
function box(xl,yt,xr,yb)
return cbox({
xl=min(xl,xr),xr=max(xl,xr),
yt=min(yt,yb),yb=max(yt,yb)
})
end
function vbox(v1,v2)
return box(v1.x,v1.y,v2.x,v2.y)
end
-------------------------------
-- entities
-------------------------------
entity=object:extend({
state="idle",t=0,
last_state="idle",
dynamic=true,
spawns={}
})
function entity:init()
if self.sprite then
self.sprite=deep_copy(self.sprite)
if not self.render then
self.render=spr_render
end
end
end
function entity:become(state)
if state~=self.state then
self.last_state=self.state
self.state,self.t=state,0
end
end
function entity:is_a(tag)
if (not self.tags) return false
for i=1,#self.tags do
if (self.tags[i]==tag) return true
end
return false
end
function entity:spawns_from(...)
for tile in all({...}) do
entity.spawns[tile]=self
end
end
static=entity:extend({
dynamic=false
})
function spr_render(e)
local s,p=e.sprite,e.pos
function s_get(prop,dflt)
local st=s[e.state]
if (st~=nil and st[prop]~=nil) return st[prop]
if (s[prop]~=nil) return s[prop]
return dflt
end
local sp=p+s_get("offset",v(0,0))
local w,h=
s.width or 1,s.height or 1
local flip_x=false
local frames=s[e.state] or s.idle
local delay=frames.delay or 1
if s.turns and type(frames[1])~="number" then
if e.facing=="up" then
frames=frames.u
elseif e.facing=="down" then
frames=frames.d
else
frames=frames.r
end
flip_x=(e.facing=="left")
end
if s_get("flips") then
flip_x=e.flipped
end
if (type(frames)~="table") frames={frames}
local frm_index=flr(e.t/delay) % #frames + 1
local frm=frames[frm_index]
local f=e.bold and ospr or spr
f(e.exr_sprite or frm,
(sp.x),(sp.y),w,h,flip_x)
return frm_index
end
function ospr(s,x,y,...)
for i=0,15 do pal(i,0) end
spr(s,x-1,y,...)
spr(s,x+1,y,...)
spr(s,x,y-1,...)
spr(s,x,y+1,...)
r_reset()
spr(s,x,y,...)
end
-------------------------------
-- entity registry
-------------------------------
function entity_reset()
entities,entities_with,
entities_tagged={},{},{}
end
function e_add(e)
add(entities,e)
for p in all(indexed_properties) do
if (e[p]) index_add(entities_with,p,e)
end
if e.tags then
for t in all(e.tags) do
index_add(entities_tagged,t,e)
end
c_update_bucket(e)
end
return e
end
function e_remove(e)
del(entities,e)
for p in all(indexed_properties) do
if (e[p]) del(entities_with[p],e)
end
if e.tags then
for t in all(e.tags) do
del(entities_tagged[t],e)
if e.bkt then
del(c_bucket(t,e.bkt.x,e.bkt.y),e)
end
end
end
e.bkt=nil
end
indexed_properties={
"dynamic",
"render","render_hud",
"vel",
"collides_with",
"feetbox"
}
-- systems
-------------------------------
-- update system
-------------------------------
function e_update_all()
for ent in all(entities_with.dynamic) do
local state=ent.state
if ent[state] then
ent[state](ent,ent.t)
end
if ent.done then
e_remove(ent)
elseif state~=ent.state then
ent.t=0
else
ent.t+=1
end
end
end
function schedule(fn)
scheduled=fn
end
-------------------------------
-- render system
-------------------------------
function r_render_all(prop)
local drawables={}
for ent in all(entities_with[prop]) do
local order=ent.draw_order or 0
if not drawables[order] then
drawables[order]={}
end
add(drawables[order],ent)
end
for o=0,15 do
for ent in all(drawables[o]) do
r_reset(prop)
if not ent.done then ent[prop](ent,ent.pos) end
end
end
end
function r_reset(prop)
pal()
palt(0,false)
palt(12,true)
if g_red then
for i=1,15 do
pal(i,8)
end
end
if (prop~="render_hud" and g_cam) g_cam:set()
end
-------------------------------
-- movement system
-------------------------------
function do_movement()
for ent in all(entities_with.vel) do
local ev=ent.vel
ent.pos+=ev
if ev.x~=0 then
ent.flipped=ev.x<0
end
if ev.x~=0 and abs(ev.x)>abs(ev.y) then
ent.facing=
ev.x>0 and "right" or "left"
elseif ev.y~=0 then
ent.facing=
ev.y>0 and "down" or "up"
end
if (ent.weight) then
local w=state_dependent(ent,"weight")
ent.vel+=v(0,w)
end
end
end
-------------------------------
-- collision
-------------------------------
function c_bkt_coords(e)
local p=e.pos
return flr(shr(p.x,4)),flr(shr(p.y,4))
end
function c_bucket(t,x,y)
local key=t..":"..x..","..y
if not c_buckets[key] then
c_buckets[key]={}
end
return c_buckets[key]
end
function c_update_buckets()
for e in all(entities_with.dynamic) do
c_update_bucket(e)
end
end
function c_update_bucket(e)
if (not e.pos or not e.tags) return
local bx,by=c_bkt_coords(e)
if not e.bkt or e.bkt.x~=bx or e.bkt.y~=by then
if e.bkt then
for t in all(e.tags) do
local old=c_bucket(t,e.bkt.x,e.bkt.y)
del(old,e)
end
end
e.bkt=v(bx,by)
for t in all(e.tags) do
add(c_bucket(t,bx,by),e)
end
end
end
function c_potentials(e,tag)
local cx,cy=c_bkt_coords(e)
local bx,by=cx-2,cy-1
local bkt,nbkt,bi={},0,1
return function()
while bi>nbkt do
bx+=1
if (bx>cx+1) bx,by=cx-1,by+1
if (by>cy+1) return nil
bkt=c_bucket(tag,bx,by)
nbkt,bi=#bkt,1
end
local e=bkt[bi]
bi+=1
return e
end
end
function collision_reset()
c_buckets={}
end
function do_collisions()
c_update_buckets()
for e in all(entities_with.collides_with) do
for tag in all(e.collides_with) do
if entities_tagged[tag] then
local nothers=
#entities_tagged[tag]
if nothers>4 then
for o in c_potentials(e,tag) do
if o~=e and not e.nocol and not o.nocol then
local ec,oc=
c_collider(e),c_collider(o)
if ec and oc then
c_one_collision(ec,oc,e,o)
end
end
end
else
for oi=1,nothers do
local o=entities_tagged[tag][oi]
local dx,dy=
abs(e.pos.x-o.pos.x),
abs(e.pos.y-o.pos.y)
if dx<=20 and dy<=20 then
local ec,oc=
c_collider(e),c_collider(o)
if ec and oc then
c_one_collision(ec,oc,e,o)
end
end
end
end
end
end
end
end
function c_check(box,tags)
local fake_e={pos=v(box.xl,box.yt)}
for tag in all(tags) do
for o in c_potentials(fake_e,tag) do
local oc=c_collider(o)
if oc and not o.nocol and box:overlaps(oc.b) then
return oc.e
end
end
end
return nil
end
function c_one_collision(ec,oc,e,o)
if ec.b:overlaps(oc.b) then
c_reaction(ec,oc,e,o)
c_reaction(oc,ec,e,o)
end
end
function c_reaction(ec,oc,e,o)
local reaction,param=
event(ec.e,"collide",oc.e)
if type(reaction)=="function" then
reaction(ec,oc,param,e,o)
end
end
function c_collider(ent)
if ent.collider then
if ent.coll_ts==g_time or not ent.dynamic then
return ent.collider
end
end
local hb=state_dependent(ent,"hitbox")
if (not hb) return nil
local coll={
b=hb:translate(ent.pos),
e=ent
}
ent.collider,ent.coll_ts=
coll,g_time
return coll
end
function c_push_out(oc,ec,allowed_dirs,e,o)
local sepv=ec.b:sepv(oc.b,allowed_dirs)
ec.e.pos+=sepv
if ec.e.vel then
local vdot=ec.e.vel:dot(sepv)
if vdot<0 then
if (sepv.y~=0) ec.e.vel.y=0
if (sepv.x~=0) ec.e.vel.x=0
end
end
ec.b=ec.b:translate(sepv)
end
function c_move_out(oc,ec,allowed)
return c_push_out(ec,oc,allowed)
end
-------------------------------
-- support
-------------------------------
function do_supports()
for e in all(entities_with.feetbox) do
local fb=e.feetbox
if fb then
fb=fb:translate(e.pos)
local support=c_check(fb,{"walls"})
-- ) support=nil
e.supported_by=support
if support and support.vel then
e.pos+=support.vel
end
end
end
end
local a="0000000000000000000000000000000000000000000000000000000000000000000000000000000000055555555550000000000000000000005555555555550000000000000000000555155555555500000000000000000005551555555555000000000000000000055555555555550000000000000000000555555555555500000000000000000005555555555555000000008888888800055555550000000000000008888888880555555500000000000000008880008888555555555500000000000080000000558888000000000000005000000000005555558000000000000050000000005555555500000000000000550000005555555555555000000000005550000555555555550050000000000055550055555555555500500000000000555555555555555555000000000000005555555555555555550000000000000005555555555555555500000000000000055555555555555550000000000000000055555555555555500000000000000000055555555555550000000000000000000055555555555000000000000000000000055555555500000000000000000000000055550555000000000000000000000000555000550000000000000000000000005500000500000000000000000000000050000005000000000000000000000000555000055500000000000000000000000000000000000000000000"
function b(y,xx,yy)
for c=0,31 do
for d=1,31 do
local e=d+c*32
local m=tonum(sub(a,e,e))
if (m~=0) pset(d+48+xx,c-48+y+yy,m)
end
end
end
function oprint(s,x,y,...)
s=smallcaps(s)
prnt(s,x,y,...)
end
function coprint(s,y,c,m,n)
s=smallcaps(s)
prnt(s,64-#s*2+(m or 0),y,c,nil,n)
end
function prnt(s,x,y,c,o,n)
if(not o) o=sget(97,c)
for xx=x-1,x+1 do
for yy=y-1,y+2 do
print(s,xx,yy,n or 0)
end
end
print(s,x,y+1,o)
print(s,x,y,c)
end
local gt=0
function f(e)
cls()
gt=min(0.5,gt+0.03)
local y=96+cos(gt)*5
for xx=-1,1 do
for yy=-1,1 do
if abs(xx)+abs(yy)==1 then
coprint("^rexellent ^games",
y+yy,0,xx,7)
end
end
end
coprint("^rexellent ^games",
y,7)
for i=0,15 do pal(i,l[e][6]) end
for xx=-1,1 do
for yy=-1,1 do
if(abs(xx)+abs(yy)==1)b(y,xx,yy)
end
end
pl(e)
b(y,0,0)
flip()
end
function g(h,i,j)
for e=h,i,j do
for m=1,5 do
pl(e)
f(e)
end
end
end
function pl(e)
local k=l[e]
pal()
pal(8,k[1])
pal(1,k[2])
pal(5,k[3])
pal(7,k[4])
pal(13,k[5])
end
l={
{0,0,0,0,0,1},
{2,0,1,1,1,5},
{4,0,1,5,13,5},
{4,1,5,6,13,6},
{8,1,5,7,13,7}
}
function m()
g(1,#l,1)
g(#l,1,-1)
pal()
fade()
end
function smallcaps(s)
s=s..""
local d=""
local c
for i=1,#s do
local a=sub(s,i,i)
if a!="^" then
if not c then
for j=1,26 do
if a==sub("abcdefghijklmnopqrstuvwxyz",j,j) then
a=sub("\65\66\67\68\69\70\71\72\73\74\75\76\77\78\79\80\81\82\83\84\85\86\87\88\89\90\91\92",j,j)
end
end
end
d=d..a
c=true
end
c=not c
end
return d
end
function noprint(s,x,y,c)
s=smallcaps(s)
prnt(s,x+4-#s*2,y,c)
end
plt={7,6,5,1,0}
function fade()
shk=20
for i=1,#plt do
cls(plt[i])
flip() flip()
end
end
-->8
-- level
function block_type(blk)
if (fget(blk,0)) return solid
if (fget(blk,1)) return support
end
level=entity:extend({
draw_order=2
})
function level:init()
local b,s=self.base,self.size
for x=0,s.x-1 do
for y=0,s.y-1 do
local blk=mget(b.x+x,b.y+y)
local cl=entity.spawns[blk]
if cl then
mset(b.x+x,b.y+y,0)
local e=cl({
pos=v(x,y)*8,
map_pos=b+v(x,y),
tile=blk
})
e_add(e)
blk=0
end
local bt=block_type(blk)
if bt then
bl=bt({
pos=v(x,y)*8,
map_pos=b+v(x,y),
tile=blk,
typ=bt
})
if (bl.needed) e_add(bl)
end
end
end
end
function level:render()
map(self.base.x,self.base.y,
0,0,self.size.x,self.size.y)
end
solid=static:extend({
tags={"walls"},
hitbox=box(0,0,8,8),
draw_order=3
})
function solid:bad()
return self.lava and (
(flr(nt_time/4 )
+self.pos.x/8)%(g_index>=23 and (g_index==31 and 2 or 6) or 7)==0)
end
function solid:render()
if(g_red) return
if self:bad() then
self.t+=1
rect(self.pos.x,self.pos.y,self.pos.x+7,self.pos.y+7,0)
for x=self.pos.x+1,self.pos.x+6 do
for y=self.pos.y+1,self.pos.y+6 do
pset(x,y,get(x,y,20))
end
end
end
if self.tile==5 and rnd()>0.99 then
mset(self.map_pos.x,self.map_pos.y,0)
end
end
function solid:init()
self.t=0
local dirs={v(-1,0),v(1,0),v(0,-1),v(0,1)}
local allowed={}
self.lava=fget(self.tile,3)
local needed=self.lava
for i=1,4 do
local np=self.map_pos+dirs[i]
allowed[i]=
block_type(mget(np.x,np.y))
~=solid
needed=needed or allowed[i]
end
self.allowed=allowed
self.needed=needed
end
function solid:collide(e)
if e:is_a("guy")
and self:bad() and self.t>=10 then
e:die()
end
return c_push_out,self.allowed
end
support=solid:extend({
hitbox=box(0,0,8,1)
})
function support:collide(e)
if (not e.vel) return
local dy,vy=e.pos.y-self.pos.y,e.vel.y
if vy>0 and dy<=vy+1 then
return c_push_out,{false,false,true,false}
end
end
-->8
-- guy
guy=entity:extend({
hitbox=box(-3,-3,3,4),
feetbox=box(-3,-3,3,4.1),
sprite={
offset=v(-4,-4),
idle={66,68,delay=30},
move={66,67,68,67,delay=8},
fly={66},
flips=true
},
draw_order=5,
tags={"guy"},
collides_with={"walls","guy"},
weight={up=0,0.1}
})
guy:spawns_from(64)
function guy:render()
if self.invt>0 then
self.invt-=1
if (self.invt%15>7) for i=1,15 do pal(i,7) end
end
spr_render(self)
end
function guy:die(f)
if(self.invt>0 and not f or self.nocol or g_red) return
if g_hp==0 or f then
self:death(f)
else
g_hp-=1
sfx(32)
if(g_hp==0) self:death(f)
end
for g in all(entities_tagged["guy"]) do
g.invt=60
end
end
function guy:death(f)
parts(self.pos.x,self.pos.y,10,5,8)
self.nocol=true
g_lost=true
fade()
sfx(33)
end
function guy:collide(o)
if o:is_a("guy") and o~=self and not o.nocol and not self.nocol then
if not self.zomb and o.zomb then
self:die(true)
sfx(40)
else
return c_push_out
end
end
end
function guy:init()
self:become("up")
self.vel=v(0,0)
self.pos.x+=4
self.start=self.pos.y+4
self.pos.y=128
self.nocol=true
self.s=1
self.t=rnd(128)
self.invt=0
end
function guy:up()
self.s+=0.1
self.pos.y-=self.s
if(self.pos.y<=self.start) self.nocol=false self.pos.y=self.start self:become("idle")
end
function guy:idle()
self.vel.x*=0.2
local s=0.7
if(btn(⬅️)) self.vel.x-=s
if(btn(➡️)) self.vel.x+=s
if(btnp(⬆️) and not g_lost and self.supported_by) self.vel.y-=1.8 parts(self.pos.x,self.pos.y,3,4,7) sfx(39)
if abs(self.vel.x)>0.1 or self.vel.y<0 then
self:become(self.supported_by and "move" or "fly")
elseif self.supported_by then
if(self.state~="idle") parts(self.pos.x,self.pos.y,3,4,5)
self:become("idle")
end
if (self.pos.x>=132) g_index+=1 restart_level()
if (self.pos.x<=-4) g_index-=1 restart_level()
if self.pos.y>=132 then
if self.nocol then
restart_level()
else g_index+=8 restart_level() end
end
if (g_lost) self.vel.x=0
if (self.pos.y<=-4) g_index-=8 restart_level()
end
guy.move=guy.idle
guy.fly=guy.idle
-->8
-- zombie
zombie=guy:extend({
sprite={
offset=v(-4,-4),
idle={82,84,delay=30},
move={82,83,84,83,delay=8},
fly={82},
flips=true
},
zomb=true
})
zombie:spawns_from(80)
-->8
-- entities
door_top=entity:extend({
hitbox=box(0,0,8,8),
tags={"walls","door"},
vy=-1
})
function door_top:clamp()
if(abs(self.pos.y-self.start)<9) self.pos.y+=self.vy/5
end
function door_top:idle()
if(abs(self.pos.y-self.start)>0.1) self.pos.y-=self.vy/5
end
door_top:spawns_from(78)
function door_top:init()
self.start=self.pos.y
self.sprite={idle={self.tile}}
end
function door_top:collide()
return c_push_out
end
door_bottom=door_top:extend({
vy=1
})
door_bottom:spawns_from(94)
button=entity:extend({
sprite={
idle={79},
down={95}
},
hitbox=box(0,6,8,8),
collides_with={"guy"}
})
button:spawns_from(79)
function button:collide(o)
-- if(self.state~="idle") return
if(self.state~="down") sfx(34)
self:become("down")
self.t=0
self:use()
end
function button:use()
self:open()
end
function button:open()
for d in all(entities_tagged["door"]) do
if (d.state~="clamp") sfx(42) d:become("clamp")
end
end
function button:down()
if self.t>3 and not g_bdown and not self.blue then
sfx(35)
for d in all(entities_tagged["door"]) do
if(d.state~="idle") sfx(43) d:become("idle")
end
self:become("idle")
end
end
blue_button=button:extend({
sprite={
idle={77},
down={93}
},
tags={"blue"}
})
blue_button:spawns_from(77)
function blue_button:use()
for b in all(entities_tagged["blue"]) do
if (b.state~="down") return
end
for b in all(entities_tagged["blue"]) do
b.blue=true
end
g_bdown=true
self:open()
end
snk=entity:extend({
sprite={
idle={96},
closed={97}
},
hitbox=box(1,1,7,7),
tags={"snk","walls"}
})
snk:spawns_from(96,97)
function snk:collide(o)
if(self.state=="idle") return c_push_out,{false,false,true,false},4
end
function snk:init()
if (self.tile==97) self:become("closed")
if (self.tile==96) self.main=true
end
function snk:closed() self.nocol=true end
function snk:idle()
self.nocol=false
if (self.state~="idle") return
if self.main and self.t%20==19 then
local m,s=16
for e in all(entities_tagged["snk"]) do
if e~=self and e.state~="idle" then
local d=(e.pos-self.pos):len()
if d<m then
m,s=d,e
end
end
end
if s~=nil then
s:become("idle")
s.main=true
self.main=false
end
end
if self.t==80 then
self:become("closed")
end
end
coin=entity:extend({
sprite={
idle={112,113,114,113,delay=10}
},
draw_order=5,
hitbox=box(2,2,6,6),
collides_with={"guy"}
})
coin:spawns_from(112)
function coin:init()
if dget(g_index+1)%2==1 then
self.done=true
end
end
function coin:idle(t)
self.pos.y+=cos(t/100)/10
end
function coin:collide(o)
self.done=true
g_money+=1
dset(g_index+1,chk(g_index+1)+1)
dset(0,g_money)
sfx(38)
parts(self.pos.x+4,self.pos.y+4,5,4,10)
end
wtr=entity:extend({
sprite={idle={26}},
hitbox=box(0,0,8,8),
collides_with={"guy"}
})
wtr:spawns_from(26)
function wtr:collide(o)
if o.die then
o:die(true)
end
end
boss=entity:extend({
sprite={
idle={42},
width=2,
height=2
},
draw_order=10,
hitbox=box(0,0,16,16),
collides_with={"guy"}
})
function boss:collide(o)
o.done=true
self:become("aaa")
end
function boss:idle()
if self.t==60 then
shk=self.t/2
self:become("main")
end
end
function boss:main()
self.pos.y+=cos(self.t/100)/10
end
function boss:render()
if self.state~="idle" or self.t>=50 then
spr_render(self)
end
if self.state=="idle"
or self.t<30 then
for i=1,30 do
local a=i/10
local r=(self.state=="idle"
and (30-i)/self.t*32 or
(self.t*self.t)/10)
circfill(cos(a)*r+
self.pos.x+8,
sin(a)*r+self.pos.y+8,
i/2+1,0)
end
end
end
function boss:render_hud()
if self.state=="idle"
or self.t<30 then
for i=1,30 do
local a=i/10
local r=(self.state=="idle"
and (30-i)/self.t*32 or
(self.t*self.t)/10)
circfill(cos(a)*r+
self.pos.x+8,
sin(a)*r+self.pos.y+8,
i/2,10-i%2)
end
end
end
function boss:aaa()
shk=self.t/2
if self.t==60 then
self.done=true
g_red=true
end
local a=self.t/15
e_add(part({
r=8,
c=10-self.t%2,
pos=v(self.pos.x+8,self.pos.y+8),
vel=v(
cos(a)*8,
sin(a)*8
),
mul=0.85,
spd=function(t)
return t>=60 and 0.2 or 0.01
end
}))
end
boss:spawns_from(42)
pet=entity:extend({
draw_order=4,
hitbox=box(0,0,8,8),
collides_with={"guy"}
})
function pet:collide(o)
self.st=3
end
function pet:init()
self.sprite={idle={self.spr},stop={45}}
self.vel=v(0,0)
self.st=0
if (self.tile) self:become("shop") return
local a=entities_tagged["guy"]
self.own=a[flr(rnd(#a))+1]
self.pos=v(self.own.pos.x,self.own.start)
end
function pet:shop(t)
if (g_pet and g_pet.id==self.id) self:become("stop")
self.vel.y=cos(t/200)/10
self.st=max(0,self.st-1)
end
function pet:stop(t)
if (g_pet==nil or g_pet.id~=self.id) self:become("shop")
self.vel.y=cos(t/200)/10
self.st=max(0,self.st-1)
end
function pet:render_hud()
if self.state=="shop" and self.st>0 then
local e=g_money>=self.cost
local s=self.cost.."$"
oprint(s,self.pos.x+4-#s*2,self.pos.y,e and 9 or 8)
s=smallcaps(self.name)
oprint(s,self.pos.x+4-#s*2,self.pos.y-9,7)
if e then
s="^press 🅾️/c to buy "
oprint(s,self.pos.x+8-#s*2,self.pos.y+9,11)
if btnp(🅾️) then
g_missed=true
g_money-=self.cost
dset(0,g_money)
if g_pet~=nil then g_pet.done=true
parts(g_pet.pos.x+4,g_pet.pos.y+4,10,4,5)
end
g_pet=pts[self.id]()
local a=entities_tagged["guy"]
g_pet.own=a[flr(rnd(#a))+1]
e_add(g_pet)
dset(41,self.id)
self:become("stop")
parts(self.pos.x+4,self.pos.y+4,10,4,10)
end
end
elseif self.state=="stop" and self.st>0 then
local s="^sell"
oprint(s,self.pos.x+8-#s*2,self.pos.y,9)
if btnp(🅾️) then
g_missed=true
g_pet.done=true
parts(g_pet.pos.x+4,g_pet.pos.y+4,10,4,5)
g_pet=nil
g_money+=self.cost
dset(0,g_money)
dset(41,0)
self:become("shop")
end
end
end
function pet:idle()
self.vel*=0.9
local dv=self.own.pos-self.pos
local d=dv:len()
if d>16 then
self.vel+=dv/d/10
end
end
str=pet:extend({
spr=29,
cost=5,
name="^strawberry",
id=1
})
str:spawns_from(29)
pico=pet:extend({
spr=44,
cost=3,
name="^p^i^c^o-8",
id=2
})
pico:spawns_from(44)
ld=pet:extend({
spr=60,
cost=10,
name="^l^d",
id=3
})
ld:spawns_from(60)
spc=pet:extend({
spr=61,
cost=7,
name="^space invader",
id=4
})
spc:spawns_from(61)
ham=pet:extend({
spr=56,
cost=2,
name="^hamster",
id=5
})
ham:spawns_from(56)
co=pet:extend({
spr=55,
cost=15,
name="^coffee",
id=6
})
co:spawns_from(55)
pts={str,pico,ld,spc,ham,co}
-->8
-- fx
part=entity:extend({
draw_order=10
})
function part:idle()
self.r-=(self.spd~=nil and self.spd(self.t) or 0.1)
self.vel*=(self.mul or 0.9)
if self.r<0 then
self.done=true
end
end
function part:render()
circfill(self.pos.x,self.pos.y,self.r,0)
end
function part:render_hud()
circfill(self.pos.x,self.pos.y,self.r-1,self.c)
end
function parts(x,y,a,r,c)
for i=1,a do
e_add(part({
pos=v(x,y),
vel=v(rnd(2)-1,rnd()),
r=r,
c=rnd()>0.7 and c or sget(97,c)
}))
end
end
water=entity:extend({
sprite={idle={9,25,41,57,delay=15}}
})
water:spawns_from(9)
fly=entity:extend({
draw_order=10,
sprite={idle={99,100,delay=10}}
})
fly:spawns_from(99)
function fly:init()
self.t=rnd(128)
end
function fly:idle(t)
t/=10
self.pos=self.pos+v(
cos(t/32)*sin(t/105),
sin(t/17)*sin(t/9)
)/2
end
-->8
-- states
ingame={}
function ingame.update()
if g_time%60==0 and not g_red then
g_sec+=1
if g_sec>=60 then
g_sec=0
g_min+=1
if g_min>=60 then
g_min=0
g_hour+=1
end
end
dset(34,g_sec)
dset(35,g_min)
dset(36,g_hour)
end
e_update_all()
do_movement()
do_collisions()
do_supports()
if btnp(❎) then
sfx(41)
if g_red then
reload(0x0800,0x0800,0x1800,"bkp.p8")
music(-1)
state=menu
g_red=false
for i=0,63 do
g_index=0
dset(i,0)
end
fade()
else
g_lost=true restart_level() fade()
end
end
end
function ingame.draw()
cls(12)
r_render_all("render")
r_render_all("render_hud")
local r=g_red
g_red=false
r_reset()
spr(11,7,2)
oprint(g_hp,2,2,8)
spr(112,119,1)
local s=g_money..""
prnt(s,119-#s*4,2,9)
if g_index==1 then
coprint("^press ❎ to restart ",110,6)
end
if btnp(🅾️) then
if g_missed then
g_missed=false
else g_spd=not g_spd end
end
if g_spd then
oprint(sb(g_hour)..":"..sb(g_min)..":"..sb(flr(g_sec)).." "..round(g_pr/32*100).."%",2,11,12)
oprint(g_deaths.." ^deaths",2,20,12)
end
if r then
local s=cos(g_time/200)*3.5-20
coprint("★★★★★ ",32+s,10)
coprint("^you won!",42+s,7)
coprint("★★★★★ ",52+s,10)
coprint("^g^g!",72+s,6)
coprint(g_deaths.." ^deaths",82+s,12)
coprint(sb(g_hour)..":"..sb(g_min)..":"..sb(flr(g_sec)),92+s,11)
coprint(round(g_pr/32*100).."% ^finished",102+s,9)
coprint(g_money.." ^coins",112+s,9)
coprint("^press ❎ to continue ",102,7)
end
if g_dith>0 then
fillp(pat[g_dith])
g_dith-=1
rectfill(0,0,127,127,0)
fillp()
end
g_red=r
end
function sb(s)
s=""..s
while #s<2 do
s="0"..s
end
return s
end
menu={}
thanks="^big thanks to: ^gruber_music, x2 ^roy ^fielding, ^riccardo straccia, ^denny ^pahlke, ^audrey, ^dylan ^bennett, ^francesco ^maida, ^gabriel ^crowe, ^szymon ^walter, ^mr^bigaston, ^someone"
lmb=0
function menu.update()
mb=stat(34)
mx,my=stat(32),stat(33)
mbp=(mb~=0 and lmb==0)
lmb=mb
if(mbp) sfx(41)
if btnp(❎) then
sfx(41)
fade()
state=diff
end
if g_time>=30 and
not g_showed then
g_showed=true
sfx(37)
shk=20
end
if(not g_showed) return
if g_time>=60 and not
g_musplayed then
g_musplayed=true
music(13,1000,1)
end
end
pll={4,2,2,2,8,8,9,10,15,7,15,10,9,8,8,2,2,2,4}
function get(x,y,s)
local t=g_time/400
local c=cos(x/80)-sin(y/100)
+cos(x/40-t)*sin(y/40-t)
+cos(x/80)*sin(y/80-t)
+cos(x/200+t/2)*sin(y/80+t)
return pll[flr(c*(s or 3))%#pll] or pll[1]
end
function menu.draw()
for i=1,300 do
local x,y=rnd(128),rnd(128)
local c=get(x,y)
circ(x,y,1,c)
end
if (not g_showed) return
r_reset()
sspr(9,60,111,64,9,24+cos(g_time/200)*3.5)
-- oprint("^by @egordorichev",48,87,6)
local s=sin(g_time/100)*3.5
spr(66+(flr(g_time/15)%2),8,8+s)
spr(66+(flr(g_time/15)%2),112,8+s)
spr(82+(flr(g_time/15)%2),8,112+s)
spr(82+(flr(g_time/15)%2),112,112+s)
local m=mchk(40,13)
spr(37+(g_mmusic and 16 or 0),
40,m and (mb>0 and 15 or 14) or 13)
if mbp and m then
g_mmusic=not g_mmusic
dset(39,g_mmusic and 1 or 0)
if g_mmusic then
omusic(-1)
else
music(13+flr(rnd(3)),1000,1)
end
end
for i=1,#thanks do
local x=(i*4-g_time/3)+24
local s=sub(thanks,i,i)
if s~=" " and s~="^" and x>-4 and x<128 then
oprint((i==1 or sub(thanks,i-1,i-1)=="^") and "^"..s or s,x,96+cos(g_time/200+i/6)*1.5,i%4+7)
end
end
local m=mchk(54,13)
spr(38+(g_msfx and 16 or 0),
54,m and (mb>0 and 15 or 14) or 13)
if mbp and m then
g_msfx=not g_msfx
dset(40,g_msfx and 1 or 0)
end
-- coprint(stat(1),96,11)
coprint("^press ❎ to start ",110+cos(g_time/200)*3.5,7)
spr(21,mx,my)
end
function mchk(x,y)
return mx>=x and mx<=x+8 and
my>=y and my<=y+8
end
diff={}
function diff.update()
if btnp(⬅️) or btnp(⬆️) then
g_selt=(g_selt-1)%4
elseif btnp(➡️) or btnp(⬇️) then
g_selt=(g_selt+1)%4
end
if btnp(❎) then
sfx(41)
reload(0x0800,0x0800,0x1800,"ld.p8")
restart_level()
state=ingame
sfx(36)
fade()
music(0,1000,1)
end
end
g_selt=1
function diff.draw()
for i=1,500 do
local x,y=rnd(128),rnd(128)
local c=get(x,y)
circ(x,y,1,c)
end
coprint("^easy"..
(g_selt==0 and " <" or ""),48,g_selt==0 and 8 or 7)
coprint("^normal"..(g_selt==1 and " <" or ""),58,
g_selt==1 and 8 or 7)
coprint("^hard"..(g_selt==2 and " <" or ""),68,g_selt==2 and 8 or 7)
coprint("^damn hard"..(g_selt==3 and " <" or ""),78,g_selt==3 and 8 or 7)
end
-- splash
-- m()
__gfx__
00000000100000000000000000000001100000017ffffffa000000000000000000000000cc060ccccccccccccc0cc0cc01000000222222222222222222222222
000000000ab3ab33b3bbb3bb3ab3bb300ab3ab30fcccccc9088888800904040220404020cc0d0cccccccccccc0700e0c1000000022c222222222222222222222
007007000b33333223333332323333100b333310fcacccc9088888800000020000002000cc0d0ccccccc000007e2e8202100000022222c222222222222cccc22
0007700003332224423322242422331003333310fcccccc908888880cccc000cccc000cccc010cccccc065dd0e88882031000000222222222222222222cccc22
000770000a32444444224444444423300a333330fcccccc908888880ccccccccccccccccccc060cccc0d5111c0e8820c420000002cc2c2222222222222cccc22
007007000b324e2444444444444423100b332210fcccccc908888880ccccccccccccccccccc0d0cccc051000cc0e20cc510000002cc222222222222222cccc22
0000000003224214444444442444423003224230fcccccc908888880ccccccccccccccccccc0d0cccc0d10ccccc00ccc65000000222222222222222222222222
0000000002444444444444444444442002444420a999999400000000ccccccccccccccccccc010cccc0000cccccccccc7d000000222222222222222222222222
4444444004444444444444444444444004444440c1cccccc00000000c05050cc0501050cccc0d0cc0000000011111111820000000b030050ccccccc22ccccccc
444442bb0944444444444444444444200a444420161ccccc09040420c03030cc0300030cccc010cc777777771111111194000000c0b3350ccccccc2222cccccc
44444423044444444444444444444420094444201761cccc00000210c03030cc030030cccc060cccdddddddd11111111a9000000c0eb520cccccc222222ccccc
444444420944444444444444444444400444444017751ccccccc0000c010030c010030cccc0d0ccc1111111111111111b30000000e788820cccc22222222cccc
4444444409444444444444444444442009444420177751cccccccccccc0c030cc0c010cccc0d0ccc1111111111111111c10000000e888620ccc2222222222ccc
444444440444444444444444444444400944444017711ccccccccccccccc010ccccc0ccccc010ccc1111111111111111d5000000c0e8820ccc222222222222cc
4444444409444444444444444444442009444420c1161cccccccccccccccc0ccccccccccccc060cc1111111111111111e2000000c0e6820cc22222222222222c
4444444404444444444444444444444004444440ccccccccccccccccccccccccccccccccccc0d0cc1111111111111111f0000000cc0e20cc2222222222222222
0444444404444444444444444444444004444440cccc0cccccc000ccccccccccccccccccccc060cccccc00000000ccccccc0ccccccc00ccc2222222222222222
bb2444440a44444444444444444424200a444420ccc0700ccc07070cccccccccccccccccccc0d0cccc008888888800cccc080ccccc0880ccc22222222222222c
324444440942444444444444e244442009444420ccc07660c0770070ccccccccccccccccccc0d0ccc08889999998880cc097f0ccc080080ccc222222222222cc
2444444409444444444444442144441009444410cc00606007770070c0ccccccc0cc0cccccc010ccc0899aaaaaa9980c0a777e0c08020020ccc2222222222ccc
4444444404444444444444444444444004444440c0776001067700700a0c0ccc0a00a0cccc060ccc0889aaaaaaaa9880c0b7d0cc08001020cccc22222222cccc
44444444094444444444444444444420094444200777601cc06700600b00a00c0b0b0c0ccc0d0ccc089aa777777aa980cc0c0cccc080020cccccc222222ccccc
4444444404242224424242244212421004224210c07601cccc060601c0b0b0b00b0b00b0cc0d0ccc089aa777777aa980ccc0cccccc0220cccccccc2222cccccc
4444444410000000000000000000000110000001cc001cccccc0001cc030303003030030cc010ccc089aa777777aa980ccccccccccc00cccccccccc22ccccccc
44444444100000000000000000000001100000018ccc0ccc8cc000cccc000cccc00cc00ccc0d0ccc089aa777777aa980c00000ccc00cc00c0000000000000000
4e2444440ab3ab33b3abb3bb3bb3ab300ab3bb3028c0700c2807070cc077700c04400440cc010ccc089aa777777aa92008009a0c07e008800000000000000000
421444440b33333233333333323333100b333310c2807660c28700700744265004ffff40ccc060cc089aa777777aa9200200a0a00e8888200000000000000000
4444442403332224223322332422331003333310cc2860600728007007777650c01ff10cccc0d0cc0889aaaaaaaa9820080090900e0880200000000000000000
444444440a32444444224422444423300a333330c072800c067280700777760cc0f7ef0cccc0d0ccc0899aaaaaa9920c0200a0a00e8888200000000000000000
444244440b32444444444444444423100b332210077728ccc0672860c07770cc0ffeeff0ccc010ccc08889999999220c08289a0cc088820c0000000000000000
4444444403242242224221422421423003224230c076028ccc06028ccc000ccc0ffffff0cc060ccccc008888822200ccc00000ccc0e0020c0000000000000000
4444444410000000000000000000000110000001cc00cc2cccc0002cccccccccc000000ccc0d0ccccccc00000000cccccccccccccc0cc0cc0000000000000000
cccccccccccccccccccccccccccccccccccccccc100000000000000000000001dddddd70000000000000000000000000076dd10ccccccccc07d51510cccccccc
ccc00cccccccccccccc00cccccc00cccccc00ccc077777777777777777777770dddddd7700000000000000000000000006d6d50ccccccccc0d5d5100cccccccc
cc0940ccccc00ccccc0940cccc0940cccc09400c077777777777777777777760dddddd57000000000000000000000000c07d10cccccccccc07d51510cccccccc
cc04f0cccc0940ccc004f0cccc04f00ccc04f0f0077777777777777777777770ddddddd5000000000000000000000000c06d50cccccccccc0d5d5100cccccccc
c07e810cc074f10c0f7e810cc07e81f0c07e810c077555555555555555555760dddddddd000000000000000000000000cc070ccccccccccc06d51510cccccccc
c0e8920cc0e8920cc0e8920c0fe8920cc0f8920c075dddddddddddddddddd570dddddddd000000000000000000000000cc060ccccc0000cc0d5d5100cc0000cc
c04f54f0c0f15f0cc04554f0c045540cc045540c075dddddddddddddddddd560dddddddd000000000000000000000000cc060cccc07dd10c05111000c07ee80c
c0d0010cc0d0010cc0d00010cc0d10ccc0d0001005dddddddddddddddddddd50dddddddd000000000000000000000000ccc0ccccc0d1100c00000000c0e8820c
cccccccccccccccccccccccccccccccccccccccc0dddddddddddddddddddddd007dddddd0000000000000000000000000dddddd0cccccccc07111150cccccccc
ccc00cccccccccccccc00cccccc00cccccc00ccc06dddddddddddddddddddd5077dddddd00000000000000000000000007ddddd0cccccccc0d5d5100cccccccc
cc0ab0ccccc00ccccc0ab0cccc0ab0cccc0ab00c06dddddddddddddddddddd5075dddddd00000000000000000000000006dddd50cccccccc07d51510cccccccc
cc0b30cccc0ab0ccc00b30cccc0b300ccc0b303006dddddddddddddddddddd505ddddddd00000000000000000000000006dddd50cccccccc0d5d5100cccccccc
c0ae120cc0ab320c03ae120cc0ae1230c0a1520c0dddddddddddddddddddddd0dddddddd0000000000000000000000000dddddd0cccccccc06d51510cccccccc
c0b3850cc0b3810cc0b3850c03b3850cc03b850c06dddddddddddddddddddd50dddddddd00000000000000000000000006dddd50cccccccc0d5d5100cccccccc
c0e15130c031530cc0e55430c0b5340cc0b3540c06dddddddddddddddddddd50dddddddd0000000000000000000000000d55d510cc0000cc06d51510cc0000cc
c0b0010cc0b0010cc0b00010cc0b10ccc0b000100dddddddddddddddddddddd0dddddddd00000000000000000000000010000001c0d1100c0d555100c0e8820c
cccccccccccccccc00000000ccccccccc0cccc0c0dddddddddddddddddddddd0100000010000000000000000000000001000000000000000000000010dddddd0
cc0000cccccccccc00000000cc0000cc0700007007dddddddddddddddddddd500777777000000000000000000000000007777777777777777777777007dddd50
c077770cccc00ccc00000000c076560cc076560c06dddddddddddddddddddd50077777600000000000000000000000000777777777777777777777600ddddd50
c07cd60ccc0760cc0000000007051070cc0510cc06dddddddddddddddddddd500777776000000000000000000000000007777777777777777777777006dddd50
c07d160ccc0650cc00000000c0c00c0cccc00ccc0dddddddddddddddddddddd0077557600000000000000000000000000775555555555555555557500ddddd10
c076650cccc00ccc00000000cccccccccccccccc06dddddddddddddddddddd50075dd570000000000000000000000000075d65ddddddddddddddd51006ddddd0
cc0000cccccccccc00000000cccccccccccccccc0d51d55dd55d5d5dd5d5d510075dd560000000000000000000000000075551ddd51d55d5d5d5510006dddd50
cccccccccccccccc00000000cccccccccccccccc10000000000000000000000105dddd500000000000000000000000001000000000000000000000010dddddd0
cccccccccccccccccccccccc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
ccc00cccccc00cccccc0cccc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
cc07a0cccc07a0cccc070ccc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
c07a940ccc0a90cccc0a0ccc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
c0a9420ccc0940cccc090ccc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
cc0420cccc0420cccc040ccc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
ccc00cccccc00cccccc0cccc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
cccccccccccccccccccccccc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
b1b1b1b1b11131800012222121212121212121212121212121212121212121212121213180001121212121212121212121212121210130800012222222222221
21222222222232000012222222222221212121212121212121212121212121212121212121212131000011212121222222222222222232000012222222222121
b1b1b1b1b111310405810012222222222121222222212121212122222222222121032131000712212121212121212121212121212121310000e081e1e0007111
310000710000000000000036000000112121212121212121032121212121212121210321212121327080122121310071e4000000007100040005008100001121
b1b1b1b1b11131808000000071e4e2d0223200e4001121212132007100810511210321318000811121032121032121212121032121213280e1e0e0e0e0f10011
310016161616161616161616161600112121212121212121212121212121212121212121212132000000001121310000e5003640800000000700000040001121
b1b1b1b1b11131000072103036e5e2e0040082e50011212131000000f400701121212131000000112121212121212121212121212131e0e0f1e0e0e0d0e0e011
31001640000000000000000040160011212121212121212122222221212121212121212121327100708000122131071030000041000000000000000041001121
b1b1b1b1b111318000100201202020202020203000112121310040004000100221212121300070112121212121212121212122222232808000e0e0e0e0e0f111
31001641a1a1a1a1a1a1a1a141160011212121212222213105000011212121212121212132000000000000f11131001101308241800000000000007041f41121
b1b1b1b1b111310000122221212121210321213100112121310041e24100112121212121310000112121212121212121033100007100000000e0f0e0e0e00011
31001641b1b1b1b1b1b1b1b141160011212121310481112120303611212121212121213200000000708000e01231001121012031000000000000008211200221
b1b1b1b1b111318000d0f11222222121212121310011212131e041e241f11121212222213200701121222221212121212131001030808080e1e1f0e0f1e0e112
32001641b1b1b1b1b1b1b1b1411600122222222233001222223200122222222222223271360000000000e1e1e042001121212131800000360000001002212121
b1b1b1b11002310000e0f00071e01221210321310011212131e241e041e011213100714100000012318100112103212121310711310000e1e0e0e0e0e000e000
00001641b1b1b1b1b1b1b1b14116007100070000003600e40081000000e47100007100000000708000e1e1e0e081001121212131000000000000701121212121
202020200221013000e2e000e1d0f11121212131001121213100410041f0112131d40041d400610041d400112121212121310011318000e0e0e100000082e200
00051612232323232323232332160000000000720000d4e500008200d4e500820000000004000000e1e0e0f0e0f1001121212101300000000000001121212121
21212121212121012020203080e000112122223200112121310041074100112222307011203000001133701121212121213100113100e1e0e0f100050040e210
30801636000000000000000000167010202020202020202020202020202020202030000070800000e0e0e0e0e0e0001121212121013072000000100221212121
21222221212121222222223200e070113181e4000011212131d441a141a1410071410011213100704100001121210321213100113180e0e2e0e0007010212002
31001600001616161616160616160011212121212121212121212121212121212101300000000000e0e0f100f2e0f21121212103210120202020022121212121
3136001222223200e1f18100e1e000113100e500001122222223222322233200004270112132000041007011212121212131001131e0e2f0e000000011212121
310006161616000000000000000000112103212121212121212121212121212121210130000000e1e04000000000001121212121212121212121212121212121
31000700e481000000e00000e2e070113100132323320000710000e4000081000036001131000070423600112222222222320012328000e0e1e0701002212121
310000000000004000004000000000112121212121212121212121212121212121212101308200d0e01130720000361121212121212121212121212121212103
31000072e58282f400e0008200e0e21131000000820000d4007200e50000000000007012328080000000704200e4000081000000710000e0e000001121212121
31a1a1a1a1a1a141808041a1a1a1a1112121212121212121212121212121210321212121013000e0e21101300000001121212121212103212121212121212121
310010202020202020202020202020020120202020202020202020202020202030000400040000000000050000e5000000040400000072e00082100221212121
31b1b1b1b1b1b141070041b1b1b1b1112121212121032121212121212121212121212121210130e0e01121310005821121212121212121212121212121212121
31001121212121212121212121212121212121212121212121212121212121210120202020202020202020202030701030707070701030e27010022121212121
012020202020203170801120202020022121212121212121212121212121212121212121212131f2e01121012020200221212121212121212121212121212121
75005565656565656565656565656565656565656565656565656566666666666666666666666665656565656575005521212121212232007011212121212121
21212121212222320000122121212121212222222222222222222221212121212121212121223261001222222121212121212222222222222222222222222121
75005565656565656565656565656565656666666666666666667600f0e0f1e400000000c40000556566666676e4705521032121320071000012212121032121
212121213100008170800011212121213100000000000000000000122121210321212122327100000071e0e011210321213200e1e0e1e0e0f100000000001221
75005566666565656565656565656565760000000000c40000000000547400e50004000000000055750000e0d0e5005521212132e1d000076100122121212121
2121212132000000000000122222212131a1a1a1a1a1a1a1a1a1a1a112212121212131e000e1e061e0e0f1e01221212131000000e2e0e0e0e036000000000011
7500f6f1e056656565666666666666660016161616161616161616165584646464d6d6d6d6e600557570c6d6d6d6d68521213181e0f200000000361121212121
2103213171000700708000e40081112131b1b1b1b1b1b1b1b1b1b1b1b1112121212132e0e0e0e0e0e0e1f1360012212131000000e000d0f2e000000000000011
7500c5e0e0e0566676e0f0e0e400c400041636000000e1e0f1000000556565657500c400000000557500e1e0c4e0f25521213100f1f116161600001121212121
2121213200000036000000e500001121012020202030b1b1b1b1b1b1b11121212131e1e0e2e0d061e0e0e00000811121317070707080e1e0e200707070707011
7500e1d0f0f1e0e2e0e2e000e5360000741600f1e0f2e0e0e0e0f100556565657500000000c6d68584d6d6d6d6e68055212131e1e00016001600001121210321
212131e0e1e0f100001020307070112121212122220130b1b1b1b1b1b1112121213100e2f0e0e0e0d0e0e0f10000122131000000e2e1e100e2f1000000000011
750400e0e0e0e0005464646464646464750600e0e2e0d0e0e0e0f2e05565656575000000003600557500003600e0e055212132e0e2e016001600a01121212121