diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2d9bb44 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +# 备份与临时文件,不进版本库 +__bak_pre_20260722/ +*.bak +*.bak2 +*.backup diff --git a/assets/bg/world_bg_keyart_16x9.png b/assets/bg/world_bg_keyart_16x9.png new file mode 100644 index 0000000..95c1070 Binary files /dev/null and b/assets/bg/world_bg_keyart_16x9.png differ diff --git a/assets/bg/world_bg_keyart_16x9_clean.png b/assets/bg/world_bg_keyart_16x9_clean.png new file mode 100644 index 0000000..5c9bde1 Binary files /dev/null and b/assets/bg/world_bg_keyart_16x9_clean.png differ diff --git a/assets/bg_core.jpg b/assets/bg_core.jpg new file mode 100644 index 0000000..d0fe1aa Binary files /dev/null and b/assets/bg_core.jpg differ diff --git a/assets/bg_earth.jpg b/assets/bg_earth.jpg new file mode 100644 index 0000000..9491ea8 Binary files /dev/null and b/assets/bg_earth.jpg differ diff --git a/assets/bg_sky.jpg b/assets/bg_sky.jpg new file mode 100644 index 0000000..3af96ca Binary files /dev/null and b/assets/bg_sky.jpg differ diff --git a/assets/bg_star.jpg b/assets/bg_star.jpg new file mode 100644 index 0000000..d52e504 Binary files /dev/null and b/assets/bg_star.jpg differ diff --git a/assets/bg_under.jpg b/assets/bg_under.jpg new file mode 100644 index 0000000..721272e Binary files /dev/null and b/assets/bg_under.jpg differ diff --git a/assets/game-api.js b/assets/game-api.js new file mode 100644 index 0000000..d114327 --- /dev/null +++ b/assets/game-api.js @@ -0,0 +1,42 @@ +// 宇森游戏 · 前端与 Odoo 通信层 +// 所有接口同源(yt.pengyuthon.cn),由 nginx 代理 /game/* 到 Odoo(game 库)。 +// 关键点:Odoo 通过 URL 上的 ?db=game 选定数据库(与 game.conf 的 /web/login?db=game 一致), +// 否则请求到达时未选中库,控制器路由找不到 → 404。因此所有调用都带 ?db=game。 +// 登录态通过 Odoo session cookie 保持,fetch 带 credentials:'same-origin'。 + +const API = { + async me() { + return (await fetch('/game/api/me?db=game', { credentials: 'same-origin' })).json(); + }, + async login(login, password) { + return (await fetch('/game/api/login?db=game', { + method: 'POST', credentials: 'same-origin', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ login, password }), + })).json(); + }, + async register(payload) { + return (await fetch('/game/api/register?db=game', { + method: 'POST', credentials: 'same-origin', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + })).json(); + }, + async logout() { + return (await fetch('/game/api/logout?db=game', { + method: 'POST', credentials: 'same-origin', + })).json(); + }, + async codex() { + return (await fetch('/game/api/codex?db=game', { credentials: 'same-origin' })).json(); + }, + async rules() { + return (await fetch('/game/api/rules?db=game', { credentials: 'same-origin' })).json(); + }, + async threads() { + return (await fetch('/game/api/threads?db=game', { credentials: 'same-origin' })).json(); + }, + async announcements() { + return (await fetch('/game/api/announcements?db=game', { credentials: 'same-origin' })).json(); + }, +}; diff --git a/assets/site-app.js b/assets/site-app.js new file mode 100644 index 0000000..2fc071b --- /dev/null +++ b/assets/site-app.js @@ -0,0 +1,69 @@ +// 宇森官网 · 公开页数据打通(图鉴/规则/论坛/公告 从 Odoo 取数) +// 依赖 assets/game-api.js + +// ---------- 规则 ---------- +async function loadRules(){ + const el = document.querySelector('#rules .rules-scroll'); + if (!el) return; + try { + const d = await API.rules(); + const groups = (d && d.groups) || []; + if (!groups.length){ el.innerHTML = '
暂无规则数据
'; return; } + el.innerHTML = groups.map(g => { + const rows = (g.items || []).map(it => { + const lvl = (it.level != null) ? ('Lv.' + it.level) : (g.key === 'world' ? '阶段' : ''); + return `
${lvl}${it.name}${it.desc || ''}
`; + }).join(''); + return `

${g.label}

