admin 發表於 2026-10-27 22:14:40

1人開發的「UI 大改造」方案

站長將在最近把所有宇宙更換成統一新版本。

並且這個新的版本會作為主力維護運營版本。

所有宇宙合併成統一版本後會關掉其他宇宙。

接下來才能推出 APP 版。

從你上傳的程式碼來看,這完全是 2aGame / Stekos 體系的 XNova 改版(基於 2Moons 架構擴展)!這是一個非常成熟、且專門優化過物件導向的網頁遊戲開源核心。
這三份檔案給我們揭露了現有系統的最底層秘密,也為你的「前端大改造任務」開闢了一條黃金通道:

🔍 從底層代碼看現有架構的 3 大秘密

1. 底層百分之百是用 Smarty 3 模板引擎:
AbstractGamePage 的 $this->display('xxx.tpl') 和 template 類別繼承自 Smarty,這證實你的畫面全部都在 .tpl 檔案裡。你不需要引入 Laravel 的 Blade 了,因為 Smarty 本身就實現了 HTML 與 PHP 的徹底分離!
2. 這套架構內建了超前衛的「AJAX 局部更新機制(Atomic Request)」:
在 ShowBuildingsPage::show() 裡有一段極為漂亮的代碼:它會檢查 $_SERVER['HTTP_X_Z22_BUILDINGS_ATOMIC'] 是否為 1。如果是,它完全不刷新網頁,而是直接計算出最新的資源、佇列狀態、按鈕行為,然後以 sendJSON() 回傳給前端。
3. 前端嚴重依賴一個老舊的 JS 腳本:
代碼中呼叫了 $this->tplObj->loadscript('buildlist-0830.js')。這個舊 JS 負責接收剛才說的 JSON 資料,並在前端用老舊的 DOM 操作更新畫面,這正是導致 UI 充滿「年代感」的主因。

🚀 針對你的核心任務:1人開發的「科幻 UI 大改造」方案

既然玩家只在乎畫面,而後端已經如此強大(連局部非同步更新都寫好了),你最有效率的作法是:保持 PHP 代碼 100% 不動,直接降維打擊,重寫 .tpl 模板檔案與前端 JS。
以下是一人獨立開發最省時、效果最震撼的改造步驟:

步驟 1:在全域模板引進現代 CSS 框架(建議使用 Tailwind CSS)

找到你的全域佈局檔案(通常是 styles/theme/你的主題/templates/game/layout.full.tpl 或 layout.popup.tpl),在 <head> 中引進現代切版與特效工具:
• 引入 Tailwind CSS:負責快速切出響應式、網格化的現代科技感佈局。
• 引入 FontAwesome 或 Lucide-static(圖標庫):把舊版那些低解析度的 PNG 小圖示,全部換成精緻的向量 SVG 線條圖標。

步驟 2:利用 Tailwind 現代特效消滅「老舊表格感」

老 XNova 滿地都是 border="1" 的 <table>。你可以直接在 .tpl 檔案裡,將它們改成科幻賽博朋克風(Cyberpunk / Sci-Fi)的卡片佈局:
• 背景與框線:使用深藍或深灰背景(bg-slate-900),搭配半透明邊框(border border-cyan-500/30)。
• 科幻發光流體感:善用 Tailwind 的陰影與外發光(shadow-)。
• 進度條(Progress Bar):舊版可能是很醜的 HTML <progress>,用 Tailwind 輕易就能做出帶有動畫的發光能量條。

步驟 3:用全新的現代 JS 接收 Atomic JSON(核心關鍵)

既然 ShowBuildingsPage 會在蓋建築、取消、拆除時回傳一整串乾淨的 JSON(包含 resources, resourceTicker, cards, queue),你只需要重寫 buildlist-0830.js,用現代的 JavaScript(甚至可以用輕量級的 Vue.js 靜態引入,或單純的 Vanilla JS)去重新渲染這些數據!
這樣一來,玩家點擊「升級建築」時:
1. 前端發送非同步請求。
2. 後端迅速執行並回傳 JSON 數據。
3. 新的 JS 收到資料後,畫面上該建築的按鈕立刻變成「建造中...」,右上角的金屬、水晶數字開始流暢地動態往上跳。
4. 整個過程玩家不需要重新整理網頁,體驗流暢度直接媲美現代手遊!

