【VC++游戏开发】用C++来架构一个适合windows游戏编程的框架——取名为BCF

一、序言

众所周知:

MFC适合桌面应用的开发,而不太适合windows游戏编程,因为它封装了很多我们游戏编程中所不需要的东西,这些东西在一定程度上都影响着GDI的效率,略显冗余了。但是MFC有丰富的类库,这在写代码时又能提供很大的方便……


再来看看Win32 SDK,接近底层,效率肯定好,但是却没有MFC那样的类库,写代码着实不太方便……


这样一想,我就有个问题了:在接下来的游戏效果模拟中,是继续使用MFC,还是专用Win32SDK呢?或者还有什么更好的方法?……

这么一想,嘿,一个idea就诞生了:用C++来自行架构一个适合windows游戏编程的框架,使它既能使用MFC类库效率又更好

这个框架如何架构呢?请继续阅读下面的内容吧^_^


二、架构的一个简易框架,MFC类库、效率都能兼顾

我的架构思路:

       1>将窗口创建过程(设计窗口类结构体实例、注册窗口类、创建窗口、显示窗口、消息循环)以及消息响应函数都封装在一个名为CCWindow的C++类中

       2>在Main.cpp源文件中就实现WinMain以及窗口过程


由于我的开源框架的源代码中有详尽的注释,F话就不多说了,直接贴上源代码:

StdAfx.h头文件:这是使用MFC类库所必须添加的头文件

[cpp] view plaincopyprint? 在CODE上查看代码片 派生到我的代码片
  1. /***
  2. *
  3. *   StdAfx.h
  4. *   包含一些用到的类库所在的头文件
  5. *
  6. ***/ 
  7.  
  8. #pragma once 
  9.  
  10. #define _AFXDLL//动态添加MFC类库 
  11. #include <SDKDDKVer.h>//定义最高版本windows 
  12.  
  13. #include <afxwin.h>       // MFC封装的核心组件和标准组件 
  14. #include <atlimage.h> //CImage类包含的头文件 
  15. #include <MMSystem.h> //播放媒体(音乐)所需包含的头文件 
  16. #pragma comment(lib, "winmm.lib")//添加媒体库 
  17.  
  18. #pragma comment(linker,"/manifestdependency:\"type='win32' \ 
  19.                 name='Microsoft.Windows.Common-Controls'
  20.                 version='6.0.0.0' processorArchitecture='x86'
  21.                 publicKeyToken='6595b64144ccf1df' language='*'\""
/***
*
*	StdAfx.h
*	包含一些用到的类库所在的头文件
*
***/

#pragma once

#define _AFXDLL//动态添加MFC类库
#include <SDKDDKVer.h>//定义最高版本windows

#include <afxwin.h>		// MFC封装的核心组件和标准组件
#include <atlimage.h>	//CImage类包含的头文件
#include <MMSystem.h>	//播放媒体(音乐)所需包含的头文件
#pragma comment(lib, "winmm.lib")//添加媒体库

#pragma comment(linker,"/manifestdependency:\"type='win32' \
				name='Microsoft.Windows.Common-Controls' \
				version='6.0.0.0' processorArchitecture='x86' \
				publicKeyToken='6595b64144ccf1df' language='*'\"")

CWindow.h头文件(CCWindow类的定义)

