0 D$404mNJNL04e$FHuqaY}},m,Ҫm^ 2TvͫgE#2Tv2Tvwg5Rf˼UED3Ce'CvF(6 7(9 7(> 7(9 79 7:(9 7(6 7 0*0z:0?0-s:0??     P [[ [ P  P U [ [[ [ AdF@i@idFAAdF@i@i@i@idFADDAffdFdFAffDD [[V\UUQUUP P[k\\UUQQAI@i@iIAdF@naa@ndF`aaafiaaa``aaafiaaa``aaafIiaaa``aaafiaaa``aaafiaaa`iiiiFFFF((((((.N@ @ @ @ UP[kŶ[UU[[UP[˶eU[UUUUP0;3S[7{{[333[30{;U;Q73;35{uUS[{{;13U0{;0[0;3373{[[S[[[0{[73U;0{;0[0;33;3{[WS[{[0W50;S70;0;3SW[[u55;s3U73{;11[11;S73{[3SUW0;0[50{;S;3;S[W1{[3UU50{{;0[U;370[Q;3s;3{U3s[111s;Q;Q;3;3u5UWs;U5s71S;P[UU[[[UUU[UP[U[Q[U[UUUU[[QUUP[P[P[UU[U[[U[[[P[[UU[P[P[P[UU[U[[U[[P[UP[U[P[P[UU[[[UU[UU[U[QQ[QQ[U[U[UUU[P[P[UP[U[U[U[[Q[UUUUP[P[U[U[P[Q[U[UUU[QQQ[Q[Q[U[UUU[[UU[QU[P[P[P[PUUP[UU[DT[DTUUP[U[[UU[[P[UUU[[[UUU[PUPUUP[PU[U[U[UUUU[[UUUUP[P[UP[UU[U[[U[[[P[[PUU[P[P[UP[UU[U[[U[[P[UUP[PU[P[P[UUU[[[UU[UU[U[UU[UUU[U[U[UUU[P[P[UUP[PU[PU[U[[U[UUUUP[P[U[PU[P[UU[U[UUU[UUUUU[U[U[U[UUU[[UUU[UU[PUUP[U[U[P[UUPU[U[YəəY[U[UU[U[[[[U[UU[U[[[[U[UUP[UK[U[U˼[UPU[U[YəəY[U[UU[U[[[[U[UU[U[[[[U[UU[UU[U[[[[[UU[[[[[[[U[U[UUUUPUPUPUPUP[UUU[UU[P[U[[UPPUU[UU[U[[[[[UU[[[[[[[U[U[[[UU[[[UUU[[U[[[UUUP[UK[U[U˼[UPUUPUPUPUPUPPUUUPUPUUUP[UU[[[U[[U[[P[U[PUP[P[P[PUP[U[U[[U[[[[UU[P[PUUP[UU[DT[DTUUP[UPUP[UP[U[U[[UUUP[UPUPUwPUwPUwPUPUPUPUPUPUwWUwwUUUUUUUUU( ( ( (  ( (  ,LUUUPUPUPUPUPUfPUfUUfUUUPU^U^UPPPUUU0::: ADD@DD@DDDD@@D@@DD@DDDDD UPUPPPUUPPUPUUUUUPP  ppwppwppppwwww0::: App::f::pp33PPP[UUUU[PPP3333330333333330DDDDDD3333333330000\V\U[ZYXW][VUZW]XVXY\XUX[YUVZ]ZWY\WVW[]U PPPPPQPQPRPSTTUVVWXXYYZ[[\]^^_ 0@@PPPP@@0  ."" !/$/)"""&&%-/! ! "0*0$@%@&@'@)@+@,@-0/ %7          @ EEFFHHIId8i4d5e;l6#######ÝÙÔÚ##d#dd#d##d#d#d#d#eedeedeedeedeede%%%% '0000000 > 00 p w" p  " "" "" """pw p03   "p 0w3p 0p03wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww0wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww 0 "0300330300000333030333 0003333330"033033330 0000033033303033pw "[[003000033[ 000033033033lU 030333333PU0000333[U0030000330333[U PUp3 003033000000303330333330330300303p000330;30300330000330S;300 3S50330030030333S;33333[;3033303V3k\\U\U UU Q QUU[ Q[ pwU PU[U[UP pw" "" "" """ pwpp8-- title: Iron Star -- author: mannzerhacker -- desc: shmup -- script: lua list={ push=function(a,v) a[#a+1]=v return a end, string=function(a) local s='' for k,v in ipairs(a)do s=s..v..',' end return s end, filter=function(a,f) local b={} for k,v in ipairs(a)do if f(v)then b[#b+1]=v end end return b end, map=function(a,f) local b={} for i,v in ipairs(a)do b[#b+1]=f(v,i,a) end return b end, pick=function(a) return a[math.floor( math.random()*#a)+1] end, concat=function(a,b) local c={} for i,v in ipairs(a)do c[#c+1]=v end for i,v in ipairs(b)do c[#c+1]=v end return c end } function isAlive(c) return c.alive end mobs={} function moveMobs() for i,m in ipairs(mobs)do m:tic() end local dead=list.filter(mobs, function(m) return not isAlive(m) end ) list.map(dead,function(m) if m.onDead then m:onDead() end end) mobs=list.filter(mobs,isAlive) end function distance(m1,m2) local a=m1.x-m2.x local b=m1.y-m2.y local a2=a*a local b2=b*b local c2=a2+b2 local c=math.sqrt(c2) return c end function moveStar(s) s.x=s.x-s.d if s.x<0 then s.alive=false list.push(mobs,star()) end circ(s.x,s.y,s.d*2,s.c) end function star(x,y) local colors={2,3,7,8,10,13} return{ x=x or 240, y=y or math.random()*136, d=math.random()+0.1, c=list.pick(colors), alive=true, tic=moveStar, } end function moveExplosion(e) local colors={1,4,6,9,14} local s=e.size or 4 e.x=e.x-0.5 e.duration=e.duration-1 if e.duration<0 then e.alive=false end circ( e.x+math.random()*s-math.random()*s, e.y+math.random()*s-math.random()*s, math.random()*s+1, list.pick(colors) ) end function explosion(x,y,duration,onDead,size) sfx(0,'c-2',duration,3,10) return { alive=true, tic=moveExplosion, x=x, y=y, duration=duration or 20, onDead=onDead, size=size, } end function moveExhaust(e) local colors={1,4,6,9,14} e.duration=e.duration-1 if e.duration<0 then e.alive=false end e.x=e.x-0.2 local c=e.duration>24 and 5 or e.duration>18 and 4 or e.duration>12 and 3 or e.duration>6 and 2 or 1 circ(e.x,e.y,math.random()*2,colors[c]) end function exhaust(x,y) sfx(0,'c-4',20,1,2) return { alive=true, tic=moveExhaust, x=x, y=y, duration=30 } end function moveBullet(b) b.x=b.x+2 if b.x>240 then b.alive=false end b.f=(b.f+0.25)%2 spr(b.o+b.t+b.f,b.x,b.y,0) end function bullet(x,y,t,o) sfx(1,'c-4',40,2,4) return{ alive=true, tic=moveBullet, x=x, y=y, t=t or 0, f=0, o=o or 10, } end function moveShip(s) local leader=cache.ships[1] local len=#cache.ships s.f=(s.f+0.5)%4 s.e=(s.e+1)%2 if s.e==0 and not btn(2) then list.push(mobs,exhaust(s.x-1,s.y+3)) end if s==cache.ships[2] and btnp(4+8)then s.p2=true end if s==cache.ships[1]then s.p2=false if btn(2) then s.x=s.x-s.s s.f=6 s.energy=s.energy+0.2 end if btn(3) then s.x=s.x+s.s s.f=7 s.energy=s.energy-0.1 end if btn(0) then s.y=s.y-s.s s.f=4 end if btn(1) then s.y=s.y+s.s s.f=5 end elseif s==cache.ships[2] and s.p2 then if btnp(4+8) then s.p2=true end if btn(2+8) then s.x=s.x-s.s s.f=6 s.energy=s.energy+0.2 end if btn(3+8) then s.x=s.x+s.s s.f=7 s.energy=s.energy-0.1 end if btn(0+8) then s.y=s.y-s.s s.f=4 end if btn(1+8) then s.y=s.y+s.s s.f=5 end else for i,v in ipairs(cache.ships)do if v==s then if leader then s.f=leader.f local pv=math.pi*2*i/(len-1)+time()/1000 s.x=leader.x+math.cos(pv)*10 s.y=leader.y+math.sin(pv)*10 end end end end s.energy=s.energy+ math.cos(s.energy/100)/10 if s.energy>100 then s.energy=100 end line(0,135,240*s.energy//100, 135,s.energy<=50 and 2 or 8) if btnp(4) and s.energy>0 and not s.p2 then list.push(mobs,bullet(s.x,s.y)) s.energy=s.energy-4 end if btnp(4+8) and s.energy>0 and s.p2 then list.push(mobs,bullet(s.x,s.y,0,74)) s.energy=s.energy-4 end if btnp(5) and s.energy>50 and s==leader and len>1 then cache.ships[#cache.ships].alive=false cls(14) list.push(mobs,explosion(s.x,s.y,60,nil,60)) s.energy=s.energy-50 addEvent(30,function() cls(9) list.push(mobs,explosion(s.x,s.y,60,nil,60)) end) list.map(mobs,function(m) if m.tic==movePew then m.alive=false end end) end if btnp(7) then TIC=pause end if s.x<0 then s.x=0 end if s.y<0 then s.y=0 end if s.x>231 then s.x=231 end if s.y>127 then s.y=127 end if s.p2 then spr(s.f+64,s.x,s.y,0) else spr(s.f,s.x,s.y,0) end end function shipDead(s) list.push(mobs,explosion( s.x+4,s.y+4,180,function() if #cache.ships==0 then init() end end)) end function ship(x,y) sfx(2,'D-6',20,3) addEvent(10,function() sfx(2,'A-6',20,3) end) addEvent(20,function() sfx(2,'G-6',20,3) end) return{ x=x or 100, y=y or 136/2, s=1, f=0, e=0, alive=true, tic=moveShip, onDead=shipDead, energy=(cache.ships[1] and cache.ships[1].energy) or 0, } end function isShip(mob) return mob.tic==moveShip end function isBullet(mob) return mob.tic==moveBullet or mob.tic==moveExhaust or mob.tic==moveExplosion end function isEnemy(mob) return mob.tic==moveMonster or mob.tic==moveSaucer or mob.tic==moveMine or mob.tic==moveBoss end function checkCollision(m1) return function(m2) local d=distance(m1,m2) local l=(m1.size or 3)+(m2.size or 3) if dm.x then m.x=m.x+m.s end if ship.xm.y then m.y=m.y+m.s end if ship.y240 then s.speed=s.speed*-1 s.y=s.y-18 end s.y=s.y+math.cos(s.x/16) s.t=(s.t+0.25)%2 if s.t==0 then s.f=list.pick({0,1})end if math.random()<0.001 then list.push(mobs,pew(s.x,s.y)) end spr(32+s.f,s.x,s.y,0) local collider=checkCollision(s) list.map(cache.collidables,collider) end function saucer(x,y) return{ tic=moveSaucer, alive=true, onDead=smallExplosion(), x=x or 240, y=y or math.random()*88+20, t=0, f=list.pick({0,1}), speed=1, } end function boss(x,y) local egg= math.random()<0.2 and monster or math.random()<0.1 and mine or math.random()<0.05 and saucer return{ tic=moveBoss, alive=true, onDead=egg and function(m) list.push(mobs,egg(m.x,m.y)) end or smallExplosion(), x=x or 236, y=y or math.random()*88+20, t=0, f=0, dx=1, dy=math.random(), speed=1, boss=true, egg=egg, r=4 } end function isBoss(m) return m.boss end function moveBoss(m) bosses=list.filter(mobs,isBoss) while math.abs(m.dx)+math.abs(m.dy)> m.speed do m.dx=m.dx*0.9 m.dy=m.dy*0.9 end m.x=m.x+m.dx m.y=m.y+m.dy local last=nil for i,b in ipairs(bosses)do if b==m and last and distance(m,last)>15 then m.dx=last.x-m.x m.dy=last.y-m.y break end last=b end if m.x>240 or m.x<0 or math.random()<0.01 then m.dx=(math.random()-math.random())*3 if m.x>240 then m.x=240 end if m.x<0 then m.x=0 end end if m.y>136 or m.y<0 or math.random()<0.01 then m.dy=(math.random()-math.random())*3 if m.y>136 then m.y=136 end if m.y<0 then m.y=0 end end if math.random()<0.1 then m.r=math.random()*3//1+3 end if m==bosses[1] then local p1=cache.ships[1] if p1==nil then return end local ox,oy=(p1.x-m.x)/240*5, (p1.y-m.y)/136*5 circ(m.x,m.y,10,15) circb(m.x,m.y,10,7) circ(m.x+ox,m.y+oy,5,6) circb(m.x+ox,m.y+oy,5,1) circ(m.x+ox,m.y+oy,m.r/2,0) if math.random()<0.02*#cache.ships then list.push(mobs,boss()) end else m.t=m.t+1 if m.egg then if m.egg==monster then spr(16+m.t//50%4,m.x-3,m.y-3,0) elseif m.egg==mine then spr(48+m.t//50%5,m.x-3,m.y-3,0) elseif m.egg==saucer then spr(32+m.t//30%2,m.x-3,m.y-3,0) end circb(m.x,m.y,m.r+2,11) else circb(m.x,m.y,m.r,11) end circb((m.x+last.x)/2, (m.y+last.y)/2,3,5) end local collider=checkCollision(m) list.map(cache.collidables,collider) end function mine(x,y) return{ tic=moveMine, alive=true, onDead=kaboom, x=x or 240, y=y or math.random()*136, t=0, f=0, speed=0.1, } end function moveMine(m) m.x=m.x-m.speed m.t=m.t+1 m.f=m.t//60%5 if m.x<-8 then m.alive=false end spr(48+m.f,m.x,m.y,0) local collider=checkCollision(m) list.map(cache.collidables,collider) end function kaboom(m) list.push(mobs,pew(m.x,m.y,-1,0)) list.push(mobs,pew(m.x,m.y,1,0)) list.push(mobs,pew(m.x,m.y,0,-1)) list.push(mobs,pew(m.x,m.y,0,1)) list.push(mobs,pew(m.x,m.y,-1,-1)) list.push(mobs,pew(m.x,m.y,1,1)) list.push(mobs,pew(m.x,m.y,-1,1)) list.push(mobs,pew(m.x,m.y,1,-1)) end function moveOneUp(o) o.x=o.x-0.25 spr(8,o.x,o.y,0) if o.x<-8 then o.alive=false end list.map(cache.ships,function(s) local d=distance(o,s) if d<6 then o.alive=false local s=cache.ships[#cache.ships] if s then list.push(mobs,ship(s.x,s.y)) sfx(2,'D-6',20,3) addEvent(10,function() sfx(2,'A-6',20,3) end) addEvent(20,function() sfx(2,'G-6',20,3) end) end end end) end function oneUp(x,y) sfx(2,'C-6',20,3) addEvent(10,function() sfx(2,'G-6',20,3) end) addEvent(20,function() sfx(2,'A-6',20,3) end) return{ x=x, y=y, alive=true, tic=moveOneUp, } end function movePew(p) p.t=(p.t+1)%4 if p.t==0 then p.f=list.pick({0,1})end p.x=p.x-p.dx p.y=p.y-p.dy if p.x>240 or p.x<-8 or p.y>136 or p.y<-8 then p.alive=false end local collider=checkCollision(p) list.map(cache.ships,collider) spr(37+p.f,p.x,p.y,0,1,p.dx>0 and 0 or 1) end function pew(x,y,dx,dy) local speed=1 local ship=not dx and list.pick(cache.ships) dx,dy=dx or 1,dy or 0 if ship then dx=x-ship.x dy=y-ship.y end while math.abs(dx)+math.abs(dy)>speed do dx=dx*0.9 dy=dy*0.9 end return{ alive=true, tic=movePew, x=x, y=y, dx=dx, dy=dy, f=0, t=0, } end function moveCreep(c) c.x=c.x-1 spr(c.f,c.x,c.y,0) if c.x<-8 or c.y>136 or c.y<0 then c.alive=false local collider=checkCollision(c) list.map(cache.ships,collider) end end function creep(x,y,g) g=g or 8 x=x or 240 y=y or math.random()<0.5 and 0 or 136-8 local p=g/10+0.1 if math.random()