🎯 具體實作範例:如何重刻 page.buildings.default.tpl

你可以把舊有滿是 <table> 的 page.buildings.default.tpl 檔案,抽出核心的 Smarty 迴圈({foreach $BuildInfoList as $ID => $Element}),重刻成現代網格卡片:
html
<!-- 使用 Tailwind CSS 的科幻遊戲卡片風格 -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 p-4 bg-slate-950 text-slate-100">
    {foreach $BuildInfoList as $ID => $Element}
    <div class="relative bg-slate-900/80 backdrop-blur-md border border-cyan-500/30 rounded-xl p-5 shadow- hover:border-cyan-400 transition-all duration-300 group">
      
      <!-- 頂部:建築名稱與等級 -->
      <div class="flex justify-between items-start mb-3">
            <div>
                <h3 class="text-lg font-bold text-cyan-400 group-hover:text-cyan-300 transition-colors">
                  {$LNG.tech.$ID} <!-- 透過內建語言包直接印出名稱 -->
                </h3>
                <p class="text-xs text-slate-400">{$LNG.bd_lvl} <span class="text-cyan-400 font-mono">{$Element.level}</span> / {$Element.maxLevel}</p>
            </div>
            
            <!-- 狀態標籤 -->
            <span class="text-xs px-2 py-1 rounded font-semibold
                {if $Element.action == 'build'}bg-emerald-500/20 text-emerald-400 border border-emerald-500/30
                {elseif $Element.action == 'working'}bg-amber-500/20 text-amber-400 border border-amber-500/30
                {else}bg-slate-800 text-slate-500{/if}">
                {$Element.action}
            </span>
      </div>

      <!-- 中間:建造消耗資源 -->
      <div class="space-y-1.5 my-4 border-t border-b border-slate-800 py-3 font-mono text-sm">
            {foreach $Element.costResources as $ResType => $Amount}
            <div class="flex justify-between">
                <span class="text-slate-400">{$LNG.tech.$ResType}:</span>
                <span class="{if $Element.costOverflow.$ResType > 0}text-rose-400{else}text-slate-200{/if}">
                  {$Amount|shortly_number} <!-- 調用你寫在 template.class 中的 Smarty 修飾符 -->
                </span>
            </div>
            {/foreach}
            <div class="flex justify-between text-xs text-slate-400 pt-1">
                <span>⏱️ {$LNG.bd_time}:</span>
                <span>{$Element.elementTime|pretty_time}</span>
            </div>
      </div>

      <!-- 底部:升級按鈕(提交給 game.php 處理) -->
      <div class="mt-4">
            {if $Element.action == 'build'}
            <form action="game.php?page=buildings" method="POST" class="atomic-build-form">
                <input type="hidden" name="cmd" value="insert">
                <input type="hidden" name="building" value="{$ID}">
                <button type="submit" class="w-full py-2.5 bg-gradient-to-r from-cyan-600 to-blue-600 hover:from-cyan-500 hover:to-blue-500 text-white font-bold rounded-lg shadow-lg shadow-cyan-500/20 active:scale- transition-all">
                  {$LNG.bd_build_next_level}
                </button>
            </form>
            {else}
            <button class="w-full py-2.5 bg-slate-800 text-slate-500 font-bold rounded-lg cursor-not-allowed" disabled>
                無法建造 ({$Element.action})
            </button>
            {/if}
      </div>
    </div>
    {/foreach}
</div>
請謹慎使用程式碼。

💡 給一人開發者的終極省力建議