[cpp] view plaincopyprint? 在CODE上查看代码片 派生到我的代码片
  1. #pragma once 
  2. #include"StdAfx.h" 
  3. #include<time.h> 
  4.  
  5. class CCWindow 
  6. //==================成员==================== 
  7. private
  8.     WNDCLASS    m_wndclass; //窗口类结构体实例 
  9. public
  10.     HWND        m_hwnd;     //窗口句柄 
  11.     CImage      m_img;      //背景图片 
  12.     CRect       m_rect;     //窗口户区大小 
  13.  
  14. //=============窗口创建相关的成员函数============= 
  15. public
  16.     //设计窗口类 
  17.     bool InitWndClass( 
  18.                     HINSTANCE hInstance,    //实例句柄 
  19.                     WNDPROC   wpWndProc,    //窗口过程 
  20.                     LPCTSTR   lpWndName,    //窗口名称 
  21.                     LPCTSTR   lpIconPath);  //图标路径 
  22.  
  23.     //设计窗口类 
  24.     bool InitWndClass(WNDCLASS); 
  25.      
  26.     //注册窗口类 
  27.     ATOM RegisterWndClass(); 
  28.  
  29.     //创建窗口(默认居中) 
  30.     void Create( 
  31.             LPCTSTR lpClassName,    //窗口类名称 
  32.             LPCTSTR lpWndName,  //窗口标题名称 
  33.             DWORD   dwStyle,        //窗口风格 
  34.             int     nWidth,         //窗口宽度 
  35.             int     nHeight);       //窗口高度 
  36.  
  37.     //显示窗口 
  38.     void Show(int); 
  39.  
  40.     //一般的消息循环 
  41.     int RunMsgLoop(); 
  42.  
  43.     //更高效的消息循环 
  44.     int RunMsgLoop(void (*Display)(), int); 
  45.  
  46. //================消息响应函数================ 
  47. public
  48.     //注:在这里添加需要响应的消息处理函数的声明 
  49.  
  50. public
  51.     //构造函数 
  52.     CCWindow(void); 
  53.     //析构函数 
  54.     ~CCWindow(void); 
  55. }; 
#pragma once
#include"StdAfx.h"
#include<time.h>

class CCWindow
{
//==================成员====================
private:
	WNDCLASS	m_wndclass; //窗口类结构体实例
public:
	HWND		m_hwnd;		//窗口句柄
	CImage		m_img;		//背景图片
	CRect		m_rect;		//窗口户区大小

//=============窗口创建相关的成员函数=============
public:
	//设计窗口类
	bool InitWndClass(
					HINSTANCE hInstance,	//实例句柄
					WNDPROC	  wpWndProc,	//窗口过程
					LPCTSTR	  lpWndName,	//窗口名称
					LPCTSTR   lpIconPath);	//图标路径

	//设计窗口类
	bool InitWndClass(WNDCLASS);
	
	//注册窗口类
	ATOM RegisterWndClass();

	//创建窗口(默认居中)
	void Create(
			LPCTSTR lpClassName,	//窗口类名称
			LPCTSTR lpWndName,	//窗口标题名称
			DWORD	dwStyle,		//窗口风格
			int		nWidth,			//窗口宽度
			int     nHeight);		//窗口高度

	//显示窗口
	void Show(int);

	//一般的消息循环
	int RunMsgLoop();

	//更高效的消息循环
	int RunMsgLoop(void (*Display)(), int);

//================消息响应函数================
public:
	//注:在这里添加需要响应的消息处理函数的声明

public:
	//构造函数
	CCWindow(void);
	//析构函数
	~CCWindow(void);
};

CWindow.cpp(CCWindow类的成员函数实现)

