首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

基於HGE引擎的RPG角色系統架構設計與實現

     編輯:關於C語言

從零構建:基於HGE 2D引擎的RPG角色模塊架構實戰

在獨立遊戲開發中,角色系統是核心玩法邏輯的載體。本文分享一套基於 HGE (Haaf's Game Engine) 2D引擎的 RPG 角色模塊完整設計,採用抽象基類 + 具體派生類 + 管理器單例的經典三層架構,展示 C++ 面向對象思想在遊戲實體管理中的落地實踐。

架構總覽:三層職責分離

  • FGRoleObject (抽象基類):定義通用屬性接口、碰撞檢測、狀態機框架,實現「高內聚、低耦合」的通用實體契約。
  • FGMyRole (玩家角色派生類):封裝 HGE 動畫渲染、鍵盤輸入響應、裝備系統、具體狀態邏輯(移動/待機/攻擊/死亡)。
  • FGRoleManager (管理器單例):統一生命週期管理、邏輯幀更新、渲染提交、陣營查詢、ID 索引。

核心代碼實現解析

1. 抽象基類 FGRoleObject — 通用實體契約

class FGRoleObject {
public:
    // 引擎綁定(靜態單例模式)
    static void Init(HGE* m_hge) { hge = m_hge; }

    // 純虛函數:強制派生類實現邏輯與渲染
    virtual void Logic() = 0;
    virtual void Render() = 0;

    // 通用屬性 Getter(內聯優化)
    float GetX() { return m_x; }
    float GetY() { return m_y; }
    int GetID() { return m_ID; }
    // ... HP, MP, ATK, DEF, SPD 等屬性獲取器 ...

    // 碰撞體係:軸對齊包圍盒 (AABB)
    void SetRect(float ltx, float lty, float rdx, float rdy) 
        { m_rect.Set(ltx, lty, rdx, rdy); }
    bool Intersect(FGRoleObject& role) 
        { return m_rect.Intersect(&role.m_rect); }

    // 屬性批量設置 / 狀態機切換
    void SetAttribute(/* 18個屬性參數 */);
    void SetMode(ActionMode _mode) { m_actionMode = _mode; }

protected:
    // 構造函數受保護:禁止直接實例化基類
    FGRoleObject(short _id, CampType _camp, const char* _name, float _x, float _y);
    virtual ~FGRoleObject();

    // 靜態共享資源
    static HGE* hge;
    static float Money;      // 全局金幣
    static float PlayTime;   // 全局遊戲時間

    // 實例數據成員
    CampType m_camp;         // 陣營:PLAYER / ENEMY / NEUTRAL
    char m_name[256];        // 角色名
    short m_id;              // 唯一ID
    float m_x, m_y;          // 世界座標
    hgeRect m_rect;          // 碰撞盒
    // ... 戰鬥屬性、經驗值、移動速度、朝向、狀態枚舉 ...
};

設計亮點:

  • 介面隔離:純虛函數 `Logic/Render` 強制派生類實現幀邏輯,管理器無需知道具體類型即可統一調度。
  • 數據封裝:所有屬性 `protected`,僅暴露 `const` Getter,防止外部隨意修改破壞不變量。
  • 碰撞復用:基類內建 `hgeRect` 與 `Intersect`,所有實體自動獲得 AABB 碰撞能力。
  • 靜態共享:`HGE*`、全局金幣、遊戲時間作為 `static` 成員,單份拷貝服務所有實例。

2. 玩家角色類 FGMyRole — 行為與表現的具體化

class FGMyRole : public FGRoleObject {
public:
    // 複雜構造:基類參數 + 動畫參數 + UI參數 + 移動速度
    FGMyRole(short id, CampType camp, char* name, float x, float y,
             float tx, float ty, float tw, float th, float fps, 
             int nframe, HTEXTURE tex, short uiIndex, float speed);
    virtual ~FGMyRole();

    // 核心幀邏輯:輸入處理 + 狀態機驅動 + 動畫更新
    void Logic() override;
    void Render() override { spr[m_direction]->Render(m_x, m_y); }

    // 裝備系統:固定5槽位數組
    void InitEquips();
    ItemObject* Equips[5];  // 武器、防具、鞋、飾品x2

private:
    // HGE 動畫資源:8方向各一組
    hgeAnimation* spr[8];   
    float m_fps; int m_nframe;
    float m_tx, m_ty, m_tw, m_th; // 材質圖集坐標/尺寸
    short m_uiPortraitIndex;      // UI頭像索引
};
關鍵邏輯實現:狀態機驅動的移動與攻擊
void FGMyRole::Logic() {
    // 1. 當前方向動畫幀更新
    spr[m_direction]->Update(hge->Timer_GetDelta());

    // 2. 狀態機分發
    switch (m_actionMode) {
        case MOVE:   HandleMoveInput();  break; // WASD 八方向移動 + 斜向速度修正
        case WAIT:   HandleWaitInput();  break; // 偵測按鍵切換到 MOVE
        case ATTACK: HandleAttack();     break; // 播放攻擊動畫,幀結束自動回 WAIT
        case HIT:    /* 被擊硬直 */     break;
        case DEAD:   /* 死亡處理 */     break;
    }
}

void FGMyRole::HandleMoveInput() {
    bool moved = false;
    // W 上
    if (hge->Input_GetKeyState(HGEK_W)) {
        if (hge->Input_GetKeyState(HGEK_D)) { m_x += m_speed; m_y -= m_speed; m_dir = RIGHT_UP; moved = true; }
        else if (hge->Input_GetKeyState(HGEK_A)) { m_x -= m_speed; m_y -= m_speed; m_dir = LEFT_UP; moved = true; }
        else { m_y -= m_speed; m_dir = UP; moved = true; }
    }
    // S 下 / D 右 / A 左 ... 類似處理
    // 無輸入時:幀歸零、切換待機貼圖、狀態轉 WAIT
    if (!moved) { spr[m_dir]->SetFrame(0); SetMode(WAIT); }
    
    // Ctrl 攻擊鍵:切換 ATTACK 狀態、重置動畫幀、提高播放速度
    if (hge->Input_GetKeyState(HGEK_CTRL)) { SetMode(ATTACK); /* 設置攻擊貼圖與速度 */ }
}

實現細節:

  • 八方向移動:組合鍵檢測實現 8 向位移,斜向同時按下兩鍵時分量各自為 `speed`,實際速度為 `√2 * speed`,若需嚴格等速需乘以 `0.707` 修正。
  • 動畫狀態同步:每種狀態切換時調用 `SetTexture` 替換貼圖、`SetSpeed` 調整幀率、`SetFrame(0)` 重置播放頭,確保視覺反饋即時。
  • 資源管理:構造函數 `new hgeAnimation[8]`,析構函數逆序 `delete` 並置空,避免內存洩漏。

3. 裝備系統:數據驅動的裝備槽位

void FGMyRole::InitEquips() {
    for (int i = 0; i < 5; ++i) Equips[i] = nullptr;
    switch (m_ID) {
        case 0: // 主角
            Equips[0] = new Weapon(/* 參數 */);      // 武器槽
            Equips[1] = new Armor(/* 參數 */);       // 防具槽
            Equips[2] = new Armor(/* 參數 */);       // 鞋子槽
            Equips[3] = new Accessory(/* 參數 */);   // 飾品1
            Equips[4] = new Accessory(/* 參數 */);   // 飾品2
            break;
        case 1: // 同伴
            Equips[0] = new Weapon(/* 參數 */);
            break;
    }
}

固定長度數組 `ItemObject* Equips[5]` 映射固定槽位(武器/防具/鞋/飾品×2),運行期通過多態調用裝備屬性加成。擴展性可改為 `std::vector` 或 `std::map`。

4. 角色管理器 FGRoleManager — 單例統一調度

class FGRoleManager {
public:
    // 單例訪問點:首次調用綁定 HGE 並初始化基類靜態指針
    static FGRoleManager* Instance(HGE* hge) {
        if (!m_instance) {
            this->hge = hge;
            FGRoleObject::Init(hge);
            m_instance = new FGRoleManager();
        }
        return m_instance;
    }

    // 統一幀更新:遍歷列表調用多態 Logic/Render
    void Logic() { for (auto obj : m_list) obj->Logic(); }
    void Render() { for (auto obj : m_list) obj->Render(); }

    // 生命週期管理
    void AddRole(FGRoleObject& obj) { 
        m_list.push_front(&obj); 
        m_idList.push_back(obj.GetID()); 
    }
    void DeleteRole(FGRoleObject& obj) { m_list.remove(&obj); }

    // 查詢接口
    FGRoleObject* GetRole(short id);           // O(n) 線性查找
    short GetMyRoleCount();                    // 陣營統計
    short GetEnemyCount();

private:
    FGRoleManager() = default;
    ~FGRoleManager() = default;

    std::list<FGRoleObject*> m_list;      // 基類指針容器:多態存儲
    std::list<short> m_idList;             // ID 索引備份
    static FGRoleManager* m_instance;
    static HGE* hge;
    static FGRoleObject* s_currentRole;    // 當前選中角色
};

架構優勢:

  • 多態容器:`std::list` 存儲基類指針,NPC、敵人、玩家統一入列,`Logic/Render` 一次遍歷全搞定。
  • 單例模式:全局唯一訪問點,確保管理器狀態一致性,便於腳本層/編輯器調用。
  • 陣營枚舉:`CampType { PLAYER, ENEMY, NEUTRAL }` 區分陣營,支持陣營篩選、AI 目標選擇、傷害判定。
  • ID 索引分離:`m_idList` 獨立維護 ID 序列,支持按序號快速獲取角色(如隊伍界面顯示)。

設計心得與擴展方向

  1. 基類只放「數據與通用行為」:渲染、動畫、輸入等引擎強相關邏輯下沉到派生類,保證基類可復用於其他引擎項目。
  2. 派生類封裝「引擎特有資源」:`hgeAnimation*`、貼圖坐標、UI索引等 HGE 專屬成員不污染基類介面。
  3. 管理器職責單一:僅負責容器維護、幀廣播、查詢服務,不包含遊戲具體規則(如傷害計算、掉落邏輯)。
  4. 未來優化點:
    • 引入組件模式 (ECS) 拆分屬性/動畫/AI/裝備為獨立組件,替代深層繼承。
    • 管理器查詢優化:`std::unordered_map` 實現 O(1) ID 查找。
    • 狀態機抽象:提取 `StateMachine` 組件,支持數據驅動的狀態配置(JSON/Script)。
    • 智能指針:`std::unique_ptr`/`shared_ptr` 替代裸指針,自動化生命週期管理。

這套架構在小型 RPG 專案中已驗證穩定高效,清晰分層讓邏輯擴展與調試更加從容。完整代碼已開源於個人倉庫,歡迎交流指正。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved