0,]']>S}Wup8d%qy)6o;]AsVl3+;?>>=?>??4?U?w?h?>?7>??<%?H>d?d>V>5?*)+///////////////////////////,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,------------------------------gZacc ccCc cc cc ccc cc_a#CCCCCC CC## CCC CC C C C C CCC#CCC CCC D`f DPf  Pa#CCCCCC CC## CCC CC C C C C CCC#CCC CCC_fbd  a aa ?@@@@@@    @@@@@@@@@@@@    @@@@@@@@@ @@- -@ O-O  - @  @@ @@ @    // ............ =-- title: Montezuma's Revene -- author: Michal Cieslik -- desc: A remake of Montezuma's Revenge in a Castle -- script: lua COLS=30 ROWS=17 PLAYER_SPRITE=256 FALL_DIST_DAMAGE=4 ENTITY={} ENTITYNONEX={} SAVEDATA={ lives=5, x=20,y=70, Rkeys=0, Pkeys=0, points=0, levelNo=24 } function render() map(levelToX(Game.levelNo),levelToY(Game.levelNo),COLS,ROWS) updateEntities() interface() if Plr.vx>=0 then spr(playerSprite(), Plr.x, Plr.y, 0) else spr(playerSprite(), Plr.x, Plr.y, 0,1,1) end updateLevel() end function renderStart() map(levelToX(0),levelToY(0),COLS,ROWS) updateEntities() print("MONTEZUMA'S\n REVENGE",30,52,13,false,3) print("Press A to continue",65,102,12,false,1) end --Scans the whole map, adds the -- enemies found into the ENEMIES -- table with the following format: -- [spriteNum, x, y, alive,levelNo,xdirection] function initialEntityScan() tempX=levelToX(Game.levelNo) tempY=levelToY(Game.levelNo) --scan the map for x=tempX,tempX+COLS,1 do for y=tempY,tempY+ROWS,1 do temp=mget(x,y) --if a tile is an entity... if temp>=111 then --..add the entity into the entity list table.insert(ENTITY,{temp,x,y,1,Game.levelNo,2,0}) if not (temp==136 or temp==137 or temp==138) then mset(x,y,64) end end end end end function enemyMovement() return t%5==0 end function enemyWalk() return t%10==0 end function enemyJump() return t%120==0 end function spikeMovement() return t%15==0 end function laser() return t%40==0 end a=0 function animateEnemySpin(i,x,y,advance) spriteNo=ENTITY[i][1] if advance then if spriteNo%2==0then spriteNo=spriteNo+1 ENTITY[i][1]=spriteNo else spriteNo=spriteNo-1 ENTITY[i][1]=spriteNo if a<3 then a=a+1 else a=0 end end end spr(spriteNo,x,y,0,1,0,a) end function animateEnemySpike(i,x,y) spriteNo=ENTITY[i][1] if spikeMovement() then if spriteNo%2==0then spriteNo=spriteNo+1 ENTITY[i][1]=spriteNo else spriteNo=spriteNo-1 ENTITY[i][1]=spriteNo end end spr(spriteNo,x,y,0) end function animateEnemyJump(i,x,y,advance,pos) if advance then if ENTITY[i][1]%2==0then ENTITY[i][1]=ENTITY[i][1]+1 else ENTITY[i][1]=ENTITY[i][1]-1 end end spr(ENTITY[i][1],x,y,0,1,pos) end function animateEnemyLaser(i,x,y) if laser() then if ENTITY[i][1]==134 then ENTITY[i][1]=135 else ENTITY[i][1]=134 end end spr(ENTITY[i][1],x,y,0) end function updateEnemy(i) --Get all the necessary info about the entity x=(ENTITY[i][2]-levelToX(Game.levelNo))*8 vx=ENTITY[i][6] y=(ENTITY[i][3]-levelToY(Game.levelNo))*8 vy=ENTITY[i][7] s=ENTITY[i][1] --sprite number --Rolling Enemy if s<=117 then if solid(x+vx,y+vy) or solid(x+7+vx,y+vy) or solid(x+vx,y+7+vy) or solid(x+7+vx,y+7+vy) then if vx == 2 then vx=-2 else vx=2 end end if solid(x+vx,y+8+vy) or solid(x+7+vx,y+8+vy) then vy=0 else vy=vy+.1 end --Move the enemy when the time is right if enemyMovement() then x=x+vx y=y+vy animateEnemySpin(i,x,y,true) end animateEnemySpin(i,x,y,false) --Jumping Enemy elseif s<=123 then if solid(x+vx,y+8+vy) or solid(x+7+vx,y+8+vy) then vy=0 else vy=vy+.1 end if solid(x+vx,y+vy) or solid(x+7+vx,y+vy) or solid(x+vx,y+7+vy) or solid(x+7+vx,y+7+vy) then if vx == 2 then vx=-2 else vx=2 end end if enemyJump() and vy==0 then vy=-5 end if enemyWalk() then if vx>0 then pos=0 else pos=1 end x=x+vx y=y+vy animateEnemyJump(i,x,y,true,pos) end animateEnemyJump(i,x,y,false,pos) --Stationary Spike-type enemy elseif s<134 then vx=0 vy=0 animateEnemySpike(i,x,y) --Stationary Laser Enemy elseif s==134 or s==135 then vx=0 vy=0 animateEnemyLaser(i,x,y) --Doors elseif s==136 or s==137 or s==138 then vx=0 vy=0 if s==137 then ENTITY[i][4]=0 elseif mget(x/8+levelToX(Game.levelNo),y/8+1+levelToY(Game.levelNo))==137 or mget(x/8+levelToX(Game.levelNo),y/8-1+levelToY(Game.levelNo))==137 then ENTITY[i][4]=0 mset(x/8+levelToX(Game.levelNo),y/8+levelToY(Game.levelNo),137) end end --save the enemy info in ENTITY ENTITY[i][2]=(x/8)+levelToX(Game.levelNo) ENTITY[i][3]=(y/8)+levelToY(Game.levelNo) ENTITY[i][6]=vx ENTITY[i][7]=vy end function updateEntities() for i in pairs(ENTITY)do if ENTITY[i][5]==Game.levelNo then --Calculate (x,y) positions of entities entityX=(ENTITY[i][2]-levelToX(Game.levelNo))*8 entityY=(ENTITY[i][3]-levelToY(Game.levelNo))*8 --Check whether player intercepts the entity xField=Plr.x>=entityX-4 and Plr.x<=entityX+4 yField=Plr.y>=entityY-4 and Plr.y<=entityY+4 if ENTITY[i][1]==149 then yField=Plr.y>=entityY-4 and Plr.y<=entityY+12 end --Handling Enemies if ENTITY[i][1]<=138 then if ENTITY[i][4]>0 then --Handling Player Interaction if xField and yField and ENTITY[i][1]<=134 then damagePlayer(1) end --Handling Position and Animation updateEnemy(i) end else --Handle Item Pickup and Display if ENTITY[i][4]>0 then if xField and yField then if playerPickup(ENTITY[i][1]) then ENTITY[i][4]=0 end end if ENTITY[i][1]==149 then spr(ENTITY[i][1],entityX,entityY,0,1,0,0,1,2) else spr(ENTITY[i][1],entityX,entityY,0) end end end end end end function playerPickup(spriteNo) if spriteNo==144 then Plr.Rkeys=Plr.Rkeys+1 Game.startingx=Plr.x Game.startingy=Plr.y elseif spriteNo==145 then if Plr.lives<5 then Game.startingx=Plr.x Game.startingy=Plr.y Plr.lives=Plr.lives+1 else return false end elseif spriteNo==146 then Game.startingx=Plr.x Game.startingy=Plr.y Plr.points=Plr.points+100 elseif spriteNo==147 then Game.startingx=Plr.x Game.startingy=Plr.y Plr.points=Plr.points+200 elseif spriteNo==148 then Game.startingx=Plr.x Game.startingy=Plr.y Plr.points=Plr.points+500 elseif spriteNo==149 then Game.startingx=Plr.x Game.startingy=Plr.y Plr.Pkeys=Plr.Pkeys+1 end return true end function deloadEntities() for a in pairs(ENTITY)do table.insert(ENTITYNONEX,ENTITY[a]) end ENTITY={} for b in pairs(ENTITYNONEX)do if ENTITYNONEX[b][5]==Game.levelNo then table.insert(ENTITYNONEX,a) end end end function savePoint() if Plr.x>240 then SAVEDATA.x=Plr.x-10 end if Plr.x<0 then SAVEDATA.x=Plr.x+10 end if Plr.y>240 then SAVEDATA.y=Plr.y-10 end if Plr.y<0 then SAVEDATA.y=Plr.y+10 end SAVEDATA.lives=Plr.lives SAVEDATA.Rkeys=Plr.Rkeys SAVEDATA.Pkeys=Plr.Pkeys SAVEDATA.points=Plr.points SAVEDATA.levelNo=Game.levelNo end function updateLevel() if Plr.x>=240 then if Game.levelNo<=64 then Game.levelNo=Game.levelNo+1 Game.startingy=Plr.y Game.startingx=Plr.x-239 Plr.x=Game.startingx --deloadEntities() initialEntityScan() end elseif Plr.x<=0 then if Game.levelNo>0 then Game.levelNo=Game.levelNo-1 Game.startingy=Plr.y Game.startingx=Plr.x+232 Plr.x=Game.startingx --deloadEntities() initialEntityScan() end elseif Plr.y<=0 then if Game.levelNo>=8 then Game.levelNo=Game.levelNo-8 Game.startingy=Plr.y+127 Game.startingx=Plr.x Plr.y=Game.startingy --deloadEntities() initialEntityScan() end elseif Plr.y>=128 then if Game.levelNo<=64 then Game.levelNo=Game.levelNo+8 Game.startingy=Plr.y-127 Game.startingx=Plr.x Plr.y=Game.startingy --deloadEntities() initialEntityScan() end end if Game.levelNo==25 or Game.levelNo==20 or Game.levelNo==13 or Game.levelNo==14 or Game.levelNo==23 or Game.levelNo==45 or Game.levelNo==60 or Game.levelNo==42 or Game.levelNo==41 then savePoint() Game.saving=true else Game.saving=false end end --Converts level number to the corresponding x coordinate -- of the (0,0) position on the current level function levelToX(level) temp=level while temp>=8 do temp=temp-8 end return temp*COLS end --Same as x, but with y function levelToY(level) temp=level levely=0 while temp>=8 do levely=levely+ROWS temp=temp-8 end return levely end function interface() lives=Plr.lives Rkeys=Plr.Rkeys Pkeys=Plr.Pkeys points=Plr.points k=0 if Plr.y<20 then k=110 end for i = 5,1,-1 do spr(274,85+i*10,10+k,0) end for i = lives,1,-1 do spr(273,85+i*10,10+k,0) end for i = Rkeys,1,-1 do spr(275,140+i*10,11+k,0) end for i = Pkeys,1,-1 do spr(276,20+i*10,11+k,0) end print(points,65,12+k,14) end --Animation Timing Helpers function aHair() return t%20==0 end function aWalk() return t%10==0 end function aHurt() return t%20==0 end sprite=256 i=0 function playerSprite() --Standing Animation if Plr.vx==0 and Plr.vy==0 and Plr.grounded then if aHair() then if i==0 then i=1 else i=0 end end sprite=256+i end --Walking Animation if not (Plr.vx == 0) and Plr.grounded then if aWalk() then if i==0 then i=1 else i=0 end end sprite=258+i end --Jumping Animation if not Plr.grounded and not Plr.climb then if Plr.vy<0 then sprite=260 else sprite=261 end end --Climbing Animation if Plr.climb then if Plr.vy==0 then sprite=263 else if aWalk() then if sprite==263 then sprite=264 else sprite=263 end end end end --Punching Animation if Plr.punch then sprite=262 end --Damaged Animation if Plr.damaged then sprite=265 if aHurt() then Plr.damaged=false end end return sprite end function solid(x,y) tile=mget((x)//8+levelToX(Game.levelNo),((y))//8+levelToY(Game.levelNo)) return tile<30 or tile==136 or tile==138 end function platform(x,y) tile = mget((x)//8+levelToX(Game.levelNo),((y))//8+levelToY(Game.levelNo)) return (tile>6 and tile<11) or (tile>22 and tile<29) end function Rdoor(x,y) return mget((x)//8+levelToX(Game.levelNo),((y))//8+levelToY(Game.levelNo))==136 end function Pdoor(x,y) return mget((x)//8+levelToX(Game.levelNo),((y))//8+levelToY(Game.levelNo))==138 end function ladder(x,y) cx=levelToX(Game.levelNo) cy=levelToY(Game.levelNo) temp = (mget( (x+4)//8+cx, (y+5)//8+cy) == 32) return temp or (mget( (x+8)//8+cx,(y+5)//8+cy) == 33) end function platformRight(x,y) return (mget((x)//8+levelToX(Game.levelNo),(y)//8+levelToY(Game.levelNo))==25) or (mget((x+7)//8+levelToX(Game.levelNo),(y)//8+levelToY(Game.levelNo))==23) or(mget((x+7)//8+levelToX(Game.levelNo),(y)//8+levelToY(Game.levelNo))==24) or (mget((x+7)//8+levelToX(Game.levelNo),(y)//8+levelToY(Game.levelNo))==25) end function platformLeft(x,y) return (mget((x+7)//8+levelToX(Game.levelNo),(y)//8+levelToY(Game.levelNo))==26) or (mget((x+7)//8+levelToX(Game.levelNo),(y)//8+levelToY(Game.levelNo))==27) or (mget((x+7)//8+levelToX(Game.levelNo),(y)//8+levelToY(Game.levelNo))==28)or (mget((x)//8+levelToX(Game.levelNo),(y)//8+levelToY(Game.levelNo))==28) end function checkpoint(x,y) return (mget((x)//8+levelToX(Game.levelNo),(y)//8+levelToY(Game.levelNo))==138) end function updatePlayer() --Player Input if btn(2) and not Plr.damaged then Plr.vx=-1 elseif btn(3) and not Plr.damaged then Plr.vx=1 else Plr.vx=0 end if btn(4) then Plr.punch=true end if not (btn(4))then Plr.punch=false end --Jumping if btnp(6) and Plr.vy==0 and Plr.grounded then Plr.jump=true Plr.climb=false Plr.vy=-2.7 Plr.grounded=false end --Climbing if ladder(Plr.x+Plr.vx,Plr.y+Plr.vy) then Plr.climb=true Plr.grounded=true if btn(0) then Plr.vy=-1 elseif btn(1) then Plr.vy=1 else Plr.vy=0 end else Plr.climb=false Plr.grounded=false end --Horizontal Collisions if solid(Plr.x+Plr.vx,Plr.y+Plr.vy) or solid(Plr.x+7+Plr.vx,Plr.y+Plr.vy) or solid(Plr.x+Plr.vx,Plr.y+7+Plr.vy) or solid(Plr.x+7+Plr.vx,Plr.y+7+Plr.vy) then Plr.vx=0 end --Vertical Collisions TODO if Plr.vy<0 and (solid(Plr.x+Plr.vx,Plr.y+Plr.vy) or solid(Plr.x+7+Plr.vx,Plr.y+Plr.vy)) then Plr.vy=0 end if not Plr.climb then Plr.vy=Plr.vy+0.21 Plr.grounded=false end if (solid(Plr.x+Plr.vx,Plr.y+7+Plr.vy) or solid(Plr.x+7+Plr.vx,Plr.y+7+Plr.vy)) then if Plr.vy>FALL_DIST_DAMAGE then damagePlayer(1) end Plr.vy=0 Plr.grounded=true end --Door if Plr.punch and Rdoor(Plr.x+Plr.vx+8,Plr.y+Plr.vy) then if Plr.Rkeys>0 then Plr.Rkeys=Plr.Rkeys-1 savePoint() mset((Plr.x+Plr.vx)/8+1+levelToX(Game.levelNo),(Plr.y+Plr.vy)/8+levelToY(Game.levelNo),137) end elseif Plr.punch and Rdoor(Plr.x+Plr.vx-8,Plr.y+Plr.vy) then if Plr.Rkeys>0 then Plr.Rkeys=Plr.Rkeys-1 savePoint() mset((Plr.x+Plr.vx)/8-1+levelToX(Game.levelNo),(Plr.y+Plr.vy)/8+levelToY(Game.levelNo),137) end elseif Plr.punch and Pdoor(Plr.x+Plr.vx+8,Plr.y+Plr.vy) then if Plr.Pkeys>0 then Plr.Pkeys=Plr.Pkeys-1 mset((Plr.x+Plr.vx)/8+1+levelToX(Game.levelNo),(Plr.y+Plr.vy)/8+levelToY(Game.levelNo),137) end elseif Plr.punch and Pdoor(Plr.x+Plr.vx-8,Plr.y+Plr.vy) then if Plr.Pkeys>0 then Plr.Pkeys=Plr.Pkeys-1 mset((Plr.x+Plr.vx)/8-1+levelToX(Game.levelNo),(Plr.y+Plr.vy)/8+levelToY(Game.levelNo),137) end end --Movement Platform if platformRight(Plr.x+Plr.vx,Plr.y+8+Plr.vy) then Plr.vx=Plr.vx+.8 end if platformLeft(Plr.x+Plr.vx,Plr.y+8+Plr.vy) then Plr.vx=Plr.vx-.8 end --Update Player Position Plr.x=Plr.x+Plr.vx Plr.y=Plr.y+Plr.vy if Plr.jump and Plr.grounded==false then sfx(1,'E-3') Plr.jump=false end if checkpoint(Plr.x,Plr.y) then Game.startingx=Plr.x Game.startingy=Plr.y end end function damagePlayer(x) if not Plr.damaged then Plr.x=Game.startingx Plr.y=Game.startingy Plr.damaged=true if Plr.lives-x>=0 then Plr.lives=Plr.lives-x else Game.mode="Game Over" end end end function restartFromSave() Game.levelNo=SAVEDATA.levelNo Plr.lives=SAVEDATA.lives Plr.x=SAVEDATA.x Plr.y=SAVEDATA.y Plr.Rkeys=SAVEDATA.Rkeys Plr.Pkeys=SAVEDATA.Pkeys Plr.points=SAVEDATA.points Plr.grounded=true Plr.punch=false Plr.climb=false Plr.damaged=false updatePlayer() render() initialEntityScan() end function renderFromTutorial() map(levelToX(1),levelToY(1),COLS,ROWS) print("Tutorial",60,15,13,false,3) print("To move, press",15,51,13) spr(304,110,50,0) spr(306,100,50,0) print("To open doors, press",15,70,13) spr(308,130,68,0) print("Red Keys",160,51,13) spr(275,210,50,0) print("Purple\n Keys",170,67,13) spr(276,210,69,0) print("Points:",35,90,13) spr(146,75,89,0) spr(147,87,89,0) spr(148,99,89,0) print("Health:",140,90,13) spr(145,190,89,0) -- print("Press A to continue",65,120,12,false,1) end function init() music(0) Plr={ lives=5, x=20,y=70, vx=0,vy=0, grounded=true, punch=false, climb=false, damaged=false, Rkeys=0, Pkeys=0, points=0, jump=false } Game={ mode="Start", levelNo=0, startingx=0, startingy=0, saving=false } updatePlayer() render() initialEntityScan() end t=0 init() function TIC() if Game.mode=="Start" then renderStart() if btnp(5,1,50) then -- A button Game.mode="Tutorial" Game.levelNo=24 end elseif Game.mode=="Tutorial" then renderFromTutorial() if btnp(5,1,50) then -- A button Game.mode="Game" end elseif Game.mode=="Game" then render() updatePlayer() if Game.saving then print("Save Point",5,130,12) end if Game.levelNo==24 then initialEntityScan() spr(309,115,22,0) print("Health Bar",92,35,13) spr(309,64,22,0) print("Points",52,35,13) spr(309,169,23,0) spr(313,149,14,0) spr(314,157,14,0) spr(314,165,14,0) spr(314,173,14,0) spr(314,181,14,0) spr(315,189,14,0) end elseif Game.mode=="Game Over" then --render() print("GAME OVER",40,60,13,false,3) print("Press A to restart", 65,100) if btnp(5,0,50) then restartFromSave() Game.mode="Game" end end t=t+1 end --NOTES: Player should snap to ladders -- Add save points -- Add