← 返回

应用详情

📦

夜蔷裂隙防御战

版本 v1 · 4 KB
ID: night_rose_galaga
⬇ 下载 CIP 🔍 返回列表
📝 应用描述
Galaga 风格的夜蔷城堡 2D 文本射击小游戏,守住裂隙并完成刘烨与夏冉的故事。
📋 详细信息
应用ID night_rose_galaga
名称 夜蔷裂隙防御战
版本 v1
文件大小 4 KB
上传时间 2026-07-29 20:51:28
状态 ✅ 已启用
💡 界面预览 (main.lua)
📄 Lua 源码
local W = 9
local H = 6

local phase = "intro"
local player_x = 5
local lives = 3
local score = 0
local wave = 1
local energy = 2
local turn = 0
local shield = false
local enemies = {}
local boss_hp = 0
local ending_shown = false

local story_intro = table.concat({
  "【夜蔷城堡·主厅】",
  "刘烨在陌生的古堡中醒来,夏冉站在回廊尽头。",
  "祖父从裂隙另一头来电:狼人群正在冲门,夜蔷城堡是连接表界与里界的节点。",
  "夏冉教他打开脑中的“现实重构”模块。",
  "这一次,防御术被重构成一架银星战机。你要在天亮前守住五道裂隙。"
}, "\n")

local story_win = table.concat({
  "【终章·裂隙闭合】",
  "裂隙之眼在银星炮火中崩解,夜蔷城堡上空第一次出现真正的黎明。",
  "夏冉收起短刃,轻声说:'你祖父没有选错人。'",
  "刘烨看着掌心逐渐熄灭的数据流,终于明白自己不是被困在城堡里,而是接过了一座城的守夜。",
  "表界与里界的门重新合拢。狼人退入黑暗,夜蔷花在晨光里盛开。",
  "故事完结:刘烨成为新一任渡梦者,夏冉与他共同守护夜蔷节点。"
}, "\n")

local function wave_title()
  if wave == 1 then
    return "第一波:铁栅门前的狼影"
  elseif wave == 2 then
    return "第二波:中庭上空的裂隙虫群"
  elseif wave == 3 then
    return "第三波:钟楼坠落的黑羽"
  elseif wave == 4 then
    return "第四波:祖父留下的旧防线"
  else
    return "最终战:裂隙之眼"
  end
end

local function story_for_wave()
  if wave == 1 then
    return "夏冉:'别怕,银星炮会回应你的意志。先把正门守住。'"
  elseif wave == 2 then
    return "刘烨追到中庭,裂隙虫群像旧电视雪花一样扑来。"
  elseif wave == 3 then
    return "钟楼破碎,黑羽怪从夜空俯冲。夏冉提醒你:'别让它们贴近核心。'"
  elseif wave == 4 then
    return "祖父的声音从通讯器里响起:'小烨,最后一道旧防线交给你了。'"
  else
    return "裂隙睁开巨大的眼睛。只要击碎它,夜蔷城堡就能迎来黎明。"
  end
end

