遊戲規範

一款 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:

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滑桿minmaxstep
bool開關
enum下拉選單options
color顏色選擇器值為 #rrggbb
string文字欄位
grid2d網格編輯器rowscolspalette;值為二維數字陣列
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/ 連同外殼一併納入。

下一步