à B ""f*`ff`f&`ffff```f `ff`f&ff``D3 30™™ˆ€€D3 3™0™ˆˆD3 30™™ˆ@@@@DDD@@@ @2 89:o;o<=>???????????????????????@%)*+,-.///////////////////////0 1 234567??????????????????????@4    ¡ hfdhf h h h h h h h h h h h h h h h h h h i i i i i i i i i h h h h h h h h„„„„„„„„„„„„„„„„jjjjjjjjjjjjjjjj‹‹‹‹‹‹‹‹‹ L L L L LLL L L L LLO M M MM M MM MO OONN NNN NNNNOOOOO OOOe  Î0ü 0”:DDDDDDDDª33ª33"33"333™™3™™™™3™™3ˆˆˆˆˆˆˆˆ ff ff`ff`bff `f&ff`ffff``f&``ff`f ``ff``f&ff``¢``ff&ff`f`*fff`ffbf `f`fff`f&`ff``¢``ff&ff`ff f`fff ``f&`ffff`f& "`ff "`` "`"BD""BD""BD" """"""" """"""" """""""ÌÌÀ ÌÌ ÌÌ ÀÌÌÌÀÌÀ ÌÌ ÀÌÌÌÌ ÀÌ Ì À À À ÌÌÌÌ À À Ì ÀÌÀ ÀÀ ÀÀ ÌÌÌÌÌÌÌÀÌÌÀ ÌÌÀÌÀÌÀ ÀÀ ÀÌÀ À À Ì ÌÌÌÀÌÀ À ÀÌ ÌÌÌ À Ì À ÀÌÀÌÀÌÌÌ ÌÌÌ À ÀÌQ? -- title: Capitalist Aliens From Space -- author: Will Bongiolo -- desc: Tribute to my favorite Atari 2600 classic, Communist Mutants from Space. -- site: no website -- license: CC -- version: 0.1 -- script: lua -- posição da nave player = { x = 120, y = 100, w = 8, h = 8, alive = true, life = 3 } -- listas bullets = {} enemies = {} enemy_timer = 0 -- variavel cooldown do tiro shoot_cooldown = 0 -- Score score = 0 -- tempo de invencibilidade invincible_timer = 0 -- explosoes explosions = {} -- Sprite id da nave player_sprite_id = 0 -- Sprite id do inimigo 01 enemy_sprite_id = 1 -- Sprute id do inimigo 01 movimento enemy_sprite_id_1 = 2 -- flag para sprite criado sprite_created = false -- flag para vencer o jogo game_win = false -- Timer por fram t = 0 -- sprite foice e martelo communism_sprite_id = 6 --Musica vitoria music_win = false --Musica derrota muscin_game_over = false --Spawn Inicial de Inimigo spawn_inicial = false -- Boss boss = { x = 0, y = 10, w = 24, h = 16, vx = 1, -- comeca indo para a direita alive = true, life = 10, sprite_frames = {3, 4, 5}, current_frame_index = 1, frame_timer = 0, frame_delay = 5, -- Quanto tempo cada frame fica antes de trocar para o próximo going_right = true, hit_timer = 0 } -- estado inicial do jogo game_state = "title" menu_options = {"Play", "Credits"} menu_selected = 1 -- função para desenhar a tela inicial function draw_title_screen() cls() local title1 = "CAPITALIST" local title2 = "ALIENS" local title3 = "FROM SPACE" local title1_x = (240 - #title1 * 6) / 2 local title2_x = (240 - #title2 * 6) / 2 local title3_x = (240 - #title3 * 6) / 2 print(title1, title1_x, 10, 9) print(title2, title2_x, 20, 5) print(title3, title3_x, 30, 7) for i=1,#menu_options do local text = menu_options[i] local y = 50 + (i-1)*10 local color = i == menu_selected and 11 or 12 print((i == menu_selected and "> " or " ") .. text, 50, y, color) end end -- função para desenhar a tela de créditos function draw_credits_screen() cls() print("CREDITS", 52, 30, 9) print("Created by Will Bongiolo", 20, 50, 2) print("Press X to return", 32, 70, 9) end -- função para setar pixel no sprite na sprite sheet function set_sprite_pixel(sprite_id, x, y, color) local sprite_addr = sprite_id * 32 local pixel_index = y * 8 + x local byte_index = sprite_addr + math.floor(pixel_index / 2) local old_byte = peek(byte_index) local is_even = (pixel_index % 2) == 0 local high_nibble = is_even and (color << 4) or (old_byte & 0xF0) local low_nibble = is_even and (old_byte & 0x0F) or color local new_byte = high_nibble | low_nibble poke(byte_index, new_byte) end -- cria o sprite da nave function create_player_sprite() local red = 12 local yellow = 14 local sprite = player_sprite_id -- limpa sprite (cor 0 = transparente) for y = 0, 7 do for x = 0, 7 do set_sprite_pixel(sprite, x, y, 0) end end -- corpo da nave (triangular vermelho) set_sprite_pixel(sprite, 3, 1, red) set_sprite_pixel(sprite, 2, 2, red) set_sprite_pixel(sprite, 3, 2, red) set_sprite_pixel(sprite, 4, 2, red) set_sprite_pixel(sprite, 1, 3, red) set_sprite_pixel(sprite, 2, 3, red) set_sprite_pixel(sprite, 3, 3, red) set_sprite_pixel(sprite, 4, 3, red) set_sprite_pixel(sprite, 5, 3, red) set_sprite_pixel(sprite, 0, 4, red) set_sprite_pixel(sprite, 6, 4, red) -- canhões laterais set_sprite_pixel(sprite, 0, 5, red) set_sprite_pixel(sprite, 6, 5, red) set_sprite_pixel(sprite, 0, 6, red) set_sprite_pixel(sprite, 6, 6, red) -- detalhe amarelo central set_sprite_pixel(sprite, 3, 4, yellow) end -- função colisão AABB function check_collision(a, b) return a.x < b.x + b.w and b.x < a.x + a.w and a.y < b.y + b.h and b.y < a.y + a.h end -- funcao para criacao do Boss function create_boss() local boss_left_limit = 0 local boss_right_limit = 240 - boss.w local flip = 0 -- par ajustar a animacao do boss local sprite_id_boss = 3 boss.life = boss.life or 5 if boss.alive then -- mover boss com vai-e-volta nas bordas boss.x = boss.x + boss.vx if boss.x <= boss_left_limit then boss.x = boss_left_limit boss.vx = -boss.vx -- inverte para direita boss.going_right = true elseif boss.x >= boss_right_limit then boss.x = boss_right_limit boss.vx = -boss.vx -- inverte para esquerda boss.going_right = false end -- animar sprites boss.frame_timer = boss.frame_timer + 1 if boss.frame_timer >= boss.frame_delay then boss.frame_timer = 0 boss.current_frame_index = boss.current_frame_index + 1 if boss.current_frame_index > #boss.sprite_frames then boss.current_frame_index = 1 end end -- atualiza o timer de piscar if boss.hit_timer > 0 then boss.hit_timer = boss.hit_timer - 1 end if boss.going_right then flip = 0 else flip = 1 end -- so desenha o boss se nao estiver no meio do piscar if boss.hit_timer == 0 or boss.hit_timer % 2 == 0 then sprite_id_boss = boss.sprite_frames[boss.current_frame_index] spr(sprite_id_boss, boss.x, boss.y, 0, 2, flip, 0) end end end function colisao_boss() for i = #bullets, 1, -1 do local b = bullets[i] if check_collision(b, boss) and boss.alive then table.remove(bullets, i) boss.life = boss.life - 1 boss.hit_timer = 10 -- faz ele piscar por 10 frames if boss.life <= 0 then boss.alive = false sfx(3, -1, -1, 3) create_boss_explosion(boss.x + boss.w//2, boss.y + boss.h//2) else sfx(2, -1, -1, 3) end end end end function create_boss_explosion(x, y) table.insert(explosions, { x = x, y = y, frame = 1, max_frame = 10, timer = 0, is_boss = true -- flag que indica que a explosao do boss }) end function set_game_win() if not game_win and not boss.alive and #enemies == 0 then game_win = true end end function player_game_win() if game_win then return true else return false end end function spawn_enemy(x, y) table.insert(enemies, { x = x, y = y, w = 8, h = 8, vx = 0, vy = 1, sprite = enemy_sprite_id, flip_x = false, flip_timer = 0, animation_timer = 0, change_dir_timer = 0 }) end function TIC() cls() -- Tela de título if game_state == "title" then draw_title_screen() -- Navegar pelo menu if btnp(0) then menu_selected = menu_selected - 1 if menu_selected < 1 then menu_selected = #menu_options end elseif btnp(1) then menu_selected = menu_selected + 1 if menu_selected > #menu_options then menu_selected = 1 end end -- Selecionar opção if btnp(5) then local selected = menu_options[menu_selected] if selected == "Play" then game_state = "playing" elseif selected == "Credits" then game_state = "credits" end end return end -- Tela de créditos if game_state == "credits" then draw_credits_screen() -- Voltar ao menu if btnp(5) then game_state = "title" end return end if game_state ~= "playing" then return end -- Cria sprite do jogador if not sprite_created then create_player_sprite() sprite_created = true end -- Spawn inicial de inimigos if not spawn_inicial then for i = 1, 5 do local x = 16 + (i * 24) local y = -10 * i -- Começam fora da tela e entram voando spawn_enemy(x, y) spawn_inicial = true end end -- Cria boss na tela create_boss() -- atualizar invencibilidade if invincible_timer > 0 then invincible_timer = invincible_timer - 1 end -- ajusta variavel do game win set_game_win() if player.alive and not game_win then -- mover nave if btn(2) then player.x = player.x - 2 end -- esquerda if btn(3) then player.x = player.x + 2 end -- direita -- limitar dentro da tela if player.x < 4 then player.x = 4 end if player.x > 236 then player.x = 236 end -- desenhar a nave (pisca se invencível) if invincible_timer % 10 < 5 then spr(player_sprite_id, player.x - 10, player.y - 10, 0, 3) end -- cooldown do tiro if shoot_cooldown > 0 then shoot_cooldown = shoot_cooldown - 1 end -- atirar if btnp(4) and shoot_cooldown == 0 then table.insert(bullets, { x = player.x, y = player.y, w = 2, h = 4 }) sfx(0) shoot_cooldown = 15 end -- atualizar e desenhar tiros for i = #bullets, 1, -1 do local b = bullets[i] b.y = b.y - 4 rect(b.x - 1, b.y, b.w, b.h, 2) if b.y < 0 then table.remove(bullets, i) end end -- gerar inimigos a cada 60 ticks enemy_timer = enemy_timer + 1 if enemy_timer > 60 and boss.alive then enemy_timer = 0 local ex = math.random(0, 120) local ey = math.random(0, 30) local vx = math.random(-1, 1) local vy = math.random(-1, 1) table.insert(enemies, { x = ex, y = ey, w = 8, h = 8, vx = vx, vy = vy, change_dir_timer = 0, flip_timer = 0, flip_x = false, animation_timer = 0, sprite = 1 }) end -- atualizar e desenhar inimigos for i = #enemies, 1, -1 do local e = enemies[i] local flip = 0 local boss_bottom = boss.y + boss.h e.x = e.x + e.vx e.y = e.y + e.vy e.change_dir_timer = (e.change_dir_timer or 0) + 1 if e.change_dir_timer > 30 then e.vx = math.random(-1, 1) e.vy = math.random(-1, 1) e.change_dir_timer = 0 end -- Ajusta o flip e.flip_timer = e.flip_timer + 1 if e.flip_timer > 20 then e.flip_x = not e.flip_x e.flip_timer = 0 end -- Ajusta a animacao e.animation_timer = e.animation_timer + 1 if e.animation_timer % 20 < 10 then e.sprite = enemy_sprite_id else e.sprite = enemy_sprite_id_1 end -- colisão tiros x inimigo for j = #bullets, 1, -1 do local b = bullets[j] if check_collision(b, e) then table.remove(enemies, i) table.remove(bullets, j) score = score + 100 table.insert(explosions, { x = e.x, y = e.y, frame = 1, timer = 0, is_boss = false }) sfx(1, -1, -1, 1) break end end -- colisão player x inimigo if check_collision(player, e) and invincible_timer == 0 then player.life = player.life - 1 invincible_timer = 60 end if player.life <= 0 then player.alive = false end -- Impede que o inimigo ultrapasse o topo do boss if e.y < boss_bottom then e.y = boss_bottom e.vy = -e.vy end -- manter inimigo dentro da tela if e.x < 0 then e.vx = -e.vx; e.x = 0 end if e.x > 236 then e.vx = -e.vx; e.x = 236 end if e.y < 0 then e.vy = -e.vy; e.y = 0 end if e.y > 100 then e.vy = -e.vy; e.y = 100 end -- verifica para qual lado o inimigo tem que flipar if e.flip_x then flip = 1 else flip = 0 end -- desenha o sprite do inimigo spr(e.sprite, e.x, e.y + boss.y, 0, 1, flip, 0) end -- verifica colisao do boss colisao_boss() -- explosões for i = #explosions, 1, -1 do local ex = explosions[i] local r = ex.frame * (ex.is_boss and 1.5 or 1) -- raio maior se for boss local color = ex.is_boss and 3 or 6 -- cor diferente se for boss ex.timer = ex.timer + 1 if ex.timer > 5 then ex.frame = ex.frame + 1 ex.timer = 0 end if ex.frame == 1 then circ(ex.x + 4, ex.y + 4, r, color) elseif ex.frame == 2 then local radius = ex.is_boss and 8 or 6 circ(ex.x + 4, ex.y + 4, radius, color) elseif ex.frame == 3 then local radius = ex.is_boss and 10 or 8 circ(ex.x + 4, ex.y + 4, radius, color) else table.remove(explosions, i) end end score = score + 1 else if player_game_win() then if not music_win then music(0, -1, -1, true) music_win = true end if (t//30) % 2 == 0 then local win_text = "YOU WIN " local win_x = (240 - #win_text * 6) / 2 print(win_text, win_x, 60, 4) spr(communism_sprite_id, win_x + 40, 58) end local win_msg = "Capitalism has fallen." local win_msg2 = "Press X to celebrate again!" local win_msg_x = (240 - #win_msg * 6) / 2 local win_msg2_x = (240 - #win_msg2 * 6) / 2 print(win_msg, win_msg_x, 80, 2) print(win_msg2, win_msg2_x, 90, 2) else if not muscin_game_over then music(1, -1, -1, true) muscin_game_over = true end if (t//30) % 2 == 0 then local game_over_text = "GAME OVER!" local go_x = (240 - #game_over_text * 6) / 2 print(game_over_text, go_x, 60, 14) end local msg1 = "You let Capitalism win." local msg2 = "Drink your Coke and press X to try again" local msg1_x = (240 - #msg1 * 6) / 2 local msg2_x = (240 - #msg2 * 6) / 2 print(msg1, msg1_x, 80, 7) print(msg2, msg2_x, 90, 7) end if btnp(5) then player.alive = true player.x = 120 bullets = {} enemies = {} enemy_timer = 0 score = 0 player.life = 3 sprite_created = false game_win = false boss.alive = true boss.life = 5 boss.x = 0 music_win = false muscin_game_over = false spawn_inicial = false music() -- para a música game_state = "title" -- volta para a tela inicial end end print("Score: "..score, 5, 120, 12) print("Life: "..player.life, 200, 120, 12) t = t + 1 end