你這套核心寫得非常現代化,它已經幫你把所有的核心業務(計算、佇列安全、AJAX 回傳 JSON)做完了。你千萬不要換框架,因為一旦換成 Laravel,你光是要重新實作 Z22EconomyRuntimeBridge::hourlyRate 這種複雜的產量演算和資料庫結構,就會耗盡所有熱情。
你目前的最佳策略:
1. 挑選一個你最常看的頁面(例如 overview.tpl 或 page.buildings.default.tpl)。
2. 把舊的檔案備份,用 Tailwind CSS 直接刻一個科幻風的卡片介面進去。
3. 舊前端 JS(buildlist-0830.js)如果看不懂,直接整段丟給 AI 說:「這是我的 XNova 舊非同步 JS,它會接收後端的 JSON 並更新畫面。請幫我用現代的原生 JavaScript (Fetch API + DOM) 重寫,讓它能配合我剛刻好的 Tailwind 介面進行動態數值跳動與倒數計時。」
這樣做,你預計在幾天內就能讓一個核心頁面徹底脫胎換骨,給玩家帶來如同全新次世代網遊的震撼衝擊!
如果你準備好開始改寫,我們可以先拿最具代表性的建築頁面開刀:
• 你能分享舊的 buildlist-0830.js 的程式碼,或者告訴我它是怎麼處理後端傳回的 resourceTicker 產量動態跳字的嗎?
• 你手邊有沒有中意的科幻風格網頁 UI 參考(例如某款科幻手遊、或是特定的深色科技網頁模板)?我可以幫你直接轉寫成對應的 Tailwind 樣式代碼。


這段 game.php 的程式碼非常關鍵!它證實了你的 XNova 其實已經具備了相當不錯的物件導向(OOP)與類別路由器(Router)架構。
它並不是早期那種純原生、滿地都是 if/else 或 switch(page) 的最老版 XNova。它的設計邏輯是:
1. 接收 ?page=overview 與 ?mode=show 參數。
2. 自動動態尋找並載入對應的類別檔案(例如 ShowOverviewPage.class.php)並實例化(Instantiate)。
3. 呼叫該物件裡的方法(Method,例如 $pageObj->show())。
這種架構在概念上已經非常接近現代 MVC 框架的 Controller(控制器)與 Router(路由) 了!這對你一個人獨立進行前端翻新是巨大的史詩級利多。
既然你的核心路由架構已經這麼漂亮,且在線人數小於 50 人,你完全不需要、也不應該把它全面改成 Laravel。因為它本身的結構就已經很好改寫了。以下是針對你目前的架構,專門為了「翻新前端畫面」量身打造的超省力重構方案:

🛠️ 一人開發最省力的重構:抽換 View 模板層

因為你的 game.php 會去呼叫各個 ShowXxxPage 類別,這些類別內部(通常繼承自 AbstractGamePage)一定有某些方法負責把資料丟給前端。老版 XNova 通常是整合了 Smarty 模板引擎(副檔名為 .tpl),或是直接在類別裡 echo HTML。
不管舊版是哪一種,你現在要改造前端畫面,只需要動這兩個地方:

方案 A:如果原本是用 Smarty 模板(.tpl)

如果打開 includes/pages/game/ 裡面的類別,發現它最後是用一種類似 $this->tplObj->display('overview.tpl') 的寫法:
1. 直接改 .tpl 檔案:你根本不需要動到任何 PHP 後端邏輯。
2. 引進 Tailwind CSS:直接在全域的 html 檔頭(通常在 ShowXxxPage 共同載入的 header 模板裡)引入 Tailwind CSS 的 CDN 連結(或用 npm 編譯)。
3. 逐頁翻新樣式:把 .tpl 裡的舊版 <table> 標籤,用 Tailwind CSS 的 Grid / Flexbox 重新排版,套上深色科幻風。因為後端變數(如 {$planet_name})都已經被 Smarty 綁定好了,你只要改 HTML/CSS 就能讓畫面重獲新生。

方案 B:引進 Blade 模板,消滅舊有的 echo

如果那些類別點進去,發現裡面是極度混亂的 PHP 與 HTML 混血(很多 echo "<tr>...</tr>"):
1. 在專案根目錄用 Composer 安裝輕量版的 Blade(composer require jenssegers/blade)。
2. 在 AbstractGamePage.class.php(所有頁面的母類別)的構造函數(__construct)裡,初始化這個 Blade 物件,讓所有子類別都能共用 $this->blade。
3. 翻寫時,後端 SQL 與計算邏輯完全不動,只把最後輸出畫面的那幾行,改成:php
// 在 ShowOverviewPage.class.php 裡面
$data = [
    'planet_name' => $this->planet['name'],
    'metal' => $this->planet['metal'],
];
$this->blade->render('game.overview', $data);
請謹慎使用程式碼。

