0,]']±>Sï}WÿÂ¥§ðp8·d%qy)6o;]ÉA¦öÿÞYôôô”°ÂVl†3???????????????????????t88ð8à8Ð?????????????????????????? 78:;<=>???????????????????????u;;<???????????????????????????     @@ppppppppppp p p p p ppp|;<<<<<<<<<=12 then es=es+1 end if v.cd>0 then es=es+16 end drawObj(v,es) end --player if alive then local sp=257 if player.f%24>=12 then sp=258 end if player.inv%30>=15 then sp=sp+16 end drawObj(player,sp) end --sword local sx,sy=sword.x-4,sword.y-2 if player.dir==1 then sx=player.x+4 end sx=sx-(offset.x*8) sy=sy-(offset.y*8) sp=259 if player.cd>0 then sp=260 end spr(sp,sx,sy,0,1,player.dir,0,1,2) --FX for k,v in pairs(fx) do if v.txt~=nil then local clr=12 if v.l<=15 then clr=15 elseif v.l<=30 then clr=14 elseif v.l<=45 then clr=13 end print(v.txt,v.x,v.y,clr,false,1,true) else spr(v.cs,v.x-(v.w*4),v.y-(v.h*4),0,1,0,0,v.w,v.h) end end --particles for k,v in pairs(particles) do pix(screenX(v),screenY(v),v.c) end --UI print("Level "..level,1,1,12) for i=1,player.hp do spr(262,208+(8*i),2) end if levelClear then printCenter("JUSTICE DELIVERED",54) if level==15 then printCenter("GAME COMPLETE",61) printCenter("Z: Return to Menu",71) else printCenter("Z: Next Level",64) end elseif not alive then printCenter("EVIL PREVAILS",54) printCenter("Z: Retry Level",64) printCenter("X: Back to Menu",74) end end function drawObj(obj,i) local dir=obj.dir or 0 spr(i,screenX(obj),screenY(obj),0,1,dir) end function gameCtrl() if player.inv>0 then player.inv=player.inv-1 end if player.cd>0 then player.cd=player.cd-1 end if btn(3) and not player.climbing then --move right player.x=player.x+1 player.f=player.f+1 player.dir=1 colDetX() elseif btn(2) and not player.climbing then --move left player.x=player.x-1 player.f=player.f+1 player.dir=0 colDetX() else player.f=0 end if btn(4) and player.m==0 then player.m=jumpHeight player.climbing=false playSound(0) end if btn(0) then local mapY=player.y/8 local mapXA=math.floor((player.x+2)/8) local mapXB=math.floor((player.x+5)/8) mapY=math.floor(mapY) --check for lever if btnp(0) then for k,v in pairs(levers) do if v[2]==mapY and math.abs(v[1]-mapXA)<2 then createMapAnim(v[1],v[2],2,v[3]) if v[3]==1 then playSound(9) else playSound(10) end v[3]=-v[3] for j,w in pairs(v[4]) do createMapAnim(w[1],w[2],w[3],w[4]) w[4]=-w[4] end end end end --check for ladder local tile1=mget(mapXA,mapY) local tile2=mget(mapXB,mapY) if fget(tile1,4) or fget(tile2,4) then player.climbing=true player.m=0 player.y=player.y-0.5 end elseif btn(1) then local mapY=player.y/8 local mapXA=math.floor((player.x+2)/8) local mapXB=math.floor((player.x+5)/8) mapY=math.floor(mapY) local tile1=mget(mapXA,mapY) local tile2=mget(mapXB,mapY) if fget(tile1,4) or fget(tile2,4) then player.climbing=true player.m=0 player.y=player.y+0.5 end end if btnp(5) and player.cd==0 then attack() playSound(1) end if btnp(7) then resetLevel() end end function clearCtrl() if btnp(4) then if level==15 then prevLevel=0 pmem(0,0) goToMenu() else nextLevel() end end end function deadCtrl() if dieDelay>0 then dieDelay=dieDelay-1 else if btnp(4) then alive=true resetLevel() elseif btnp(5) then goToMenu() end end end function menuDraw() cls() spr(48,55,2,0,1,0,0,13,2) spr(80,155,2,0,1,0,0,4,2) spr(112,59,20,0,1,0,0,8,2) spr(144,126,20,0,1,0,0,7,2) if menuScr==0 then printCenter("New Game",60) if prevLevel==0 then printCenter("Continue",70,13) else printCenter("Continue",70) end printCenter("Controls",80) printCenter("Options",90) spr(448,70,60+menuSel*10) spr(449,160,60+menuSel*10) print("Made in 72 hours for Ludum Dare 53.",1,130,12) if showWarning then rect(45,50,150,50,0) rectb(45,50,150,50,12) printCenter("Are you sure you want to",53) printCenter("erase your previous save",60) printCenter("and start a new one?",67) printCenter("Yes",81) printCenter("No",91) spr(448,102,81+subSel*10) spr(449,128,81+subSel*10) end elseif menuScr==1 then print("Left/Right:",54,60,12) print("Up:",100,67,12) print("Down:",85,74,12) print("Z:",105,81,12) print("X:",105,88,12) print("S:",105,95,12) print("Move",120,60,12) print("Climb ladders/Use levers",120,67,12) print("Descend ladders",120,74,12) print("Jump/Select",120,81,12) print("Swing sword/Cancel",120,88,12) print("Restart level",120,95,12) printCenter("Kill all enemies, then rescue the captive!",110) printCenter("X: Back",130) elseif menuScr==2 then print("Music:",80,70,12) print("SFX:",90,80,12) print("Blood:",80,90,12) for k,v in pairs(options) do local c="On" if v==1 then c="Off" end print(c,120,60+k*10,12) end if options[subSel+1]==1 then spr(449,110,70+subSel*10,0) elseif options[subSel+1]==0 then spr(448,139,70+subSel*10,0) end printCenter("X: Save and Return",130) end end function menuCtrl() if menuScr==0 then if btnp(0) then if showWarning and subSel==1 then subSel=0 playSound(13) elseif menuSel>0 then menuSel=menuSel-1 playSound(13) end elseif btnp(1) then if showWarning and subSel==0 then subSel=1 playSound(13) elseif menuSel<3 then menuSel=menuSel+1 playSound(13) end end if btnp(4) then if menuSel==0 then if prevLevel>0 then if showWarning then if subSel==0 then startGame() else showWarning=false end else showWarning=true end else startGame() end elseif menuSel==1 then if prevLevel>0 then resumeGame() else playSound(15) end elseif menuSel==2 then menuScr=1 playSound(16) elseif menuSel==3 then menuScr=2 playSound(16) end end elseif menuScr==1 then if btnp(5) then menuScr=0 playSound(14) end elseif menuScr==2 then if btnp(0) and subSel>0 then subSel=subSel-1 playSound(13) elseif btnp(1) and subSel<2 then subSel=subSel+1 playSound(13) end if btnp(2) and options[subSel+1]==1 then options[subSel+1]=0 playSound(13) if subSel==0 then playMusic(0) end elseif btnp(3) and options[subSel+1]==0 then options[subSel+1]=1 playSound(13) if subSel==0 then music() end end if btnp(5) then menuScr=0 playSound(16) for k,v in pairs(options) do pmem(k,v) end end end end function attack() player.cd=30 local col={} local x,y=player.x,player.y if player.dir==0 then instantiateFx(1,screenX(player),screenY(player)+6) col={x1=x-8, x2=x, y1=y-2, y2=y+14} elseif player.dir==1 then instantiateFx(2,screenX(player)+8,screenY(player)+6) col={x1=x, x2=x+16, y1=y-2, y2=y+14} end for k,v in pairs(enemies) do eCol={ {x=v.x, y=v.y}, {x=v.x+7,y=v.y}, {x=v.x, y=v.y+7}, {x=v.x+7,y=v.y+7} } for j,w in pairs(eCol) do if w.x>=col.x1 and w.x<=col.x2 and w.y>=col.y1 and w.y<=col.y2 and v.cd==0 then v.hp=v.hp-1 v.cd=15 end end end end function startGame() menu=false playing=true alive=true level=0 nextLevel() end function resumeGame() menu=false playing=true alive=true level=prevLevel-1 nextLevel() end function nextLevel() level=level+1 levelClear=false prevLevel=level --save progress pmem(0,level) local data=levelData[level] offset={x=data.o[1],y=data.o[2]} resetLevel() end function resetLevel() local data=levelData[level] player={ x=data.p[1]*8, y=data.p[2]*8, hp=3, f=0, m=-0.2, dir=data.p[3], inv=0, isPlayer=true, climbing=false, cd=0 } damsel={x=data.d[1]*8,y=data.d[2]*8,dir=data.d[3]} wiggle=math.random(240,360) sword={x=player.x,y=player.y,m=0} enemies={} fx={} particles={} for k,v in pairs(levelEnemies[level]) do local eData=bestiary[v.b] table.insert(enemies,{ x=v.x*8, y=v.y*8, sp=eData.sp, hp=eData.hp, mp=v.mp, ms=eData.ms, dir=v.dir, cd=0, f=0 }) end crates={} for k,v in pairs(levelCrates[level]) do table.insert(crates,{ x=v.x*8, y=v.y*8, m=0 }) end mapAnims={} for k,v in pairs(levers) do mset(v[1],v[2],13) v[3]=1 for j,w in pairs(v[4]) do mset(w[1],w[2],w[5]) w[6]=w[4] end end end function screenX(obj) return obj.x-(offset.x*8) end function screenY(obj) return obj.y-(offset.y*8) end function moveObjects() --FX processFX() --particles processParticles() --sword if not alive then applyGravity(sword) else sword.x=player.x sword.y=player.y end --damsel if not levelClear then wiggle=wiggle-1 if wiggle==0 then damsel.x=damsel.x-1 wiggle=math.random(240,360) elseif wiggle==12 then damsel.x=damsel.x+2 elseif wiggle==24 then damsel.x=damsel.x-2 elseif wiggle==36 then damsel.x=damsel.x+2 elseif wiggle==48 then damsel.x=damsel.x-1 end end --enemies for k,v in pairs(enemies) do local mp=movePatterns[v.mp] if v.cd>0 then v.cd=v.cd-1 if v.cd==0 and v.hp==0 then if options[3]==0 then createBurst(v.x,v.y,1) else createBurst(v.x,v.y,2) end table.remove(enemies,k) playSound(2) end else --X axis if mp.x1~=nil then if v.dir==0 then v.x=v.x-v.ms else v.x=v.x+v.ms end local x1=mp.x1*8 local x2=mp.x2*8 if v.x<=x1 then v.x=x1 v.dir=1 elseif v.x>=x2 then v.x=x2 v.dir=0 end end --Y axis if mp.y1~=nil then if v.vdir==0 then v.y=v.y-v.ms else v.y=v.y+v.ms end local y1=mp.y1*8 local y2=mp.y2*8 if v.y<=y1 then v.vdir=1 elseif v.y>=y2 then v.vdir=0 end end --animate v.f=v.f+1 --check for player collision if math.abs(v.x-player.x)<8 and math.abs(v.y-player.y)<8 then playerHit() end end end --crates for k,v in pairs(crates) do applyGravity(v) end end function applyGravity(obj) if obj.climbing~=nil and obj.climbing then return end obj.y=obj.y+obj.m local hitGround=false local mapY=obj.y/8 if obj.m>=0 then local mapXA=math.floor((obj.x+2)/8) local mapXB=math.floor((obj.x+5)/8) mapY=math.floor(mapY)+1 local tile1=mget(mapXA,mapY) local tile2=mget(mapXB,mapY) if fget(tile1,7) or fget(tile2,7) then if obj.isPlayer~=nil and obj.inv==0 then playerHit() end hitGround=true elseif fget(tile1,0) or fget(tile2,0) then hitGround=true end if not hitGround then --check for crates for k,v in pairs(crates) do if v.y-obj.y<8 and v.y-obj.y>0 and math.abs(v.x-obj.x)<8 then hitGround=true end end end end if hitGround then if obj.m>1 then playSound(5) end obj.y=(mapY-1)*8 obj.m=0 elseif obj.m<8 then obj.m=obj.m+grav end end function playerHit() if player.inv>0 then return end playSound(3) player.hp=player.hp-1 if player.hp==0 then die() else player.inv=120 end end function die() alive=false playSound(15) dieDelay=60 if options[3]==0 then createBurst(player.x,player.y,1) else createBurst(player.x,player.y,2) end end --collision detection notes: --fget(0): can collide with top --fget(1): can collide with right --fget(2): can collide with bottom --fget(3): can collide with left function colDetX() local sp={x=0,y=math.floor(player.y/8)} local flag=-1 --moving right? if player.dir==1 then if player.x%8==3 then sp.x=math.ceil(player.x/8) flag=3 end --moving left? elseif player.dir==0 then if player.x%8==5 then sp.x=math.floor(player.x/8) flag=1 end end --check collision flags local tile=mget(sp.x,sp.y) if fget(tile,6) then player.y=player.y-1 elseif flag~=-1 and fget(tile,flag) then --solid object; stop if player.dir==0 then player.x=player.x+1 else player.x=player.x-1 end elseif fget(tile,7) then playerHit() end --check for crates for k,v in pairs(crates) do if math.abs(v.y-player.y)<8 and math.abs(v.x-player.x)<8 then if canMove(v,player.dir) then moveCrate(v,player.dir) if player.dir==0 then player.x=player.x+0.5 else player.x=player.x-0.5 end end end end end function canMove(obj,dir) local c=math.ceil(obj.x) local flag=3 if c%8==0 then local cx=(c/8)+1 local cy=obj.y/8 if dir==0 then cx=(c/8)-1 flag=1 end tile=mget(cx,cy) if fget(tile,flag) then return false else return true end else return true end end function moveCrate(obj,dir) if dir==1 then obj.x=obj.x+0.5 elseif dir==0 then obj.x=obj.x-0.5 end playSound(7) for k,v in pairs(crates) do --is on top? if obj.y-v.y==8 and math.abs(obj.x-v.x)<8 then if canMove(v,dir) then moveCrate(v,dir) end --is in front? elseif obj.y==v.y and math.abs(obj.x-v.x)==7.5 then if canMove(v,dir) then moveCrate(v,dir) end end end end function colDetY() local mapY=player.y/8 local mapXA=math.floor((player.x+2)/8) local mapXB=math.floor((player.x+5)/8) applyGravity(player) --have you hit something above you? if player.m<0 then mapY=math.floor(mapY) local tile1=mget(mapXA,mapY) local tile2=mget(mapXB,mapY) if fget(tile1,2) or fget(tile2,2) then player.y=player.y-player.m player.m=player.m*-1 playSound(5) end end end function clearCheck() if math.abs(player.x-damsel.x)<8 and player.y==damsel.y then if #enemies==0 then levelClear=true playSound(6) else printCenter("Vanquish enemies first!",120) end end end function instantiateFx(i,x,y,d) d=d or 0 local f=fxLibrary[i] table.insert(fx,{ x=x, y=y, vx=f.vx or 0, vy=f.vy or 0, w=f.w or 1, h=f.h or 1, ss=f.s, cs=f.s, as=f.as, l=f.l, sl=f.l, r=f.r, delay=d, }) end function processFX() for k,e in pairs(fx) do e.x=e.x+e.vx e.y=e.y+e.vy if e.delay~=nil and e.delay>0 then e.delay=e.delay-1 else e.l=e.l-1 if e.l==0 then if e.r~=nil and e.r>1 then table.insert(fx,{ ss=e.ss, cs=e.ss, x=e.x, y=e.y, w=e.w, h=e.h, vx=e.vx, vy=e.vy, as=e.as, l=e.sl, sl=e.sl, r=e.r-1, w=e.w, h=e.h }) end table.remove(fx,k) elseif e.l%e.as==0 then e.cs=e.cs+e.w end end end end function printCenter(str,y,clr) clr=clr or 12 local x=120-(print(str,0,200,0)/2) print(str,x,y,clr) end function logo() cls() ic=ic+1 local l,t=0,0 if (ic>=10 and ic<20) or (ic>=220 and ic<230) then l=470 t=456 elseif (ic>=20 and ic<30) or (ic>=210 and ic<220) then l=468 t=472 elseif (ic>=30 and ic<40) or (ic>=200 and ic<210) then l=466 t=488 elseif ic>=40 and ic<200 then l=464 t=504 end if ic==270 then goToMenu() playMusic(0) end if l>0 then spr(l,112,44,0,1,0,0,2,3) spr(t,104,71,0,1,0,0,4,1) end end function goToMenu() playing=false intro=false menu=true menuScr=0 menuSel=0 end function playSound(id,c) c=c or 3 if options[2]==0 then sfx(id,nil,-1,c) end end function playMusic(id) if options[1]==0 then music(id) end end function createMapAnim(x,y,s,dir,r) table.insert(mapAnims,{ x=x, y=y, f=1, s=s, dir=dir, r=r or nil }) end function processMapAnims() for k,v in pairs(mapAnims) do v.f=v.f+1 if v.f%8==0 then mset(v.x,v.y,mget(v.x,v.y)+v.dir) end if v.f/8==v.s then if v.r~=nil then v.f=0 v.dir=-v.dir else table.remove(mapAnims,k) end end end end function processParticles() for k,v in pairs(particles) do v.x=v.x+v.vx v.y=v.y+v.vy v.l=v.l-1 if v.l==0 then table.remove(particles,k) end end end function createBurst(x,y,i) local b=burstLibrary[i] for j=1,b.n do createParticle(b,x,y) end end function createParticle(obj,x,y) local r=math.random(obj.r[1],obj.r[2]) local l=math.random(obj.pl[1],obj.pl[2]) local v=math.random(obj.v[1]*10,obj.v[2]*10)/10 local c=obj.c[math.random(#obj.c)] --calculate momentum local rot=math.rad(r) local vx=math.sin(rot)*v local vy=-math.cos(rot)*v table.insert(particles,{ x=x, y=y, vx=vx, vy=vy, l=l, c=c }) end