pico-8 cartridge // http://www.pico-8.com version 43 __lua__ -- global function _init() frame_time = 0.01666666666 state_menu = "menu" state_play = "play" set_state(state_menu) end function _update60() if state == state_menu then menu_update() elseif state == state_play then map_update() player_update() enemies_update() ufo_update() end end function _draw() cls(1) if state == state_menu then menu_draw() elseif state == state_play then map_draw() player_draw() enemies_draw() ufo_draw() end end function set_state(st) state = st music(-1, 100) if state == state_menu then menu_init() elseif state == state_play then map_init() player_init() enemies_init() ufo_init() end end function sp2m(sp) return (sp+4)/8 end function is_collide(e1,e2) return e2.x+e2.sx > e1.x and e1.x+e1.sx > e2.x and e2.y+e2.sy > e1.y and e1.y+e1.sy > e2.y end -->8 -- player function player_init() pl = { x = 0, y = 0, sx = 8, sy = 8, sp = 0x1, lives = 3, speed = 0, m_speed = 1.0, accel = 0.25, sp_speed = 0.25, at_tm = 0.0, at_delay = 0.5, proj_speed = 2, projs = {}, score = 0, can_shoot = false, } pl_reset_pos() end function player_update() if btn(⬅️) then pl.speed -= pl.accel pl.sp -= pl.sp_speed elseif btn(➡️) then pl.speed += pl.accel pl.sp += pl.sp_speed else if pl.speed < 0 then pl.speed += pl.accel elseif pl.speed > 0 then pl.speed -= pl.accel end end local m_speed = btn(🅾️) and pl.m_speed*2 or pl.m_speed pl.speed = mid(-m_speed, pl.speed, m_speed) pl.x += pl.speed pl.x = mid(0, pl.x, 120) if pl.sp < 1 then pl.sp += 2 elseif pl.sp >= 3.0 then pl.sp -= 2 end if btn(❎) then if pl.can_shoot and pl.at_tm <= 0 then pl_attack() end else pl.can_shoot = true end if pl.at_tm > 0 then pl.at_tm -= frame_time end for proj in all(pl.projs) do pl_proj_update(proj) end end function player_draw() for proj in all(pl.projs) do spr(proj.sp, proj.x, proj.y) end spr(pl.sp, pl.x, pl.y) if pl.at_tm <= 0 then spr(0x3, pl.x, pl.y) end rectfill(0, 0, 128, 7, 6) for i = 1,pl.lives do spr(0x1, 9*i - 8, -1) end print( sub("000000"..pl.score, -6), 103, 1, 13) end function pl_attack() pl.at_tm = pl.at_delay local proj = { sp = 0x4, x = flr(pl.x)+3, y = flr(pl.y), sx = 2, sy = 2, } add(pl.projs, proj) sfx(0) end function pl_proj_update(proj) proj.y -= pl.proj_speed if proj.y < -8 or map_damage(proj) or en_damage(proj) or ufo_damage(proj) then del(pl.projs, proj) end end function pl_damage(proj) if is_collide(proj, pl) then pl.lives -= 1 if pl.lives > 0 then pl_reset_pos() sfx(4) else set_state(state_menu) sfx(5) end return true end return false end function pl_reset_pos() pl.x = 60 pl.y = 119 end -->8 -- map function map_init() map_c = 6 map_areas = {} foreach(get_shelter(19, 107), function(v) add(map_areas, v) end) foreach(get_shelter(49, 107), function(v) add(map_areas, v) end) foreach(get_shelter(79, 107), function(v) add(map_areas, v) end) foreach(get_shelter(109, 107), function(v) add(map_areas, v) end) end function map_update() end function map_draw() map() --rectfill(0, 104, 128, 127, 12) --rectfill(0, 127, 128, 128, 5) for a in all(map_areas) do for i = 0, 15 do if a.v & (1 << i) != 0 then local x = a.x+i%4 local y = a.y+i\4 pset(x, y, map_c) end end end end function map_damage(proj) local is_collided = false for a in all(map_areas) do if is_collide(a, proj) and a.v != 0 then for i = 0, 15 do if a.v & (1 << i) != 0 then local p = { x = a.x+i%4, y = a.y+i\4, sx = 1, sy = 1, } if is_collide(p,proj) then a.v &= ~(1 << i) is_collided = true end end end end end return is_collided end function get_area(ax, ay, av) return { x = ax, y = ay, sx = 4, sy = 4, v = av, } end function get_shelter(x, y) return { get_area(x-10, y, 0xec80), get_area(x-6, y, 0xfffe), get_area(x-2, y, 0xffff), get_area(x+2, y, 0xfff7), get_area(x+6, y, 0x7310), get_area(x-10, y+4, 0xffff), get_area(x-6, y+4, 0xffff), get_area(x-2, y+4, 0xffff), get_area(x+2, y+4, 0xffff), get_area(x+6, y+4, 0xffff), get_area(x-10, y+8, 0xffff), get_area(x-6, y+8, 0x0013), get_area(x+2, y+8, 0x008c), get_area(x+6, y+8, 0xffff), } end -->8 -- enemies function enemies_init() en = { mv_left = true, mv_speed = 0.025, mv_speed_inc = 0.01, mv_speed_inc_inc = 0.0005, descent_speed = 1.0, descent_speed_inc = 0.03, at_tm = 1.0, at_delay = 1.5, at_delay_dec = -0.01, proj_speed = 1, projs = {}, } enemies = {} local row = 1 for ly = 9, 60, 9 do local en_row = {} for lx = 17, 102, 8 do local enemy = { x = lx, y = ly, sx = 8, sx = (ly<21) and 8 or (ly<38) and 6 or 4, sy = 8, sp = (ly<21) and 0x22 or (ly<38) and 0x21 or 0x20, } add(en_row, enemy) end enemies[row] = en_row row += 1 end end function enemies_update() if en.at_tm > 0 then en.at_tm -= frame_time end en_move() if en.at_tm <= 0 then en.at_tm = en.at_delay en_attack() end for proj in all(en.projs) do en_proj_update(proj) end end function enemies_draw() for proj in all(en.projs) do spr(proj.sp, proj.x, proj.y) end for row in all(enemies) do for e in all(row) do spr(e.sp, e.x, e.y) end end end function en_move() if en.mv_left then if en_can_mv_side(true) then en_mv_side(-en.mv_speed) else en_mv_down() en.mv_left = false end else if en_can_mv_side(false) then en_mv_side(en.mv_speed) else en_mv_down() en.mv_left = true end end end function en_attack() local e = en_random() if e == nil then sfx(6) set_state(state_menu) return end sfx(2) local proj = { sp = 0x24, x = flr(e.x)+3, y = flr(e.y), sx = 2, sy = 2, } add(en.projs, proj) end function en_mv_side(speed) for i = 1,#enemies do for e in all(enemies[i]) do e.x += speed end end end function en_mv_down() sfx(3) for i = 1,#enemies do for e in all(enemies[i]) do e.y += flr(en.descent_speed) if e.y > 101 then sfx(8) set_state(state_menu) elseif e.y > 96 then sfx(9) end end end end function en_can_mv_side(left) for row in all(enemies) do if #row != 0 then if (left and row[1].x <= 0) or (not left and row[#row].x >= 120) then return false end end end return true end function en_proj_update(proj) proj.y += en.proj_speed if proj.y > 128 or map_damage(proj) or pl_damage(proj) then del(en.projs, proj) end end function en_random() local rows = {} for row in all(enemies) do if #row != 0 then add(rows, row) end end if #rows == 0 then return nil end return rnd(rnd(rows)) end function en_damage(proj) for row in all(enemies) do for e in all(row) do if is_collide(proj, e) then en.mv_speed += en.mv_speed_inc en.mv_speed_inc += en.mv_speed_inc_inc en.at_delay += en.at_delay_dec en.descent_speed += en.descent_speed_inc pl.score += e.sp==0x20 and 25 or e.sp==0x21 and 100 or 250 del(row, e) sfx(1) return true end end end return false end -->8 -- menu function menu_init() menu_text = "press ❎ to play" can_select = false end function menu_update() if btn(❎) then if can_select then set_state(state_play) end else can_select = true end end function menu_draw() print(menu_text, 32, 60, 6) end -->8 -- ufo function ufo_init() ufo = { exists = false, x = 60, y = 7, sx = 8, sy = 4, dir = 1, speed = 0.25, speed_inc = 0.1, tm = 15.0, delay = 10.0, delay_dec = -1.0, score = 2500, score_inc = 1000, } end function ufo_update() if ufo.exists then ufo.x += ufo.speed * ufo.dir if ufo.x < -16 or ufo.x > 136 then uf_remove() end elseif ufo.tm > 0 then ufo.tm -= frame_time if ufo.tm <= 0 then ufo.tm = ufo.delay ufo.delay += ufo.delay_dec uf_spawn() end end end function ufo_draw() if ufo.exists then spr(0x1f, ufo.x, ufo.y) end end function uf_spawn() ufo.exists = true if rnd(1) < 0.5 then ufo.x = -16 ufo.dir = 1 else ufo.x = 136 ufo.dir = -1 end music(0) end function ufo_damage(proj) if ufo.exists and is_collide(proj, ufo) then uf_remove() pl.score += ufo.score ufo.speed += ufo.speed_inc ufo.score += ufo.score_inc sfx(7) return true end return false end function uf_remove() ufo.exists = false music(-1, 100) end __gfx__ 000000000000000000000000000000003b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000066000000660000003b000b30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00700700008dd800008dd800000b3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00077000008998000089980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00077000099999900999999000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 007007009aaaaaa99aaaaaa900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000009aaaaaa99aaaaaa900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000005d5d5d00d5d5d5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ccccccccccccccccc0c0c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 cccccccccccccccc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ccccccccccccccccc0c0c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000 cccccccccccccccc0c000c0000c000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022ee220 ccccccccccccccccc0c0c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000099aaaa99 cccccccccccccccc0c0c0c0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022eeee22 ccccccccccccccccc0c0c0c0c000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 44444444cccccccccc0ccc0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00055000055005500550055000000000980000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 009aa9002ee22ee23bb33bb300000000890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 009aa90002eeee203bbbbbb300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 009aa90002eeee203bbbbbb300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0096690002266200036bb63000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 009aa900002ee20003b66b3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0009900000022000003bb30000098000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000dd000000dd000000dd00000089000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 __gff__ 0000000000000000000000000000000000000000000000000000000000000000020200020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 __map__ 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 1313131313131313131313131313131300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 1212121212121212121212121212121200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 1111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 1111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 1010101010101010101010101010101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 __sfx__ 01050000226501b64011630262002a200312003c20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 010400002e0502b050290402703024020220101f0101f0001d0001d0001d0001d0001b0001a00017000110000d0000a0000800007000070000600005000000000000000000000000000000000000000000000000 01020000166400a630046200060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600006000060000600 100200000c0500f04013030180201b010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 0005000017650186501b65018650186401664018640186401b6401d6401f6401d6401863018630186301b6301d6301d6301d6301b6201b6201b6201b6201d6201d6201b6101b6101d6101d6101d6001b6001d600 0106000027150241501f1501f1501d1501b150181500000024150221501d1501d1501b150181501615000000221501f1501d1501d1501b1501815016150000000000000000000000000000000000000000000000 0006000016150181501b1501d1501f150221502415000000181501b1501d1501f150221502415027150000001b1501d1501f15022150241502715029150000000000000000000000000000000000000000000000 000500002205024050220501d0501f0502405027050240501f0501d0501f0502405027050220501f0401b0301f020240100000000000000000000000000000000000000000000000000000000000000000000000 0106000027253242531f2531f2531d2531b253182530020324253222531d2531d2531b253182531625300203222531f2531d2531d2531b2531825316253002030020300203002030020300203002030020300203 d40300002411125121261312714128151291512a1512b1512c1512a1512915128151271512615125151241512415125151261512715128151291512a1512b1512c1512a151291512815127141261312512124111 a80f00000e050100500e050100500e050100500e050100500e050100500e050100500e050100500e050100500e050100500e050100500e050100500e050100500e050100500e050100500e050100500e05010050 __music__ 03 0a424344