📝 应用描述
校园奇幻恋爱 · 好感度分支剧情
📋 详细信息
| 应用ID |
star_chronicles |
| 名称 |
星辰编年史 |
| 版本 |
v2 |
| 文件大小 |
4.1 KB |
| 上传时间 |
2026-07-29 20:50:47 |
| 状态 |
✅ 已启用 |
| 权限 |
storage |
💡 界面预览 (main.lua)
📄 Lua 源码
-- ============================================================
-- 《星辰编年史·未响应的告白》 Oldchat CIP 移植版(稳定修复)
-- ============================================================
-- -------- 角色定义 --------
local CHARACTERS = {
snow = { name = "绫濑雪奈", emoji = "❄️", color = "#60a5fa" },
shi = { name = "天野诗织", emoji = "🎵", color = "#fbbf24" },
tsuki = { name = "月读冥", emoji = "🌙", color = "#a78bfa" }
}
-- -------- 游戏状态 --------
local state = {
scene = "start",
affection = { snow = 0, shi = 0, tsuki = 0 },
flags = {}
}
-- -------- 存储读写 --------
function saveState()
local data = {
scene = state.scene,
affection = state.affection,
flags = state.flags
}
app.storage_set("game_state", app.json_encode(data))
end
function loadState()
local raw = app.storage_get("game_state")
if raw then
local ok, data = pcall(app.json_decode, raw)
if ok and data then
state.scene = data.scene or "start"
state.affection = data.affection or { snow=0, shi=0, tsuki=0 }
state.flags = data.flags or {}
return true
end
end
return false
end
-- -------- 重置游戏 --------
function resetGame()
state.scene = "start"
state.affection = { snow = 0, shi = 0, tsuki = 0 }
state.flags = {}
app.storage_remove("game_state")
render("start")
end
-- -------- UI 更新 --------
function updateAffectionDisplay()
local parts = {}
for id, ch in pairs(CHARACTERS) do
local val = state.affection[id] or 0
table.insert(parts, string.format("%s %s : %d", ch.emoji, ch.name, val))
end
app.set_text("affection", table.concat(parts, " | "))
end
-- -------- 选项处理 --------
local currentOptions = {}
function handleOption(index)
local opt = currentOptions[index]
if not opt then return end
if opt.effects then
for id, delta in pairs(opt.effects) do
local old = state.affection[id] or 0
state.affection[id] = math.max(0, math.min(1000, old + delta))
end
end
if opt.next == "reset" then
resetGame()
return
end
if opt.next then
render(opt.next)
else
app.toast("故事继续……")
end
end
-- -------- 场景渲染(带安全检查) --------
function render(sceneId)
-- 如果场景不存在,自动重置到开始
if not scenes[sceneId] then
app.toast("场景不存在,已重置")
state.scene = "start"
saveState()
render("start")
return
end
local scene = scenes[sceneId]
if not scene then
app.toast("场景数据无效,已重置")
resetGame()
return
end
app.set_text("narrator", scene.narrator or "")
local speakerText = ""
if scene.speaker and CHARACTERS[scene.speaker] then
speakerText = CHARACTERS[scene.speaker].name .. ":"
end
app.set_text("speaker", speakerText)
app.set_text("message", scene.message or "")
app.set_text("chapter", scene.chapter or "")
updateAffectionDisplay()
local opts = scene.options
if type(opts) == "function" then
opts = opts()
end
if not opts then opts = {} end
currentOptions = opts
for i = 1, 4 do
local btnId = "opt" .. i
if i <= #opts then
app.set_text(btnId, opts[i].label or "选项")
app.set_visible(btnId, true)
app.set_enabled(btnId, true)
else
app.set_visible(btnId, false)
end
end
state.scene = sceneId
saveState()
end
-- -------- 场景定义 --------
local scenes = {}
scenes.start = {
chapter = "✦ 序章",
narrator = "星澜学园 · 新学期",
message = "昨夜,一颗流星划破天际。\n你站在窗前,心中涌起一阵莫名的悸动。",
options = {
{ label = "✦ 前往学园", next = "intro" }
}
}
scenes.intro = {
chapter = "第一章 · 流星",
narrator = "—— 校门口 · 樱花树下 ——",
message = "三位少女同时看向你,她们的情感颜色在晨光中闪烁。",
options = {
{ label = "❄️ 走向雪奈", next = "snow_1", effects = { snow = 10 } },
{ label = "🎵 走向诗织", next = "shi_1", effects = { shi = 10 } },
{ label = "🌙 走向冥", next = "tsuki_1", effects = { tsuki = 10 } }
}
}
-- 雪奈路线
scenes.snow_1 = {
chapter = "第二章 · 静谧之蓝",
speaker = "snow",
message = "雪奈微微垂下眼帘,声音很轻:\n「……你也感觉到了,对吗?」",
options = {
{ label = "「你还好吗?看起来有点累。」", next = "snow_2", effects = { snow = 20 } },
{ label = "「那颗星……和你有关?」", next = "snow_2", effects = { snow = 10 } }
}
}
scenes.snow_2 = {
speaker = "snow",
message = "她露出一丝难得的微笑:\n「……谢谢你,你是第一个会这么问我的人。」",
options = {
{ label = "「我会一直陪着你。」", next = "snow_final", effects = { snow = 30 } },
{ label = "「以后有问题可以找我。」", next = "snow_final", effects = { snow = 20 } }
}
}
scenes.snow_final = {
chapter = "第六章 · 星朔之夜",
speaker = "snow",
message = "雪奈站在星光下,向你伸出手:\n「……你愿意和我一起,成为真正的自己吗?」",
options = function()
local aff = state.affection.snow or 0
if aff >= 150 then
return { { label = "✦ 接受告白", next = "ending_true_snow" } }
elseif aff >= 80 then
return { { label = "✦ 接受告白", next = "ending_normal_snow" } }
else
return { { label = "✦ 接受告白", next = "ending_bad_snow" } }
end
end
}
-- 诗织路线
scenes.shi_1 = {
chapter = "第二章 · 活力之橙",
speaker = "shi",
message = "诗织眼睛亮晶晶的:\n「嘿嘿~我就知道你也会在意!那颗流星超帅的!」",
options = {
{ label = "「你许了什么愿?」", next = "shi_2", effects = { shi = 20 } },
{ label = "「你总是这么有精神啊。」", next = "shi_2", effects = { shi = 10 } }
}
}
scenes.shi_2 = {
speaker = "shi",
message = "她忽然压低声音,罕见地认真:\n「……秘密。不过——如果是你,我愿意告诉你。」",
options = {
{ label = "「那告诉我吧。」", next = "shi_final", effects = { shi = 30 } },
{ label = "「……还是保持神秘吧。」", next = "shi_final", effects = { shi = 15 } }
}
}
scenes.shi_final = {
chapter = "第六章 · 星朔之夜",
speaker = "shi",
message = "诗织站在聚光灯下,歌声温柔:\n「这首只唱给你听的歌——你愿意一直听下去吗?」",
options = function()
local aff = state.affection.shi or 0
if aff >= 150 then
return { { label = "✦ 接受告白", next = "ending_true_shi" } }
elseif aff >= 80 then
return { { label = "✦ 接受告白", next = "ending_normal_shi" } }
else
return { { label = "✦ 接受告白", next = "ending_bad_shi" } }
end
end
}
-- 冥路线
scenes.tsuki_1 = {
chapter = "第二章 · 紫罗兰之瞬",
speaker = "tsuki",
message = "冥的目光沉静如水:\n「……你看见了。那颗星的颜色。」",
options = {
{ label = "「你也是……共感者?」", next = "tsuki_2", effects = { tsuki = 20 } },
{ label = "「星的颜色……?」", next = "tsuki_2", effects = { tsuki = 10 } }
}
}
scenes.tsuki_2 = {
speaker = "tsuki",
message = "她微微勾了勾嘴角:\n「……我看到的,是紫罗兰色的光。你呢?」",
options = {
{ label = "「我看到的……是你。」", next = "tsuki_final", effects = { tsuki = 30 } },
{ label = "「……和你一样。」", next = "tsuki_final", effects = { tsuki = 20 } }
}
}
scenes.tsuki_final = {
chapter = "第六章 · 星朔之夜",
speaker = "tsuki",
message = "冥将星砂轻轻放入你掌心:\n「……你愿意成为我的星辰吗?」",
options = function()
local aff = state.affection.tsuki or 0
if aff >= 150 then
return { { label = "✦ 接受告白", next = "ending_true_tsuki" } }
elseif aff >= 80 then
return { { label = "✦ 接受告白", next = "ending_normal_tsuki" } }
else
return { { label = "✦ 接受告白", next = "ending_bad_tsuki" } }
end
end
}
-- 结局场景(通用)
local function ending_scene(title, desc)
return {
chapter = "✦ " .. title,
narrator = "—— 结局 ——",
message = desc,
options = {
{ label = "✦ 重新开始", next = "reset" }
}
end
end
scenes.ending_true_snow = ending_scene("真结局 · 星辰守护", "雪奈与你紧握双手,星光永恒。\n「从今以后,我的星光只为你而亮。」")
scenes.ending_normal_snow = ending_scene("普通结局 · 记忆轨迹", "雪奈获得了自由,却失去了那些记忆。\n你们重新认识,但星光已逝。")
scenes.ending_bad_snow = ending_scene("坏结局 · 星尘消散", "雪奈的身影消散在星光中,你再也找不到那片静谧的蓝。")
scenes.ending_true_shi = ending_scene("真结局 · 星辰守护", "诗织的歌声传遍学园,她终于做回了自己。\n「从今以后,我只唱给你一个人听。」")
scenes.ending_normal_shi = ending_scene("普通结局 · 记忆轨迹", "诗织回到舞台,依旧戴着面具。\n她隐约记得你,却记不清那些约定。")
scenes.ending_bad_shi = ending_scene("坏结局 · 星尘消散", "诗织的歌声戛然而止,她化作星光消散在夜空。")
scenes.ending_true_tsuki = ending_scene("真结局 · 星辰守护", "冥的眼中不再只有悲悯,她找到了属于自己的光芒。\n「……从今以后,我的星辰就是你了。」")
scenes.ending_normal_tsuki= ending_scene("普通结局 · 记忆轨迹", "冥继续她的医学之路,偶尔仰望星空时会感到一阵怀念。")
scenes.ending_bad_tsuki = ending_scene("坏结局 · 星尘消散", "冥选择了消散,你再也无法触及那片紫罗兰。")
-- -------- 页面布局 --------
local page = ui.page({
title = "星辰编年史",
children = {
ui.text({ id = "chapter", text = "", size = 14, color = "#888888", margin = 4 }),
ui.text({ id = "narrator", text = "", size = 13, color = "#aaaaaa", margin = 4, center = true }),
ui.text({ id = "speaker", text = "", size = 16, color = "#ffffff", margin = 4 }),
ui.text({ id = "message", text = "", size = 15, color = "#f0f0f0", margin = 8 }),
ui.text({ id = "affection", text = "", size = 13, color = "#cccccc", margin = 6 }),
ui.button({ id = "opt1", text = "", on_click = function() handleOption(1) end, margin = 4 }),
ui.button({ id = "opt2", text = "", on_click = function() handleOption(2) end, margin = 4 }),
ui.button({ id = "opt3", text = "", on_click = function() handleOption(3) end, margin = 4 }),
ui.button({ id = "opt4", text = "", on_click = function() handleOption(4) end, margin = 4 })
}
})
-- -------- 启动入口 --------
if not loadState() then
state.scene = "start"
end
render(state.scene) -- 如果场景无效,内部会自动重置
return page