${rows}
`; + }).join(''); + } catch (e) { /* 保留静态兜底内容 */ } +} + +// ---------- 论坛 ---------- +async function loadForum(){ + const threadsEl = document.getElementById('threads'); + const catsEl = document.querySelector('#forum .f-cats'); + if (!threadsEl) return; + try { + const list = await API.threads(); + if (!list || !list.length){ threadsEl.innerHTML = '
暂无主题
'; return; } + // 分类筛选 + const cats = []; + list.forEach(t => { if (t.category && cats.indexOf(t.category) < 0) cats.push(t.category); }); + if (catsEl){ + catsEl.innerHTML = `
全部
` + + cats.map(c => `
${c}
`).join(''); + catsEl.querySelectorAll('.ch').forEach(b => b.addEventListener('click', () => { + catsEl.querySelectorAll('.ch').forEach(x => x.classList.remove('active')); + b.classList.add('active'); + const c = b.dataset.fcat; + threadsEl.querySelectorAll('.th').forEach(t => { t.style.display = (c === 'all' || t.dataset.fcat === c) ? '' : 'none'; }); + })); + } + threadsEl.innerHTML = list.map(t => + `
` + + (t.pinned ? `置顶` : '') + + `${t.name}` + + `${(t.replies || []).length} 回复 · ${t.author_name || '匿名'}
` + ).join(''); + } catch (e) { /* 保留静态兜底内容 */ } +} + +// ---------- 公告 ---------- +async function loadAnnounce(){ + const el = document.querySelector('#announce .notes'); + if (!el) return; + try { + const list = await API.announcements(); + if (!list || !list.length){ el.innerHTML = '
暂无公告
'; return; } + el.innerHTML = list.map(n => + `
${n.date}
${n.body_html || ''}
` + ).join(''); + } catch (e) { /* 保留静态兜底内容 */ } +} + +document.addEventListener('DOMContentLoaded', () => { + loadRules(); + loadForum(); + loadAnnounce(); +}); diff --git a/assets/terrain/desert_1.png b/assets/terrain/desert_1.png new file mode 100644 index 0000000..db25e39 Binary files /dev/null and b/assets/terrain/desert_1.png differ diff --git a/assets/terrain/desert_2.png b/assets/terrain/desert_2.png new file mode 100644 index 0000000..78118f6 Binary files /dev/null and b/assets/terrain/desert_2.png differ diff --git a/assets/terrain/desert_3.png b/assets/terrain/desert_3.png new file mode 100644 index 0000000..5aa1a7b Binary files /dev/null and b/assets/terrain/desert_3.png differ diff --git a/assets/terrain/desert_4.png b/assets/terrain/desert_4.png new file mode 100644 index 0000000..28b3eab Binary files /dev/null and b/assets/terrain/desert_4.png differ diff --git a/assets/terrain/desert_5.png b/assets/terrain/desert_5.png new file mode 100644 index 0000000..684adcd Binary files /dev/null and b/assets/terrain/desert_5.png differ diff --git a/assets/terrain/desert_6.png b/assets/terrain/desert_6.png new file mode 100644 index 0000000..cf85dcb Binary files /dev/null and b/assets/terrain/desert_6.png differ diff --git a/assets/terrain/desert_7.png b/assets/terrain/desert_7.png new file mode 100644 index 0000000..9ac324d Binary files /dev/null and b/assets/terrain/desert_7.png differ diff --git a/assets/terrain/forest_1.png b/assets/terrain/forest_1.png new file mode 100644 index 0000000..fb06244 Binary files /dev/null and b/assets/terrain/forest_1.png differ diff --git a/assets/terrain/forest_2.png b/assets/terrain/forest_2.png new file mode 100644 index 0000000..ee3d663 Binary files /dev/null and b/assets/terrain/forest_2.png differ diff --git a/assets/terrain/forest_3.png b/assets/terrain/forest_3.png new file mode 100644 index 0000000..0e1c712 Binary files /dev/null and b/assets/terrain/forest_3.png differ diff --git a/assets/terrain/forest_5.png b/assets/terrain/forest_5.png new file mode 100644 index 0000000..5922e6f Binary files /dev/null and b/assets/terrain/forest_5.png differ diff --git a/assets/terrain/forest_6.png b/assets/terrain/forest_6.png new file mode 100644 index 0000000..11fd2b0 Binary files /dev/null and b/assets/terrain/forest_6.png differ diff --git a/assets/terrain/forest_7.png b/assets/terrain/forest_7.png new file mode 100644 index 0000000..91ee4a7 Binary files /dev/null and b/assets/terrain/forest_7.png differ diff --git a/assets/terrain/forest_8.png b/assets/terrain/forest_8.png new file mode 100644 index 0000000..d22b8f5 Binary files /dev/null and b/assets/terrain/forest_8.png differ diff --git a/assets/terrain/manifest.json b/assets/terrain/manifest.json new file mode 100644 index 0000000..f0bb6d8 --- /dev/null +++ b/assets/terrain/manifest.json @@ -0,0 +1,60 @@ +{ + "desert": [ + "desert_1.png", + "desert_2.png", + "desert_3.png", + "desert_4.png", + "desert_5.png", + "desert_6.png", + "desert_7.png" + ], + "snow": [ + "snow_1.png", + "snow_2.png", + "snow_3.png", + "snow_4.png", + "snow_5.png", + "snow_6.png", + "snow_8.png" + ], + "forest": [ + "forest_1.png", + "forest_2.png", + "forest_3.png", + "forest_5.png", + "forest_6.png", + "forest_7.png", + "forest_8.png" + ], + "plain": [ + "plain_1.png", + "plain_2.png", + "plain_3.png", + "plain_4.png", + "plain_5.png", + "plain_6.png", + "plain_7.png", + "plain_8.png" + ], + "mountain": [ + "mountain_1.png", + "mountain_2.png", + "mountain_3.png", + "mountain_4.png", + "mountain_5.png", + "mountain_6.png", + "mountain_7.png", + "mountain_8.png" + ], + "water": [ + "water_1.png", + "water_2.png", + "water_3.png", + "water_4.png", + "water_5.png", + "water_6.png", + "water_7.png", + "water_8.png", + "water_9.png" + ] +} \ No newline at end of file diff --git a/assets/terrain/mountain_1.png b/assets/terrain/mountain_1.png new file mode 100644 index 0000000..34a5081 Binary files /dev/null and b/assets/terrain/mountain_1.png differ diff --git a/assets/terrain/mountain_2.png b/assets/terrain/mountain_2.png new file mode 100644 index 0000000..a94e37d Binary files /dev/null and b/assets/terrain/mountain_2.png differ diff --git a/assets/terrain/mountain_3.png b/assets/terrain/mountain_3.png new file mode 100644 index 0000000..e0771ee Binary files /dev/null and b/assets/terrain/mountain_3.png differ diff --git a/assets/terrain/mountain_4.png b/assets/terrain/mountain_4.png new file mode 100644 index 0000000..ccf759f Binary files /dev/null and b/assets/terrain/mountain_4.png differ diff --git a/assets/terrain/mountain_5.png b/assets/terrain/mountain_5.png new file mode 100644 index 0000000..1f3b263 Binary files /dev/null and b/assets/terrain/mountain_5.png differ diff --git a/assets/terrain/mountain_6.png b/assets/terrain/mountain_6.png new file mode 100644 index 0000000..4fc66b4 Binary files /dev/null and b/assets/terrain/mountain_6.png differ diff --git a/assets/terrain/mountain_7.png b/assets/terrain/mountain_7.png new file mode 100644 index 0000000..9c32c81 Binary files /dev/null and b/assets/terrain/mountain_7.png differ diff --git a/assets/terrain/mountain_8.png b/assets/terrain/mountain_8.png new file mode 100644 index 0000000..67b2df4 Binary files /dev/null and b/assets/terrain/mountain_8.png differ diff --git a/assets/terrain/plain_1.png b/assets/terrain/plain_1.png new file mode 100644 index 0000000..6c13838 Binary files /dev/null and b/assets/terrain/plain_1.png differ diff --git a/assets/terrain/plain_2.png b/assets/terrain/plain_2.png new file mode 100644 index 0000000..c06e084 Binary files /dev/null and b/assets/terrain/plain_2.png differ diff --git a/assets/terrain/plain_3.png b/assets/terrain/plain_3.png new file mode 100644 index 0000000..97d1ee7 Binary files /dev/null and b/assets/terrain/plain_3.png differ diff --git a/assets/terrain/plain_4.png b/assets/terrain/plain_4.png new file mode 100644 index 0000000..aa28fb9 Binary files /dev/null and b/assets/terrain/plain_4.png differ diff --git a/assets/terrain/plain_5.png b/assets/terrain/plain_5.png new file mode 100644 index 0000000..a7ce38a Binary files /dev/null and b/assets/terrain/plain_5.png differ diff --git a/assets/terrain/plain_6.png b/assets/terrain/plain_6.png new file mode 100644 index 0000000..e238490 Binary files /dev/null and b/assets/terrain/plain_6.png differ diff --git a/assets/terrain/plain_7.png b/assets/terrain/plain_7.png new file mode 100644 index 0000000..dda809e Binary files /dev/null and b/assets/terrain/plain_7.png differ diff --git a/assets/terrain/plain_8.png b/assets/terrain/plain_8.png new file mode 100644 index 0000000..523f286 Binary files /dev/null and b/assets/terrain/plain_8.png differ diff --git a/assets/terrain/snow_1.png b/assets/terrain/snow_1.png new file mode 100644 index 0000000..7f79f0f Binary files /dev/null and b/assets/terrain/snow_1.png differ diff --git a/assets/terrain/snow_2.png b/assets/terrain/snow_2.png new file mode 100644 index 0000000..2942371 Binary files /dev/null and b/assets/terrain/snow_2.png differ diff --git a/assets/terrain/snow_3.png b/assets/terrain/snow_3.png new file mode 100644 index 0000000..d147f09 Binary files /dev/null and b/assets/terrain/snow_3.png differ diff --git a/assets/terrain/snow_4.png b/assets/terrain/snow_4.png new file mode 100644 index 0000000..98919d6 Binary files /dev/null and b/assets/terrain/snow_4.png differ diff --git a/assets/terrain/snow_5.png b/assets/terrain/snow_5.png new file mode 100644 index 0000000..3014116 Binary files /dev/null and b/assets/terrain/snow_5.png differ diff --git a/assets/terrain/snow_6.png b/assets/terrain/snow_6.png new file mode 100644 index 0000000..3346976 Binary files /dev/null and b/assets/terrain/snow_6.png differ diff --git a/assets/terrain/snow_8.png b/assets/terrain/snow_8.png new file mode 100644 index 0000000..258cc1b Binary files /dev/null and b/assets/terrain/snow_8.png differ diff --git a/assets/terrain/water_1.png b/assets/terrain/water_1.png new file mode 100644 index 0000000..c27795f Binary files /dev/null and b/assets/terrain/water_1.png differ diff --git a/assets/terrain/water_2.png b/assets/terrain/water_2.png new file mode 100644 index 0000000..0443ae3 Binary files /dev/null and b/assets/terrain/water_2.png differ diff --git a/assets/terrain/water_3.png b/assets/terrain/water_3.png new file mode 100644 index 0000000..fba1d14 Binary files /dev/null and b/assets/terrain/water_3.png differ diff --git a/assets/terrain/water_4.png b/assets/terrain/water_4.png new file mode 100644 index 0000000..815ff61 Binary files /dev/null and b/assets/terrain/water_4.png differ diff --git a/assets/terrain/water_5.png b/assets/terrain/water_5.png new file mode 100644 index 0000000..9519e20 Binary files /dev/null and b/assets/terrain/water_5.png differ diff --git a/assets/terrain/water_6.png b/assets/terrain/water_6.png new file mode 100644 index 0000000..df3a064 Binary files /dev/null and b/assets/terrain/water_6.png differ diff --git a/assets/terrain/water_7.png b/assets/terrain/water_7.png new file mode 100644 index 0000000..58b0a8d Binary files /dev/null and b/assets/terrain/water_7.png differ diff --git a/assets/terrain/water_8.png b/assets/terrain/water_8.png new file mode 100644 index 0000000..5f2cd60 Binary files /dev/null and b/assets/terrain/water_8.png differ diff --git a/assets/terrain/water_9.png b/assets/terrain/water_9.png new file mode 100644 index 0000000..86629ae Binary files /dev/null and b/assets/terrain/water_9.png differ diff --git a/assets/ui/logo_planet.png b/assets/ui/logo_planet.png new file mode 100644 index 0000000..4026f98 Binary files /dev/null and b/assets/ui/logo_planet.png differ diff --git a/assets/ui/logo_planet_256.png b/assets/ui/logo_planet_256.png new file mode 100644 index 0000000..4561b42 Binary files /dev/null and b/assets/ui/logo_planet_256.png differ diff --git a/assets/ui/logo_planet_48.png b/assets/ui/logo_planet_48.png new file mode 100644 index 0000000..8cbc5ff Binary files /dev/null and b/assets/ui/logo_planet_48.png differ diff --git a/assets/world-app.js b/assets/world-app.js new file mode 100644 index 0000000..753454c --- /dev/null +++ b/assets/world-app.js @@ -0,0 +1,164 @@ +// 宇森 · 世界内面板逻辑(图鉴 / 规则 / 论坛 / 公告) +// 依赖 assets/game-api.js(提供 API) + +// ---------- 登录态守卫 ---------- +// TEMP: 本地临时默认放行,跳过 Odoo 登录校验;打通后端后删除此分支并恢复下面逻辑 +const TEMP_SKIP_AUTH = true; +(async () => { + if (TEMP_SKIP_AUTH) { + const u = document.getElementById('userName'); + if (u) u.textContent = '园丁'; + return; + } + try { + const me = await API.me(); + if (!me.uid) { location.href = 'login.html?next=world.html'; return; } + const u = document.getElementById('userName'); + if (u) u.textContent = me.name || me.login; + } catch (e) { + location.href = 'login.html'; + } +})(); + +// ---------- 退出 ---------- +const logoutBtn = document.getElementById('logoutBtn'); +if (logoutBtn) logoutBtn.addEventListener('click', async () => { + await API.logout(); + location.href = 'index.html'; +}); + +// ---------- 面板控制 ---------- +const panel = document.getElementById('dataPanel'); +const dpTitle = document.getElementById('dpTitle'); +const dpBody = document.getElementById('dpBody'); +const dpClose = document.getElementById('dpClose'); +if (dpClose) dpClose.addEventListener('click', () => panel.classList.remove('open')); + +async function openPanel(kind) { + if (!panel) return; + panel.classList.add('open'); + dpBody.innerHTML = '
加载中…
'; + try { + if (kind === 'codex') { dpTitle.textContent = '图鉴'; renderCodex(await API.codex()); } + else if (kind === 'rules') { dpTitle.textContent = '规则'; renderRules(await API.rules()); } + else if (kind === 'forum') { dpTitle.textContent = '论坛'; renderForum(await API.threads()); } + else if (kind === 'announce') { dpTitle.textContent = '公告'; renderAnnounce(await API.announcements()); } + } catch (e) { + dpBody.innerHTML = '
加载失败,请稍后重试
'; + } +} + +document.querySelectorAll('.world-nav button[data-panel]').forEach(b => { + b.addEventListener('click', () => openPanel(b.dataset.panel)); +}); + +// ---------- 程序化矢量缩略图(零 AI 生图,不消耗积分) ---------- +function hashStr(s){let h=2166136261;for(let i=0;i>>0;} +function rng(seed){let s=seed>>>0;return function(){s=(Math.imul(s,1664525)+1013904223)>>>0;return s/4294967296;};} +const TIERCOL={'普通':'#9aa6c4','精良':'#5fd38a','稀有':'#4cc9f0','史诗':'#c77dff','传说':'#e7b85c'}; +function starPts(cx,cy,spikes,outer,inner){let pts=[],rot=-Math.PI/2;for(let i=0;i`;if(v===0){x+=``;}else if(v===1){x+=``;}else{x+=``;}x+=``;return x;} +function shBuild(r,s){let x=``;x+=``;for(let i=0;i<3;i++)x+=``;return x;} +function shElement(r,s){const sides=3+Math.floor(r()*6);let x=``;x+=``;return x;} +function shPersona(r,s){let x=``;x+=``;x+=``;return x;} +function shTalent(r,s){const sp=4+Math.floor(r()*4);let x=``;x+=``;return x;} +function shRelic(r,s){let x=``;x+=``;return x;} +function shEquip(sub,s){switch(sub){case 'head':return ``;case 'hand':{let x=``;for(let i=0;i<3;i++)x+=``;return x;}case 'chest':return ``;case 'pants':return ``;case 'shoes':return ``;case 'ring':return ``;case 'neck':return ``;case 'treasure':return ``;default:return ``;}} +function shEvent(r,s){let x=``;x+=``;return x;} +function shapeFor(cat,sub,r,s){switch(cat){case 'race':return shRace(r,s);case 'build':return shBuild(r,s);case 'element':return shElement(r,s);case 'persona':return shPersona(r,s);case 'talent':return shTalent(r,s);case 'relic':return shRelic(r,s);case 'equip':return shEquip(sub,s);case 'event':return shEvent(r,s);default:return ``;}} +function thumbSVG(it){ + const seed=hashStr(it.cat+it.sub+it.name);const r=rng(seed);const h=Math.floor(r()*360);const h2=(h+40)%360; + const tcol=TIERCOL[it.tier]||'#9aa6c4';const shape=shapeFor(it.cat,it.sub,r,seed); + return ``+ + ``+ + ``+ + `${shape}`+ + ``; +} + +// ---------- 渲染:图鉴(分类 → 子级 → 条目) ---------- +function renderCodex(data){ + const groups = (data && data.groups) || []; + if (!groups.length){ dpBody.innerHTML = '
暂无图鉴数据
'; return; } + let html = ''; + groups.forEach(g => { + html += `

