1. 程式人生 > >傳奇源碼分析-客戶端(遊戲邏輯處理源分析四)

傳奇源碼分析-客戶端(遊戲邏輯處理源分析四)

操作 ons get rect 消息處理 min rem log ise

現在假設玩家開始操作遊戲:
傳奇的客戶端源代碼工程WindHorn
一、CWHApp派生CWHWindow和CWHDXGraphicWindow。
二、CWHDefProcess派生出CloginProcess、CcharacterProcess、CgameProcess
客戶端WinMain調用CWHDXGraphicWindow g_xMainWnd;創建一個窗口。
客戶端CWHDXGraphicWindow在自己的Create函數中調用了CWHWindow的Create來創建窗口,然後再調用自己的CreateDXG()來初始化DirectX。

消息循環:
因此,當客戶端鼠標單擊的時候,先調用CWHWindow窗口的回調函數WndProc,即: g_pWHApp->MainWndProc g_pWHApp定義為:static CWHApp* g_pWHApp = NULL;在CWHApp
構造函數中賦值為:g_pWHApp = this;
g_pWHApp->MainWndProc便調用了CWHApp::MainWndProc,這是一個虛函數,實際上則是調用它的派生類CWHDXGraphicWindow::MainWndProc。
if ( m_pxDefProcess )
return m_pxDefProcess->DefMainWndProc(hWnd, uMsg, wParam, lParam);
根據g_xMainWnd.m_pxDefProcess和全局變量g_bProcState標記當前的處理狀態。調用
CLoginProcess->DefMainWndProc
CCharacterProcess->DefMainWndProc
CGameProcess->DefMainWndProc

當用戶進行遊戲之後,點擊鼠標左鍵,來處理玩家走動的動作:
客戶端執行流程:(玩家走動)
CGameProcess::OnLButtonDown(WPARAM wParam, LPARAM lParam)函數:該函數的處理流程:
1. g_xClientSocket.SendNoticeOK();如果點中CnoticeBox則m_xNotice.OnButtonDown
if m_xMsgBtn.OnLButtonDown則調用g_xClientSocket.SendNoticeOK()方法,發送還CM_LOGINNOTICEOK消息。
2.m_pxSavedTargetActor = NULL;設置為空。CInterface::OnLButtonDown函數會判斷
鼠標點擊的位置(CmirMsgBox, CscrlBar,CgameBtn,GetWindowInMousePos)
a. g_xClientSocket.SendItemIndex(CM_DROPITEM 丟棄物品)
遊戲服務器執行流程m_pxPlayerObject->Operate()調用
m_pUserInfo->UserDropGenItem
m_pUserInfo->UserDropItem 刪除普通物品。
SM_DROPITEM_SUCCESS 返回刪除成功命令
SM_DROPITEM_FAIL 返回刪除失敗命令

b. 遍歷m_stMapItemList列表(存儲玩家,怪物,NPC), g_xClientSocket.SendPickUp 發送CM_PICKUP命令。
遊戲服務器:m_pxPlayerObject->Operate()調用 PickUp(撿東西)消息處理:
m_pMap->GetItem(m_nCurrX, m_nCurrY) 返回地圖裏的物體(草藥,物品,金子等)
1.memcmp(pMapItem->szName, g_szGoldName 如果是黃金:
m_pMap->RemoveObject從地圖中移走該的品。
if (m_pUserInfo->IncGold(pMapItem->nCount))增加用戶的金錢(向周轉玩家發送RM_ITEMHIDE 消息,隱藏該物體,GoldChanged(),改變玩家的金錢。否則,把黃金返回地圖中。
2.m_pUserInfo->IsEnoughBag()
如果玩家的還可以隨身帶裝備(空間)。m_pMap->RemoveObject從地圖中移走該的品。UpdateItemToDB,更新用戶信息到數據庫。(向周轉玩家發送RM_ITEMHIDE 消息,隱藏該物體,SendAddItem(lptItemRcd)向本玩家發送撿到東西的消息。m_pUserInfo->m_lpTItemRcd.AddNewNode並把該物品加入自己的列表中。

c. if m_pxMouseTargetActor g_xClientSocket.SendNPCClick發送CM_CLICKNPC命令。
客戶端RenderScene調用m_pxMouseTargetActor = NULL;
CheckMappedData(nLoopTime, bIsMoveTime)處理,如果鼠標在某個移動對象的區域內就會設置 m_pxMouseTargetActor為該對象。
如果是NPC:
if ( m_pxMouseTargetActor->m_stFeature.bGender == _GENDER_NPC )
g_xClientSocket.SendNPCClick(m_pxMouseTargetActor->m_dwIdentity);
CM_CLICKNPC消息:
否則:
m_xMyHero.OnLButtonDown

d. 否則m_xMyHero.OnLButtonDown
先判斷m_xPacketQueue是否有數據,有則先處理。返回。
判斷m_pxMap->GetNextTileCanMove 根據坐標,判斷地圖上該點屬性是否可以移動到該位置:
可移動時:
人:SetMotionState(_MT_WALK
騎馬:SetMotionState(_MT_HORSEWALK
不可移動時:
人:SetMotionState(_MT_STAND, bDir);
騎馬:SetMotionState(_MT_HORSESTAND, bDir);
SetMotionState函數:
判斷循環遍歷目標點的周圍八個坐標,如果發現是一扇門,則向服務器發送打開這扇門的命令。g_xClientSocket.SendOpenDoor,否則則發送CM_WALK命令到服務器。
m_bMotionLock = m_bInputLock = TRUE; 設置遊戲狀態
m_wOldPosX = m_wPosX; 保存玩家X點
m_wOldPosY = m_wPosY; 保存玩家Y點
m_bOldDir = m_bCurrDir; 保存玩家方向
然後調用SetMotionFrame設置m_bCurrMtn = _MT_WALK,方向等遊戲狀態。
設置m_bMoveSpeed = _SPEED_WALK(移動速度1)。m_pxMap->ScrollMap設置地圖的偏移位置(m_shViewOffsetX, m_shViewOffsetY)。然後滾動地圖,重繪玩家由CGameProcess::RenderScene CGameProcess::RenderObject->DrawActor重繪。


此文章來自網絡,如有版權沖突請和我聯系 [email protected]


傳奇源碼分析-客戶端(遊戲邏輯處理源分析四)