[cpp] view plaincopyprint? 在CODE上查看代码片 派生到我的代码片
  1. #include "CWindow.h" 
  2.  
  3.  
  4. CCWindow::CCWindow(void
  5.  
  6. CCWindow::~CCWindow(void
  7.  
  8. /*------------------------------
  9.     *功能:设计窗口类
  10.     *@hInstance:    实例句柄
  11.     *@WndProc:      窗口过程
  12.     *@WndName:      窗口名称
  13.     *@IconPath:     图标路径
  14. -----------------------------*/ 
  15. bool CCWindow::InitWndClass(HINSTANCE hInstance,//实例句柄 
  16.                             WNDPROC WndProc,    //窗口过程 
  17.                             LPCTSTR WndName,    //窗口名称 
  18.                             LPCTSTR IconPath)   //图标路径 
  19.     ZeroMemory(&m_wndclass, sizeof(WNDCLASS)); 
  20.  
  21.     m_wndclass.style            = CS_HREDRAW | CS_VREDRAW; 
  22.     m_wndclass.lpfnWndProc      = WndProc; 
  23.     m_wndclass.hInstance        = hInstance; 
  24.     m_wndclass.cbClsExtra       = 0; 
  25.     m_wndclass.cbWndExtra       = 0; 
  26.     m_wndclass.hIcon            =  
  27.         static_cast<HICON>(LoadImage(NULL, IconPath, IMAGE_ICON, 
  28.                         0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE)); 
  29.     m_wndclass.hCursor          = ::LoadCursor(NULL, IDC_ARROW); 
  30.     m_wndclass.hbrBackground    =  
  31.         static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); 
  32.     m_wndclass.lpszMenuName     = NULL; 
  33.     m_wndclass.lpszClassName    = WndName; 
  34.  
  35.     return true
  36.  
  37. /*--------------------------------------
  38.                 设计窗口类
  39. --------------------------------------*/ 
  40. bool CCWindow::InitWndClass(WNDCLASS wndclass) 
  41.     m_wndclass = wndclass; 
  42.  
  43.     return true
  44.  
  45. /*--------------------------------------
  46.                注册窗口类
  47. --------------------------------------*/ 
  48. ATOM CCWindow::RegisterWndClass() 
  49.     return RegisterClass(&m_wndclass); 
  50.  
  51. /*--------------------------------------
  52.                 创建窗口
  53. --------------------------------------*/ 
  54. void CCWindow::Create( 
  55.         LPCTSTR lpClassName, 
  56.         LPCTSTR lpWindowName, 
  57.         DWORD dwStyle, 
  58.         int nWidth, 
  59.         int nHeight) 
  60.     //获取屏幕宽度和高度 
  61.     int screenW = GetSystemMetrics(SM_CXSCREEN); 
  62.     int screenH = GetSystemMetrics(SM_CYSCREEN); 
  63.  
  64.     //创建并居中显示窗口 
  65.     m_hwnd = CreateWindow(lpClassName, lpWindowName, dwStyle, 
  66.                  (screenW-nWidth)/2, (screenH-nHeight)/2, 
  67.                  nWidth, nHeight, NULL, NULL, 
  68.                  m_wndclass.hInstance, NULL); 
  69.  
  70. /*--------------------------------------
  71.                 显示窗口
  72. --------------------------------------*/ 
  73. void CCWindow::Show(int nCmdShow) 
  74.     ShowWindow(m_hwnd, nCmdShow); 
  75.  
  76. //UpdateWindow(...)更新窗口(可以省略) 
  77.  
  78. /*--------------------------------------
  79.             一般的消息循环
  80.              GetMessage()
  81. --------------------------------------*/ 
  82. int CCWindow::RunMsgLoop() 
  83.     MSG msg; 
  84.     ZeroMemory(&msg, sizeof(MSG)); 
  85.  
  86.     while(GetMessage(&msg, NULL, 0, 0)) 
  87.     { 
  88.         TranslateMessage(&msg); 
  89.         DispatchMessage(&msg); 
  90.     } 
  91.  
  92.     return msg.wParam; 
  93.  
  94. /*--------------------------------------
  95.         消息循环(更好的消息循环)
  96.             PeekMessage()
  97. --------------------------------------*/ 
  98. int CCWindow::RunMsgLoop(void (*Display)(), int interval) 
  99.     MSG msg; 
  100.     ZeroMemory(&msg, sizeof(MSG)); 
  101.  
  102.     //获取运行到此处时的时间 
  103.     int last = GetTickCount(); 
  104.  
  105.     //如果不是退出消息 
  106.     while(msg.message != WM_QUIT) 
  107.     { 
  108.         //如果有消息 
  109.         if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) 
  110.         { 
  111.             TranslateMessage(&msg); 
  112.             DispatchMessage(&msg); 
  113.         } 
  114.         //否则, 空闲的时候执行响应函数(大多数是绘制函数) 
  115.         else 
  116.         { 
  117.             //如果窗口客户区大小不为0就是显示(有可能窗口是在最小化) 
  118.             if(m_rect.Width() &&  
  119.                m_rect.Height()) 
  120.             { 
  121.                 Display(); 
  122.                 Sleep(interval); 
  123.             } 
  124.         } 
  125.     } 
  126.  
  127.     return msg.wParam; 
  128.  
  129. //---------------------------------------------------------- 
  130. //                      消息响应函数 
  131. //---------------------------------------------------------- 
  132. //注:在这里添加需要响应的消息处理函数的实现 
