遊戲規範
一款 Gamentic 遊戲,就是一款普通、自成一體的 HTML5 遊戲,再加上幾行標記註解。遵循這些標記,遊戲就能獲得即時的 Inspector、由伺服器注入的美術與音訊,以及匯出與 Remix 功能。忽略它們,它仍然是一款遊戲——這套規範純粹是附加的。
你的 AI 會透過 get_convention 從伺服器讀取這份規範的正式版本,而且在撰寫任何遊戲之前都必須先讀取。本頁是供人閱讀的摘要——適合用來檢查 AI 產出的內容,或是自己動手寫遊戲時參考。
標記註解
平台能看到或更改的一切,都由五個全域變數承載。每個變數在
game.html 中只宣告一次,而且每一次賦值都以一行完全相符的標記註解結尾。伺服器會以文字比對找出這些標記,藉此注入生成的美術、音訊與模型;Inspector 則會找出
GAME_CONFIG 來建立調校面板。
| 全域變數 | 標記 | 內容 |
|---|---|---|
window.GAME_CONFIG | // __GI_CONFIG__ | 所有可調的數值、顏色、開關與關卡配置 |
window.GAME_ASSETS | // __GI_ASSETS__ | 生成的圖片,依名稱索引 |
window.GAME_AUDIO | // __GI_AUDIO__ | 生成的音樂、語音與音效 |
window.GAME_MODELS | // __GI_MODELS__ | 生成的 3D 模型與骨架綁定 |
window.GAME_DATA | // __GI_DATA__ | AI 不必更動程式碼就能編輯的內容——對話、關卡、道具表 |
1. 單一設定物件
所有可調的東西都放在單一全域變數裡,而且賦值的右側必須是合法的 JSON:鍵要用雙引號、不能有結尾逗號,也不能有函式、註解或運算式。
window.GAME_CONFIG = {
"gravity": 0.6,
"playerSpeed": 4.5,
"enemyColor": "#ff4757",
"hardMode": false,
"level": [[1,1,0],[0,1,0],[0,1,1]]
}; // __GI_CONFIG__
絕對不要在標記那一行加上防禦性的後備寫法。這是最常犯的一個錯誤:
window.GAME_ASSETS = {}; // __GI_ASSETS__ correct
window.GAME_ASSETS = window.GAME_ASSETS || {}; // __GI_ASSETS__ breaks injection
一旦用了 ||、??、三元運算子或 Object.assign(...),右側就不再是 JSON,伺服器也就無法再改寫這個區塊——生成的美術因此永遠不會出現。不會有任何錯誤訊息。而且這種防護本來就不需要:這些全域變數就是在這裡定義的,而且只定義一次。
每個標記在整個檔案中只能出現一次,而且遊戲迴圈必須每一影格都直接讀取
window.GAME_CONFIG。如果在啟動時把值複製到區域變數,面板上的修改就要等到下次重新載入才會生效。
2. Harness
這五行程式碼讓 Inspector 能把修改推送進執行中的遊戲。請一字不差地照抄。
window.__GI_SET = function (patch) {
Object.assign(window.GAME_CONFIG, patch);
if (typeof window.__giOnChange === 'function') window.__giOnChange(patch);
};
console.log('__GI__' + JSON.stringify({ type: 'ready', config: window.GAME_CONFIG }));
兩個選用的 hook:
window.__giOnChange = (patch) => {...}—— 用於不會每一影格重新讀取的衍生狀態,例如在數量改變後重建敵人池。window.__giOnAction = (key) => {...}—— 用於面板按鈕,例如重新開始或清空盤面。
3. Schema
schema 描述的是面板。它會傳給 create_game,而且永遠不會內嵌進遊戲的 HTML——因此在 Inspector 中編輯遊戲不會破壞它。
{
"groups": [
{ "label": "Feel", "fields": [
{ "key": "gravity", "type": "float", "min": 0.1, "max": 2, "step": 0.05, "label": "Gravity" }
]},
{ "label": "Controls", "fields": [
{ "key": "restart", "type": "action", "label": "Restart" }
]}
]
}
| 類型 | 控制項 | 需要 |
|---|---|---|
int / float | 滑桿 | min、max、step |
bool | 開關 | — |
enum | 下拉選單 | options |
color | 顏色選擇器 | 值為 #rrggbb |
string | 文字欄位 | — |
grid2d | 網格編輯器 | rows、cols、palette;值為二維數字陣列 |
action | 按鈕 | 觸發 __giOnAction(key) |
除了 action 之外,每個欄位都需要在 GAME_CONFIG 中有對應的預設值。分組應具有意義——例如手感(Feel)、難度(Difficulty)、外觀(Appearance)、操作(Controls)——
而不是全部混雜在一起、不加區分。如果一款遊戲的難度數值沒有開放出來,玩家就無法調校它——
而讓玩家自行調校,幾乎就是這一切的重點所在。
4. 自成一體的套件
不得從其他網域載入任何東西:不能有 CDN 腳本、遠端字型、外部圖片,也不能用
fetch() 連到網際網路。圖形用 canvas 繪製,聲音用 WebAudio 合成,或以生成的音訊注入。這不是我們自訂的風格偏好——這些遊戲執行時所在的沙盒,會直接封鎖外部資源。
「自成一體」指的是套件,而不是單一檔案。一款遊戲是一個資料夾:
game.html the shell: markers, boot, <script src="src/..."> in load order
src/**.js your code, split by responsibility
media/** images and audio (the server puts them here)
標記區塊與 harness 都要留在 game.html。把其中一個移到 src/,不會出現任何錯誤——只是生成的美術與音訊會悄悄地不再送達,因為伺服器只會在 game.html 裡尋找這些標記。
game.html 必須以 </html> 結尾;被截斷的上傳內容會直接遭到拒絕,而不會以只寫了一半的狀態儲存。匯出、Remix,以及發佈到 itch.io 或 Newgrounds 時,都會把
src/ 與 media/ 連同外殼一併納入。