' LOSE YOUR MARBLES ' ' AN ISOMETRIC 3D PLATFORM GAME ' ' WRITTEN ENTIRELY ON AN IPHONE! ' ' CODE & GRAPHICS COPYRIGHT (C) 2019 NAT PRYCE ' LICENSE: CC BY-NC-SA 4.0 GLOBAL TRUE, FALSE TRUE = -1 FALSE = 0 GLOBAL NONE NONE = -1 GLOBAL _X, _Y, _Z _X = 0 _Y = 1 _Z = 2 GLOBAL GRAVITY GRAVITY = 0.0125 SUB FAIL(FNAME$, MSG$) BG 0 ATTR (,0,0,1) SCROLL 0, 0, 0 TEXT 0,1, "ERROR!" TEXT 1,2, FNAME$ TEXT 1,3, MSG$ END END SUB '--------------------------------------------' CENTERED TEXT DIM GLOBAL TITLE_LINE_OFFSETS(16) SUB TITLE_INIT SPRITE OFF CLS FOR I = 0 TO 16 TITLE_LINE_OFFSETS(I) = 0 NEXT I ON RASTER CALL TITLE_CENTER_LINES END SUB SUB TITLE_CENTER_LINES L = RASTER/8 SCROLL 0, TITLE_LINE_OFFSETS(L), 0 END SUB SUB TITLE_END ON RASTER OFF END SUB SUB CTEXT(Y, L$) BG 0 BG FILL 0, Y TO 19, Y CHAR 0 TEXT 0, Y, L$ TITLE_LINE_OFFSETS(Y) = -(20-LEN(L$))*4 Y = Y + 1 END SUB SUB BLANK(Y) Y = Y + 1 END SUB SUB CLT(Y) BG 0 BG FILL 0, Y TO 19, Y CHAR 0 TITLE_LINE_OFFSETS(Y) = 0 Y = Y + 1 END SUB '-------------------------------------------- ' ISOMETRIC 3D PROJECTION SUB ISO(P3(), SCR()) ' ISOMETRIC PROJECTION OF A POINT IN ' 3D WORLD COORDINATES TO A POINT IN ' 2D VIRTUAL SCREEN COORDINATES CALL ISOC(P3(_X), P3(_Y), P3(_Z), SCR()) END SUB SUB ISOE(A(), I, SCR()) ' ISOMETRIC PROJECTION OF A WORLD POINT ' THAT IS A SLICE IN A MULTIDIMENSIONAL ' ARRAY CALL ISOC(A(I,_X),A(I,_Y),A(I,_Z), SCR()) END SUB SUB ISOC(X,Y,Z, SCREEN()) ' ISOMETRIC PROJECTION WITH EACH WORLD ' COORDINATE PASSED INDIVIDUALLY SCREEN(_X) = X*8 SCREEN(_Y) = 4*Z - 8*Y END SUB '-------------------------------------------- ' DEFORMABLE 2D MAP STORED IN WORKING MEMORY GLOBAL MAP_WIDTH GLOBAL MAP_DEPTH GLOBAL START_X, START_Z SUB MAP_INIT(W, D) MAP_WIDTH = W MAP_DEPTH = D FILL $A000, W*D, 0 END SUB SUB MAP_ADDR(X, Z, AOUT) AOUT = $A000 + MAP_WIDTH*INT(Z) + INT(X) END SUB SUB MAP_GET(X, Z, VOUT) IF X<0 OR X>=MAP_WIDTH THEN VOUT = 0 ELSE IF Z<0 OR Z>=MAP_DEPTH THEN VOUT = 0 ELSE A = NONE CALL MAP_ADDR(X, Z, A) VOUT = PEEK(A) END IF END SUB SUB MAP_GET_PATCH(X, Z, PATCH()) FOR DZ = 0 TO 3 FOR DX = 0 TO 2 PX = X-1+DX PZ = Z-1+DZ CALL MAP_GET(PX, PZ, PATCH(DX,DZ)) NEXT DX NEXT DZ END SUB SUB MAP_SET(X, Z, V) A = -1 CALL MAP_ADDR(X, Z, A) POKE A, V END SUB SUB MAP_SETRECT(MINX, MINZ, MAXX, MAXZ, V) FOR X = MINX TO MAXX FOR Z = MINZ TO MAXZ CALL MAP_SET(X, Z, V) NEXT Z NEXT X END SUB '-------------------------------------------- ' DRAW THE MAP SUB MAP_DRAW DISPLAY (,0,0,,) BG 1 ATTR (,,,1,) FOR X = 0 TO MIN(MAP_WIDTH,19) FOR Z = 0 TO MIN(MAP_DEPTH,31) STEP 2 CALL MAP_DRAW_TILE(X, Z) NEXT Z NEXT X DISPLAY (,1,1,,) END SUB SUB MAP_DRAW_TILE(X, Z) DIM P(2,3) CALL MAP_GET_PATCH(X, Z, P()) C=0 A = 0 IF P(1,1)=0 AND P(1,2)=0 THEN A = 0 CALL MAP_TILE_SPACE(P(), C) ELSE IF P(1,1)=0 AND P(1,2)=1 THEN A = 0 CALL MAP_TILE_LOWER_HALF(P(), C) ELSE IF P(1,1)=1 AND P(1,2)=0 THEN A = 0 CALL MAP_TILE_UPPER_HALF(P(), C) ELSE IF P(1,1)=1 AND P(1,2)=1 THEN A = 0 CALL MAP_TILE_BOTH(P(), C) ELSE IF P(1,1)=2 OR P(1,2)=2 THEN A = 2 CALL MAP_TILE_FINISHLINE(P(), C) ELSE IF P(1,1)=3 OR P(1,2)=3 THEN A = 2 CALL MAP_TILE_SPIKES(P(), C) ELSE IF P(1,1)=4 OR P(1,2)=4 THEN A = 0 CALL MAP_TILE_MARSH(P(), C) END IF ATTR (A) CELL X, Z/2, C END SUB SUB MAP_TILE_SPACE(P(), C) IF P(1,0) <> 0 THEN IF P(0,0)<>0 AND P(2,0)<>0 THEN C=17 ELSE IF P(0,0)<>0 THEN C=21 ELSE IF P(2,0)<>0 THEN C=20 END IF ELSE C = 0 END IF END SUB SUB MAP_TILE_BOTH(P(), C) IF P(1,3) = 0 THEN IF P(0,2)=0 AND P(0,3)=0 THEN C = 4 ELSE IF P(2,2)=0 AND P(2,3)=0 THEN C = 5 ELSE C = 1 END IF ELSE IF P(1,0) = 0 THEN IF P(0,0)=0 AND P(0,1)=0 THEN C = 2 ELSE IF P(2,0)=0 AND P(2,1)=0 THEN C = 3 ELSE C = 1 END IF ELSE C = 1 END IF END SUB SUB MAP_TILE_LOWER_HALF(P(), C) IF P(0,1)=0 AND P(0,2)=0 THEN C = 9 ELSE IF P(2,1)=0 AND P(2,2)=0 THEN C = 11 ELSE C = 10 END IF END SUB SUB MAP_TILE_UPPER_HALF(P(), C) IF P(0,1)=0 AND P(0,2)=0 THEN C = 6 ELSE IF P(2,1)=0 AND P(2,2)=0 THEN C = 8 ELSE C = 7 END IF END SUB SUB MAP_TILE_FINISHLINE(P(), C) CALL MAP_TILE_SURFACE(P(), 32, C) END SUB SUB MAP_TILE_SPIKES(P(), C) CALL MAP_TILE_SURFACE(P(), 35, C) END SUB SUB MAP_TILE_MARSH(P(), C) CALL MAP_TILE_SURFACE(P(), 35, C) END SUB SUB MAP_TILE_SURFACE(P(), BASEC, C) IF P(1,1)=1 THEN C=BASEC+2 ELSE IF P(1,2)=1 THEN C=BASEC+1 ELSE C=BASEC END IF END SUB '-------------------------------------------- ' ACTORS ' 0 = THE PLAYER'S BALL ' 1+ = ENEMIES DIM GLOBAL ACTOR_TYPE(63) DIM GLOBAL ACTOR_P(63, 2) DIM GLOBAL ACTOR_V(63, 2) ' TODO: TAKE RADIUS INTO ACCOUNT 'DIM GLOBAL ACTOR_RADIUS(63) ' TODO: TAKE SPRITE HOTSPOT INTO ACCOUNT 'DIM GLOBAL ACTOR_HOTSPOT(63, 2) DIM GLOBAL ACTOR_FRAME(63) DIM GLOBAL ACTOR_COLOR(63) DIM GLOBAL ACTOR_SHADOW(63) GLOBAL ACTOR_MAX ' ACTOR TYPES GLOBAL T_BALL T_BALL = 1 GLOBAL T_ROBOT_NS T_ROBOT_NS = 2 GLOBAL T_ROBOT_EW T_ROBOT_EW = 3 SUB ACTOR_INIT ACTOR_MAX = -1 END SUB SUB ACTOR_ALLOC(TYPE, E) ACTOR_MAX = ACTOR_MAX + 1 E = ACTOR_MAX ACTOR_TYPE(E) = TYPE END SUB SUB SORT(REFS(), N, ROWS(), SORTCOL) I = 1 WHILE I < N J = I DO IF J <= 0 THEN GOTO ENDINSERT END IF A = ROWS(REFS(J-1), SORTCOL) B = ROWS(REFS(J), SORTCOL) IF A >= B THEN GOTO ENDINSERT END IF SWAP REFS(J), REFS(J-1) J = J - 1 LOOP ENDINSERT: I = I + 1 WEND END SUB SUB DRAW_ACTORS DIM ORDER(ACTOR_MAX) FOR I = 0 TO ACTOR_MAX ORDER(I) = I NEXT I CALL SORT(ORDER(),ACTOR_MAX+1,ACTOR_P(),_Z) SPRITE OFF S = 0 DIM P2(1) FOR I = 0 TO ACTOR_MAX A = ORDER(I) AX = ACTOR_P(A,_X) AY = ACTOR_P(A,_Y) AZ = ACTOR_P(A,_Z) AC = ACTOR_COLOR(A) AF = ACTOR_FRAME(A) CALL ISOC(AX, AY, AZ, P2()) PRIORITY = 0 - (AY >= 0) SPRITE S, P2(_X)-4, P2(_Y)-6, AF SPRITE.A S, (AC,,,PRIORITY,) S = S + 1 IF ACTOR_SHADOW(A) AND AY >= 0 THEN IF TIMER MOD 2 = 0 THEN CALL ISOC(AX, 0, AZ, P2()) SPRITE S, P2(_X)-4, P2(_Y)-6, AF+16 SPRITE.A S, (7,,,1,) S = S + 1 END IF END IF NEXT I END SUB SUB ACTOR_ANIM(A, BASE, NFRAMES, FRAMET) F = (GTIMER/FRAMET) MOD NFRAMES ACTOR_FRAME(A) = BASE + F END SUB SUB ACTOR_MOVE_ALL FOR A = 0 TO ACTOR_MAX CALL ACTOR_MOVE(A) NEXT A END SUB SUB ACTOR_SETPOS(A, X, Y, Z) ACTOR_P(A,_X) = X ACTOR_P(A,_Y) = Y ACTOR_P(A,_Z) = Z END SUB SUB ACTOR_SETVEL(A, X, Y, Z) ACTOR_V(A,_X) = X ACTOR_V(A,_Y) = Y ACTOR_V(A,_Z) = Z END SUB SUB ACTOR_MOVEV(A) FOR I = 0 TO 2 ACTOR_P(A,I) = ACTOR_P(A,I)+ACTOR_V(A,I) NEXT I END SUB SUB ACTOR_ACCEL(A, DX, DY, DZ) ACTOR_V(A,_X) = ACTOR_V(A,_X) + DX ACTOR_V(A,_Y) = ACTOR_V(A,_Y) + DY ACTOR_V(A,_Z) = ACTOR_V(A,_Z) + DZ END SUB SUB ACTOR_MOVE(A) TYPE = ACTOR_TYPE(A) IF TYPE = T_BALL THEN CALL BALL_MOVE(A) ELSE IF TYPE = T_ROBOT_NS THEN CALL ROBOT_MOVE(A) ELSE IF TYPE = T_ROBOT_EW THEN CALL ROBOT_MOVE(A) ELSE BG 1 ATTR (0,0,0,1) TEXT 0,0, "UNKNOWN ACTOR TYPE" + STR$(A) END END IF END SUB SUB ACTOR_TRACE(A) BG 0 ATTR (7) X = ACTOR_P(A,_X) Y = ACTOR_P(A,_Y) Z = ACTOR_P(A,_Z) C = NONE CALL MAP_GET(X, Z, C) BG FILL 0,0 TO 15,3 CHAR 0 TEXT 0,0,"X:"+STR$(X) TEXT 0,1,"Y:"+STR$(Y) TEXT 0,2,"Z:"+STR$(Z) ADDR = NONE CALL MAP_ADDR(X, Z, ADDR) TEXT 0,3,"A:"+HEX$(ADDR) END SUB '-------------------------------------------- ' ENEMIES SUB ROBOT_NEW(TYPE, X, Z) E = NONE CALL ACTOR_ALLOC(TYPE, E) CALL ACTOR_SETPOS(E, X, 0, Z) ACTOR_FRAME(E) = 69 ACTOR_COLOR(E) = 3 ACTOR_SHADOW(E) = FALSE SPEED = 1/16 IF TYPE = T_ROBOT_NS THEN CALL ACTOR_SETVEL(E, 0, 0, SPEED) ELSE IF TYPE = T_ROBOT_EW THEN CALL ACTOR_SETVEL(E, SPEED, 0, 0) ELSE CALL FAIL("ROBOT_NEW", STR$(TYPE)) END IF END SUB SUB ROBOT_MOVE(E) TYPE = ACTOR_TYPE(E) X = ACTOR_P(E,_X) Z = ACTOR_P(E,_Z) VX = ACTOR_V(E,_X) VZ = ACTOR_V(E,_Z) ' REVERSE AT EDGE OF PLATFORM MX = X + SGN(VX)/2 MZ = Z + SGN(VZ)/2 C = NONE CALL MAP_GET(MX, MZ, C) IF C = 0 THEN ACTOR_V(E,_X) = VX * -1 ACTOR_V(E,_Z) = VZ * -1 END IF CALL ACTOR_MOVEV(E) CALL ACTOR_ANIM(E, 69, 2, 15) END SUB '-------------------------------------------- ' BALL GLOBAL BALL GLOBAL BALL_STARTED GLOBAL BALL_FALLEN SUB BALL_NEW(A) CALL ACTOR_ALLOC(T_BALL, A) ACTOR_COLOR(A) = 1 ACTOR_FRAME(A) = 64 ACTOR_SHADOW(A) = TRUE CALL BALL_INIT(A) END SUB SUB BALL_INIT(A) BALL_STARTED = 0 CALL BALL_LAUNCH(A) END SUB SUB BALL_LAUNCH(A) CALL ACTOR_SETPOS(A, START_X, 8, START_Z) ACTOR_V(A,_X) = 0 ACTOR_V(A,_Y) = 0 ACTOR_V(A,_Z) = 0 BALL_FALLEN = FALSE END SUB SUB BALL_MOVE(A) CALL ACTOR_MOVEV(A) PX = ACTOR_P(A,_X) PY = ACTOR_P(A,_Y) PZ = ACTOR_P(A,_Z) VY = ACTOR_V(A,_Y) C = -1 CALL MAP_GET(INT(PX), INT(PZ), C) ROLLING=PY<0.05 AND ABS(VY)<0.05 AND C<>0 IF ROLLING THEN ACTOR_P(A,_Y) = 0 ACTOR_V(A,_Y) = 0 ' APPLY SURFACE FRICTION CALL APPLY_FRICTION(A, 0.025) CALL CONTROL_BALL(A) ELSE IF PY < 0 THEN IF C <> 0 AND NOT BALL_FALLEN THEN CALL BOUNCE(A) ' APPLY SURFACE & ELASTIC FRICTION CALL APPLY_FRICTION(A, 0.05) CALL CONTROL_BALL(A) ELSE IF PY <= -12 THEN CALL BALL_LAUNCH(A) ELSE BALL_FALLEN = TRUE END IF END IF CALL ACTOR_ACCEL(A, 0, -GRAVITY, 0) END IF END SUB SUB BOUNCE(A) ACTOR_P(A,_Y) = -ACTOR_P(A,_Y) ACTOR_V(A,_Y) = -ACTOR_V(A,_Y) * 0.6 END SUB SUB APPLY_FRICTION(A, COEFF) VX = ACTOR_V(A,_X) VZ = ACTOR_V(A,_Z) V = SQR(VX^2 + VZ^2) IF V = 0 THEN EXIT SUB F = COEFF * V ' EMERGENCY BRAKE IF BUTTON(0,1) THEN F = F * 5 END IF ' UNIT VECTOR UX = VX / V UZ = VZ / V CALL ACTOR_ACCEL(A, -UX*F, 0, -UZ*F) END SUB SUB CONTROL_BALL(A) DX = LEFT(0) - RIGHT(0) DZ = UP(0) - DOWN(0) THRUST = 0.005 CALL ACTOR_ACCEL(A, DX*THRUST, 0, DZ*THRUST) ' JUMP IF BUTTON(0,0) THEN ACTOR_V(A,_Y) = 0.25 END IF IF BALL_STARTED = 0 THEN IF DX OR DZ OR BUTTON(0) THEN BALL_STARTED = GTIMER CALL CLEAR_TIP END IF END IF END SUB SUB BALL_AT_END(A, RESULT) X = ACTOR_P(A,_X) Y = ACTOR_P(A,_Y) Z = ACTOR_P(A,_Z) VY = ACTOR_V(A,_Y) ROLLING = Y=0 AND VY=0 C = NONE CALL MAP_GET(X, Z, C) RESULT = (C = 2 AND ROLLING) END SUB '-------------------------------------------- ' LEVELS GLOBAL LEVEL_TIP_MAX LEVEL_TIP_MAX = 3 DIM GLOBAL LEVEL_TIP$(LEVEL_TIP_MAX) SUB FLOOR(MINX, MINY, MAXX, MAXY) CALL MAP_SETRECT(MINX, MINY, MAXX, MAXY, 1) END SUB SUB FINISH(MINX, MINY, MAXX, MAXY) CALL MAP_SETRECT(MINX, MINY, MAXX, MAXY, 2) END SUB SUB SPIKES(MINX, MINY, MAXX, MAXY) CALL MAP_SETRECT(MINX, MINY, MAXX, MAXY, 3) END SUB SUB MARSH(MINX, MINY, MAXX, MAXY) CALL MAP_SETRECT(MINX, MINY, MAXX, MAXY, 4) END SUB SUB TIP(I, S$) LEVEL_TIP$(I) = S$ END SUB SUB START(X, Z) START_X = X START_Z = Z END SUB SUB LEVEL00 CALL MAP_INIT(20, 32) CALL TIP(0, "USE THE GAMEPAD TO") CALL TIP(1, "MOVE THE BALL ONTO") CALL TIP(2, "THE CHECKERED AREA") CALL FLOOR(2, 4, 7, 13) CALL FLOOR(8, 7, 12, 10) CALL FLOOR(13, 4, 18, 13) CALL FINISH(17, 4, 17, 13) CALL START(3, 5) END SUB SUB LEVEL01 CALL MAP_INIT(20, 32) CALL TIP(0, "USE BUTTON A") CALL TIP(1, "TO JUMP GAPS") CALL FLOOR(2, 4, 7, 13) CALL FLOOR(8, 7, 9, 10) CALL FLOOR(11, 7, 12, 10) CALL FLOOR(13, 4, 18, 13) CALL FINISH(17, 4, 17, 13) CALL START(3, 5) END SUB SUB LEVEL02 CALL MAP_INIT(20, 32) CALL TIP(0, "USE BUTTON B") CALL TIP(1, "TO BRAKE") CALL FLOOR(5, 4, 7, 11) CALL FLOOR(2, 18, 4, 25) CALL FLOOR(8, 7, 16, 8) CALL FLOOR(15, 9, 16, 22) CALL FLOOR(5, 21, 16, 22) CALL START(6, 5) CALL FINISH(3, 18, 3, 25) END SUB SUB LEVEL03 CALL MAP_INIT(20, 32) CALL TIP(0, "NOT ALL SURFACES") CALL TIP(1, "ARE SAFE") CALL FLOOR(2, 4, 7, 13) CALL FLOOR(8, 6, 12, 11) CALL SPIKES(9, 6, 11, 11) CALL FLOOR(13, 4, 18, 13) CALL FINISH(17, 4, 17, 13) CALL START(3, 5) END SUB SUB LEVEL04 CALL MAP_INIT(20, 32) CALL TIP(0, "AVOID ENEMIES OR") CALL TIP(1, "JUMP OVER THEM") CALL FLOOR(2, 7, 8, 10) CALL FLOOR(9, 4, 18, 13) CALL FLOOR(13, 14, 15, 22) CALL FINISH(13, 21, 15, 21) CALL ROBOT_NEW(T_ROBOT_NS, 9.5, 4.5) CALL ROBOT_NEW(T_ROBOT_EW, 9.5, 13.5) CALL START(2.5, 8) END SUB SUB LEVEL_INIT(N) FOR I = 0 TO LEVEL_TIP_MAX LEVEL_TIP$(I) = "" NEXT I IF N = 0 THEN CALL LEVEL00 ELSE IF N = 1 THEN CALL LEVEL01 ELSE IF N = 2 THEN CALL LEVEL02 ELSE IF N = 3 THEN CALL LEVEL03 ELSE IF N = 4 THEN CALL LEVEL04 ELSE CALL FAIL("LEVEL", "INVALID: "+STR$(N)) END IF END SUB GLOBAL LEVEL_MAX LEVEL_MAX = 4 DIM GLOBAL LEVEL_BEST(LEVEL_MAX) DIM GLOBAL LEVEL_LAST(LEVEL_MAX) '-------------------------------------------- ' MAIN SUB SHOW_TIP BG 0 ATTR (4) FOR I = 0 TO LEVEL_TIP_MAX CALL CTEXT(13+I, LEVEL_TIP$(I)) NEXT I END SUB SUB CLEAR_TIP FOR I = 0 TO 2 CALL CLT(13+I) NEXT I END SUB SUB FORMAT_TIME(T, T$) T$ = STR$((T\6)/10)+" S" END SUB SUB TITLE_SCREEN(STARTL) CALL TITLE_INIT BG 0 ATTR (1) CALL CTEXT(1, "LOSE YOUR MARBLES!") ATTR (4) CALL CTEXT(4, "STARTING LEVEL") ATTR(4) CALL CTEXT(13, "PRESS ANY BUTTON") CALL CTEXT(14, "TO PLAY") REPEAT ATTR(4) CALL CTEXT(6, "< "+STR$(STARTL+1)+" >") ATTR (0) BEST = LEVEL_BEST(STARTL) IF BEST > 0 THEN BEST$ = "" CALL FORMAT_TIME(BEST, BEST$) CALL CTEXT(9, "BEST: "+BEST$) ELSE CALL CTEXT(9, "NO BEST TIME YET") END IF LAST = LEVEL_LAST(STARTL) IF LAST > 0 THEN LAST$ = "" CALL FORMAT_TIME(LAST, LAST$) CALL CTEXT(10, "LAST: "+LAST$) ELSE CALL CLT(10) END IF WAIT VBL DL = LEFT TAP(0) - RIGHT TAP(0) NEXTL = STARTL + LEVEL_MAX + 1 + DL STARTL = NEXTL MOD (LEVEL_MAX + 1) UNTIL BUTTON TAP(0) CALL TITLE_END CLS END SUB GLOBAL GTIMER SUB PLAY_LEVEL(N, TIME) CALL TITLE_INIT CALL ACTOR_INIT CALL LEVEL_INIT(N) CALL MAP_DRAW CALL SHOW_TIP BALL = NONE CALL BALL_NEW(BALL) LEVEL_COMPLETE = FALSE REPEAT IF BALL_STARTED THEN TIME = GTIMER - BALL_STARTED TIME$ = "" CALL FORMAT_TIME(TIME, TIME$) ATTR (4,,,1,) TEXT 0, 0, TIME$+" " END IF ' ENSURE RANDOM ENEMY BEHAVIOUR IS ' ACTUALLY PREDICTABLE RANDOMIZE GTIMER CALL ACTOR_MOVE_ALL CALL DRAW_ACTORS CALL BALL_AT_END(BALL, LEVEL_COMPLETE) WAIT VBL GTIMER = GTIMER + 1 UNTIL LEVEL_COMPLETE END SUB SUB WAIT_TAP REPEAT WAIT VBL UNTIL BUTTON TAP(0) END SUB SUB PLAY_GAME(START_LEVEL) FOR L = START_LEVEL TO LEVEL_MAX LEVEL_TIME = 0 BG FILL 0,0 TO 0, 20 CHAR 0 CALL PLAY_LEVEL(L, LEVEL_TIME) ' TODO: A WARP OUT EFFECT BG 0 ATTR (4) CALL CTEXT(6, "SUCCESS") BEST = LEVEL_BEST(L) IF BEST = 0 OR LEVEL_TIME < BEST THEN CALL CTEXT(8, "BEST TIME!") LEVEL_BEST(L) = LEVEL_TIME END IF LEVEL_LAST(L) = LEVEL_TIME CALL WAIT_TAP CLS 0 NEXT L END SUB GAMEPAD 1 START_LEVEL = 0 DO CALL TITLE_SCREEN(START_LEVEL) CALL PLAY_GAME(START_LEVEL) TEXT 1, 7, "THAT'S ALL, FOLKS!" CALL WAIT_TAP CLS 0 LOOP #1:MAIN PALETTES 002D1814003F3020003F181500322A15 002F1B06003F2A15003F2A15002A1500 #2:MAIN CHARACTERS 00000000000000000000000000000000 0000000000000000FFFFFFFFFFFFFFFF 00000000000000007FFFFFFFFFFFFFFF 0000000000000000FEFFFFFFFFFFFFFF 0000000000000080FFFFFFFFFFFFFFFF 0000000000000001FFFFFFFFFFFFFFFF 00000080FF7F0000FFFFFFFFFF7F0000 00000000FFFF0000FFFFFFFFFFFF0000 00000001FFFE0000FFFFFFFFFFFE0000 0000000000000000000000007FFFFFFF 000000000000000000000000FFFFFFFF 000000000000000000000000FEFFFFFF 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 FFFF000000000000FFFF000000000000 00000000000000000000000000000000 00000000000000000000000000000000 FF7F000000000000FF7F000000000000 FFFE000000000000FFFE000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 FFFFFFFFFFFFFFFF0F0FF0F00F0FF0F0 FFFFFFFF000000000F0FF0F0FFFFFFFF 00000000FFFFFFFFFFFFFFFF0F0FF0F0 888822228888222277FFDDFF77FFDDFF 888822220000000077FFDDFFFFFFFFFF 0000000088882222FFFFFFFF77FFDDFF AA55AA55AA55AA55FFFFFFFFFFFFFFFF EE55BB55AA77AA55FFFFFFFFFFFFFFFF 000000000000000000000000FFFFFFFF 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 0000182202061C00003C665E7E7E3C00 0008041C0404040000183C243C3C3C00 000804340404040000183C0C3C3C3C00 0008040C0404040000183C303C3C3C00 000804040404040000183C3C3C3C3C00 181C02030303077E00247EFFFFFFFF7E 181C06030303077E183C7EFFFFFFFF7E 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000003C7E7E3C000000003C7E7E3C 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000007EFFFF7E000000007EFFFF7E 000000007EFFFF7E000000007EFFFF7E 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00606000000000006090906000000000 0000000000000000C0C0000000000000 00000000000000008000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 0F30404080808080000F3F3F7F7F7F7F FF0000000000000000FFFFFFFFFFFFFF F00802020101010100F4FEFEFFFFFFFF 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 80808080808080807F7F7F7F7F7F7F7F 0000000000000000FFFFFFFFFFFFFFFF 0101010101010101FFFFFFFFFFFFFFFF 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 808080804000300F7F7F7F7F3F7F3F0F 00000000000000FFFFFFFFFFFFFFFFFF 0101010102020CF0FFFFFFFFFEFEFCF0 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 183C3C3C3C183C181824242424182418 6CFEFE7E240000006C92925A24000000 247EFF7E7EFF7E24245A815A5A815A24 083E7F7E3F7F3E080836414631413608 62F7FE7C3E7FEF4662959A742E59A946 1C3E7E7EFFFE7F3A1C224A46919A453A 183C3C78300000001824244830000000 0C1E3C78783C1E0C0C1224484824120C 30783C1E1E3C78303048241212244830 00247E7EFF7E7E2400245A6681665A24 00183C7EFF7E3C180018246681662418 000000183C3C78300000001824244830 0000007EFF7E00000000007E817E0000 00000000183C3C180000000018242418 060F1E3C78F0E040060912244890A040 3C7EFFFFFFFF7E3C3C4299918999423C 183C7C3C3C7EFF7E182444242466817E 3C7EFF7E3C7EFF7E3C429972244E817E 3C7EFF7E6FFF7E3C3C4299726999423C 66FFFFFF7F0F0F066699998179090906 7EFFFEFE7F7FFE7C7E819E827979827C 1C3E7CFEFFFF7E3C1C224C829999423C 7EFF7F1E3C7878307E81791224484830 3C7EFF7EFFFF7E3C3C4299429999423C 3C7EFF7F7FFF7E3C3C4299417999423C 0000183C183C18000000182418241800 0000183C183C78300000182418244830 000C1E3C783C1E0C000C12244824120C 00007EFF7EFF7E0000007E817E817E00 0030783C1E3C78300030482412244830 3C7EFF7E3C183C183C42997224182418 3C7EFFFFFFFE7E3C3C429991919E423C 183C7EFFFFFFFF661824429981999966 7CFEFFFEFFFFFE7C7C8299829999827C 3C7EFFF6F6FF7E3C3C4299969699423C 78FCFEFFFFFEFC787884929999928478 7EFFFEFCF8FEFF7E7E819E84989E817E 7EFFFEFCF8F0F0607E819E8498909060 3C7EFEFFFFFF7E3C3C429E919999423C 66FFFFFFFFFFFF666699998199999966 3C7E3C3C3C3C7E3C3C4224242424423C 1E3F1F0F6FFF7E3C1E2119096999423C 66FFFEFCFCFEFF666699928484929966 60F0F0F0F0FEFF7E60909090909E817E 42E7FFFFFFFFFF6642A5998181999966 66FFFFFFFFFFFF666699898191999966 3C7EFFFFFFFF7E3C3C4299999999423C 7CFEFFFEFCF0F0607C8299829C909060 3C7EFFFFFFFE7F3E3C4299999592413E 7CFEFFFEFCFEFF667C82998284929966 3E7FFE7E3F7FFE7C3E419E423979827C 7EFF7E3C3C3C3C187E81662424242418 66FFFFFFFFFF7E3C669999999999423C 66FFFFFFFF7E3C186699999999422418 66FFFFFFFFFFE742669999818199A542 66FF7E3C7EFFFF666699422442999966 66FFFF7E3C3C3C186699994224242418 7EFF7E3C78FEFF7E7E817224489E817E 3C7E7C78787C7E3C3C424C48484C423C 60F0783C1E0F07026090482412090502 3C7E3E1E1E3E7E3C3C4232121232423C 183C7EFF660000001824429966000000 00000000007EFF7E00000000007E817E