#include "CWindow.h"


CCWindow::CCWindow(void)
{
}

CCWindow::~CCWindow(void)
{
}

/*------------------------------
	*功能:设计窗口类
	*@hInstance:	实例句柄
	*@WndProc:		窗口过程
	*@WndName:		窗口名称
	*@IconPath:		图标路径
 -----------------------------*/
bool CCWindow::InitWndClass(HINSTANCE hInstance,//实例句柄
							WNDPROC WndProc,	//窗口过程
							LPCTSTR WndName,	//窗口名称
							LPCTSTR IconPath)	//图标路径
{
	ZeroMemory(&m_wndclass, sizeof(WNDCLASS));

	m_wndclass.style			= CS_HREDRAW | CS_VREDRAW;
	m_wndclass.lpfnWndProc		= WndProc;
	m_wndclass.hInstance		= hInstance;
	m_wndclass.cbClsExtra		= 0;
	m_wndclass.cbWndExtra		= 0;
	m_wndclass.hIcon			= 
		static_cast<HICON>(LoadImage(NULL, IconPath, IMAGE_ICON,
						0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE));
	m_wndclass.hCursor			= ::LoadCursor(NULL, IDC_ARROW);
	m_wndclass.hbrBackground	= 
		static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
	m_wndclass.lpszMenuName		= NULL;
	m_wndclass.lpszClassName	= WndName;

	return true;
}

/*--------------------------------------
				设计窗口类
--------------------------------------*/
bool CCWindow::InitWndClass(WNDCLASS wndclass)
{
	m_wndclass = wndclass;

	return true;
}

/*--------------------------------------
			   注册窗口类
--------------------------------------*/
ATOM CCWindow::RegisterWndClass()
{
	return RegisterClass(&m_wndclass);
}

/*--------------------------------------
				创建窗口
--------------------------------------*/
void CCWindow::Create(
	    LPCTSTR lpClassName,
		LPCTSTR lpWindowName,
		DWORD dwStyle,
		int nWidth,
		int nHeight)
{
	//获取屏幕宽度和高度
	int screenW = GetSystemMetrics(SM_CXSCREEN);
	int screenH = GetSystemMetrics(SM_CYSCREEN);

	//创建并居中显示窗口
	m_hwnd = CreateWindow(lpClassName, lpWindowName, dwStyle,
				 (screenW-nWidth)/2, (screenH-nHeight)/2,
				 nWidth, nHeight, NULL, NULL,
				 m_wndclass.hInstance, NULL);
}

/*--------------------------------------
				显示窗口
--------------------------------------*/
void CCWindow::Show(int nCmdShow)
{
	ShowWindow(m_hwnd, nCmdShow);
}

//UpdateWindow(...)更新窗口(可以省略)