local function add_enemy(x, y, hp, mark)
  enemies[#enemies + 1] = { x = x, y = y, hp = hp, mark = mark }
end

local function spawn_wave()
  enemies = {}
  turn = 0
  shield = false
  energy = energy + 1
  if energy > 4 then
    energy = 4
  end

  if wave == 1 then
    add_enemy(3, 1, 1, "w")
    add_enemy(5, 1, 1, "w")
    add_enemy(7, 1, 1, "w")
  elseif wave == 2 then
    add_enemy(2, 1, 1, "x")
    add_enemy(4, 1, 1, "x")
    add_enemy(6, 1, 1, "x")
    add_enemy(8, 1, 1, "x")
  elseif wave == 3 then
    add_enemy(1, 1, 1, "v")
    add_enemy(3, 2, 1, "v")
    add_enemy(5, 1, 1, "v")
    add_enemy(7, 2, 1, "v")
    add_enemy(9, 1, 1, "v")
  elseif wave == 4 then
    add_enemy(2, 1, 2, "W")
    add_enemy(5, 1, 2, "W")
    add_enemy(8, 1, 2, "W")
  else
    boss_hp = 7
    add_enemy(3, 1, 1, "e")
    add_enemy(7, 1, 1, "e")
  end
end

local function cell_at(x, y)
  if y == H and x == player_x then
    return "A"
  end
  if wave >= 5 and y == 1 and x >= 4 and x <= 6 and boss_hp > 0 then
    return "O"
  end
  local i
  for i = 1, #enemies do
    if enemies[i].x == x and enemies[i].y == y then
      return enemies[i].mark
    end
  end
  return "."
end

local function build_grid()
  local lines = {}
  local y
  for y = 1, H do
    local row = {}
    local x
    for x = 1, W do
      row[#row + 1] = cell_at(x, y)
    end
    lines[#lines + 1] = table.concat(row, " ")
  end
  return table.concat(lines, "\n")
end

local function render(message)
  local status = "章节:" .. wave_title() ..
    "\n生命:" .. tostring(lives) ..
    "  能量:" .. tostring(energy) ..
    "  分数:" .. tostring(score)

  if wave >= 5 then
    status = status .. "  裂隙之眼:" .. tostring(boss_hp)
  else
    status = status .. "  敌人:" .. tostring(#enemies)
  end

  if shield then
    status = status .. "\n状态:概念墙已展开,下一次伤害会被抵消。"
  else
    status = status .. "\n状态:银星战机待命。"
  end

  app.set_text("story", story_for_wave())
  app.set_text("status", status)
  app.set_text("field", build_grid())
  app.set_text("message", message or "操作:左右移动,发射银星,阻止敌群触底。")
end

local function show_intro()
  phase = "intro"
  app.set_text("story", story_intro)
  app.set_text("status", "玩法:Galaga 风格回合制 2D 射击\n目标:清除四波敌群,并击败最终 Boss“裂隙之眼”。")
  app.set_text("field", ". . . O . O . . .\n. . . . . . . . .\n. w . w . w . w .\n. . . . . . . . .\n. . . . . . . . .\n. . . . A . . . .")
  app.set_text("message", "点击“剧情/开始”进入夜蔷裂隙防御战。")
end

local function show_ending()
  phase = "ending"
  ending_shown = true
  app.set_text("story", story_win)
  app.set_text("status", "通关完成\n最终分数:" .. tostring(score) .. "\n结局:夜蔷黎明")
  app.set_text("field", ". . . . * . . . .\n. . * . . . * . .\n. . . \\ | / . . .\n* . . - ☼ - . . *\n. . . / | \\ . . .\n. . . . A . . . .")
  app.set_text("message", "你守住了夜蔷节点。点击“重新开始”可以再次挑战。")
end

local function game_over()
  phase = "over"
  app.set_text("story", "【坏结局·城堡失守】\n裂隙吞没中庭,夏冉把刘烨推出门外。通讯器里只剩祖父的杂音。\n但渡梦印没有熄灭,只要重新开始,故事仍能改写。")
  app.set_text("status", "挑战失败\n最终分数:" .. tostring(score))
  app.set_text("field", "x x x x x x x x x\nx . . . O . . . x\nx . . O O O . . x\nx . . . O . . . x\nx x x x x x x x x\n. . . . A . . . .")
  app.set_text("message", "点击“重新开始”再守一次夜蔷城堡。")
end

local function reset_game()
  phase = "intro"
  player_x = 5
  lives = 3
  score = 0
  wave = 1
  energy = 2
  turn = 0
  shield = false
  boss_hp = 0
  ending_shown = false
  enemies = {}
  show_intro()
end

local function start_game()
  phase = "play"
  player_x = 5
  lives = 3
  score = 0
  wave = 1
  energy = 2
  ending_shown = false
  spawn_wave()
  render("现实重构完成:银星战机上线。夏冉在城墙上为你掩护。")
end

local function next_wave()
  wave = wave + 1
  if wave > 5 then
    show_ending()
  else
    spawn_wave()
    render("裂隙震动,新的敌群出现。\n" .. story_for_wave())
  end
end

local function hit_player(reason)
  if shield then
    shield = false
    app.toast("概念墙挡下了攻击")
    return "概念墙挡下了" .. reason
  end
  lives = lives - 1
  if lives <= 0 then
    game_over()
    return "生命耗尽"
  end
  return reason .. ",生命 -1"
end

local function enemy_step()
  turn = turn + 1
  local note = ""

  if wave >= 5 and boss_hp > 0 and turn % 3 == 0 then
    if player_x >= 4 and player_x <= 6 then
      note = hit_player("裂隙之眼的凝视命中银星战机")
    else
      note = "裂隙之眼扫射中路,你及时避开。"
    end
  end

  if phase ~= "play" then
    return note
  end

  if turn % 2 == 0 then
    local i
    for i = #enemies, 1, -1 do
      enemies[i].y = enemies[i].y + 1
      if enemies[i].y >= H then
        local reason = "敌人突破底线"
        table.remove(enemies, i)
        note = hit_player(reason)
        if phase ~= "play" then
          return note
        end
      end
    end
  end
  return note
end

local function clear_if_done(message)
  if phase ~= "play" then
    return
  end
  if wave >= 5 and boss_hp <= 0 then
    score = score + 50
    show_ending()
    return
  end
  if #enemies == 0 and wave < 5 then
    score = score + 10
    next_wave()
    return
  end
  render(message)
end

local function move_left()
  if phase ~= "play" then
    app.toast("先点击“剧情/开始”")
    return
  end
  if player_x > 1 then
    player_x = player_x - 1
  end
  local note = enemy_step()
  clear_if_done(note ~= "" and note or "银星战机左移。")
end

local function move_right()
  if phase ~= "play" then
    app.toast("先点击“剧情/开始”")
    return
  end
  if player_x < W then
    player_x = player_x + 1
  end
  local note = enemy_step()
  clear_if_done(note ~= "" and note or "银星战机右移。")
end

local function fire()
  if phase ~= "play" then
    app.toast("先点击“剧情/开始”")
    return
  end

  local hit_index = 0
  local best_y = H + 1
  local i
  for i = 1, #enemies do
    if enemies[i].x == player_x and enemies[i].y < best_y then
      hit_index = i
      best_y = enemies[i].y
    end
  end

  local message = ""
  if hit_index > 0 then
    enemies[hit_index].hp = enemies[hit_index].hp - 1
    if enemies[hit_index].hp <= 0 then
      table.remove(enemies, hit_index)
      score = score + 5
      message = "银星命中,敌机碎成黑色花瓣。"
    else
      score = score + 2
      message = "银星击中重甲狼人,还需要一次命中。"
    end
  elseif wave >= 5 and player_x >= 4 and player_x <= 6 and boss_hp > 0 then
    boss_hp = boss_hp - 1
    score = score + 8
    message = "银星穿透瞳孔,裂隙之眼 HP -1。"
  else
    message = "银星划过夜空,没有命中目标。"
  end

  if phase == "play" then
    local note = enemy_step()
    if note ~= "" then
      message = message .. "\n" .. note
    end
  end
  clear_if_done(message)
end

local function guard()
  if phase ~= "play" then
    app.toast("先点击“剧情/开始”")
    return
  end
  if energy <= 0 then
    app.toast("能量不足")
    return
  end
  energy = energy - 1
  shield = true
  local note = enemy_step()
  clear_if_done(note ~= "" and note or "你展开概念墙,下一次伤害将被抵消。")
end

local function story_button()
  if phase == "intro" then
    start_game()
  elseif phase == "play" then
    render(story_for_wave())
  elseif phase == "ending" and ending_shown then
    app.toast("故事已经完结:夜蔷黎明")
  else
    show_intro()
  end
end

return ui.page({
  title = "夜蔷裂隙防御战",
  children = {
    ui.text({
      text = "夜蔷裂隙防御战",
      size = 22,
      center = true,
      color = "#D86B8A",
      margin = 8
    }),
    ui.text({
      id = "story",
      text = story_intro,
      size = 14,
      color = "#5F6470",
      margin = 8
    }),
    ui.text({
      id = "status",
      text = "玩法:Galaga 风格回合制 2D 射击\n目标:清除四波敌群,并击败最终 Boss“裂隙之眼”。",
      size = 14,
      color = "#2F4858",
      margin = 8
    }),
    ui.text({
      id = "field",
      text = ". . . O . O . . .\n. . . . . . . . .\n. w . w . w . w .\n. . . . . . . . .\n. . . . . . . . .\n. . . . A . . . .",
      size = 18,
      color = "#101820",
      center = true,
      margin = 8
    }),
    ui.text({
      id = "message",
      text = "点击“剧情/开始”进入夜蔷裂隙防御战。",
      size = 14,
      color = "#8A3D5A",
      margin = 8
    }),
    ui.list({
      children = {
        ui.button({
          text = "剧情 / 开始",
          on_click = function()
            story_button()
          end
        }),
        ui.button({
          text = "← 左移",
          on_click = function()
            move_left()
          end
        }),
        ui.button({
          text = "发射银星",
          on_click = function()
            fire()
          end
        }),
        ui.button({
          text = "右移 →",
          on_click = function()
            move_right()
          end
        }),
        ui.button({
          text = "构筑护盾",
          on_click = function()
            guard()
          end
        }),
        ui.button({
          text = "重新开始",
          on_click = function()
            reset_game()
          end
        })
      }
    })
  }
})
⬇ 下载 CIP 文件 🔍 返回列表