${g.label}

`; + (g.subs || []).forEach(sub => { + if (sub.name && sub.name !== '其他') html += `
${sub.name}
`; + html += '
'; + sub.items.forEach(it => { + const imgTag = it.image + ? `${it.name}` + : ''; + const fallback = `
${thumbSVG(it)}
`; + html += `
`+ + `
${imgTag || fallback}
`+ + `
${it.name}
`+ + `
${it.sub||''}${it.tier||''}
`+ + `
${it.desc||''}
`; + }); + html += '
'; + }); + html += '
'; + }); + dpBody.innerHTML = html; + // 处理有 image 但加载失败的:替换为程序化 SVG + dpBody.querySelectorAll('img.dp-thumb-img').forEach(img => { + img.addEventListener('error', () => { + const svg = thumbSVG({cat:img.dataset.cat, sub:img.dataset.sub, name:img.dataset.name, tier:img.dataset.tier}); + const div = document.createElement('div'); div.className='dp-thumb-svg'; div.innerHTML = svg; + img.replaceWith(div); + }); + }); +} + +// ---------- 渲染:规则(按类别分组) ---------- +function renderRules(data){ + const groups = (data && data.groups) || []; + if (!groups.length){ dpBody.innerHTML = '
暂无规则数据
'; return; } + let html = ''; + groups.forEach(g => { + html += `