/*--------------------------------------
			一般的消息循环
			 GetMessage()
--------------------------------------*/
int CCWindow::RunMsgLoop()
{
	MSG	msg;
	ZeroMemory(&msg, sizeof(MSG));

	while(GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return msg.wParam;
}

/*--------------------------------------
		消息循环(更好的消息循环)
			PeekMessage()
--------------------------------------*/
int CCWindow::RunMsgLoop(void (*Display)(), int interval)
{
	MSG	msg;
	ZeroMemory(&msg, sizeof(MSG));

	//获取运行到此处时的时间
	int last = GetTickCount();

	//如果不是退出消息
	while(msg.message != WM_QUIT)
	{
		//如果有消息
		if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		//否则, 空闲的时候执行响应函数(大多数是绘制函数)
		else
		{
			//如果窗口客户区大小不为0就是显示(有可能窗口是在最小化)
			if(m_rect.Width() && 
			   m_rect.Height())
			{
				Display();
				Sleep(interval);
			}
		}
	}

	return msg.wParam;
}

//----------------------------------------------------------
//						消息响应函数
//----------------------------------------------------------
//注:在这里添加需要响应的消息处理函数的实现

Main.h头文件(主程序头文件)

[cpp] view plaincopyprint? 在CODE上查看代码片 派生到我的代码片
  1. /***
  2. *
  3. *   Main.h
  4. *   主程序所需包含的头文件、宏定义、声明等
  5. *
  6. ***/ 
  7.  
  8. #pragma once 
  9. #include "CWindow.h" 
  10.  
  11. #define WNDNAME "【VC++游戏开发】窗口名称"//窗口名称 
  12. #define WNDWIDTH 800//窗口宽度 
  13. #define WNDHEIGHT 600//窗口高度 
  14.  
  15. //窗口关联对象:全局对象 
  16. CCWindow wnd; 
  17.  
  18. //窗口过程 
  19. LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 
/***
*
*	Main.h
*	主程序所需包含的头文件、宏定义、声明等
*
***/

#pragma once
#include "CWindow.h"

#define WNDNAME	"【VC++游戏开发】窗口名称"//窗口名称
#define WNDWIDTH 800//窗口宽度
#define WNDHEIGHT 600//窗口高度

//窗口关联对象:全局对象
CCWindow wnd;

//窗口过程
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

Main.cpp(主程序代码:负责WinMain、WndProc)

[cpp] view plaincopyprint? 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size: 18px;">#include "Main.h" 
  2.  
  3. /*
  4.     显示函数:绘制随机位置、大小、颜色的矩形
  5.     注:由于调用很频繁,故设为内联函数
  6. */ 
  7. inline void Display() 
  8.     //做响应的操作 
  9.  
  10. // 
  11. //==============WinMain======================= 
  12. // 
  13. int WINAPI WinMain(HINSTANCE hInstance, 
  14.                    HINSTANCE hPrevInstance, 
  15.                    LPSTR lpCmdLine, 
  16.                    int nCmdShow) 
  17.     //设计窗口类 
  18.     CString iconPath = "";//图标的路径(这里没有, 需自己设定) 
  19.     wnd.InitWndClass(hInstance, WndProc, WNDNAME, iconPath); 
  20.  
  21.     //注册窗口类 
  22.     if(!wnd.RegisterWndClass()) 
  23.     { 
  24.         ::AfxMessageBox("RegisterWndClass() Failed"); 
  25.  
  26.         return 0; 
  27.     } 
  28.  
  29.     DWORD style = WS_OVERLAPPEDWINDOW & 
  30.                 ~(WS_THICKFRAME | WS_MAXIMIZEBOX); 
  31.  
  32.     //创建窗口并居中窗口 
  33.     wnd.Create(WNDNAME, WNDNAME, style, 
  34.                WNDWIDTH, WNDHEIGHT); 
  35.  
  36.     //显示窗口 
  37.     wnd.Show(nCmdShow); 
  38.  
  39.     /*进入消息循环
  40.         1. 使用更好的消息循环 如:wnd.RunMsgLoop(Display, 100)
  41.         2. 使用一般的消息循环 如:wnd.RunMsgLoop()
  42.     */ 
  43.     return wnd.RunMsgLoop(); 
  44.  
  45. // 
  46. //================窗口过程:处理消息================= 
  47. // 
  48. LRESULT CALLBACK WndProc( 
  49.                 HWND hwnd, 
  50.                 UINT msg, 
  51.                 WPARAM wParam, 
  52.                 LPARAM lParam) 
  53.     /*
  54.     在这里添加消息映射代码(switch-case语句)
  55.     如:
  56.         switch(msg)
  57.         {
  58.         case WM_CREATE:
  59.             wnd.OnCreate(); //窗口建立消息:进行一些初始化操作
  60.             return 0;
  61.         }
  62.     */ 
  63.  
  64.     return DefWindowProc(hwnd, msg, wParam, lParam); 
  65. }</span> 
