GridObject¶
遊戲世界由許多具有位置和行為的實體組成。玩家會移動,敵人會追蹤,道具會在碰撞後消失;即使它們外觀和規則不同,都需要回答相同的基本問題:目前位於哪一格、應該畫成什麼、是否可見,以及和其他物件同格時要做什麼。
GridObject 是 Grid++ 對這類遊戲實體的共同描述,也是玩家、敵人、道具和其他網格內容共用的基底。GridObject 把所有物件都會使用的資料和生命週期放在同一個介面中,Engine 因此可以用一致方式更新、碰撞和繪製不同類型的內容。
資料與行為¶
一個 GridObject 包含兩類資訊。「資料」描述物件現在的狀態,例如 x、y、素材、方向、顏色與顯示層級;「行為」描述狀態何時改變,例如按鍵後移動、碰到玩家後消失,或每隔一段時間切換素材。
GridObject 已經提供所有物件共通的資料。行為則有兩種提供方式:將普通函式交給 CallbackGridObject,或建立衍生 class 覆寫生命週期函式。無論選擇哪一種,Engine 看到的都是 GridObject,因此兩種物件可以同時存在於同一個遊戲。
物件與 Engine 的關係¶
只在 C++ 中建立一個物件,並不會讓它自動出現在遊戲裡。物件必須透過 GridEngine::Spawn() 加入某個 Engine,才能進入該 Engine 的更新、碰撞與繪製流程。Spawn 也會把物件的所有權交給 Engine,使資源清理只有一個明確負責者。
下列程式建立一個位於 (3, 2) 的物件,並保留 Engine 回傳的借用指標。
這個多載會建立 CallbackGridObject,但回傳型別是它的基底類別 GridObject*。呼叫端只需使用所有網格物件共通的 API,不必依賴實際類別。
將物件加入打地鼠¶
目前的 8×8 Engine 還沒有任何遊戲內容。加入一個地鼠物件只需要素材名稱與網格位置;第三個參數暫時傳入 nullptr,表示物件目前沒有每幀更新函式。
int main() {
GridEngine game(8, 8, 64);
game.set_background_color(BEIGE);
game.set_show_grid(true);
GridObject* mole = game.Spawn("mole", 3, 4, nullptr);
mole->set_tag("mole");
game.Run();
}
程式尚未載入名為 mole 的素材,因此畫面會在第 3 欄、第 4 列顯示紅色 fallback 方塊。這個結果已足以驗證 Spawn()、座標與繪製;素材可以在功能正確後再加入。
位置與移動¶
x() 和 y() 讀取目前位置;set_x() 與 set_y() 設定單一座標;Move(dx, dy) 以相對位移修改兩個座標。Grid++ 不會自動阻止物件離開地圖,移動規則應在遊戲程式中根據 engine()->cols()、engine()->rows() 或 GridMaze::IsWall() 判斷。
player->set_x(4);
player->set_y(5);
player->Move(-1, 0); // 移動至 (3, 5)
int column = player->x();
int row = player->y();
位於地圖外的物件仍會執行 OnUpdate() 和繪製,但不參與碰撞。若素材繪製位置也在視窗外,raylib 會自然裁掉看不見的部分。將物件移至 (-1, -1) 可以讓它離開畫面,但需要暫停碰撞與繪製時,應使用 set_visible(false) 表達意圖。
素材與外觀¶
asset_name() 指定 Render() 使用的素材。set_asset_name() 可在遊戲執行期間切換素材。素材名稱不存在或尚未載入素材包時,預設繪製會顯示紅色方塊,讓程式在沒有素材的情況下仍可測試。
direction 以 90 度為單位旋轉素材,數值會正規化到 0~3。方向增加時,素材逆時針旋轉。tint 使用 raylib 的 Color;WHITE 保留原始素材顏色,其餘顏色會與素材混合。
tag 是由遊戲自行定義的文字標記,通常用於碰撞時辨識物件類型。它不會自動改變繪製或碰撞規則。
顯示狀態¶
set_visible(false) 隱藏物件。隱藏的物件不會繪製,也不會參與碰撞,但仍會每幀執行 OnUpdate()。這項行為適合需要暫時消失、之後再次出現的物件。
若物件之後不會再使用,呼叫 game.Destroy(object) 釋放它。不要在 set_visible(false) 後自行 delete 指標;物件仍由引擎持有。
繪製順序¶
z_index 控制 GridObject 的繪製層級。數值較小的物件先畫,數值較大的物件後畫,因此較大的值顯示在上方。預設值是 0,也可以使用負數。
相同 z-index 保留 spawn 順序,後 spawn 的物件會較晚繪製。z-index 只影響畫面,不改變更新或碰撞 callback 的執行順序。Overlay 永遠繪製在所有 GridObject 上方。
所有權¶
Spawn(GridObject*) 與 AddOverlay(Overlay*) 接受 raw pointer,是為了讓入門程式保持直接;所有權會在呼叫成功後轉交給引擎。只能傳入使用 new 建立、尚未交給其他引擎的物件。
// 正確:引擎接管 new 建立的物件。
GridObject* object = game.Spawn(new GridObject("box", 1, 1));
// 錯誤:區域變數不是由引擎配置,之後不可由引擎 delete。
GridObject local("box", 1, 1);
game.Spawn(&local);
同一指標不可 spawn 兩次,也不可同時交給兩個引擎。Spawn() 回傳的指標只在物件仍存在時有效;呼叫 Destroy()、ClearObjects() 或讓引擎結束生命週期後,不可再次讀取該指標。
完整成員列表見 GridObject API。