⏳ 關於全域 Hook(資源產出與倒數計時)的處理

你提到在 includes/common.php 裡有一個全域 Hook。在 XNova 的邏輯中,這通常是 PlanetResourceUpdate() 或者是核心的 tick 機制。
• 它的運作原理:每次玩家點擊任何頁面、觸發 game.php 載入 common.php 時,這個 Hook 就會去撈資料庫,計算「上一次更新時間」到「現在時間」之間的秒數,乘上每小時產量,然後把金屬、水晶、重氫的數值加進資料庫並更新。
• 重構前端時的注意點:這個全域 Hook 絕對不要去動它! 它是整款遊戲的心臟。因為不論你的前端畫面是用 Vue、Livewire、還是最簡單的 Tailwind CSS 靜態網頁,只要玩家點擊、刷新網頁,這個 Hook 依然會在後端默默地、精準地幫你算好資源。

💡 如何讓前端的倒數計時與資源跳字變得現代化?

老版 XNova 的建築倒數計時通常是靠一段很老的 JavaScript(例如 counter.js)在前端每秒扣除 1 秒。
既然你要翻新前端,你可以利用現代的 原生 JavaScript (Vanilla JS) 來寫一個漂亮、不會卡頓的動態跳字與倒數計時組件。
你只需要讓你的 PHP 輸出目標時間戳(Timestamp)給前端:
html
<!-- 在你的新版 Blade 或 Smarty 模板中 -->
<div class="resource-card bg-gray-800 p-4 rounded-lg border border-cyan-500">
    <div>金屬:<span id="metal-counter" data-base="{{ $metal }}" data-production="{{ $metal_per_second }}">{{ number_format($metal) }}</span></div>
   
    <!-- 建築倒數計時器 -->
    <div class="countdown mt-2 text-sm text-yellow-400" data-endtime="{{ $building_completion_time }}">
      正在建造中... 00:00:00
    </div>
</div>
請謹慎使用程式碼。
然後寫一個全域的現代 JS 腳本(可以使用 requestAnimationFrame 或簡單的 setInterval):
1. 自動抓取畫面上所有帶有 data-production 的欄位,在前端每微秒自動動態跳字(數字會自己一直往上滾動,看起來非常現代、非常流暢)。
2. 自動抓取帶有 data-endtime 的欄位,在前端做倒數計時,時間一到就彈出視窗提示玩家,或者自動引導網頁重新整理(此時會觸發 common.php 的全域 Hook,後端就會正式完成建造)。

一人獨立開發的最終策略總結

看過你的 api.php 與 game.php 後,我非常有信心。你的後端架構完全不需要動,它已經足夠應付 50 人在線,且物件導向的路由格式非常清晰。
1. 不要安裝完整的 Laravel 框架:因為那代表你要重寫路由、重寫 Model、重新把這個漂亮的 game.php 分流器打碎,一人開發會精疲力竭。
2. 主攻 includes/pages/game/ 資料夾:這裡就是你的戰場。你需要做的,只是把這裡面每一個 Page 類別最後輸出的「畫面層」抽離。
3. 專注於 Tailwind CSS 與現代前端切版:將原本的舊表格全部替換掉。
既然你的遊戲已經有這麼棒的 Page 類別路由架構:
• 你可以去翻一下 includes/pages/game/AbstractGamePage.class.php 或者其中一個子類別(例如 ShowOverviewPage.class.php),看看它們在程式碼的最後,到底是用什麼方式把畫面呈現給玩家的?(是 Smarty 的 $this->display(),還是直接在裡面 echo HTML 呢?)
我可以針對他們輸出畫面的具體方式,提供你最精準的「畫面抽離與 Tailwind 套用」步驟!
如果你想進一步優化前端,請告訴我:
• 舊程式碼中是使用 Smarty 模板 (.tpl) 還是純 PHP echo 來輸出 HTML?
• 你的前端 CSS 是想自己用 Tailwind 慢慢調整,還是希望能直接套用現成的科幻/網頁遊戲 UI 框架?
• 核心的資源每秒產出跳字,目前有現成的 JavaScript 在跑,還是需要一段現代化的 JS 範例來替換它?
頁: [1]
檢視完整版本: 1人開發的「UI 大改造」方案