rem Errata rem dim foreground_color=COLUPF barfed rem Compiler options set smartbranching on set romsize 16k set kernel_options no_blank_lines rem Declare constants def true = 1 def false = 0 rem English names for joystick directions const west = 1 const east = 2 const north = 3 const south = 4 const nwest = 5 const neast = 6 const swest = 7 const seast = 8 const none = 0 rem My 25 standard colors for NTSC const c_brown = $F2 const c_pink = $3C const c_skyblue = $98 const c_olive = $E4 const c_lilac = $7A const c_aqua = $B8 const c_orange = $38 const c_blue = $86 const c_red = $46 const c_purple = $64 const c_lime = $DA const c_gold = $2E const c_navy = $84 const c_green = $C6 const c_maroon = $42 const c_yellow = $1E const c_fuchsia = $58 const c_cyan = $A6 const c_white = $0E const c_ltgray = $0C const c_silver = $0A const c_gray = $08 const c_dkgray = $02 const c_black = $00 const c_tan = $FC const c_forestgreen = $D2 const screen_height = 160 const screen_width = 192 rem Can't foreground_color=COLUPF for some reason.. dim fground_color=COLUPF dim bground_color=COLUBK rem Declare variables rem "Global" Variables (i.e. Don't reuse these!) dim counter = a dim level = p dim tempvar = q dim whatcollide = r rem Knightmare Level Variables dim cooldown = b dim boolean = c dim enemyhp = d dim enemycolor = e dim enemypattern = f dim enemysize = g dim enemies = h dim enemytype = i dim nitebearhp = j dim weapondmg = k rem 4 Way Scrolling Variables dim vk_key = m dim lastkey = o dim steffie_lastx = d dim steffie_lasty = i rem Stage Screen Variables dim tx = d dim ty = e rem Define boolean variables def march=counter{4} def enemydir=boolean{2} def canshoot=boolean{3} def scrolling=boolean{4} score = 0 init_game rem Init variables scorecolor = c_silver fground_color = c_tan bground_color = c_navy enemies = 8 enemyhp = 25 nitebearhp = 100 weapondmg = 1 cooldown = 0 missile1x = 0 missile1y = 0 missile1height = 4 level = 1 scrolling = true gosub sound_stop_all bank2 gosub clearscreen bank4 playfield: .X..X.X.XXX.XXX..XX..XX..X..XX.. .XX.X.X..X..X....X.X.X..X.X.X.X. .X.XX.X..X..XX...XX..XX.XXX.XX.. .X..X.X..X..X....X.X.X..X.X.X.X. .X..X.X..X..XXX..XXX.XX.X.X.X.X. ................................ ............XX....XX............ ............XXXXXXXX............ ..........XXX.XXXX.XXX.......... .....XX....X.X.XX.X.X....XX..... ....XXXX..XXX.X..X.XXX..XXXX.... end draw_title gosub update_counters drawscreen if joy0fire then rand = counter : gosub print_stage bank2 : goto main_creation_event goto draw_title main_creation_event playfieldpos = 8 playfield: X.X..........................XXX XX...........................X.X XXX...........................XX XXX..........................XXX X.X..........................XXX XX...........................X.X XXX...........................XX XXX..........................XXX X.X..........................XXX XX...........................X.X XXX...........................XX XXX..........................XXX end player0: %11100000 %01100011 %01110011 %00111110 %00111100 %11011100 %10111101 %11111111 %01111110 %00100100 %10100101 %11011011 %10100101 %11011011 %01111110 %01100110 end player0x = 80 player0y = 80 ballx = 35 bally = 0 fground_color = c_gray bground_color = c_forestgreen boolean{0} = 0 boolean{1} = 0 enemydir = 0 enemytype = (rand&7) + 1 gosub createenemy main_begin_step if cooldown > 0 then cooldown = cooldown - 1 : AUDV0 = 4 : AUDC0 = 8 : AUDF0 = cooldown else AUDV0 = 0 main_draw_event gosub update_counters if switchreset then reboot if player0x > 29 && joy0left then player0x = player0x - 2 if player0x < 125 && joy0right then player0x = player0x + 2 if player0y > 32 && joy0up then player0y = player0y - 1 if player0y < 88 && joy0down then player0y = player0y + 1 if joy0fire && bally = 0 && cooldown = 0 then bally = player0y - 9 : ballx = player0x + 4 : cooldown = 10 if bally > 1 then gosub draw_weapon rem GOTCHA: enemyph will wrap around to 255 instead of being a negative number thus the OR operation.. if enemyhp < 1 || enemyhp > 128 then gosub kill_enemy else if counter{0} then gosub move_enemy if enemies = 0 then scrolling = true : goto 4way_scroll_init bank3 if nitebearhp < 1 then goto init_game if player1y > 160 then gosub createenemy draw_event rem if enemies > 1 then pfscroll down if scrolling && counter{0} then pfscroll down if march then REFP0 = 8 : REFP1 = 8 gosub paint_nitebear COLUP1 = enemycolor NUSIZ1 = enemysize drawscreen gosub find_collide if whatcollide = 3 then enemyhp = enemyhp - weapondmg: gosub draw_hit if whatcollide = 1 then gosub nitebear_col_event if whatcollide = 2 then gosub nitebear_col_event main_end_step goto main_begin_step change_score if enemytype = 1 then score = score + 25 if enemytype = 2 then score = score + 25 if enemytype = 3 then score = score + 10 if enemytype = 4 then score = score + 30 if enemytype = 5 then score = score + 30 if enemytype = 6 then score = score + 25 if enemytype = 7 then score = score + 10 if enemytype = 8 then score = score + 25 if enemytype = 9 then score = score + 100 return kill_enemy gosub change_score ballx = 0 : bally = 0 player1x = 0 : player1y = -1 enemies = enemies - 1 enemyhp = 25 + level gosub createenemy return find_collide whatcollide = 0 if collision(player0, player1) then whatcollide = 1 if collision(player0, missile1) then whatcollide = 2 if collision(player1, ball) then whatcollide = 3 return paint_nitebear if nitebearhp > 50 then COLUP0 = c_tan : return if nitebearhp > 25 then COLUP0 = c_orange : return if nitebearhp > 10 then COLUP0 = c_red return draw_hit AUDV0 = 5 : AUDC0 = counter&4 : AUDF0 = counter&15 if march then REFP0 = 8 : REFP1 = 8 gosub paint_nitebear COLUP1 = c_red NUSIZ1 = enemysize drawscreen return draw_nitebearhit AUDV0 = 4 : AUDC0 = 2 : AUDF0 = (counter&15) if march then REFP0 = 8 : REFP1 = 8 COLUP0 = c_yellow COLUP1 = enemycolor NUSIZ1 = enemysize drawscreen return update_counters counter = counter + 1 return draw_weapon bally = bally - 2 if bally < 4 then bally = 0 : ballx = 0 : return if counter{0} then goto shaft else goto hilt shaft ballx = ballx + 1 bally = bally + 2 CTRLPF = $11 ballheight = 9 return hilt ballx = ballx - 1 bally = bally - 2 CTRLPF = $21 ballheight = 1 return heat_seeking_shot if player0x > missile1x then missile1x = missile1x + 1 else missile1x = missile1x - 1 if counter{1} then missile1x = missile1x - 1 else missile1x = missile1x + 1 return move_enemy if canshoot then if missile1y = 0 then if counter{6} then missile1y = player1y : missile1x = player1x + 2 if missile1y > 0 then missile1y = missile1y + 4 : if enemytype = 9 then gosub heat_seeking_shot if missile1y > 160 then missile1y = 0 rem on goto crashed game for some reason.. if enemypattern = 1 then goto pattern_fastdown if enemypattern = 2 then goto pattern_down if enemypattern = 3 then goto pattern_backforth if enemypattern = 4 then goto pattern_swoop return pattern_fastdown player1y = player1y + 2 return pattern_down player1y = player1y + 1 return pattern_backforth if enemydir then player1x = player1x - 1 else player1x = player1x + 1 if player1x > 115 then enemydir = 1 if player1x < 29 then enemydir = 0 return pattern_swoop player1y = player1y + 1 if march then player1x = player1x - 4 else player1x = player1x + 4 return nitebear_col_event if enemytype = 8 then weapondmg = weapondmg + 1 : gosub createenemy : return nitebearhp = nitebearhp - 1 : gosub draw_nitebearhit : if player0y < 88 then player0y = player0y return createenemy missile1y = 0 if enemies = 1 then enemytype = 9 else enemytype = (rand&7) + 1 if enemytype = 1 then goto create_spacecars if enemytype = 2 then goto create_frogsnake if enemytype = 3 then goto create_bat if enemytype = 4 then goto create_four if enemytype = 5 then goto create_spacecars if enemytype = 6 then goto create_bat if enemytype = 7 then goto create_frogsnake if enemytype = 8 then goto create_powerup if enemytype = 9 then goto create_boss return create_spacecars gosub draw_spacecars player1x = (rand&63) + 32 player1y = 0 enemycolor = c_white enemypattern = 1 enemysize = $20 canshoot = false return create_frogsnake gosub draw_frogsnake player1x = (rand&63) + 32 player1y = 0 enemycolor = c_lime enemypattern = 2 enemysize = $10 canshoot = true return create_bat gosub draw_bat player1x = (rand&63) + 32 player1y = 0 enemycolor = c_skyblue enemypattern = 4 enemysize = $35 canshoot = true return create_four gosub draw_frogsnake player1x = (rand&63) + 32 player1y = 0 enemycolor = c_orange enemypattern = 1 enemysize = $25 canshoot = true return create_boss gosub draw_castle gosub draw_boss scrolling = false player1x = (rand&63) + 32 player1y = 36 enemyhp = 60 + level enemycolor = c_fuchsia enemypattern = 3 enemysize = $35 canshoot = true drawscreen return create_powerup gosub draw_powerup player1x = (rand&63) + 32 player1y = 24 enemyhp = 5 enemycolor = c_fuchsia enemypattern = 1 enemysize = $00 canshoot = false return draw_frogsnake player1: %11100000 %00100110 %00111100 %00111101 %11111110 %00100100 %01011010 %00100100 %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 %00000000 %00111110 %01100011 %11001110 %00011000 %01100110 %10111101 %10011001 %01100110 end return draw_spacecars player1: %00001001 %00000110 %00001001 %00000110 %00000110 %00001111 %00001111 %00001001 %01100000 %01100000 %11110000 %10010000 %10010000 %11110000 %01100000 %11110000 %00000110 %00001111 %00000110 %00000110 %00001001 %00001111 %00001001 %00001111 end return draw_bat player1: %10000000 %11010101 %01111111 %00111110 %01101100 %11010110 %10111011 %00101001 end return draw_boss player1: %11000011 %01100110 %01111110 %11111111 %11111111 %10011001 %01111110 %11111111 %00011000 %00100100 %01100110 %10011001 %10111101 %11111111 %01111110 %10100101 end return draw_powerup player1: %00000000 %00000000 %00011000 %00011000 %00011000 %00011000 %00011000 %00000000 %00111100 %01000010 %10111001 %11101101 %10100101 %10111101 %01000010 %00111100 end return draw_castle playfieldpos = 8 playfield: X.X.XX.XX.XX.XX..XX.XX.XX.XX.XXX XX...XXXXXXXXXXXXXXXXXXXXXX..X.X XXX...XXXXXX........XXXXXX....XX XXX..........................XXX X.X..........................XXX XX...........................X.X XXX...........................XX XXX..........................XXX X.X..........................XXX XX...........................X.X XXX...........................XX end return bank 2 sound_stop_all AUDV0=0 AUDV1=0 return otherbank print_stage gosub clearscreen bank4 fground_color = c_white bground_color = c_black gosub draw_stage_screen gosub print_lvl ps_drawevent counter = counter + 1 drawscreen if counter = 255 then scorecolor = c_silver : return otherbank goto ps_drawevent draw_stage_screen gosub clearscreen bank4 pfclear playfieldpos = 8 scorecolor = c_black playfield: ..XXXX.XXXXX..XXX...XXXX.XXXXX.. .X.......X...X...X.X.....X...... ..XXX....X...XXXXX.X..XX.XXX.... .....X...X...X...X.X...X.X...... .XXXX....X...X...X..XXXX.XXXXX.. ................................ ................................ ................................ ................................ ................................ end return print_0 gosub bit_pattern_111 gosub bit_pattern_101 gosub bit_pattern_101 gosub bit_pattern_101 gosub bit_pattern_111 return print_1 gosub bit_pattern_110 gosub bit_pattern_010 gosub bit_pattern_010 gosub bit_pattern_010 gosub bit_pattern_111 return print_2 gosub bit_pattern_111 gosub bit_pattern_001 gosub bit_pattern_111 gosub bit_pattern_100 gosub bit_pattern_111 return print_3 gosub bit_pattern_111 gosub bit_pattern_001 gosub bit_pattern_111 gosub bit_pattern_001 gosub bit_pattern_111 return print_4 gosub bit_pattern_101 gosub bit_pattern_101 gosub bit_pattern_111 gosub bit_pattern_001 gosub bit_pattern_001 return print_5 gosub bit_pattern_111 gosub bit_pattern_100 gosub bit_pattern_111 gosub bit_pattern_001 gosub bit_pattern_111 return print_6 gosub bit_pattern_111 gosub bit_pattern_100 gosub bit_pattern_111 gosub bit_pattern_101 gosub bit_pattern_111 return print_7 gosub bit_pattern_111 gosub bit_pattern_001 gosub bit_pattern_001 gosub bit_pattern_001 gosub bit_pattern_001 return print_8 gosub bit_pattern_111 gosub bit_pattern_101 gosub bit_pattern_111 gosub bit_pattern_101 gosub bit_pattern_111 return print_9 gosub bit_pattern_111 gosub bit_pattern_101 gosub bit_pattern_111 gosub bit_pattern_001 gosub bit_pattern_111 return bit_pattern_000 pfpixel tx ty off : tx=tx+1 : pfpixel tx ty off : tx=tx+1 : pfpixel tx ty off : tx=tx-2 : ty=ty+1 return bit_pattern_001 pfpixel tx ty off : tx=tx+1 : pfpixel tx ty off : tx=tx+1 : pfpixel tx ty on : tx=tx-2 : ty=ty+1 return bit_pattern_010 pfpixel tx ty off : tx=tx+1 : pfpixel tx ty on : tx=tx+1 : pfpixel tx ty off : tx=tx-2 : ty=ty+1 return bit_pattern_011 pfpixel tx ty off : tx=tx+1 : pfpixel tx ty on : tx=tx+1 : pfpixel tx ty on : tx=tx-2 : ty=ty+1 return bit_pattern_100 pfpixel tx ty on : tx=tx+1 : pfpixel tx ty off : tx=tx+1 : pfpixel tx ty off : tx=tx-2 : ty=ty+1 return bit_pattern_101 pfpixel tx ty on : tx=tx+1 : pfpixel tx ty off : tx=tx+1 : pfpixel tx ty on : tx=tx-2 : ty=ty+1 return bit_pattern_110 pfpixel tx ty on : tx=tx+1 : pfpixel tx ty on : tx=tx+1 : pfpixel tx ty off : tx=tx-2 : ty=ty+1 return bit_pattern_111 pfpixel tx ty on : tx=tx+1 : pfpixel tx ty on : tx=tx+1 : pfpixel tx ty on : tx=tx-2 : ty=ty+1 return print_lvl tx = 14 ty = 6 if level = 1 then gosub print_1 if level = 2 then gosub print_2 if level = 3 then gosub print_3 if level = 4 then gosub print_4 if level = 5 then gosub print_5 if level = 6 then gosub print_6 if level = 7 then gosub print_7 if level = 8 then gosub print_8 if level = 9 then gosub print_9 return bank 3 4way_scroll_init gosub sound_stop_all bank2 level = level + 1 enemies = 5 + level ballx = 0 bally = 0 player0x = 77 player0y = 48 fground_color = c_skyblue bground_color = c_black rem I use alot of double blocks as collision seems to play nicer with them. pfclear playfieldpos = 8 rand = counter tempvar = (rand&1) + 1 if tempvar = 1 then gosub print_lbed bank4 if tempvar = 2 then gosub print_ltv bank4 tempvar = (rand&1) + 1 if tempvar = 1 then gosub print_rloli bank4 if tempvar = 2 then gosub print_rsmile bank4 gosub draw_steffie gosub warp_steffie rem Run the player sprite animation code to show the player sprite rem for the first time. 4way_scroll_main rem Keep the counter variable adding up. Note no check is needed to rem loop back since after 255 it resets to 0 automatically. counter = counter + 1 steffie_lastx = player1x steffie_lasty = player1y rem I know this looks stupid but the right way doesn't work.. rem Basically store last joystick direction and clear current joystick press. rem Run animation for player sprite. if !vk_key = none then vk_key = none else lastkey = vk_key vk_key = none rem Get the current joystick state if switchreset then reboot if joy0left then vk_key = west if joy0right then vk_key = east if joy0up then vk_key = north if joy0down then vk_key = south rem Check for collisions and move screen in requested direction if vk_key = east && !pfread(17, 5) then pfscroll left : player1x = player1x - 4 if vk_key = west && !pfread(14, 5) then pfscroll right : player1x = player1x + 4 rem One if statement would be too complicated so multiple if statements are chained. rem Basically, up and down require collision checking in 2 locations. if vk_key = north && !pfread(15, 4) then if !pfread(16, 5) then pfscroll downdown : player1y = player1y + 2 if vk_key = south && !pfread(15, 6) then if !pfread(16, 6) then pfscroll upup : player1y = player1y - 2 if player1x > 36 && player1x < 96 then gosub run_away if player1y > 33 && player1y < 64 then gosub run_away if player1y < 1 then player1y = 96 if player1y > 96 then player1y = 1 if player1x < 4 then player1x = 128 if player1x > 128 then player1x = 4 if collision(player0, player1) then enemies = enemies - 1 : score = score + 10 : gosub warp_steffie if enemies = 0 then gosub print_stage bank2 : enemies = 8 + level : goto main_creation_event bank1 rem Run drawscreen and refresh variables. if collision(player1, playfield) then player1x = steffie_lastx : player1y = steffie_lasty - 1 gosub 4way_scroll_draw_event goto 4way_scroll_main run_away if counter < 240 then goto flee else goto seek flee if counter{5} then if player0x > player1x then player1x = player1x - 1 else player1x = player1x + 1 if counter{6} then if player0y > player1y then player1y = player1y - 1 else player1y = player1y + 1 seek if player0x > player1x then player1x = player1x + 1 if player0y > player1y then player1y = player1y + 1 return 4way_scroll_draw_event rem For some reason the 2600 forgets the player color each drawscreen.. COLUP0 = c_tan COLUP1 = enemycolor if march then REFP0 = 8 :REFP1 = 8 drawscreen return warp_steffie player1x = (rand&63) + 1 player1y = (rand&63) + 1 gosub 4way_scroll_draw_event if collision(player1, playfield) then goto warp_steffie temp1 = (rand&7) + 1 if temp1 = 1 then enemycolor = c_white : return if temp1 = 2 then enemycolor = c_ltgray : return if temp1 = 3 then enemycolor = c_silver : return if temp1 = 4 then enemycolor = c_gray : return if temp1 = 5 then enemycolor = c_aqua : return if temp1 = 6 then enemycolor = c_skyblue : return if temp1 = 7 then enemycolor = c_yellow : return if temp1 = 8 then enemycolor = c_gold : return return draw_steffie player1: %00011111 %00100010 %01000100 %10000010 %10000001 %10000001 %01000001 %00100010 %11100110 %10111101 %01111111 %00011000 %10100101 %11011011 %11011011 %01111110 %00111100 end return bank 4 clearscreen player0x = 0 player0y = -1 player1x = 0 player1y = -1 ballx = 0 bally = -1 pfclear drawscreen return otherbank print_rloli pfpixel 18 0 on : pfpixel 19 0 on : pfpixel 20 0 on : pfpixel 21 0 on pfpixel 22 0 on : pfpixel 17 1 on : pfpixel 18 1 on : pfpixel 19 1 on pfpixel 20 1 on : pfpixel 21 1 on : pfpixel 22 1 on : pfpixel 23 1 on pfpixel 17 2 on : pfpixel 18 2 on : pfpixel 19 2 on : pfpixel 20 2 on pfpixel 21 2 on : pfpixel 22 2 on : pfpixel 23 2 on : pfpixel 17 3 on pfpixel 18 3 on : pfpixel 19 3 on : pfpixel 20 3 on : pfpixel 21 3 on pfpixel 22 3 on : pfpixel 23 3 on : pfpixel 18 4 on : pfpixel 19 4 on pfpixel 20 4 on : pfpixel 21 4 on : pfpixel 22 4 on : pfpixel 20 5 on pfpixel 20 6 on : pfpixel 20 7 on : pfpixel 20 8 on return otherbank print_rsmile pfpixel 20 1 on : pfpixel 21 1 on : pfpixel 22 1 on : pfpixel 26 1 on pfpixel 27 1 on : pfpixel 28 1 on : pfpixel 20 2 on : pfpixel 21 2 on pfpixel 22 2 on : pfpixel 26 2 on : pfpixel 27 2 on : pfpixel 28 2 on pfpixel 23 4 on : pfpixel 24 4 on : pfpixel 23 5 on : pfpixel 24 5 on pfpixel 25 5 on : pfpixel 20 7 on : pfpixel 21 7 on : pfpixel 26 7 on pfpixel 27 7 on : pfpixel 21 8 on : pfpixel 22 8 on : pfpixel 23 8 on pfpixel 24 8 on : pfpixel 25 8 on : pfpixel 26 8 on return otherbank print_lbed pfpixel 7 0 on : pfpixel 8 0 on : pfpixel 9 0 on : pfpixel 8 1 on pfpixel 9 1 on : pfpixel 1 2 on : pfpixel 2 2 on : pfpixel 8 2 on pfpixel 9 2 on : pfpixel 1 3 on : pfpixel 2 3 on : pfpixel 3 3 on pfpixel 4 3 on : pfpixel 5 3 on : pfpixel 6 3 on : pfpixel 7 3 on pfpixel 8 3 on : pfpixel 9 3 on : pfpixel 2 4 on : pfpixel 8 4 on return otherbank print_ltv pfpixel 1 1 on : pfpixel 2 1 on : pfpixel 5 1 on : pfpixel 6 1 on pfpixel 3 2 on : pfpixel 4 2 on : pfpixel 0 3 on : pfpixel 1 3 on pfpixel 2 3 on : pfpixel 3 3 on : pfpixel 4 3 on : pfpixel 5 3 on pfpixel 6 3 on : pfpixel 7 3 on : pfpixel 8 3 on : pfpixel 0 4 on pfpixel 2 4 on : pfpixel 3 4 on : pfpixel 4 4 on : pfpixel 5 4 on pfpixel 6 4 on : pfpixel 7 4 on : pfpixel 8 4 on : pfpixel 0 5 on pfpixel 1 5 on : pfpixel 2 5 on : pfpixel 3 5 on : pfpixel 4 5 on pfpixel 5 5 on : pfpixel 6 5 on : pfpixel 7 5 on : pfpixel 8 5 on pfpixel 0 6 on : pfpixel 1 6 on : pfpixel 2 6 on : pfpixel 3 6 on pfpixel 4 6 on : pfpixel 5 6 on : pfpixel 6 6 on : pfpixel 7 6 on pfpixel 8 6 on : pfpixel 1 7 on : pfpixel 7 7 on return otherbank