2D游戏引擎(四)—— 向引擎添加游戏杆支持

 暑假刚买了个北通的游戏杆,想不到那么快便派上了编程的用场,呵呵~~

让游戏引擎支持游戏杆输入,无疑对于游戏发烧友来说是很重要的,修改后的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"

游戏截图:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C 2D 游戏引擎是一种用于开发二维游戏的软件工具,它提供了一系列的功能和工具,以帮助游戏开发者创建、设计和实现2D游戏。这种引擎通常包括图形渲染、物理模拟、音频管理、碰撞检测等核心功能,以及提供脚本语言、动画编辑器、场景编辑器等辅助工具。 C 2D 游戏引擎具有很多优点。首先,它提供了开发者所需的基础功能,轻松实现游戏中的动画效果、粒子效果、地图编辑、角色控制等。其次,C 2D 游戏引擎通常使用简单易懂的API,使得开发者可以更加便捷地进行编程工作,从而加快开发进度。此外,这种引擎通常具有较高的兼容性和跨平台性,可以在不同的操作系统和设备上运行。 当然,C 2D 游戏引擎也有一些限制。首先,由于是2D游戏引擎,它的功能相对较为有限。相较于3D游戏引擎,C 2D 游戏引擎无法实现逼真的三维场景和效果。其次,由于C语言本身的限制,C 2D 游戏引擎在可视化设计方面可能略显欠缺,开发者需要用代码实现许多细节。此外,C 2D 游戏引擎对开发者的编程能力要求相对较高,需要具备良好的基础知识和经验。 总的来说,C 2D 游戏引擎是一种用于开发二维游戏的强大工具,提供了丰富的功能和工具,帮助开发者实现各种2D游戏效果。虽然它的功能和可视化设计相对有限,但在跨平台兼容性和编程效率方面具有一定优势。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值