Post date: Jul 4, 2011 5:17:32 PM
Trong phần này, ta tiến hành thay đổi một vài chỗ trong cấu trúc hiện tại, tạo tiền đề cho việc hổ trợ multi-platform.
Ở mô hình hiện tại, CGame giữ quyền trung tâm, kiểm soát vòng lập chính. Tuy nhiên, mô hình này không thể áp dụng cho multi-platform vì trong nhiều trường hợp, vòng lặp chính được kiểm soát bởi platform (Android/IPhone, ...) thông qua các lớp quản lý view của từng platform.
Để đảm bảo thực thi platform, mô hình mới chuyển trung tâm đều khiển thuộc về lớp view.
SConfig chứa những thông tin cơ bản về game:
SConfig.h
#ifndef __SGAMECONFIG_H__ #define __SGAMECONFIG_H__ #include "Header.h" #include "CGame.h" namespace GameTutor { typedef struct _SGameConfig { __UINT16 iWidth; __UINT16 iHeight; bool isUseFullScreen; const char *strTitle; CGame* pGame; }SGameConfig; } #endif
Phương thức này có thể nằm bất kỳ file cpp nào, nhưng khuyến cáo thực hiện trong file CDevice.cpp
StartApp
namespace GameTutor { void StartApp(SGameConfig cnf) { //init view if (!CViewController::GetInstance()) { CViewController::GetInstance()->CreateView(cnf.iWidth, cnf.iHeight, cnf.isUseFullScreen, cnf.strTitle); CViewController::GetInstance()->GetView()->Update(); } } }
main.cpp
#include "CExample.h" #include "SGameConfig.h" #include "CDevice.h" int main() { SGameConfig cnf = { 400, 200, false, "Hello", new CExample() }; GameTutor::StartApp(cnf); }
Hàm main thực hiện gọi StartApp với các điều kiện được thiết lập bởi config.
CGame.h
#ifndef __CGAME_H__ #define __CGAME_H__ #include "Header.h" namespace GameTutor { enum EGameStatus { EGSTATUS_INIT = 0, EGSTATUS_RUNNING, EGSTATUS_PAUSED, EGSTATUS_EXIT }; class CGame { public: static CGame* GetInstance() {return s_pInstance;} virtual ~CGame() {} virtual void Update(); virtual void Exit(); virtual void Pause(); virtual void Resume(); bool IsAlive() {return (m_eStatus != EGSTATUS_EXIT);} bool IsPause() {return (m_eStatus == EGSTATUS_PAUSED);} protected: CGame(); static CGame* s_pInstance; virtual void Init() = 0; virtual void Destroy() = 0; protected: enum EGameStatus m_eStatus; }; } #endif
Lúc này, CGame không còn đóng vai trò điều khiển vòng lặp chính nên được thay đổi lại cho phù hợp:
CGame.cpp
#include "CGame.h" #include "Header.h" #include "CStateManagement.h" #include "CDevice.h" #include "CFpsController.h" #include "CViewController.h" namespace GameTutor { CGame* CGame::s_pInstance = 0; CGame::CGame(): m_eStatus(EGSTATUS_INIT) { s_pInstance = this; } void CGame::Pause() { m_eStatus = EGSTATUS_PAUSED; } void CGame::Resume() { m_eStatus = EGSTATUS_RUNNING; } void CGame::Exit() { m_eStatus = EGSTATUS_EXIT; } void CGame::Update() { switch (m_eStatus) { case EGSTATUS_INIT: this->Init(); m_eStatus = EGSTATUS_RUNNING; break; case EGSTATUS_RUNNING: case EGSTATUS_PAUSED: CFpsController::GetInstance()->BeginCounter(); CStateManagement::GetInstance()->Update(m_eStatus == EGSTATUS_PAUSED); CFpsController::GetInstance()->EndCounter(); break; case EGSTATUS_EXIT: //force clean up current state CStateManagement::GetInstance()->SwitchState(0); CStateManagement::GetInstance()->Update(false); Destroy(); break; default: break; } } }
Việc thay đổi này đảm bảo lớp này đóng vai trò điều khiển vòng lặp chính
CVSView.cpp
void CVSView::Update() { while (true) { // handle win32 message MSG msg; if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); if (msg.hwnd == m_hwndWindow) { WndProc(m_hwndWindow, msg.message, msg.wParam, msg.lParam); } } CGame::GetInstance()->Update(); if (!CGame::GetInstance()->IsAlive()) { return; } RefreshGL(); DispatchMessage(&msg); } }
Donwload