赞
踩
暑假刚买了个北通的游戏杆,想不到那么快便派上了编程的用场,呵呵~~
让游戏引擎支持游戏杆输入,无疑对于游戏发烧友来说是很重要的,修改后的GameEngine.h如下
//----------------------------------------------------------------- // Game Engine Object // C++ Header - GameEngine.h //----------------------------------------------------------------- #pragma once //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include #include //----------------------------------------------------------------- // Joystick Flags //----------------------------------------------------------------- typedef WORD JOYSTATE; const JOYSTATE JOY_NONE = 0x0000L, JOY_LEFT = 0x0001L, JOY_RIGHT = 0x0002L, JOY_UP = 0x0004L, JOY_DOWN = 0x0008L, JOY_FIRE1 = 0x0010L, JOY_FIRE2 = 0x0020L; //----------------------------------------------------------------- // Windows Function Declarations //----------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow); LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); //----------------------------------------------------------------- // Game Engine Function Declarations //----------------------------------------------------------------- BOOL GameInitialize(HINSTANCE hInstance); void GameStart(HWND hWindow); void GameEnd(); void GameActivate(HWND hWindow); void GameDeactivate(HWND hWindow); void GamePaint(HDC hDC); void GameCycle(); void HandleKeys(); void MouseButtonDown(int x, int y, BOOL bLeft); void MouseButtonUp(int x, int y, BOOL bLeft); void MouseMove(int x, int y); void HandleJoystick(JOYSTATE jsJoystickState); //----------------------------------------------------------------- // GameEngine Class //----------------------------------------------------------------- class GameEngine { protected: // Member Variables static GameEngine* m_pGameEngine; HINSTANCE m_hInstance; HWND m_hWindow; TCHAR m_szWindowClass[32]; TCHAR m_szTitle[32]; WORD m_wIcon, m_wSmallIcon; int m_iWidth, m_iHeight; int m_iFrameDelay; BOOL m_bSleep; UINT m_uiJoystickID; //游戏杆ID RECT m_rcJoystickTrip; //移动矩形 public: // Constructor(s)/Destructor GameEngine(HINSTANCE hInstance, LPTSTR szWindowClass, LPTSTR szTitle, WORD wIcon, WORD wSmallIcon, int iWidth = 640, int iHeight = 480); virtual ~GameEngine(); // General Methods static GameEngine* GetEngine() { return m_pGameEngine; }; BOOL Initialize(int iCmdShow); LRESULT HandleEvent(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam); void ErrorQuit(LPTSTR szErrorMsg); BOOL InitJoystick(); //初始化游戏杆设置 void CaptureJoystick(); //捕获游戏杆 void ReleaseJoystick(); //释放游戏杆 void CheckJoystick(); //游戏引擎游戏杆方法 // Accessor Methods HINSTANCE GetInstance() { return m_hInstance; }; HWND GetWindow() { return m_hWindow; }; void SetWindow(HWND hWindow) { m_hWindow = hWindow; }; LPTSTR GetTitle() { return m_szTitle; }; WORD GetIcon() { return m_wIcon; }; WORD GetSmallIcon() { return m_wSmallIcon; }; int GetWidth() { return m_iWidth; }; int GetHeight() { return m_iHeight; }; int GetFrameDelay() { return m_iFrameDelay; }; void SetFrameRate(int iFrameRate) { m_iFrameDelay = 1000 / iFrameRate; }; BOOL GetSleep() { return m_bSleep; }; void SetSleep(BOOL bSleep) { m_bSleep = bSleep; }; };
修改后的GameEngine.cpp
//----------------------------------------------------------------- // Game Engine Object // C++ Source - GameEngine.cpp //----------------------------------------------------------------- //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include "GameEngine.h" //----------------------------------------------------------------- // Static Variable Initialization //----------------------------------------------------------------- GameEngine *GameEngine::m_pGameEngine = NULL; //----------------------------------------------------------------- // Windows Functions //----------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { MSG msg; static int iTickTrigger = 0; int iTickCount; if (GameInitialize(hInstance)) { // Initialize the game engine if (!GameEngine::GetEngine()->Initialize(iCmdShow)) return FALSE; // Enter the main message loop while (TRUE) { if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { // Process the message if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } else { // Make sure the game engine isn't sleeping if (!GameEngine::GetEngine()->GetSleep()) { // Check the tick count to see if a game cycle has elapsed iTickCount = GetTickCount(); if (iTickCount > iTickTrigger) { iTickTrigger = iTickCount + GameEngine::GetEngine()->GetFrameDelay(); HandleKeys(); GameEngine::GetEngine()->CheckJoystick(); GameCycle(); } } } } return (int)msg.wParam; } // End the game GameEnd(); return TRUE; } LRESULT CALLBACK WndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam) { // Route all Windows messages to the game engine return GameEngine::GetEngine()->HandleEvent(hWindow, msg, wParam, lParam); } //----------------------------------------------------------------- // GameEngine Constructor(s)/Destructor //----------------------------------------------------------------- GameEngine::GameEngine(HINSTANCE hInstance, LPTSTR szWindowClass, LPTSTR szTitle, WORD wIcon, WORD wSmallIcon, int iWidth, int iHeight) { // Set the member variables for the game engine m_pGameEngine = this; m_hInstance = hInstance; m_hWindow = NULL; if (lstrlen(szWindowClass) > 0) lstrcpy(m_szWindowClass, szWindowClass); if (lstrlen(szTitle) > 0) lstrcpy(m_szTitle, szTitle); m_wIcon = wIcon; m_wSmallIcon = wSmallIcon; m_iWidth = iWidth; m_iHeight = iHeight; m_iFrameDelay = 50; // 20 FPS default m_bSleep = TRUE; } GameEngine::~GameEngine() { } //----------------------------------------------------------------- // Game Engine General Methods //----------------------------------------------------------------- BOOL GameEngine::Initialize(int iCmdShow) { WNDCLASSEX wndclass; // Create the window class for the main window wndclass.cbSize = sizeof(wndclass); wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = m_hInstance; wndclass.hIcon = LoadIcon(m_hInstance, MAKEINTRESOURCE(GetIcon())); wndclass.hIconSm = LoadIcon(m_hInstance, MAKEINTRESOURCE(GetSmallIcon())); wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = m_szWindowClass; // Register the window class if (!RegisterClassEx(&wndclass)) return FALSE; // Calculate the window size and position based upon the game size int iWindowWidth = m_iWidth + GetSystemMetrics(SM_CXFIXEDFRAME) * 2, iWindowHeight = m_iHeight + GetSystemMetrics(SM_CYFIXEDFRAME) * 2 + GetSystemMetrics(SM_CYCAPTION); if (wndclass.lpszMenuName != NULL) iWindowHeight += GetSystemMetrics(SM_CYMENU); int iXWindowPos = (GetSystemMetrics(SM_CXSCREEN) - iWindowWidth) / 2, iYWindowPos = (GetSystemMetrics(SM_CYSCREEN) - iWindowHeight) / 2; // Create the window m_hWindow = CreateWindow(m_szWindowClass, m_szTitle, WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX, iXWindowPos, iYWindowPos, iWindowWidth, iWindowHeight, NULL, NULL, m_hInstance, NULL); if (!m_hWindow) return FALSE; // Show and update the window ShowWindow(m_hWindow, iCmdShow); UpdateWindow(m_hWindow); return TRUE; } LRESULT GameEngine::HandleEvent(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam) { // Route Windows messages to game engine member functions switch (msg) { case WM_CREATE: // Set the game window and start the game SetWindow(hWindow); GameStart(hWindow); return 0; case WM_SETFOCUS: // Activate the game and update the Sleep status GameActivate(hWindow); SetSleep(FALSE); return 0; case WM_KILLFOCUS: // Deactivate the game and update the Sleep status GameDeactivate(hWindow); SetSleep(TRUE); return 0; case WM_PAINT: HDC hDC; PAINTSTRUCT ps; hDC = BeginPaint(hWindow, &ps); // Paint the game GamePaint(hDC); EndPaint(hWindow, &ps); return 0; case WM_LBUTTONDOWN: // Handle left mouse button press MouseButtonDown(LOWORD(lParam), HIWORD(lParam), TRUE); return 0; case WM_LBUTTONUP: // Handle left mouse button release MouseButtonUp(LOWORD(lParam), HIWORD(lParam), TRUE); return 0; case WM_RBUTTONDOWN: // Handle right mouse button press MouseButtonDown(LOWORD(lParam), HIWORD(lParam), FALSE); return 0; case WM_RBUTTONUP: // Handle right mouse button release MouseButtonUp(LOWORD(lParam), HIWORD(lParam), FALSE); return 0; case WM_MOUSEMOVE: // Handle mouse movement MouseMove(LOWORD(lParam), HIWORD(lParam)); return 0; case WM_DESTROY: // End the game and exit the application GameEnd(); PostQuitMessage(0); return 0; } return DefWindowProc(hWindow, msg, wParam, lParam); } void GameEngine::ErrorQuit(LPTSTR szErrorMsg) { MessageBox(GetWindow(), szErrorMsg, TEXT("Critical Error"), MB_OK | MB_ICONERROR); PostQuitMessage(0); } BOOL GameEngine::InitJoystick() { //确保存在游戏杆驱动程序 UINT uiNumJoysticks; if((uiNumJoysticks=joyGetNumDevs())==0) return FALSE; //确保连接了游戏杆 JOYINFO jiInfo; if(joyGetPos(JOYSTICKID1,&jiInfo)!=JOYERR_UNPLUGGED) m_uiJoystickID=JOYSTICKID1; else return FALSE; //计算移动值 JOYCAPS jcCaps; joyGetDevCaps(m_uiJoystickID,&jcCaps,sizeof(jcCaps)); DWORD dwXCenter = ((DWORD)jcCaps.wXmin+jcCaps.wXmax)/2; DWORD dwYCenter = ((DWORD)jcCaps.wYmin+jcCaps.wYmax)/2; m_rcJoystickTrip.left = (jcCaps.wXmin + (WORD)dwXCenter) / 2; m_rcJoystickTrip.right = (jcCaps.wXmax + (WORD)dwXCenter) / 2; m_rcJoystickTrip.top = (jcCaps.wYmin + (WORD)dwYCenter) / 2; m_rcJoystickTrip.bottom = (jcCaps.wYmax + (WORD)dwYCenter) / 2; return TRUE; } void GameEngine::CaptureJoystick() { // 捕获游戏杆 if (m_uiJoystickID == JOYSTICKID1) joySetCapture(m_hWindow, m_uiJoystickID, NULL, TRUE); } void GameEngine::ReleaseJoystick() { // 释放游戏杆 if (m_uiJoystickID == JOYSTICKID1) joyReleaseCapture(m_uiJoystickID); } void GameEngine::CheckJoystick() { if(m_uiJoystickID==JOYSTICKID1) { JOYINFO jiInfo; JOYSTATE jsJoystickState=0; if(joyGetPos(m_uiJoystickID,&jiInfo)==JOYERR_NOERROR) { //检查水平移动 if(jiInfo.wXpos m_rcJoystickTrip.right) jsJoystickState|=JOY_RIGHT; //检查垂直移动 if(jiInfo.wYpos m_rcJoystickTrip.bottom) jsJoystickState|=JOY_DOWN; //检查按钮 if(jiInfo.wButtons&JOY_BUTTON1) jsJoystickState|=JOY_FIRE1; if(jiInfo.wButtons&JOY_BUTTON2) jsJoystickState|=JOY_FIRE2; } HandleJoystick(jsJoystickState); } }
基于以上修改,对前一篇文章中的UFO示例进行扩充
代码清单:
//----------------------------------------------------------------- // UFO Application // C++ Header - UFO.h //----------------------------------------------------------------- #pragma once //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include #include "Resource.h" #include "GameEngine.h" #include "Bitmap.h" //----------------------------------------------------------------- // Global Variables //----------------------------------------------------------------- HINSTANCE g_hInstance; GameEngine* g_pGame; const int g_iMAXSPEED = 8; //最大速度 Bitmap* g_pBackground; //背景位图 Bitmap* g_pSaucer[2]; //UFO位图 BOOL g_bSaucerFlame; //判断UFO是否有火焰 int g_iSaucerX, g_iSaucerY; //UFO的X/Y坐标 int g_iSpeedX, g_iSpeedY; //UFO的X/Y方向的速度
//----------------------------------------------------------------- // UFO Application // C++ Source - UFO.cpp //----------------------------------------------------------------- //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include "UFO.h" //----------------------------------------------------------------- // Game Engine Functions //----------------------------------------------------------------- BOOL GameInitialize(HINSTANCE hInstance) { // Create the game engine g_pGame = new GameEngine(hInstance, TEXT("UFO"), TEXT("UFO"), IDI_UFO, IDI_UFO_SM, 500, 400); if (g_pGame == NULL) return FALSE; // Set the frame rate g_pGame->SetFrameRate(30); //初始化游戏杆 g_pGame->InitJoystick(); // Store the instance handle g_hInstance = hInstance; return TRUE; } void GameStart(HWND hWindow) { srand(GetTickCount()); // Create and load the background and saucer bitmaps HDC hDC = GetDC(hWindow); g_pBackground = new Bitmap(hDC, IDB_BACKGROUND, g_hInstance); g_pSaucer[0] = new Bitmap(hDC, IDB_SAUCER, g_hInstance); g_pSaucer[1] = new Bitmap(hDC,IDB_SAUCERFLAME,g_hInstance); // Set the initial saucer position and speed g_iSaucerX = 250 - (g_pSaucer[0]->GetWidth() / 2); g_iSaucerY = 200 - (g_pSaucer[0]->GetHeight() / 2); g_iSpeedX = 0; g_iSpeedY = 0; } void GameEnd() { // Cleanup the background and saucer bitmaps delete g_pBackground; delete g_pSaucer[0]; delete g_pSaucer[1]; // Cleanup the game engine delete g_pGame; } void GameActivate(HWND hWindow) { g_pGame->CaptureJoystick(); } void GameDeactivate(HWND hWindow) { g_pGame->ReleaseJoystick(); } void GamePaint(HDC hDC) { // Draw the background and saucer bitmaps g_pBackground->Draw(hDC, 0, 0); g_pSaucer[g_bSaucerFlame ? 1:0]->Draw(hDC, g_iSaucerX, g_iSaucerY, TRUE); } void GameCycle() { // 更新飞碟位置 g_iSaucerX = min(500 - g_pSaucer[0]->GetWidth(), max(0, g_iSaucerX + g_iSpeedX)); g_iSaucerY = min(320, max(0, g_iSaucerY + g_iSpeedY)); // Force a repaint to redraw the saucer InvalidateRect(g_pGame->GetWindow(), NULL, FALSE); } void HandleKeys() { // Change the speed of the saucer in response to arrow key presses if (GetAsyncKeyState(VK_LEFT) < 0) g_iSpeedX = max(-g_iMAXSPEED, --g_iSpeedX); else if (GetAsyncKeyState(VK_RIGHT) < 0) g_iSpeedX = min(g_iMAXSPEED, ++g_iSpeedX); if (GetAsyncKeyState(VK_UP) < 0) g_iSpeedY = max(-g_iMAXSPEED, --g_iSpeedY); else if (GetAsyncKeyState(VK_DOWN) < 0) g_iSpeedY = min(g_iMAXSPEED, ++g_iSpeedY); } void MouseButtonDown(int x, int y, BOOL bLeft) { if (bLeft) { //鼠标左键事件 // Set the saucer position to the mouse position g_iSaucerX = x - (g_pSaucer[0]->GetWidth() / 2); g_iSaucerY = y - (g_pSaucer[0]->GetHeight() / 2); } else { // Stop the saucer g_iSpeedX = 0; g_iSpeedY = 0; } } void MouseButtonUp(int x, int y, BOOL bLeft) { } void MouseMove(int x, int y) { } void HandleJoystick(JOYSTATE jsJoystickState) { // Check horizontal movement if (jsJoystickState & JOY_LEFT) g_iSpeedX = max(-g_iMAXSPEED, g_iSpeedX - 2); else if (jsJoystickState & JOY_RIGHT) g_iSpeedX = min(g_iMAXSPEED, g_iSpeedX + 2); // Check vertical movement if (jsJoystickState & JOY_UP) g_iSpeedY = max(-g_iMAXSPEED, g_iSpeedY - 2); else if (jsJoystickState & JOY_DOWN) g_iSpeedY = min(g_iMAXSPEED, g_iSpeedY + 2); // Check primary joystick button g_bSaucerFlame = (jsJoystickState & JOY_FIRE1); if(g_bSaucerFlame) { g_iSpeedY = max(-g_iMAXSPEED, g_iSpeedY - 5); } // Check secondary joystick button if (jsJoystickState & JOY_FIRE2) { // Force the flying saucer into hyperspace g_iSaucerX = rand() % (500 - g_pSaucer[0]->GetWidth()); g_iSaucerY = rand() % 320; } }
//----------------------------------------------------------------- // UFO 2 Resource Identifiers // C++ Header - Resource.h //----------------------------------------------------------------- //----------------------------------------------------------------- // Icons Range : 1000 - 1999 //----------------------------------------------------------------- #define IDI_UFO 1000 #define IDI_UFO_SM 1001 //----------------------------------------------------------------- // Bitmaps Range : 2000 - 2999 //----------------------------------------------------------------- #define IDB_BACKGROUND 2000 #define IDB_SAUCER 2001 #define IDB_SAUCERFLAME 2002
//----------------------------------------------------------------- // UFO 2 Resources // RC Source - UFO.rc //----------------------------------------------------------------- //----------------------------------------------------------------- // Include Files //----------------------------------------------------------------- #include "Resource.h" //----------------------------------------------------------------- // Icons //----------------------------------------------------------------- IDI_UFO ICON "Res//UFO.ico" IDI_UFO_SM ICON "Res//UFO_sm.ico" //----------------------------------------------------------------- // Bitmaps //----------------------------------------------------------------- IDB_BACKGROUND BITMAP "Res//Background.bmp" IDB_SAUCER BITMAP "Res//Saucer.bmp" IDB_SAUCERFLAME BITMAP "Res//SaucerFlame.bmp"
游戏截图:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。