#include "Main.h"

/*
	显示函数:绘制随机位置、大小、颜色的矩形
	注:由于调用很频繁,故设为内联函数
*/
inline void Display()
{
	//做响应的操作
}

//
//==============WinMain=======================
//
int WINAPI WinMain(HINSTANCE hInstance,
				   HINSTANCE hPrevInstance,
				   LPSTR lpCmdLine,
				   int nCmdShow)
{
	//设计窗口类
	CString iconPath = "";//图标的路径(这里没有, 需自己设定)
	wnd.InitWndClass(hInstance, WndProc, WNDNAME, iconPath);

	//注册窗口类
	if(!wnd.RegisterWndClass())
	{
		::AfxMessageBox("RegisterWndClass() Failed");

		return 0;
	}

	DWORD style = WS_OVERLAPPEDWINDOW &
				~(WS_THICKFRAME | WS_MAXIMIZEBOX);

	//创建窗口并居中窗口
	wnd.Create(WNDNAME, WNDNAME, style,
			   WNDWIDTH, WNDHEIGHT);

	//显示窗口
	wnd.Show(nCmdShow);

	/*进入消息循环
		1. 使用更好的消息循环 如:wnd.RunMsgLoop(Display, 100)
		2. 使用一般的消息循环 如:wnd.RunMsgLoop()
	*/
	return wnd.RunMsgLoop();
}

//
//================窗口过程:处理消息=================
//
LRESULT CALLBACK WndProc(
				HWND hwnd,
				UINT msg,
				WPARAM wParam,
				LPARAM lParam)
{
	/*
	在这里添加消息映射代码(switch-case语句)

	如:
		switch(msg)
		{
		case WM_CREATE:
			wnd.OnCreate();	//窗口建立消息:进行一些初始化操作
			return 0;
		}
	*/

	return DefWindowProc(hwnd, msg, wParam, lParam);
}


下面,我简单地介绍一下这个框架的使用方法:

1>创建一个空项目(我这里是VS2010)

2>将这3个头文件以及2个cpp源文件添加到创建好的项目中

3>在 CWindow.h中添加消息响应函数(CCWindow类的成员函数)的声明

如:(名称还是遵循MFC的命名方式)

[cpp] view plaincopyprint? 在CODE上查看代码片 派生到我的代码片
  1. //================消息响应函数================ 
  2. public
  3.     //注:在这里添加需要响应的消息处理函数的声明 
  4.     void OnCreate();; 
//================消息响应函数================
public:
	//注:在这里添加需要响应的消息处理函数的声明
	void OnCreate();;
4>CWindow.cpp中实现这些消息响应函数

5>在Main.cpp的窗口过程函数中调用响应的消息响应函数

如:

[cpp] view plaincopyprint? 在CODE上查看代码片 派生到我的代码片
  1. switch(msg) 
  2. case WM_CREATE: 
  3.     wnd.OnCreate(); //窗口建立消息:进行一些初始化操作 
  4.     return 0; 
switch(msg)
{
case WM_CREATE:
	wnd.OnCreate();	//窗口建立消息:进行一些初始化操作
	return 0;
}


我还是为这个框架取一个"艺名儿",名为:BCF

BC:我的csdn博客ID缩写——BlueCoder

F:frame——框架的意思

合起来就是BlueCoder的框架,当然,大家都可以用,只要你愿意,我也乐意^_^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值