${g.label}

`; + (g.items || []).forEach(it => { + const lvl = (it.level!=null) ? ('Lv.'+it.level) : ''; + html += `
${lvl}${it.name}${it.desc||''}
`; + }); + html += '
'; + }); + dpBody.innerHTML = html; +} + +// ---------- 渲染:论坛 ---------- +function renderForum(threads){ + threads = threads || []; + if (!threads.length){ dpBody.innerHTML = '
暂无主题
'; return; } + let html = '
'; + threads.forEach(t => { + const replies = (t.replies || []).map(p => + `
${p.author_name||'匿名'}${p.create_date}
${p.body_html||''}
` + ).join(''); + html += `
`+ + `
${t.category_label||''}`+ + (t.pinned?`置顶`:'')+`${t.name}`+ + `${t.author_name||''}
`+ + `
${t.body_html||''}
`+ + `
${replies}
`; + }); + html += '
'; + dpBody.innerHTML = html; +} + +// ---------- 渲染:公告 ---------- +function renderAnnounce(list){ + list = list || []; + if (!list.length){ dpBody.innerHTML = '
暂无公告
'; return; } + let html = '
'; + list.forEach(n => { + const pri = n.priority==='urgent' ? 'urgent' : (n.priority==='important' ? 'imp' : ''); + html += `
${n.date}
`+ + `
${n.body_html||''}
`; + }); + html += '
'; + dpBody.innerHTML = html; +} diff --git a/assets/world_core.mp4 b/assets/world_core.mp4 new file mode 100644 index 0000000..5db0e97 Binary files /dev/null and b/assets/world_core.mp4 differ diff --git a/assets/world_earth.mp4 b/assets/world_earth.mp4 new file mode 100644 index 0000000..6ff81a9 Binary files /dev/null and b/assets/world_earth.mp4 differ diff --git a/assets/world_sky.mp4 b/assets/world_sky.mp4 new file mode 100644 index 0000000..dd81fc9 Binary files /dev/null and b/assets/world_sky.mp4 differ diff --git a/assets/world_star.mp4 b/assets/world_star.mp4 new file mode 100644 index 0000000..8441d06 Binary files /dev/null and b/assets/world_star.mp4 differ diff --git a/assets/world_under.mp4 b/assets/world_under.mp4 new file mode 100644 index 0000000..5f3bd87 Binary files /dev/null and b/assets/world_under.mp4 differ diff --git a/assets/yusen-trailer.mp4 b/assets/yusen-trailer.mp4 new file mode 100644 index 0000000..ab0cd98 Binary files /dev/null and b/assets/yusen-trailer.mp4 differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..6c5b90f --- /dev/null +++ b/index.html @@ -0,0 +1,572 @@ + + + + + +宇森 · Yusen|活的文明系统模拟 + + + + + + +
+
+ + +
+
+
+ +
+ +
+
+ +
+
+ +
+
+

宇森

+
你不是玩家,你是园丁。
+
一款活的文明系统模拟——播种一个会自己生长的世界,从地心到陨石星空,见证文明在垂直切面中自发演化。
+
+
+
+ + + + + + + + +
+
等级制度TIERS & RANK SYSTEM
+
+
+

① 世界等级 · 五阶段

+

世界从蒙昧到飞升的整体进化阶段,决定可解锁的内容深度与事件池上限。园丁对世界施加的影响会推动阶段跃迁——这是文明能"发生什么"的舞台上限。

+
+
阶段一蒙昧文明萌芽,仅基础采集与居住,无势力概念,事件以自然为主。
+
阶段二聚落出现村落与分工,解锁基础建造与贸易,可建立首个势力。
+
阶段三王国统一政权成形,解锁军事/宗教/科技分支,传奇事件开始频现。
+
阶段四文明跨层互通成熟,地下与星空纳入治理,神器与装备体系全开。
+
阶段五飞升文明触及世界本质,可开启飞升轮回,进入更高维的演化实验。
+
+
+
+

② 势力等级

+

文明内部群体的聚合度,由人口、领土、影响力累计。势力等级越高,可调动的世界资源与外交权重越大——决定文明"能调动什么"。

+
+
Lv.1部族血缘纽带的小群体,无正式制度。
+
Lv.2城邦多聚落联盟,出现雏形治理与税收。
+
Lv.3公国领地整合,常备军与法典成型。
+
Lv.4王国统一王朝,跨层资源调度能力。
+
Lv.5帝国大陆级霸权,可发起跨世界行动。
+
Lv.6星盟联结多方世界,参与宏观文明博弈。
+
+
+
+

③ 人物角色等级 · 十二阶段

+

个体(英雄 / 领袖 / 特殊 NPC)的成长阶序,通过历练、天赋点亮与装备积累提升,影响可承担的职责与战力——决定个体"能做成什么"。

+
+
Lv.1萌新初入世界的无名者。
+
Lv.2学徒掌握基础技艺。
+
Lv.3熟手可独立完成任务。
+
Lv.4好手在某领域崭露头角。
+
Lv.5精英群体中的中坚。
+
Lv.6大师技艺臻于化境。
+
Lv.7宗匠开宗立派的人物。
+
Lv.8传奇事迹被载入编年史。
+
Lv.9神话近乎传说的存在。
+
Lv.10半神触及世界法则。
+
Lv.11圣者被信仰托举的意志。
+
Lv.12永恒超越生死的世界锚点。
+
+
+
+

④ 制度说明

+

三者相互独立又彼此加成:世界等级是舞台上限,决定能发生什么;势力等级是群体进度,决定能调动什么;角色等级是个体成长,决定能做成什么。园丁的核心策略,是在三者间分配有限的引导资源,让文明自洽地向上演化。

跃迁逻辑:角色历练与装备积累→提升势力实力→推动世界阶段跃迁→解锁更深内容(更深的地下层、更远的星空层、更强的神器)。每一级提升都会扩大可叙事的事件池,世界因此越活越厚。

+
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+ + +
+
+
全部
+
综合讨论
+
玩法攻略
+
同人创作
+
BUG 反馈
+
+
+
+

社区论坛

+
发新帖
+
+
+ + +
+
+
+
PIN【公告】宇森官网第一阶段上线,欢迎园丁们入驻128 回复 · 官方
+
新手向:园丁视角的三种开局思路42 回复 · 行者
+
你们更喜欢哪种族?来投个票76 回复 · 雾岛
+
手绘了我的主世界浮空岛,求轻喷31 回复 · 青柠
+
反馈:飞入微观时偶现卡顿9 回复 · K
+
地下矿脉怎么规划最省心?18 回复 · 老周
+
+
+
+ + +
+
公告ANNOUNCEMENTS
+
+
2026.07.09
宇森官网第一阶段上线:介绍 / 特色 / 背景 / 规则 / 图鉴 / 论坛 / 公告 七块,单页切换呈现,介绍页即概念宣传片。
+
2026.07.09
图鉴系统升级:种族 204 条、系别/性格/天赋/神器/传奇事件全面扩量,装备槽位对齐 头/手/胸/裤/鞋/戒指(双)/项链/宝物;全部缩略图改为程序化矢量插画,零 AI 生图。
+
2026.07.08
概念宣传片《垂直生长》完成,呈现五层世界自上而下生长的镜头语言(天空层改为云朵地基块,星空层改为陨石科技带)。
+
2026.07.01
园丁视角核心玩法原型启动,首版六边形地图与活 NPC 验证中。
+
2026.06.20
图鉴系统规划确定:种族 / 建筑 / 生物 / 神器 四大类目,美术持续补充中。
+
+
+
+
+ + + + + + + + diff --git a/login.html b/login.html new file mode 100644 index 0000000..d4b84dc --- /dev/null +++ b/login.html @@ -0,0 +1,193 @@ + + + + + +宇森 · 登录 + + + + +
+
+
宇森
+
YUSEN · GARDEN OF CIVILIZATION
+
你不是玩家,你是园丁。
+
+ +
+ +
+ + +
+ + +
+
+ + +
+
+ + +
+ +
+ + + + +
+
+ + +
+ + + + + diff --git a/terrain_preview.html b/terrain_preview.html new file mode 100644 index 0000000..de72eeb --- /dev/null +++ b/terrain_preview.html @@ -0,0 +1,154 @@ +草地变体预览 +

草地变体预览

视频为动态循环播放(与游戏内一致)。扫一眼,哪个不顺眼就告诉我编号,我直接删。
+
动态视频变体(游戏中实际使用的 7 个)
+
+#2 + +
+
+#2 +plain_2.png +
+
+
+
+#4 + +
+
+#4 +plain_4.png +
+
+
+
+#5 + +
+
+#5 +plain_5.png +
+
+
+
+#8 + +
+
+#8 +plain_8.png +
+
+
+
+#12 + +
+
+#12 +plain_12.png +
+
+
+
+#13 + +
+
+#13 +plain_13.png +
+
+
+
+#14 + +
+
+#14 +plain_14.png +
+
静态 PNG 变体(含 #16 兜底,共 8 个)
+
+#2 +
+
+#2 +plain_2.png +
+
+
+
+#4 +
+
+#4 +plain_4.png +
+
+
+
+#5 +
+
+#5 +plain_5.png +
+
+
+
+#8 +
+
+#8 +plain_8.png +
+
+
+
+#12 +
+
+#12 +plain_12.png +
+
+
+
+#13 +
+
+#13 +plain_13.png +
+
+
+
+#14 +
+
+#14 +plain_14.png +
+
+
+
+#16 +
+
+#16 +plain_16.png +
+
\ No newline at end of file diff --git a/world.html b/world.html new file mode 100644 index 0000000..95767bb --- /dev/null +++ b/world.html @@ -0,0 +1,3112 @@ + + + + + +宇森 - 微观场景 + + + + + + + + + +
+
+
+
+
0%
+
+
+ + + + +
+ 宇森大地 + + 坐标: (0, 0) +
+ + +
+ 功能栏 +
+
+
+
+
+
+
+
+
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
清晨 07:30
+
星元 1年 · 春
+
+ +
+
星空
+
天空
+
大地
+
地下
+
地心
+
+ + + + + + + +
+
面板
+
+
+ + + +
+
💡 拖拽空白处可平移视角,滚轮缩放沙盘
+
+
+
0%
+
+
+ + +
+
+ + 平原村落 + 微观世界视角 +
+
+
+
+ + +
+
微观世界 · 工具栏
+
+
+ +
+
+
地块信息
+
🟢 平原
+
坐标: (0, 0)
+
+
+
建筑
+
+
+
+
资源产出
+
+
+
+
人口
+
+
+
+
+
+
素材工具栏
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + +
+
+
👤 单位详情
+
+ +
+
+ + + + + +