0 @$404mJJJL04e$FHuqa },m,m^ `2Tv޼xV4!CeͫTvxBe޼V4fUD3#"""23CTevQwOr}E UUUUDDDDDDDDIDDDDDIDDDDDDDDDDDDDDDDDDIDDDDDIDDDD77ssw37s7s3w77ssw37s7s3wwwwwUQUUQQUQUQU7777wwwws37333333s373333s37s33333s3s3333s3s333333s373333s37s33333333ws7w33337ws73333s7ws3333ws7wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwppwDDDDDDDD33333333Q뻻UUUUUUUU[UUUUU[UUUUUUUUUUUUUUUUUU[UUUUU[UUUUIIDIIDIIDIIDDDDDUUUUQQQQQ."..""""""""""""""""""""""""'"-'""""""""""""""""""""""""-"/-""""""""""""""""""""""""wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwppwppwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww@@@@@@@@00000000ݪڭڪݭݪڭڪUUUU[[[[QQQQQQQ""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwpwppwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww@@DD@DDDDDDDDDD@DD@DD@0033033333333330330330QQQQQQDDDDNNDNNDNNDNND>>33>>33>>33>>wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww""""""""""""""""""""""r"""r""r""""r""r""r"""""""""""""""""""""""""wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpppppwpp`ff63?c6?c63?c63?c63?c6c`ff`ff6?c63c63?c63c6?3c6c`ff`ff6?c63c6?c63c63c6?c`ffDDDDDDDDDDDDDDIDDDDDIDDDD77ssw37s7s3w77ssw37s7s3swwwwPUUUP UU UUUUUUUUUUpwwwpwwwwwwwwwwwwppUU[[UUUQ[U[P U[ UUU U Pwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwppwppw030000003000000003000303`ff6c6?3c6?c6?3c6?3c6?3c`ff UPUU[UUUUUU UPUP[UU[UUUUUw0333s033303s033C433000UUwwwpwpwwwpwwwwwwpwwPPP[ P[U[UUUUUUwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwpwppwpppwwww7ww7ww7ww77www70333pwww`ffff``ffffpwwwffffffff""**""""*"*  "* """ " ""--""""-"-  "- """ " 3033?333333PUUUP UU UUUUUUUUUU@@UU[[UUUT[U[P U[ UUU U P   wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww " ""*""""""wwww7w7ww7w7w7www70333fff```fffffffffff   ""  * *"*""""""   ""  - -"-""""""3030?33?33333UUD@D@DDD@DDDDDD@DD@@@@DD@PPP[ P[U[UUUUUU  " " *""*"""""wwwww7w77ww7ww7www70333 DDD DDD [U[U -"-" ``V`UV`U pp 'p"'p"ofof  [U[U IDIDwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww7ww77ww7ww7www70333wwwww7ww77w7ww7www70333wwwww7ww77ww7ww7www70333`ff ^^__ "" Z Z __0330330<<`ff`oo`ooff`ff` `ff`nn`nnffffff``qwpwqqwwqwwPPPPUU^ ^PUUUUUUP@DDPPUU II䙞NINDIDs77w?sw7ss?3w7s3wwwwwwwwssss 陙 ```ffn n`ff```  nnkf zzwwzww @D f`fffffff`fff`  氻 n ߐ zwpw 3333 ` k nnnf f`  ````ffn n`ffffff``ffnnnn`ffff``PUU^^^^PUUUUPP`ff`ff`nn`nnffff`ff NNDD`ff`nn`nnff`ff` 陙 l ```ffnn`ff``` ssss333377773333ssss333377ssw37s7s3w77ssw37s7s3wwwwwIIDIIDIIDIIDDDDDݪڭڪݭݪڭڪݙNNDNNDNNDNNDUUUUDDDDIIIIDDDDDDDDUUUUUUUU[^[^UUUUUUUUUQUUQQUQUQU3333ws7w33337ws73333s7ws3333ws7w@@@@UUUUeUUeUUUUUeUUUUPP`ffnnnn`ffff``"""""""""""""""    `f```ff`ff``ff`f`ffff`ff`f`ff`ff`ff``ff```fffff`ff`ffff`ff`ffff`````ff`f`ff`ff`ff`f`ff`ff`ff``ff```````f`ff`f`````ff`ff``f````f`ffwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww0??0333?0003330003330 n` 03333@D@@ @@@   wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww0??0333?00ww77ww033ww0s70wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww ??0033?00??0333 ?0 ;33;33;3;;;;3;33 03333 { p00ppp00p0ppppffff`fff0033000330    ~y @@@@@@@@@@@@wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwqqwwqwwzzwwzww `fff   0330330030>0<<3>3<<NDDNODDODDNNDD@@@DD@C4@C4@33@DDUQQQQQQQQQQQQQQQQQQQQQ _U[U /"-" `_`UV`U p /p"'p" lfof  _U[U ODIDwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww [U_U -"/" ``VU_U pp '"/"oflf  [U_U IDOD```ffnnn `f`f`````ffnn`nn`ff`f`` `ffnnnn`fff`f`wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww  `ff`nn`nnffffffffwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww "..""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww 陙 ninf `fr"/-r"""""""""""""""""""""""""""r""""""""""""""""r""rr"r""r""r""""""""""r""r"""r""r"""r"""""""""""""""  wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwffffffffff`fff  l "/-"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""`ffnnnn`fff`f`PUU^^^^PUUUPUP`ff`nn`ff`nn`nnffff`ffffff wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww` k wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww PPPUU^^^ PUUUUUPPPPUU^^P^^PUUUUUUPPwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww 陙  `f`ff`f`f`f``f``f`fff`f`nknf 00DI33 wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww n  3333wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww`ff`nn`nnff``ff`ff`nn`nnff`ff`wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww  ```ffnnn `fffff````ffnn`nn`ffffff``wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww`ff`oo`ooff``ff`ff`oo`ooff`ff`wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww```ffnnn`f`f`````ffnn`nn`ff`f`` ppppwpwwpwpppwwpwwpwwwwwpwwwppppppppwppwppwpwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwP66PQ6e8׆6PPP$LJ86$EPPPׇ86EZ$Z8$6ZgPeZe86PQPPP$xZ86E$ZZZZIPEQ86QZZEPPeQ8$6$Z$IZI^xZee8^PQZ6ZZZ^Z&&&PPQZ$Q$Z8ZZZxxePQe8PPPEPZ8Z$837000070000ee333170000QQ270000%%QQQ^270000%QQ%%%%%%%%%e1111270000^%g%x%%%%%%%%%%%%x222211112713333%0000%%%xxx%Q%%%Z%%%%%%%%%%%227233333^%0000%%%e%%%%%eP%%%e%%%%%%%%%%%%%%i2272333331%%%%0000g%%%%%%%%%0000%%%%%%Zx%%%P%%%%%%%%%%%%%%%%%%227221111%%%g%%%0000%%%%%%x%%%%0000P%%%%%%%%%%g%%%%%%%%%%%%%%%%%%zzz11112111272''''233312222%%%%%%g%%%%000%%%%%%%%%%%%%%%%%0000g%%00%%%%%ZZP%%%%%%%%%%%%%%%%%%%%%i1111222222221111272'2122222%%%%%%Z%%%%%%%%%000%%%%%%%%%%%%%%%%%%%%%%%%%0000xx%%%00%%%%%Q%%%%%%%%%%%%%%%%%%%%%z1111222222222i7221222222%%%%%%%%%%%%%%%%%%%%%%000g%%%%%%%%%%%%%%%%%%%%%%%%%%%0000%%%%00%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%1111222222222222272212222222%%%%xxx%%%%%%%%%%%%%%%%%%%%%%%%%%%%%000P%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0000%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%222222222222222221111722222222222222222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%000%%%%%%%%%%%%%3333033333^0^ň3333333333e0333ǂ711e0e33371220%%i33333i371222Lj%%%%e044%%%%33712222%%%%%E%%%%0%%%%1111311113722222E%%%%%%%%%%%%0%%%%22223i11122223i722222%%%%%%%%%%%%%%E0%%%%2222322222223i122222^%%%%%%%%%%%%%%%%%%%0%%%%2222111Ăii22222223i111222222ee%%%%%%%%%%%%%%%e%%%%0%%%%222222211122222221i1111222222222222E%%%%%%%%%%%%%%%%%%%%%%0%%%%22222222222222211111111222222221112222222222222222EEE%%%%%%%%%%%%%%%%%%%%%%0%%%%222222222222222222211112222222222221112222222222222222222%%%%%%%%%%%%%%%%%%%%%%%%%%%%0%%%%2222222222222222222222222222222222222222222222222222222222222%%%%%%%%%%%%%%%%%%%%%%%%%%%%%0%%%%g####3Z##::::Pg::::::3333Pg$ZZ::::::ZZ^::::::!!iP:::::!""!!!^1Lj$ZZ::::!"""G211113ZZ$$:::!""""!!!2222211111dt`:!"""""!!!"""2222222222G!!:""""""""""""22222222i221i(P$""!!!!:""""""""""""22222222222z((P$g$$G!!!"""""":"""""""""""""""22222222111122211333331z^PQZPPl!!!"""""!"""":"""""""""""""""22222222zzzizz1112222111222221111ii3333321z(gP!!!"""""""""""""""":"""""""""""""""22222222zzzz1111111122222222222222222221133221111ZZZZZZ!"""""""""""""""""""":"""""""""""""""22222222zz11112222111222222222222222222222222111112222222"""""""""""""""""""""""""""""":"""""""""""""""222222221111222222222222222222222222222222222222221122222222222###!########8:::"#e8:::`l"#e8e:::!###!"`xe8:::!"q#!!!""qgZZ8eZ:::!!!##!::"""####8PP:::"""`:::"###""qq`###!!!g!!gg^8e:::{:!::"""!!qqq{"""!!""!!!xxxee8P:::!!!!!!g::::"""""!!!!!!g^"""!PPP!!!""""!!!!!!!!!!xZ8:::""""""!qq::::""!!"""x""""g!!!"""""""!!!""""PP""""""8`:::"""""""!!!!q`::::"##""""!!!!!!"""!"Pg""""""""""""""!!""""""ee8e:::"""""""""""!{::::""""""""""!!!!!g!!"""""!!!!xg""""""""""""""!!!!""""""""Z8Z^!!!:::""""""""""""!!::::"""""""""""""""!!"""""!!!""""""!!!!x""""""""""""""""""""""""""e((""":::""""""""""""""!"``{{{!""""""""""""""!!!""""""""""""""""""""g!!!"""""""""""""""""""""""""""""!::""""""""""""""""{{{{{{!!!"""""""""""""""!!"""""""""""""""""""""""xx"""""""""""""""""""""""""""""""""::""""""""""""""""""""!!!!!!!!"""""""""""""""""""""""""""""""""""""""""""!!!!"""""""""""""""""""""""""""""::::::4`::::%%q::::%%q:::``::%)%Dž%%%%%%:q::l%%%q::%Dž%%%%%%%%%%%%%%%%%%:`::%%%%%%%^::%%%%%%%%%%%%%%%%%%%%%%%:q`::%%%%%%%%%%%%%q::%%%q%%%%`%%%%%%%%%%%%%%%%`:%::%%%%%%%%%%%%%:%`%%%%%%%`%%%%%%%%%%%q%%%%%%%%%%%%%%%%q:q%%%%%::%%%%%%%%%%%%%%%%%`:%%%%%%%%%`%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%qqq%%%%%%%%%`:%%%%:%%%%%%%%%%%%%%%%%%:%%%%%%%%%%q%%%%%%%%%%%%%%%%%%%%`%%%%%%%%%%%%%%%%%%%%%%%%%%%%~%%%%%%%%%%%%`:%%%%:%%%%%%%%%%%%%%%%%%%%%%:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%^%%%%%%%%%%%%%%%%`q%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%qq`%%%%%%%%%%%%%%:%%%%:%%%%%%%%%%%%%%%%%%%%%%%%%%%:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%q%%%%%%%%%%%%%%%%%%%%%%:%%%%:%%%%%%%%%%%%%%%%%%%%%%%%%%%%:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%:%%%%:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"""""=>>? =""""""""""""//"""""? =.>.""""""""""""BCDBCD}|MN MN""""""##########]m2222"""""}= ?222222""""?.>.MN\22222222"""22222222"GHGHū^_>= ?= ?>22222222MN,WXWXnoMNL22222##############################MN<222##############################|] {KJIHHGGFFEEEEFFGHHIIJJKKKLLMMMYZ[]]^^^______________________ 000000000000000000000000000000komololokoiojolojoiojokomononoS            S                       gjnnooooooooooooooooooooooooooreihiiYjYkIl9lm mnnnoooooooooooooooooo,FFFffFFFffFFFffFFFffFFFffFFFffFFFffFFFff$$$$$$$$$$FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF$$$$$$$$$$$$$$$$jJjJjJjJjJjJjJjJjJjJjJjJjJjJjJjJ$$$$$$$$$$$$$$$$fFffFffFffFffFffFffFffFfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff$$$$$$$$$$$$$$$$hhhhhhhhhhh``````````````````00P`TeTemTaTaTuTThhL\nnm?          ------""""""------""""""           ----""""----""""ڭڭڭڭڭڭڭڭݪݪݪݪݪݪݪݪݪݪڪݭڪݭڪݭڪݭڪڪݭڪݭڪݭڪݭڪڭڭڭڭڭڭڭڭݪݪݪݪݪݪݪݪݪݪڪݭڪݭڪݭڪݭڪڪݭڪݭڪݭڪݭڪ `` `ffppwpw n pwwwwwwwwww wwww n`ffffwwww wwww`ffffffpwwwwpwwww``p p``wwp wwp `ffffffff00www wwwffffffp p`wwww`pwwpww`333pw pwffww ww ffpww pww ff0www www ffڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪڭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪڭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪڭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭڭݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪݪڭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪݭڪ J-- title:8 Bit Panda Great Adventure -- author:OtherGuy24 -- original made by Bruno Oliveira -- desc:new levels -- script:lua -- saveid:8bitpandagreatadventure1.07 TEST1=false TEST2=false NAME="8-BIT PANDA GREAT ADVENTURE" AUTHOR="2024 OtherGuy24" C=8 ROWS=17 COLS=30 SCRW=240 SCRH=136 JUMP_DY={-3,-3,-3,-3,-2,-2,-2,-2, -1,-1,0,0,0,0,0} SWIM_JUMP_DY={-2,-2,-1,-1,-1,-1,0,0,0,0,0} RESURF_DY={-3,-3,-2,-2,-1,-1,0,0,0,0,0} ATK_SEQ={1,1,1,1,2,3,3,3} DIE_SEQ={{-1,-1},{-2,-2},{-3,-3},{-4,-4}, {-5,-5},{-6,-5},{-7,-4},{-8,-3},{-8,-2}, {-8,1},{-8,3},{-8,5},{-8,9},{-8,13}, {-8,17},{-8,21},{-8,26},{-8,32},{-8,39} } SX_MIN=50 SX_MAX=70 SOL={ NOT=0, HALF=1, FULL=2, } FIRE={ DUR=1000, INTERVAL=20, OFFY=2,OFFX=7,OFFX_FLIP=-2, OFFX_PLANE=14,OFFY_PLANE=8, COLL={x=0,y=0,w=3,h=3}, } T={ EMPTY=0, HPLAF1=4, HPLAF2=20, HPLAF3=36, SURF1=16, SURF2=22, SURF3=23, SURF4=24, SURF5=25, SURF6=26, WATER1=32, WATER2=38, WATER3=39, WATER4=40, WATER5=41, WATER6=42, WFALL1=48, WFALL2=54, WFALL3=55, WFALL4=56, WFALL5=57, WFALL6=58, TARMAC=52, FIRST_DECO=64, GATE_L=110,GATE_R=111, GATE_L2=142,GATE_R=143, FIRST_ENT=128, FIRST_META=240, META_NUM_0=240, META_A=254, META_B=255, } TPAT={ [69]={w=2,h=2}, [71]={w=2,h=2}, [73]={w=2,h=2}, [94]={w=2,h=2}, [96]={w=2,h=2}, [98]={w=2,h=2}, [101]={w=2,h=2}, [103]={w=2,h=2}, [105]={w=2,h=2}, } TSOL={ [T.EMPTY]=SOL.NOT, [T.HPLAF1]=SOL.HALF, [T.HPLAF2]=SOL.HALF, [T.HPLAF3]=SOL.HALF, [T.SURF1]=SOL.NOT, [T.SURF2]=SOL.NOT, [T.SURF3]=SOL.NOT, [T.SURF4]=SOL.NOT, [T.SURF5]=SOL.NOT, [T.SURF6]=SOL.NOT, [T.WATER1]=SOL.NOT, [T.WATER2]=SOL.NOT, [T.WATER3]=SOL.NOT, [T.WATER4]=SOL.NOT, [T.WATER5]=SOL.NOT, [T.WATER6]=SOL.NOT, [T.WFALL1]=SOL.NOT, [T.WFALL2]=SOL.NOT, [T.WFALL3]=SOL.NOT, [T.WFALL4]=SOL.NOT, [T.WFALL5]=SOL.NOT, [T.WFALL6]=SOL.NOT, } TANIM={ [T.SURF1]={T.SURF1,316}, [T.SURF2]={T.SURF2,332}, [T.SURF3]={T.SURF3,348}, [T.SURF4]={T.SURF4,364}, [T.SURF5]={T.SURF5,380}, [T.SURF6]={T.SURF6,396}, [T.WFALL1]={T.WFALL1,317,318,319}, [T.WFALL2]={T.WFALL2,333,334,335}, [T.WFALL3]={T.WFALL3,349,350,351}, [T.WFALL4]={T.WFALL4,365,366,367}, [T.WFALL5]={T.WFALL5,381,382,383}, [T.WFALL6]={T.WFALL6,397,398,399}, } S={ PLR={ STAND=257, WALK1=258, WALK2=259, JUMP=273, SWING=276, SWING_C=260, HIT=277, HIT_C=278, DIE=274, SWIM1=290,SWIM2=291, FIRE_BAMBOO=261, FIRE_F=288, FIRE_P=289, FIRE_S=307, SUPER_F=304, SUPER_P=305, SUPER_S=306, }, EN={ A1=181, A2=197, A3=213, A4=155, A5=156, B1=176, B2=154, DEMON1=171, DEMON2=187, DEMON3=203, DEMON4=219, DEMON5=205, DEMON_THROW1=346, DEMON_THROW2=362, DEMON_THROW3=378, DEMON_THROW4=394, DEMON_THROW5=458, SDEMON1=173, SDEMON2=189, SDEMON4=221, SDEMON_THROW1=426, SDEMON_THROW2=442, SDEMON_THROW4=474, PDEMON1=159, PDEMON2=175, PDEMON3=191, PDEMON4=207, PDEMON5=223, PDEMON_THROW1=415, PDEMON_THROW2=431, PDEMON_THROW3=447, PDEMON_THROW4=463, PDEMON_THROW5=479, SLIME1=163, SLIME2=179, SLIME3=195, SLIME4=211, SLIME5=178, BAT1=177, BAT2=193, BAT3=209, BAT4=192, BAT5=208, BAT6=236, HSLIME3=210, DASHER1=184, DASHER2=200, DASHER3=216, DASHER4=153, VBAT1=180, VBAT2=196, VBAT3=212, FISH1=169, FISH2=185, FISH3=201, FISH4=217, DFISH1=170,--dash fish DFISH2=186, DFISH3=202, DFISH4=218, }, CRUMBLE=164,CRUMBLE_2=270,CRUMBLE_3=271, CRUMBLE2=165,CRUMBLE2_2=286,CRUMBLE2_3=287, FIREBALL1=172, FIREBALL2=188, FIREBALL3=204, FIREBALL4=220, FIREBALL5=206, SNOWBALL1=174, SNOWBALL2=190, SNOWBALL4=222, PLASMA1=412, PLASMA2=428, PLASMA3=444, PLASMA4=460, PLASMA5=476, FIRE_1=262,FIRE_2=263, LIFT1=224, LIFT2=225, LIFT3=226, LIFT4=227, LIFT5=228, LIFT6=229, LIFT7=230, LIFT8=231, LIFT9=232, LIFT10=233, PFIRE=262, FIRE_PWUP=168, BGMNT={DIAG=496,FULL=497}, SCRIM=498, SPIKE=182, SPIKE2=158, FLOATINGSPIKE=194, FLOATINGSPIKE2=157, CHEST=215,CHEST_OPEN=315, TPLAF1=166, TPLAF1_HALF=264, TPLAF1_OFF=280, TPLAF2=167, TPLAF2_HALF=265, TPLAF2_OFF=281, SUPER_PWUP=152, SIGN1=235, SIGN3=237, SIGN4=238, SIGN5=239, FLAG=199, FLAG_T=285, ICICLE=198, ICICLE_F=293, PLANE=234, AVIATOR=432, AVIATOR_PROP_1=451, AVIATOR_PROP_2=435, SICICLE=214, SICICLE_F=309, FUEL=183, TINY_NUM_00=480, TINY_NUM_50=481, TINY_NUM_R1=482, FOOD= {LEAF1=128,LEAF2=129,LEAF3=130,LEAF4=131, LEAF5=132,LEAF6=133,LEAF7=134,LEAF8=135,LEAF9=136, A1=144,A2=160,A3=147,B1=145,B2=161,B3=148, C1=146,C2=162,C3=149,D1=150,D2=151}, WLD={ ROADS={13,14,15,30,31,46,47}, LVL1=61,LVL2=62,LVL3=63, LVLF=79,LVLC=279}, POP=600, } EID=S ANIM={ [EID.EN.A1]={S.EN.A1,373}, [EID.EN.A2]={S.EN.A2,389}, [EID.EN.A3]={S.EN.A3,405}, [EID.EN.A4]={S.EN.A4,357}, [EID.EN.A5]={S.EN.A5,358}, [EID.EN.B1]={S.EN.B1,368}, [EID.EN.B2]={S.EN.B2,352}, [EID.EN.DEMON1]={S.EN.DEMON1,345}, [EID.EN.DEMON2]={S.EN.DEMON2,361}, [EID.EN.DEMON3]={S.EN.DEMON3,377}, [EID.EN.DEMON4]={S.EN.DEMON4,393}, [EID.EN.DEMON5]={S.EN.DEMON5,457}, [EID.FIREBALL1]={S.FIREBALL1,347}, [EID.FIREBALL2]={S.FIREBALL2,363}, [EID.FIREBALL3]={S.FIREBALL3,379}, [EID.FIREBALL4]={S.FIREBALL4,395}, [EID.FIREBALL5]={S.FIREBALL5,459}, [EID.EN.SDEMON1]={S.EN.SDEMON1,425}, [EID.EN.SDEMON2]={S.EN.SDEMON2,441}, [EID.EN.SDEMON4]={S.EN.SDEMON4,473}, [EID.SNOWBALL1]={S.SNOWBALL1,427}, [EID.SNOWBALL2]={S.SNOWBALL2,443}, [EID.SNOWBALL4]={S.SNOWBALL4,475}, [EID.EN.PDEMON1]={S.EN.PDEMON1,414}, [EID.EN.PDEMON2]={S.EN.PDEMON2,430}, [EID.EN.PDEMON3]={S.EN.PDEMON3,446}, [EID.EN.PDEMON4]={S.EN.PDEMON4,462}, [EID.EN.PDEMON5]={S.EN.PDEMON5,478}, [EID.PLASMA1]={S.PLASMA1,413}, [EID.PLASMA2]={S.PLASMA2,429}, [EID.PLASMA3]={S.PLASMA3,445}, [EID.PLASMA4]={S.PLASMA4,461}, [EID.PLASMA5]={S.PLASMA5,477}, [EID.EN.SLIME1]={S.EN.SLIME1,355}, [EID.EN.SLIME2]={S.EN.SLIME2,371}, [EID.EN.SLIME3]={S.EN.SLIME3,387}, [EID.EN.SLIME4]={S.EN.SLIME4,403}, [EID.EN.SLIME5]={S.EN.SLIME5,370}, [EID.EN.BAT1]={S.EN.BAT1,369}, [EID.EN.BAT2]={S.EN.BAT2,385}, [EID.EN.BAT3]={S.EN.BAT3,401}, [EID.EN.BAT4]={S.EN.BAT4,384}, [EID.EN.BAT5]={S.EN.BAT5,400}, [EID.EN.BAT6]={S.EN.BAT6,353}, [EID.FOOD.LEAF1]={S.FOOD.LEAF1,320,336}, [EID.FOOD.LEAF2]={S.FOOD.LEAF2,321,337}, [EID.FOOD.LEAF3]={S.FOOD.LEAF3,322,338}, [EID.FOOD.LEAF4]={S.FOOD.LEAF4,323,339}, [EID.FOOD.LEAF5]={S.FOOD.LEAF5,324,340}, [EID.FOOD.LEAF6]={S.FOOD.LEAF6,325,341}, [EID.FOOD.LEAF7]={S.FOOD.LEAF7,326,342}, [EID.FOOD.LEAF8]={S.FOOD.LEAF8,327,343}, [EID.FOOD.LEAF9]={S.FOOD.LEAF9,328,344}, [EID.PFIRE]={S.PFIRE,263}, [EID.FIRE_PWUP]={S.FIRE_PWUP,282,283}, [EID.EN.HSLIME3]={S.EN.HSLIME3,402}, [EID.SPIKE]={S.SPIKE,303}, [EID.SPIKE2]={S.SPIKE2,302}, [EID.FLOATINGSPIKE]={S.FLOATINGSPIKE,386}, [EID.FLOATINGSPIKE2]={S.FLOATINGSPIKE2,356}, [EID.CHEST]={S.CHEST,313,314}, [EID.EN.DASHER1]={S.EN.DASHER1,421}, [EID.EN.DASHER2]={S.EN.DASHER2,437}, [EID.EN.DASHER3]={S.EN.DASHER3,453}, [EID.EN.DASHER4]={S.EN.DASHER4,469}, [EID.EN.VBAT1]={S.EN.VBAT1,372}, [EID.EN.VBAT2]={S.EN.VBAT2,388}, [EID.EN.VBAT3]={S.EN.VBAT3,404}, [EID.SUPER_PWUP]={S.SUPER_PWUP,266,267}, [EID.FOOD.D1]={S.FOOD.D1,294,295,296}, [EID.FOOD.D2]={S.FOOD.D2,310,311,312}, [EID.FLAG]={S.FLAG,284}, [EID.ICICLE]={S.ICICLE,292}, [EID.SICICLE]={S.SICICLE,308}, [EID.PLANE]={S.PLANE,297,298,299}, [EID.FUEL]={S.FUEL,268,269}, [EID.EN.FISH1]={S.EN.FISH1,375}, [EID.EN.FISH2]={S.EN.FISH2,391}, [EID.EN.FISH3]={S.EN.FISH3,407}, [EID.EN.FISH4]={S.EN.FISH4,423}, [EID.EN.DFISH1]={S.EN.DFISH1,376}, [EID.EN.DFISH2]={S.EN.DFISH2,392}, [EID.EN.DFISH3]={S.EN.DFISH3,408}, [EID.EN.DFISH4]={S.EN.DFISH4,424}, } PLANE={ START_FUEL=2000, MAX_FUEL=4000, FUEL_INC=1000, FUEL_BAR_W=50, } M={ BOOT=0, TITLE=1, TUT=2, RESTORE=3, WLD=4, PREROLL=5, PLAY=6, DYING=7, EOL=8, GAMEOVER=9, WIN=10, } CR={ PLR={x=2,y=0,w=4,h=8}, AVIATOR={x=-6,y=2,w=18,h=10}, DFLT={x=2,y=0,w=4,h=8}, FULL={x=0,y=0,w=8,h=8}, BALL={x=2,y=2,w=3,h=3}, TOP={x=0,y=0,w=8,h=2}, ATK={x=6,y=0,w=7,h=8}, ATK_FLIP_X=-5, FOOD={x=1,y=1,w=6,h=6}} ENT_MAX_DIST=220 ALWAYS_UPDATED_EIDS={ [EID.LIFT1]=true, [EID.LIFT2]=true, [EID.LIFT3]=true, [EID.LIFT4]=true, [EID.LIFT5]=true, [EID.LIFT6]=true, [EID.LIFT7]=true, [EID.LIFT8]=true, [EID.LIFT9]=true, [EID.LIFT10]=true, } DMG={ MELEE=0,FIRE=1,PLANE_FIRE=2} PAL={ [0]=0x000000, [1]=0x402434, [2]=0x30346d, [3]=0x4a4a4a, [4]=0x854c30, [5]=0x346524, [6]=0xd04648, [7]=0x757161, [8]=0x34446d, [9]=0xd27d2c, [10]=0x8595a1,[11]=0x6daa2c, [12]=0x1ce68d,[13]=0x6dc2ca, [14]=0xdad45e,[15]=0xdeeed6, } BGM={A=0,B=1,EOL=2,C=3,WLD=4,TITLE=5, FINAL=6,WIN=7} BGMM={ [M.TITLE]=BGM.TITLE, [M.WLD]=BGM.WLD, [M.EOL]=BGM.EOL, [M.WIN]=BGM.WIN, } LVL={ { name="1-1",bg=2, palor={[8]=0x000028,[1]=0x44262c, [4]=0x652c10,[14]=0xbab43e, [9]=0xb25d0c,[6]=0xb02628, [5]=0x144504}, pkstart=8,pklen=3, mus=BGM.A, }, { name="1-2",bg=0, palor={[8]=0x000028,[4]=0x652c10, [14]=0xbab43e,[9]=0xb25d0c, [6]=0xb02628,[5]=0x144504}, pkstart=27,pklen=2, mus=BGM.B, }, { name="1-3",bg=2, palor={[8]=0x000028,[1]=0x44262c, [4]=0x652c10,[14]=0xbab43e, [9]=0xb25d0c,[6]=0xb02628, [5]=0x144504}, pkstart=11,pklen=2, mus=BGM.C, save=true, }, { name="2-1",bg=1, palor={[8]=0x351818,[2]=0x1a240c, [4]=0x652c10,[14]=0xbab43e, [9]=0xb25d0c,[6]=0xb02628, [5]=0x144504,[1]=0x200414}, pkstart=40,pklen=3, mus=BGM.A, }, { name="2-2",bg=0, palor={[8]=0x250808,[2]=0x1a240c, [4]=0x652c10,[14]=0xbab43e, [9]=0xb25d0c,[6]=0xb02628, [5]=0x144504}, snow={clr=4}, pkstart=32,pklen=3, mus=BGM.B, }, { name="2-3",bg=1, palor={[8]=0x351818,[2]=0x1a240c, [4]=0x652c10,[14]=0xbab43e, [9]=0xb25d0c,[6]=0xb02628, [5]=0x144504,[1]=0x200414}, pkstart=13,pklen=3, mus=BGM.C, save=true, }, { name="3-1",bg=2, palor={[8]=0x3e2e70,[2]=0x1f1738, [10]=0x454561,[1]=0x8595a1}, snow={clr=10}, pkstart=45,pklen=3, mus=BGM.A, }, { name="3-2",bg=0, palor={[8]=0x3e2e70,[2]=0x1f1738, [10]=0x454561,[1]=0x8595a1}, snow={clr=10}, pkstart=43,pklen=2, mus=BGM.B, }, { name="3-3",bg=2, palor={[8]=0x3e2e70,[2]=0x1f1738, [10]=0x454561,[1]=0x8595a1, [5]=0xff0000}, pkstart=35,pklen=2, mus=BGM.C, save=true, }, { name="4-1",bg=2, palor={[8]=0x06246d,[2]=0x26448d, [1]=0x181818,[9]=0xc26d1c, [14]=0xcac44e,[4]=0x753c20, [6]=0xc03638}, pkstart=37,pklen=3, mus=BGM.A, }, { name="4-2",bg=2, palor={[8]=0x0b1a3e,[1]=0x14120d, [2]=0x060d1f}, pkstart=19,pklen=2, mus=BGM.B, }, { name="4-3",bg=2, palor={[8]=0x06246d,[2]=0x26448d, [1]=0x181818,[9]=0xc26d1c, [14]=0xcac44e,[4]=0x753c20, [6]=0xc03638}, pkstart=24,pklen=3, mus=BGM.C, save=true, }, { name="5-1",bg=2, palor={[8]=0x200c40,[2]=0x400c60, [1]=0x1c500c,[5]=0x3c701c}, pkstart=16,pklen=3, mus=BGM.A, }, { name="5-2",bg=2, palor={[8]=0x200c40,[2]=0x400c60, [1]=0x1c500c,[5]=0x3c701c}, pkstart=29,pklen=3, mus=BGM.B, }, { name="5-3",bg=2, palor={[8]=0x200c40,[2]=0x400c60, [1]=0x1c500c,[5]=0x3c701c}, pkstart=21,pklen=3, mus=BGM.C, save=true, }, { name="6-1",bg=0, palor={[1]=0x303030,[5]=0x505050, [8]=0x000010,[2]=0x101010}, snow={clr=2}, pkstart=53,pklen=3, mus=BGM.FINAL, }, { name="6-2",bg=0, palor={[1]=0x303030,[5]=0x505050, [8]=0x000010,[2]=0x101010}, snow={clr=2}, pkstart=51,pklen=2, mus=BGM.FINAL, }, { name="6-3",bg=0, palor={[1]=0x303030,[5]=0x505050, [8]=0x000010,[2]=0x101010}, snow={clr=2}, pkstart=48,pklen=3, mus=BGM.FINAL, }, } LVL_LEN=240 SND={ KILL={sfxid=62,note=30,dur=5}, JUMP={sfxid=61,note=30,dur=4}, SWIM={sfxid=61,note=50,dur=3}, ATTACK={sfxid=62,note=40,dur=4}, POINT={sfxid=60,note=60,dur=5,speed=3}, DIE={sfxid=63,note=18,dur=20,speed=-1}, HURT={sfxid=63,note="C-4",dur=4}, PWUP={sfxid=60,note=45,dur=15,speed=-2}, ONEUP={sfxid=60,note=40,dur=60,speed=-3}, PLANE={sfxid=59,note="C-4",dur=70,speed=-3}, OPEN={sfxid=62,note="C-3",dur=4,speed=-2}, } WLD={FPAGE=61,BPAGE=62} POI={LVL=0} Sett={snd=true,mus=true} Game={ m=M.BOOT, t=0, lvlNo=0, lvl=nil, scr=0, bgmnt=nil, snow=nil, topLvl=-1, } Wld={ pois={}, spos={}, plr={ x0=-1,y0=-1, x=0,y=0, dx=0,dy=0, ldx=0,ldy=0, flipped=false, }} Plr={} PLR_INIT_STATE={ lives=3, x=0,y=0, dx=0,dy=0, flipped=false, jmp=0, jmpSeq=JUMP_DY, grounded=false, swim=false, surf=false, atk=0, dying=0, nudgeX=0,nudgeY=0, firePwup=0, fireCd=0, invuln=0, super=false, drag=0, signMsg=0, signC=0, respX=-1,respY=-1, plane=0, score=0, scoreDisp={text=nil,value=-1}, scoreMt=-999, locked=0, } SIGN_C_MAX=10 SIGN_MSGS={ [0]={ l1="", l2="", }, } Ents={} Parts={} Toasts={} Tanims={} function SetMode(m) Game.m=m Game.t=0 if m~=M.PLAY and m~=M.DYING and m~=M.EOL then ResetPal() end UpdateMus() end function UpdateMus() if Game.m==M.PLAY then PlayMus(Game.lvl.mus) else PlayMus(BGMM[Game.m] or -1) end end function TIC() Game.t=Game.t+1 TICF[Game.m]() end function Boot() ResetPal() WldInit() SetMode(M.TITLE) end function ResetPal(palor) for c=0,15 do local clr=PAL[c] if palor and palor[c] then clr=palor[c] end poke(0x3fc0+c*3+0,(clr>>16)&255) poke(0x3fc0+c*3+1,(clr>>8)&255) poke(0x3fc0+c*3+2,clr&255) end end function TitleTic() ResetPal() name=print(NAME) author=print(AUTHOR) cls(0)--bg color local m=MapPageStart(63) map(m.c,m.r,30,17,0,0,0) spr(S.PLR.WALK1+(time()//128)%2,16,104,0) rect(0,0,240,24,1) print(NAME,(240-name)//2,10,13) rect(0,24,240,1,10) rect(0,26,240,1,10) rect(0,SCRH-8,SCRW,8,0) print(AUTHOR..", 2017 btco",(182-author)//2,129,10) if (time()//512)%2>0 then print("- PRESS 'Z' TO START -",65,84,10) end RendSpotFx(COLS//2,ROWS//2,Game.t) if btnp(4) then SetMode(M.RESTORE) end end function RestoreTic() local saveLvl=pmem(0) or 0 if saveLvl<1 then StartGame(1) return end Game.restoreSel=Game.restoreSel or 0 cls(0) local X=40 local Y1=30 local Y2=60 print("CONTINUE (LEVEL ".. LVL[saveLvl].name ..")",X,Y1) print("START NEW GAME",X,Y2) spr(S.PLR.STAND,X-20, Iif(Game.restoreSel>0,Y2,Y1)) if btnp(0) or btnp(1) then Game.restoreSel= Iif(Game.restoreSel>0,0,1) elseif btnp(4) then StartGame(Game.restoreSel>0 and 1 or saveLvl) end end function TutTic() cls(0) if Game.tutdone then StartLvl(1) return end local p=MapPageStart(56) map(p.c,p.r,COLS,ROWS) print("CONTROLS",100,10) print("JUMP",56,55); print("ATTACK",72,90); print("MOVE",160,50); print("10,000 PTS = EXTRA LIFE",60,110,3); if Game.t>150 and 0==((Game.t//16)%2) then print("- Press Z to continue -",60,130) end if Game.t>150 and btnp(4) then Game.tutdone=true StartLvl(1) end end function WldTic() WldUpdate() WldRend() end function PrerollTic() cls(0) print("LEVEL "..Game.lvl.name,100,40) spr(S.PLR.STAND,105,60) print("X " .. Plr.lives,125,60) if Game.t>60 then SetMode(M.PLAY) end end function PlayTic() UpdatePlr() UpdateEnts() UpdateParts() DetectColl() ApplyNudge() CheckEndLvl() AdjustScroll() Rend() if Game.m==M.PLAY then RendSpotFx((Plr.x-Game.scr)//C, Plr.y//C,Game.t) end end function EolTic() if Game.t>160 then AdvanceLvl() return end Rend() print("LEVEL CLEAR",85,20) end function DyingTic() Plr.dying=Plr.dying+1 if Game.t>100 then if Plr.lives>1 then if TEST1 then else Plr.lives=Plr.lives-1 end SetMode(M.WLD) else SetMode(M.GAMEOVER) end else Rend() end end function GameOverTic() cls(0) print("GAME OVER!",92,50) if Game.t>150 then SetMode(M.TITLE) end end function WinTic() cls(0) Game.scr=0 local m=MapPageStart(57) map(m.c,m.r, math.min(30,(Game.t-300)//8),17,0,0,0) print("THE END!",100, math.max(20,SCRH-Game.t//2)) print("Thanks for playing!",70, math.max(30,120+SCRH-Game.t//2)) if Game.t%100==0 then SpawnParts(PFX.FW,Rnd(40,SCRW-40), Rnd(40,SCRH-40),Rnd(2,15)) end UpdateParts() RendParts() if Game.t>1200 and btnp(4) then SetMode(M.TITLE) end end TICF={ [M.BOOT]=Boot, [M.TITLE]=TitleTic, [M.TUT]=TutTic, [M.RESTORE]=RestoreTic, [M.WLD]=WldTic, [M.PREROLL]=PrerollTic, [M.PLAY]=PlayTic, [M.DYING]=DyingTic, [M.GAMEOVER]=GameOverTic, [M.EOL]=EolTic, [M.WIN]=WinTic, } function StartGame(startLvlNo) Game.topLvl=startLvlNo-1 Plr=DeepCopy(PLR_INIT_STATE) local sp=Wld.spos[startLvlNo] or {x=Wld.plr.x0,y=Wld.plr.y0} Wld.plr.x=sp.x Wld.plr.y=sp.y SetMode(M.WLD) end function StartLvl(lvlNo) local oldLvlNo=Game.lvlNo Game.lvlNo=lvlNo Game.lvl=LVL[lvlNo] Game.scr=0 local old=Plr Plr=DeepCopy(PLR_INIT_STATE) Plr.lives=old.lives Plr.score=old.score Plr.super=old.super if oldLvlNo==lvlNo then Plr.respX=old.respX Plr.respY=old.respY end SetMode(M.PREROLL) Ents={} Parts={} Toasts={} Tanims={} UnpackLvl(lvlNo,UMODE.GAME) GenBgMnt() GenSnow() ResetPal(Game.lvl.palor) AdjustRespawnPos() end function AdjustRespawnPos() if Plr.respX<0 then return end for i=1,#Ents do local e=Ents[i] if e.eid==EID.FLAG and e.xMAX_Y then cd=Rnd(MIN_CD,MAX_CD) dy=-dy else y=y+dy end end RndSeed(time()) end function GenSnow() if not Game.lvl.snow then Game.snow=nil return end Game.snow={} for r=0,ROWS-1,2 do for c=0,COLS-1,2 do Ins(Game.snow,{ x=c*C+Rnd(-8,8), y=r*C+Rnd(-8,8) }) end end end function IsOnGround() return not CanMove(Plr.x,Plr.y+1) end function LvlTileAtPt(x,y) return LvlTile(x//C,y//C) end function LvlTile(c,r) if c<0 or c>=LVL_LEN then return 0 end if r<0 then return 0 end if r>=ROWS then r=ROWS-1 end return mget(c,r) end function SetLvlTile(c,r,t) if c<0 or c>=LVL_LEN then return false end if r<0 or r>=ROWS then return false end mset(c,r,t) end function UpdatePlr() local oldx=Plr.x local oldy=Plr.y Plr.plane=Max(Plr.plane-1,0) Plr.fireCd=Max(Plr.fireCd-1,0) Plr.firePwup=Max(Plr.firePwup-1,0) Plr.invuln=Max(Plr.invuln-1,0) Plr.drag=Iif2(Plr.drag>0,Plr.drag-1, Plr.drag<0,Plr.drag+1,0) Plr.signC=Max(Plr.signC-1,0) Plr.locked=Max(Plr.locked-1,0) UpdateSwimState() local swimmod=Plr.swim and Game.t%2 or 0 if (Plr.plane==0 and Plr.jmp==0 and not IsOnGround()) then Plr.y=Plr.y+1-swimmod end if Plr.y>SCRH+8 then if TEST2 then Plr.y=0 else StartDying() return end end local dx=0 local dy=0 local wantLeft=Plr.locked==0 and Iif(Plr.drag==0,btn(2),Plr.drag<0) local wantRight=Plr.locked==0 and Iif(Plr.drag==0,btn(3),Plr.drag>0) local wantJmp=Plr.locked==0 and Plr.plane==0 and btnp(4) and Plr.drag==0 local wantAtk=Plr.locked==0 and btnp(5) and Plr.drag==0 if wantLeft then dx=-1+swimmod Plr.flipped=true elseif wantRight then dx=1-swimmod Plr.flipped=false end dy=dy+Iif2(Plr.plane>0 and btn(0) and Plr.y>8,-1, Plr.plane>0 and btn(1) and Plr.y0,false,btn(2),true, btn(3),false,Plr.flipped) TryMoveBy(dx,dy) Plr.grounded=Plr.plane==0 and IsOnGround() local canJmp=Plr.grounded or Plr.swim if wantJmp and canJmp then Plr.jmp=1 Plr.jmpSeq=Plr.surf and RESURF_DY or (Plr.swim and SWIM_JUMP_DY or JUMP_DY) Snd(Plr.surf and SND.JUMP or Plr.swim and SND.SWIM or SND.JUMP) end if Plr.jmp>#Plr.jmpSeq then Plr.jmp=0 elseif Plr.jmp>0 then local ok=TryMoveBy( 0,Plr.jmpSeq[Plr.jmp]) Plr.jmp=ok and Plr.jmp+1 or 0 end if Plr.atk==0 then if wantAtk then if Plr.plane==0 then Plr.atk=1 end Snd(SND.ATTACK) TryFire() end elseif Plr.atk>#ATK_SEQ then Plr.atk=0 else Plr.atk=Plr.atk+1 end if Plr.plane>0 then CheckTarmac() end Plr.dx=Plr.x-oldx Plr.dy=Plr.y-oldy end function IsWater(t) return t==T.WATER1 or t==T.WATER2 or t==T.WATER3 or t==T.WATER4 or t==T.WATER5 or t==T.WATER6 or t==T.SURF1 or t==T.SURF2 or t==T.SURF3 or t==T.SURF4 or t==T.SURF5 or t==T.SURF6 or t==T.WFALL1 or t==T.WFALL2 or t==T.WFALL3 or t==T.WFALL4 or t==T.WFALL5 or t==T.WFALL6 end function UpdateSwimState() local wtop=IsWater( LvlTileAtPt(Plr.x+4,Plr.y+1)) local wbottom=IsWater( LvlTileAtPt(Plr.x+4,Plr.y+7)) local wtop2=IsWater( LvlTileAtPt(Plr.x+4,Plr.y-8)) Plr.swim=wtop and wbottom Plr.surf=wbottom and not wtop2 end function TryFire() if Plr.firePwup<1 and Plr.plane==0 then return end if Plr.fireCd>0 then return end Plr.fireCd=FIRE.INTERVAL local x=Plr.x if Plr.plane==0 then x=x+(Plr.flipped and FIRE.OFFX_FLIP or FIRE.OFFX) else x=x+FIRE.OFFX_PLANE end local y=Plr.y+Iif(Plr.plane>0, FIRE.OFFY_PLANE,FIRE.OFFY) local e=EntAdd(EID.PFIRE,x,y) e.moveDx=Plr.plane>0 and 2 or (Plr.flipped and -1 or 1) e.ttl=Plr.plane>0 and e.ttl//2 or e.ttl end function ApplyNudge() Plr.y=Plr.y+Plr.nudgeY Plr.x=Plr.x+Plr.nudgeX Plr.nudgeX=0 Plr.nudgeY=0 end function TryMoveBy(dx,dy) if CanMove(Plr.x+dx,Plr.y+dy) then Plr.x=Plr.x+dx Plr.y=Plr.y+dy return true end return false end function GetPlrCr() return Iif(Plr.plane>0,CR.AVIATOR,CR.PLR) end function CanMove(x,y) local dy=y-Plr.y local pcr=GetPlrCr() local r=CanMoveEx(x,y,pcr,dy) if not r then return false end local pr=RectXLate(pcr,x,y) for i=1,#Ents do local e=Ents[i] local effSolid=(e.sol==SOL.FULL) or (e.sol==SOL.HALF and dy>0 and Plr.y+5=T.FIRST_DECO,SOL.NOT,SOL.FULL) end function CanMoveEx(x,y,cr,dy) local x1=x+cr.x local y1=y+cr.y local x2=x1+cr.w-1 local y2=y1+cr.h-1 local startC=x1//C local endC=x2//C local startR=y1//C local endR=y2//C for c=startC,endC do for r=startR,endR do local sol=GetTileSol(LvlTile(c,r)) if sol==SOL.FULL then return false end end end local sA=GetTileSol(LvlTileAtPt(x1,y2)) local sB=GetTileSol(LvlTileAtPt(x2,y2)) if dy>0 and (sA==SOL.HALF or sB==SOL.HALF) and y2%C==0 then return false end return true end function EntWouldFall(e,x) return EntCanMove(e,x,e.y+1) end function CheckTarmac() local pr=RectXLate( CR.AVIATOR,Plr.x,Plr.y) local bottom=pr.y+pr.h+1 local t1=LvlTileAtPt(pr.x,bottom) local t2=LvlTileAtPt(pr.x+pr.w,bottom) if t1==T.TARMAC and t2==T.TARMAC then Plr.plane=0 SpawnParts(PFX.POP,Plr.x+4,Plr.y,14) end end function AdjustScroll() local dispx=Plr.x-Game.scr if dispx>SX_MAX then Game.scr=Plr.x-SX_MAX elseif dispx1000 or (rem~=50 and rem~=0) then return end local sp2=rem==50 and S.TINY_NUM_50 or S.TINY_NUM_00 local sp1=points>=100 and (S.TINY_NUM_R1-1+points//100) or 0 Ins(Toasts,{ x=Iif(points>=100,x-8,x-12), y=y,ttl=40,sp1=sp1,sp2=sp2}) end function AddScore(points,tx,ty) local old=Plr.score Plr.score=Plr.score+points Plr.scoreMt=Game.t if (old//10000)<(Plr.score//10000) then Snd(SND.ONEUP) Plr.lives=Plr.lives+1 else Snd(SND.POINT) end if tx and ty then AddToast(points,tx,ty) end end function StartDying() SetMode(M.DYING) Snd(SND.DIE) Plr.dying=1 Plr.super=false Plr.firePwup=0 Plr.plane=0 end function EntAdd(newEid,newX,newY) local e={ eid=newEid, x=newX, y=newY } Ins(Ents,e) EntInit(e) return e end function EntInit(e) if ANIM[e.eid] then e.anim=ANIM[e.eid] e.sprite=e.anim[1] else e.sprite=e.eid end e.flipped=false e.coll=CR.DFLT e.sol=SOL.NOT local ebte=EBT[e.eid] e.beh=ebte and ebte.beh or {} for _,b in pairs(e.beh) do ShallowMerge(e,b.data) end if ebte and ebte.data then ShallowMerge(e,ebte.data) end for _,b in pairs(e.beh) do if b.init then b.init(e) end end end function EntRepl(e,eid,data) e.dead=true local newE=EntAdd(eid,e.x,e.y) if data then ShallowMerge(newE,data) end end function EntHasBeh(e,soughtBeh) for _,b in pairs(e.beh) do if b==soughtBeh then return true end end return false end function EntAddBeh(e,beh) if EntHasBeh(e,beh) then return end e.beh=DeepCopy(e.beh) ShallowMerge(e,beh.data,true) Ins(e.beh,beh) end function UpdateEnts() for i=#Ents,1,-1 do local e=Ents[i] UpdateEnt(e) if e.dead then Rem(Ents,i) end end end function UpdateEnt(e) if not ALWAYS_UPDATED_EIDS[e.eid] and Abs(e.x-Plr.x)>ENT_MAX_DIST then return end if e.anim then e.sprite=e.anim[1+(time()//128)%#e.anim] end for _,b in pairs(e.beh) do if b.update then b.update(e) end end end function GetEntAt(x,y) for i=1,#Ents do local e=Ents[i] if e.x==x and e.y==y then return e end end return nil end function DetectColl() local pr=RectXLate(GetPlrCr(), Plr.x,Plr.y) local ar=nil if ATK_SEQ[Plr.atk]==2 then ar=RectXLate(CR.ATK,Plr.x,Plr.y) if Plr.flipped then ar.x=Plr.x+CR.ATK_FLIP_X end end for i=1,#Ents do local e=Ents[i] local er=RectXLate(e.coll,e.x,e.y) if RectIsct(pr,er) then HandlePlrColl(e) elseif ar and RectIsct(ar,er) then HandleDamage(e,DMG.MELEE) end end end function CheckEndLvl() local t=LvlTileAtPt( Plr.x+C//2,Plr.y+C//2) if t==T.GATE_L or t==T.GATE_R or t==T.GATE_L2 or t==T.GATE_R2 then EndLvl() end end function EndLvl() Game.topLvl=Max( Game.topLvl,Game.lvlNo) SetMode(M.EOL) end function AdvanceLvl() if Game.lvl.save then pmem(0,Max(pmem(0) or 0, Game.lvlNo+1)) end if Game.lvlNo>=#LVL then pmem(0,0) SetMode(M.WIN) else SetMode(M.WLD) end end function HandlePlrColl(e) for _,b in pairs(e.beh) do if b.coll then b.coll(e) end if e.dead then break end end end function HandleDamage(e,dtype) for _,b in pairs(e.beh) do if b.dmg then b.dmg(e,dtype) end if e.dead then SpawnParts(PFX.POP,e.x+4,e.y+4,e.clr) Snd(SND.KILL) break end end end function HandlePlrHurt() if Plr.invuln>0 then return end if Plr.plane==0 and Plr.super then Snd(SND.HURT) Plr.super=false Plr.invuln=100 Plr.drag=Iif(Plr.dx>=0,-10,10) Plr.jmp=0 else if TEST2 then else StartDying()end end end function Snd(spec) if not Sett.snd then return end sfx(spec.sfxid,spec.note,spec.dur, 0,spec.vol or 15,spec.speed or 0) end function PlayMus(musid) if Sett.mus or musid==-1 then music(musid) end end PFX={ POP={ rad=4, count=15, speed=4, fall=true, ttl=15}, FW={ rad=3, count=40, speed=1, fall=false, ttl=100}} function SpawnParts(fx,cx,cy,clr) for i=1,fx.count do local r=Rnd01()*fx.rad local phi=Rnd01()*math.pi*2 local part={ x=cx+r*Cos(phi), y=cy+r*Sin(phi), vx=fx.speed*Cos(phi), vy=fx.speed*Sin(phi), fall=fx.fall, ttl=fx.ttl, age=0, clr=clr} Ins(Parts,part) end end function UpdateParts() for i=#Parts,1,-1 do local p=Parts[i] p.age=p.age+1 if p.age>=p.ttl then Rem(Parts,i) else p.x=p.x+p.vx p.y=p.y+p.vy+(p.fall and p.age//2 or 0) end end end function RendParts() for i,p in pairs(Parts) do pix(p.x-Game.scr,p.y,p.clr) end end function Wl(w,l) return (w-1)*3+l end function WldInit() for r=0,ROWS-1 do for c=0,COLS-1 do local t=WldFgTile(c,r) local lval=WldLvlVal(t) if t==T.META_A then Wld.plr.x0=c*C Wld.plr.y0=(r-1)*C elseif t==T.META_B then local mv=WldGetTag(c,r) Wld.spos[Wl(mv,1)]={ x=c*C,y=(r-1)*C} elseif lval>0 then local mv=WldGetTag(c,r) local poi={c=c,r=r, t=POI.LVL,lvl=Wl(mv,lval)} Ins(Wld.pois,poi) end end end end function WldGetTag(tc,tr) for r=tr-1,tr+1 do for c=tc-1,tc+1 do local mv=MetaVal(WldFgTile(c,r),0) if mv>0 then return mv end end end trace("No WLD tag @"..tc..","..tr) return 0 end function WldLvlVal(t) return Iif4(t==S.WLD.LVLF,1, t==S.WLD.LVL1,1, t==S.WLD.LVL2,2, t==S.WLD.LVL3,3,0) end function WldFgTile(c,r) return MapPageTile(WLD.FPAGE,c,r) end function WldBgTile(c,r) return MapPageTile(WLD.BPAGE,c,r) end function WldPoiAt(c,r) for i=1,#Wld.pois do local poi=Wld.pois[i] if poi.c==c and poi.r==r then return poi end end return nil end function WldHasRoadAt(c,r) local t=WldFgTile(c,r) for i=1,#S.WLD.ROADS do if S.WLD.ROADS[i]==t then return true end end if TEST1 then return true else return false end end function WldUpdate() local p=Wld.plr if p.dx~=0 or p.dy~=0 then p.x=p.x+p.dx p.y=p.y+p.dy if p.x%C==0 and p.y%C==0 then p.ldx=p.dx p.ldy=p.dy p.dx=0 p.dy=0 end return end if btn(0) then WldTryMove(0,-1) end if btn(1) then WldTryMove(0,1) end if btn(2) then WldTryMove(-1,0) end if btn(3) then WldTryMove(1,0) end Wld.plr.flipped=Iif( Iif(Wld.plr.flipped,btn(3),btn(2)), not Wld.plr.flipped, Wld.plr.flipped) if btnp(4) then local poi=WldPoiAt(p.x//C,p.y//C) if poi and poi.lvl>Game.topLvl then if poi.lvl==1 then SetMode(M.TUT) else StartLvl(poi.lvl) end end end end function WldTryMove(dx,dy) local p=Wld.plr local poi=WldPoiAt(p.x//C,p.y//C) if not Plr.dbgFly and poi and poi.lvl>Game.topLvl and (dx ~= -p.ldx or dy ~= -p.ldy) then return end local tc=p.x//C+dx local tr=p.y//C+dy if WldHasRoadAt(tc,tr) or WldPoiAt(tc,tr) then p.dx=dx p.dy=dy return end end function WldFgRemapFunc(t) return t=LVL_LEN then trace("ERROR: level too long: "..lvlNo) return end end end if mode==UMODE.GAME then for c=0,LVL_LEN-1 do for r=0,ROWS-1 do local t=mget(c,r) local tpat=TPAT[t] if tpat then ExpandTpat(tpat,c,r) end if Plr.x==0 and Plr.y==0 and t==T.META_A then Plr.x=c*C Plr.y=r*C end if t>=T.FIRST_META then mset(c,r,0) end end end if Plr.x==0 and Plr.y==0 then trace("*** start pos UNSET L"..lvlNo) end FillWater1() FillWater2() FillWater3() FillWater4() FillWater5() FillWater6() SetUpTanims() end end function ExpandTpat(tpat,c,r) local s=mget(c,r) for i=0,tpat.w-1 do for j=0,tpat.h-1 do mset(c+i,r+j,s+j*16+i) end end end function SetUpTanims() for c=0,LVL_LEN-1 do for r=0,ROWS-1 do local t=mget(c,r) if TANIM[t] then TanimAdd(c,r) end end end end function FindLvlEndCol(c0,r0,len) for c=c0+len-1,c0,-1 do for r=r0,r0+ROWS-1 do if mget(c,r)>0 then return c end end end return c0 end function FillWater1() local surfs={} local waters={} for c=LVL_LEN-1,0,-1 do for r=ROWS-1,0,-1 do if mget(c,r)==T.SURF1 then Ins(surfs,{c=c,r=r}) elseif mget(c,r)==T.WATER1 then Ins(waters,{c=c,r=r}) end end end for i=1,#surfs do local s=surfs[i] FillWaterAt1(s.c,s.r,1) end for i=1,#waters do local s=waters[i] FillWaterAt1(s.c,s.r,-1) FillWaterAt1(s.c,s.r,1) end end function FillWaterAt1(c,r0,dir) local from=r0+dir local to=Iif(dir>0,ROWS-1,0) for r=from,to,dir do if mget(c,r)==T.EMPTY then mset(c,r,T.WATER1) else return end end end function FillWater2() local surfs={} local waters={} for c=LVL_LEN-1,0,-1 do for r=ROWS-1,0,-1 do if mget(c,r)==T.SURF2 then Ins(surfs,{c=c,r=r}) elseif mget(c,r)==T.WATER2 then Ins(waters,{c=c,r=r}) end end end for i=1,#surfs do local s=surfs[i] FillWaterAt2(s.c,s.r,1) end for i=1,#waters do local s=waters[i] FillWaterAt2(s.c,s.r,-1) FillWaterAt2(s.c,s.r,1) end end function FillWaterAt2(c,r0,dir) local from=r0+dir local to=Iif(dir>0,ROWS-1,0) for r=from,to,dir do if mget(c,r)==T.EMPTY then mset(c,r,T.WATER2) else return end end end function FillWater3() local surfs={} local waters={} for c=LVL_LEN-1,0,-1 do for r=ROWS-1,0,-1 do if mget(c,r)==T.SURF3 then Ins(surfs,{c=c,r=r}) elseif mget(c,r)==T.WATER3 then Ins(waters,{c=c,r=r}) end end end for i=1,#surfs do local s=surfs[i] FillWaterAt3(s.c,s.r,1) end for i=1,#waters do local s=waters[i] FillWaterAt3(s.c,s.r,-1) FillWaterAt3(s.c,s.r,1) end end function FillWaterAt3(c,r0,dir) local from=r0+dir local to=Iif(dir>0,ROWS-1,0) for r=from,to,dir do if mget(c,r)==T.EMPTY then mset(c,r,T.WATER3) else return end end end function FillWater4() local surfs={} local waters={} for c=LVL_LEN-1,0,-1 do for r=ROWS-1,0,-1 do if mget(c,r)==T.SURF4 then Ins(surfs,{c=c,r=r}) elseif mget(c,r)==T.WATER4 then Ins(waters,{c=c,r=r}) end end end for i=1,#surfs do local s=surfs[i] FillWaterAt4(s.c,s.r,1) end for i=1,#waters do local s=waters[i] FillWaterAt4(s.c,s.r,-1) FillWaterAt4(s.c,s.r,1) end end function FillWaterAt4(c,r0,dir) local from=r0+dir local to=Iif(dir>0,ROWS-1,0) for r=from,to,dir do if mget(c,r)==T.EMPTY then mset(c,r,T.WATER4) else return end end end function FillWater5() local surfs={} local waters={} for c=LVL_LEN-1,0,-1 do for r=ROWS-1,0,-1 do if mget(c,r)==T.SURF5 then Ins(surfs,{c=c,r=r}) elseif mget(c,r)==T.WATER5 then Ins(waters,{c=c,r=r}) end end end for i=1,#surfs do local s=surfs[i] FillWaterAt5(s.c,s.r,1) end for i=1,#waters do local s=waters[i] FillWaterAt5(s.c,s.r,-1) FillWaterAt5(s.c,s.r,1) end end function FillWaterAt5(c,r0,dir) local from=r0+dir local to=Iif(dir>0,ROWS-1,0) for r=from,to,dir do if mget(c,r)==T.EMPTY then mset(c,r,T.WATER5) else return end end end function FillWater6() local surfs={} local waters={} for c=LVL_LEN-1,0,-1 do for r=ROWS-1,0,-1 do if mget(c,r)==T.SURF6 then Ins(surfs,{c=c,r=r}) elseif mget(c,r)==T.WATER6 then Ins(waters,{c=c,r=r}) end end end for i=1,#surfs do local s=surfs[i] FillWaterAt6(s.c,s.r,1) end for i=1,#waters do local s=waters[i] FillWaterAt6(s.c,s.r,-1) FillWaterAt6(s.c,s.r,1) end end function FillWaterAt6(c,r0,dir) local from=r0+dir local to=Iif(dir>0,ROWS-1,0) for r=from,to,dir do if mget(c,r)==T.EMPTY then mset(c,r,T.WATER6) else return end end end function TanimAdd(c,r) if Tanims[c] then Ins(Tanims[c],r) else Tanims[c]={r} end end function PackLvl(lvlNo) local lvl=LVL[lvlNo] local start=MapPageStart(lvl.pkstart) local outc=start.c local outr=start.r local len=lvl.pklen*30 local endc=FindLvlEndCol(0,0,LVL_LEN) local reps=0 MapClear(outc,outr,len,ROWS) for c=0,endc do if c>0 and MapColsEqual(c,c-1,0) and reps<12 then local m=mget(outc-1,outr) m=Iif(m==0,T.META_NUM_0+2,m+1) mset(outc-1,outr,m) reps=reps+1 else reps=1 MapCopy(c,0,outc,outr,1,ROWS) outc=outc+1 if outc>=start.c+len then trace("Capacity exceeded.") return false end end end trace("packed "..(endc+1).." -> ".. (outc+1-start.c)) return true end function CreateCol(srcc,dstc,offr,ie) MapCopy(srcc,offr,dstc,0,1,ROWS) mset(dstc,0,T.EMPTY) if not ie then return end for r=1,ROWS-1 do local t=mget(dstc,r) if t>=T.FIRST_ENT and EBT[t] then mset(dstc,r,T.EMPTY) EntAdd(t,dstc*C,r*C) end end end function Rend() RendBg() if Game.snow then RendSnow() end RendMap() RendTanims() RendEnts() RendToasts() if Game.m==M.EOL then RendScrim() end RendPlr() RendParts() RendHud() RendSign() end function RendBg() local END_R=ROWS cls(Game.lvl.bg) local offset=Game.scr//2+50 local startI=Max(1,1+offset//C) local endI=Min( startI+COLS,#Game.bgmnt) for i=startI,endI do local sx=(i-1)*C-offset local part=Game.bgmnt[i] for r=part.y,END_R do local spid=Iif(r==part.y, S.BGMNT.DIAG,S.BGMNT.FULL) spr(spid,(i-1)*C-offset,r*C,0,1, Iif(part.dy>0,1,0)) end end end function RendSnow() local dx=-Game.scr local dy=Game.t//2 for _,p in pairs(Game.snow) do local sx=((p.x+dx)%SCRW+SCRW)%SCRW local sy=((p.y+dy)%SCRH+SCRH)%SCRH pix(sx,sy,Game.lvl.snow.clr) end end function RendToasts() for i=#Toasts,1,-1 do local t=Toasts[i] t.ttl=t.ttl-1 if t.ttl<=0 then Toasts[i]=Toasts[#Toasts] Rem(Toasts) else t.y=t.y-1 spr(t.sp1,t.x-Game.scr,t.y,0) spr(t.sp2,t.x-Game.scr+C,t.y,0) end end end function RendMap() local c=Game.scr//C local sx=-Game.scr+c*C local w=Min(COLS+1,LVL_LEN-c) if c<0 then sx=sx+C*(-c) c=0 end map( c,0,w,ROWS, sx,0,0,1) end function RendPlr() local spid local walking=false if Plr.plane>0 then RendPlane() return end if Plr.dying>0 then spid=S.PLR.DIE elseif Plr.atk>0 then spid= ATK_SEQ[Plr.atk]==1 and S.PLR.SWING or S.PLR.HIT elseif Plr.grounded then if btn(2) or btn(3) then spid=S.PLR.WALK1+time()%2 walking=true else spid=S.PLR.STAND end elseif Plr.swim then spid=S.PLR.SWIM1+(Game.t//4)%2 else spid=S.PLR.JUMP end local sx=Plr.x-Game.scr local sy=Plr.y local flip=Plr.flipped and 1 or 0 if spid==S.PLR.DIE then if Plr.dying<=#DIE_SEQ then sx=sx+DIE_SEQ[Plr.dying][1] sy=sy+DIE_SEQ[Plr.dying][2] else sx=-1000 sy=-1000 end end if Plr.invuln>0 and 0==(Game.t//4)%2 then return end spr(spid,sx,sy,0,1,flip) if spid==S.PLR.SWING then spr(S.PLR.SWING_C,sx,sy-C,0,1,flip) elseif spid==S.PLR.HIT then spr(S.PLR.HIT_C, sx+(Plr.flipped and -C or C), sy,0,1,flip) end if Plr.super then local osp=Iif3(Plr.atk>0,S.PLR.SUPER_F, Plr.swim and not Plr.grounded, S.PLR.SUPER_S, walking,S.PLR.SUPER_P,S.PLR.SUPER_F) spr(osp,sx,Plr.y,0,1,flip) end if spid~=S.PLR.SWING and Plr.firePwup>0 and (time()//128)%2==0 then spr(S.PLR.FIRE_BAMBOO,sx,Plr.y,0,1,flip) end if Plr.firePwup>100 or 1==(Plr.firePwup//16)%2 then local osp=Iif3(Plr.atk>0,S.PLR.FIRE_F, Plr.swim and not Plr.grounded, S.PLR.FIRE_S, walking,S.PLR.FIRE_P,S.PLR.FIRE_F) spr(osp,sx,Plr.y,0,1,flip) end if Game.m==M.PLAY and Plr.dying==0 and Plr.respX>=0 and Game.t<100 and (Game.t//8)%2==0 then rectb(Plr.x-Game.scr-2,Plr.y-2, C+4,C+4,15) end end function RendPlane() local ybias=(Game.t//8)%2==0 and 1 or 0 local sx=Plr.x-Game.scr spr(S.AVIATOR, sx-C,Plr.y+ybias,0,1,0,0,3,2) local spid=(Game.t//4)%2==0 and S.AVIATOR_PROP_1 or S.AVIATOR_PROP_2 spr(spid,sx+C, Plr.y+ybias+4,0) end function RendHud() rect(0,0,SCRW,C,3) if Plr.scoreDisp.value~=Plr.score then Plr.scoreDisp.value=Plr.score Plr.scoreDisp.text=Lpad(Plr.score,6) end local clr=15 print(Plr.scoreDisp.text,192,1,clr,true) print((Game.m==M.WLD and "WORLD MAP" or ("LEVEL "..Game.lvl.name)),95,1,7) spr(S.PLR.STAND,5,0,0) print("x "..Plr.lives,16,1) if Plr.plane>0 then local barw=PLANE.FUEL_BAR_W local lx=120-barw//2 local y=8 local clr=(Plr.plane<800 and (Game.t//16)%2==0) and 6 or 14 local clrLo=(clr==14 and 4 or clr) print("E",lx-7,y,clr) print("F",lx+barw+1,y,14) rectb(lx,y,barw,6,clrLo) local bw=Plr.plane* (PLANE.FUEL_BAR_W-2)//PLANE.MAX_FUEL rect(lx+1,y+1,Max(bw,1),4,clr) pix(lx+barw//4,y+4,clrLo) pix(lx+barw//2,y+4,clrLo) pix(lx+barw//2,y+3,clrLo) pix(lx+3*barw//4,y+4,clrLo) end end function RendEnts() for i=1,#Ents do local e=Ents[i] local sx=e.x-Game.scr if sx>-C and sx45,0, Game.t>30,S.SCRIM+2, Game.t>15,S.SCRIM+1, S.SCRIM) for r=0,ROWS-1 do for c=0,COLS-1 do spr(sp,c*C,r*C,15) end end end function RendSpotFx(fc,fr,t) local rad=Max(0,t//2-2) if rad>COLS then return end for r=0,ROWS-1 do for c=0,COLS-1 do local d=Max(Abs(fc-c), Abs(fr-r)) local sa=d-rad local spid=Iif2(sa<=0,-1,sa<=3, S.SCRIM+sa-1,0) if spid>=0 then spr(spid,c*C,r*C,15) end end end end function RendSign() if 0==Plr.signC then return end local w=Plr.signC*20 local h=Plr.signC*3 local x=SCRW//2-w//2 local y=SCRH//2-h//2-20 local s=SIGN_MSGS[Plr.signMsg] rect(x,y,w,h,15) if Plr.signC==SIGN_C_MAX then print(s.l1,x+6,y+8,0) print(s.l2,x+6,y+8+C,0) end end function RendTanims() local c0=Max(0,Game.scr//C) local cf=c0+COLS for c=c0,cf do local anims=Tanims[c] if anims then for i=1,#anims do local r=anims[i] local tanim=TANIM[mget(c,r)] if tanim then local spid=tanim[ 1+(Game.t//16)%#tanim] spr(spid,c*C-Game.scr,r*C) end end end end end MOVE_HIT={ NONE=0, STOP=1, BOUNCE=2, DIE=3} AIM={ NONE=0, HORIZ=1, VERT=2, FULL=3} function BehMove(e) if e.moveT>0 then e.moveT=e.moveT-1 end if e.moveT==0 then return end if e.moveWaitPlr>0 then if Abs(Plr.x-e.x)>e.moveWaitPlr then return else e.moveWaitPlr=0 end end e.moveNum=e.moveNum+1 if e.moveNum0 elseif e.moveHitMode==MOVE_HIT.NONE or EntCanMove(e,e.x+e.moveDx,e.y) then e.x=e.x+(e.moveDx or 0) e.y=e.y+(e.moveDy or 0) elseif e.moveHitMode==MOVE_HIT.BOUNCE then e.moveDx=-(e.moveDx or 0) e.flipped=e.moveDx>0 elseif e.moveHitMode==MOVE_HIT.DIE then e.dead=true end end function BehUpDownInit(e) e.maxy=e.y e.miny=e.maxy-e.yamp end function BehUpDown(e) e.ynum=e.ynum+1 if e.ynum=e.maxy then e.dy=-1 end end function BehFacePlr(e) e.flipped=Plr.x>e.x if e.moveDx then e.moveDx=Abs(e.moveDx)* (e.flipped and 1 or -1) end end function BehFlip(e) e.flipNum=e.flipNum+1 if e.flipNum#JUMP_DY then e.jmp=0 else local dy=JUMP_DY[e.jmp] if EntCanMove(e,e.x,e.y+dy) then e.y=e.y+dy else e.jmp=0 end end end end function BehFall(e) e.grounded=not EntCanMove(e,e.x,e.y+1) if not e.grounded and e.jmp==0 then e.y=e.y+1 end end function BehTakeDmg(e,dtype) if not ArrayContains(e.dtypes,dtype) then return end e.hp=e.hp-1 if e.hp>0 then return end e.dead=true local roll=Rnd(0,99) roll=Max(Iif2(Game.lvlNo<2,roll-50, Game.lvlNo<4,roll-25,roll),0) if rollb then e.boty=a e.topy=b e.dir=1 else e.topy=a e.boty=b e.dir=-1 end e.coll=CR.FULL end function BehLift(e) e.liftNum=e.liftNum+1 if e.liftNum0 and e.y>e.boty or e.dir<0 and e.yPlr.y,-1,1) end function BehShootInit(e) e.shootNum=Rnd(0,e.shootDen-1) end function BehShoot(e) e.shootNum=e.shootNum+1 if e.shootNum<30 then e.sprite=e.shootSpr or e.sprite end if e.shootNume.x and 1 or -1)* Abs(shot.moveDx) elseif e.aim==AIM.VERT then shot.moveDy=(Plr.y>e.y and 1 or -1)* Abs(shot.moveDy) elseif e.aim==AIM.FULL then local tx=Plr.x-shot.x local ty=Plr.y-shot.y local mag=math.sqrt(tx*tx+ty*ty) local spd=math.sqrt( shot.moveDx*shot.moveDx+ shot.moveDy*shot.moveDy) shot.moveDx=math.floor(0.5+tx*spd/mag) shot.moveDy=math.floor(0.5+ty*spd/mag) if shot.moveDx==0 and shot.moveDy==0 then shot.moveDx=-1 end end end function BehCrumble(e) if not e.crumbling then if Plr.xe.x+8 then return end local pr=RectXLate( GetPlrCr(),Plr.x,Plr.y) local er=RectXLate(e.coll,e.x,e.y-1) e.crumbling=RectIsct(pr,er) end if e.crumbling then e.cd=e.cd-1 e.sprite=Iif(e.cd>66,S.CRUMBLE, Iif(e.cd>33,S.CRUMBLE_2,S.CRUMBLE_3)) if e.cd<0 then e.dead=true end end end function BehCrumble2(e) if not e.crumbling2 then if Plr.xe.x+8 then return end local pr=RectXLate( GetPlrCr(),Plr.x,Plr.y) local er=RectXLate(e.coll,e.x,e.y-1) e.crumbling2=RectIsct(pr,er) end if e.crumbling2 then e.cd=e.cd-1 e.sprite=Iif(e.cd>66,S.CRUMBLE2, Iif(e.cd>33,S.CRUMBLE2_2,S.CRUMBLE2_3)) if e.cd<0 then e.dead=true end end end function BehTtl(e) e.ttl=e.ttl-1 if e.ttl <= 0 then e.dead = true end end function BehDmgEnemy(e) local fr=RectXLate(FIRE.COLL,e.x,e.y) for i=1,#Ents do local ent=Ents[i] local er=RectXLate(ent.coll,ent.x,ent.y) if e~=ent and RectIsct(fr,er) and EntHasBeh(ent,BE.VULN) then HandleDamage(ent,Plr.plane>0 and DMG.PLANE_FIRE or DMG.FIRE) e.dead=true end end end function BehGrantFirePwupColl(e) Plr.firePwup=FIRE.DUR e.dead=true Snd(SND.PWUP) end function BehGrantSuperPwupColl(e) Plr.super=true e.dead=true Snd(SND.PWUP) end function BehReplace(e) local d=Abs(e.x-Plr.x) if d1 then EntAdd(c,cx,ty) end if e.mul>2 then EntAdd(c,lx,by) end if e.mul>3 then EntAdd(c,rx,by) end if e.mul>4 then EntAdd(c,lx,ty) end if e.mul>5 then EntAdd(c,rx,ty) end end function BehTplafInit(e) e.phase=MetaVal(FetchEntTag(e),0) end function BehTplaf1(e) local UNIT=40 local PHASE_LEN=3 local uclk=e.phase+Game.t//UNIT local open=((uclk//PHASE_LEN)%2==0) local tclk=e.phase*UNIT+Game.t e.sprite=Iif2( (tclk%(UNIT*PHASE_LEN)<=6), S.TPLAF1_HALF,open,S.TPLAF1,S.TPLAF1_OFF) e.sol=Iif(open,SOL.HALF,SOL.NOT) end function BehTplaf2(e) local UNIT=40 local PHASE_LEN=3 local uclk=e.phase+Game.t//UNIT local open=((uclk//PHASE_LEN)%2==0) local tclk=e.phase*UNIT+Game.t e.sprite=Iif2( (tclk%(UNIT*PHASE_LEN)<=6), S.TPLAF2_HALF,open,S.TPLAF2,S.TPLAF2_OFF) e.sol=Iif(open,SOL.HALF,SOL.NOT) end function BehDashInit(e) assert(EntHasBeh(e,BE.MOVE)) e.origAnim=e.anim e.origMoveDen=e.moveDen end function BehDash(e) local dashing=e.cddr2.x and r2.x+r2.w>r1.x and r1.y+r1.h>r2.y and r2.y+r2.h>r1.y end function DeepCopy(t) if type(t)~="table" then return t end local r={} for k,v in pairs(t) do if type(v)=="table" then r[k]=DeepCopy(v) else r[k]=v end end return r end function ShallowMerge(target,src, preserve) if not src then return end for k,v in pairs(src) do if not preserve or not target[k] then target[k]=DeepCopy(src[k]) end end end function MapCopy(sc,sr,dc,dr,w,h) for r=0,h-1 do for c=0,w-1 do mset(dc+c,dr+r,mget(sc+c,sr+r)) end end end function MapClear(dc,dr,w,h) for r=0,h-1 do for c=0,w-1 do mset(dc+c,dr+r,0) end end end function MapColsEqual(c1,c2,r) for i=0,ROWS-1 do if mget(c1,r+i)~=mget(c2,r+i) then return false end end return true end function MetaVal(t,deflt) return Iif( t>=T.META_NUM_0 and t<=T.META_NUM_0+12, t-T.META_NUM_0,deflt) end function FetchTile(m,c,nowarn) for r=0,ROWS-1 do if LvlTile(c,r)==m then if erase then SetLvlTile(c,r,0) end return r end end if not nowarn then trace("Marker not found "..m.." @"..c) end return -1 end function FetchEntTag(e) local t=mget(e.x//C,e.y//C-1) if t>=T.FIRST_META then mset(e.x//C,e.y//C-1,0) return t else return 0 end end function Max(x,y) return math.max(x,y) end function Min(x,y) return math.min(x,y) end function Abs(x,y) return math.abs(x,y) end function Rnd(lo,hi) return math.random(lo,hi) end function Rnd01() return math.random() end function RndSeed(s) return math.randomseed(s) end function Ins(tbl,e) return table.insert(tbl,e) end function Rem(tbl,e) return table.remove(tbl,e) end function Sin(a) return math.sin(a) end function Cos(a) return math.cos(a) end