Win32游戏制作之---Bizzard

之前写了一片关于游戏引擎设计的文章,今天就用游戏引擎来实现一个小游戏(其实不算是严格意义上的游戏),主要就是为了感受游戏引擎给游戏设计带来的便利,而并不是游戏本身,使用游戏引擎之后你会发现,游戏设计会简便很多。它给你提供一个框架,而你所需要做的就是往里面填内容。

多得不说了,下面来看游戏引擎在游戏之中具体的使用。

先来想一想怎么在原来的游戏引擎上面填写内容,你需要在原来的基础上再新建一个游戏头文件以及游戏实现文件,关于游戏引擎上一篇内容已经讲过了,那么这一次只需要往里面填内容即可。

先来看看头文件Bizzard.h:

//Blizzard应用程序
//C++头文件-Blizzard.h
#pragma once

//--------------------------------------
//包含文件
//--------------------------------------
#include <Windows.h>
#include <time.h>
#include <tchar.h>
#include "resource.h"
#include "GameEngine.h"

//--------------------------------------
//全局变量
//--------------------------------------
GameEngine * g_pGame = NULL;                    //每一个基于游戏引擎的游戏都需要一个全局游戏引擎指针

这个头文件中的指针为Blizzard对游戏引擎的访问,因此非常重要。

资源文件没什么可说的,它定义了在程序之中使用的所有的资源标识符,在这个例子之中比肩简单,只是定义了两个图标以及标题和名字,当然你还可以添加其他资源,这里就不再多说。

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 GameEngine.rc 使用
//
#define IDS_APP_TITLE                   101
#define IDC_BIZZARD                     102
#define IDI_BLIZZARD                    1000
#define IDI_BLIZZARD_SM                 1001

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        103
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

最后来看一下重点的内容,就是游戏主体的实现:

//--------------------------------------
//Blizzard应用程序
//C++源程序 - - Blizzard.cpp
//--------------------------------------

//--------------------------------------
//包含文件
//--------------------------------------
#include "Blizzard.h"

//--------------------------------------
//游戏引擎函数
//--------------------------------------
BOOL GameInitialize(HINSTANCE hInstance)
{
	//创建游戏引擎
	g_pGame = new GameEngine(hInstance, TEXT("Blizzard"), TEXT("Blizzard"), IDI_BLIZZARD, IDI_BLIZZARD_SM);
	if (NULL == g_pGame)
	{
		return FALSE;
	}
	//设置帧频
	g_pGame->SetFrameRate(10000);         //15帧每秒,这里没必要使用默认的(20帧每秒)
	return TRUE;
}

void GameStart(HWND hWindow)
{
	//生成随机生成器种子
	srand((unsigned int)GetTickCount());        //如果游戏需要调用标准的rand()函数来生成随机数字,那么总是应该调用Srand()函数来指定随机数字生成器种子
}

void GameEnd()
{
	//清理游戏
	delete g_pGame;
}

void GameActivate(HWND hWindow)
{
	HDC hdc;
	RECT rect;
	//在游戏屏幕上绘制文本
	GetClientRect(hWindow, &rect);
	hdc = GetDC(hWindow);
	DrawText(hdc, TEXT("Here comes the blizzard!"), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
	ReleaseDC(hWindow, hdc);
}
void GameDeactivate(HWND hWindow)
{
	HDC hdc;
	RECT rect;
	//在屏幕上绘制停用文本
	GetClientRect(hWindow, &rect);
	hdc = GetDC(hWindow);
	DrawText(hdc, TEXT("The blizzard has passed."), -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
	ReleaseDC(hWindow, hdc);
}
void GamePaint(HDC hdc)
{
	//在这个例子中没有必要调用这个重绘函数,因为所有的绘制工作都在GameCycle()函数之中就完成了,不过这种情况较为少见
}
void GameCycle()
{
	HDC hdc;
	HWND hWindow = g_pGame->GetWindow();

	//在游戏屏幕上随机随机位置绘制雪花图标
	hdc = GetDC(hWindow);
	DrawIcon(hdc, rand() % (g_pGame->GetWidth()), rand() % (g_pGame->GetHeight()), (HICON)(WORD)GetClassLong(hWindow, GCL_HICON));
	ReleaseDC(hWindow, hdc);
}

这里附上游戏引擎代码:

#pragma once

//所要包含的文件
#include <windows.h>

#define MAX_LOADSTRING 32

//windows函数声明
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

//
//游戏引擎函数的声明
//这些函数的特定实现是游戏特有的,必须由使用该游戏引擎的各个游戏提供
BOOL GameInitialize(HINSTANCE hInstance);
void GameStart(HWND hWindow);
void GameEnd();
void GameActivate(HWND hWindow);
void GameDeactivate(HWND hWindow);
void GamePaint(HDC hdc);
void GameCycle();

//
//GameEngine
//
class GameEngine
{
protected:
	//成员变量
	static GameEngine * m_pGameEngine;
	HINSTANCE m_hInstance;
	HWND m_hWindow;
	TCHAR m_szWindowClass[MAX_LOADSTRING];
	TCHAR m_szTitle[MAX_LOADSTRING];
	WORD m_wIcon, m_wSmallIcon;
	int m_iWidth, m_iHeight;
	int m_iFrameDelay;
	BOOL m_bSleep;

public:
	//构造函数/析构函数
	GameEngine(HINSTANCE hInstance, LPTSTR szWindowClass, LPTSTR szTitle, WORD wIcon, WORD wSmallIcon, int iWidth = 640, int iHeight = 480);
	virtual ~GameEngine();

	//常规方法
	static GameEngine * GetEngine(){ return m_pGameEngine; };
	BOOL Initialize(int nCmdShow);
	LRESULT HandleEvent(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);

	//访问方法
	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; };
};

游戏引擎源文件:

#include "GameEngine.h"

GameEngine * GameEngine::m_pGameEngine = NULL;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	MSG msg;
	static int iTickTrigger = 0;
	int iTickCount;
	if (GameInitialize(hInstance))
	{
		//初始化游戏引擎
		if (!GameEngine::GetEngine()->Initialize(nCmdShow))
		{
			return FALSE;
		}
		//进入主消息循环
		while (TRUE)
		{
			if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
			{
				//处理消息
				if (WM_QUIT == msg.message)
				{
					break;
				}
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
			else
			{
			if (!GameEngine::GetEngine()->GetSleep())
			{
				//检查滴答计数,看看是否过了一个周期
				iTickCount = GetTickCount();
				if (iTickCount - iTickTrigger)
				{
					iTickTrigger = iTickCount + GameEngine::GetEngine()->GetFrameDelay();
					GameCycle();
				}
			}
			}
		}
		return (int)msg.wParam;
	}
	GameEnd();
	return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam)
{
	//将所有的Windows消息都传递给游戏引擎
	return GameEngine::GetEngine()->HandleEvent(hWindow, msg, wParam, lParam);
}

//
//GameEngine的构造函数/析构函数
//
GameEngine::GameEngine(HINSTANCE hInstance, LPTSTR szWindowClass, LPTSTR szTitle, WORD wIcon, WORD wSmallIcon, int iWidth, int iHeight)
{
	//设置游戏引擎的成员变量
	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_iHeight = iHeight;
	m_iWidth = iWidth;
	m_iFrameDelay = 20;        //默认为20帧每秒
	m_bSleep = TRUE;
}
//析构函数
GameEngine::~GameEngine()
{}

int GameEngine::Initialize(int nCmdShow)
{
	//注册窗口类
	WNDCLASSEX wndclass;
	wndclass.cbSize = sizeof(WNDCLASSEX);
	wndclass.style = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc = (WNDPROC)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)GetStockObject(BLACK_BRUSH);
	wndclass.lpszMenuName = NULL;
	wndclass.lpszClassName = m_szWindowClass;

	if (!RegisterClassEx(&wndclass))
	{
		MessageBox(m_hWindow, L"注册窗口失败!", L"警告", MB_OK);
		return FALSE;
	}
	//根据游戏的大小计算窗口大小和位置
	int iWindowWidth = m_iWidth + GetSystemMetrics(SM_CXFIXEDFRAME) * 2;
	int 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;
	int iYWindowPos = (GetSystemMetrics(SM_CYSCREEN) - iWindowHeight) / 2;

	//创建窗口
	m_hWindow = CreateWindowEx(NULL, m_szWindowClass, m_szTitle, WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX, iXWindowPos, iYWindowPos, iWindowWidth, iWindowHeight, NULL, NULL, m_hInstance, NULL);
	if (!m_hWindow)
	{
		MessageBox(m_hWindow, L"创建窗口失败!", L"警告", MB_OK);
		return FALSE;
	}
	//更新和显示窗口
	ShowWindow(m_hWindow,nCmdShow);
	UpdateWindow(m_hWindow);
	return TRUE;
}

LRESULT GameEngine::HandleEvent(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam)
{
	//将Windows消息传递给游戏引擎的成员函数
	switch (msg)
	{
	case WM_CREATE:
		//设置游戏窗口并开始游戏
		SetWindow(hWindow);
		GameStart(hWindow);
		break;
	case WM_SETFOCUS:
		//激活游戏并更新休眠状态
		GameActivate(hWindow);
		SetSleep(FALSE);
		break;
	case WM_KILLFOCUS:
		GameDeactivate(hWindow);
		SetSleep(TRUE);
		break;
	case WM_PAINT:
		PAINTSTRUCT ps;
		HDC hdc;
		hdc = BeginPaint(hWindow, &ps);
		//绘制游戏
		GamePaint(hdc);

		EndPaint(hWindow, &ps);
		break;
	case WM_DESTROY:
		//结束游戏并退出应用程序
		GameEnd();
		PostQuitMessage(0);
		break;
	default:
		break;
	}
	return DefWindowProc(hWindow, msg, wParam, lParam);
}

这样一个游戏就算制作完成了,此次博客主要倒不是游戏制作,而是游戏引擎带来的方便!

来看一下效果:

当然你可以换成更好看的图片,这样可以更好的看到雪花布满整个屏幕的感觉!

我试着换了一张图,效果如下:

如果想要将游戏做的更有乐趣,那么就可以不让它随机生成,而是有条件的生成,这样会更有乐趣!

时间: 2024-10-10 23:05:47

Win32游戏制作之---Bizzard的相关文章

Win32游戏制作之---FreakOut

记得自己小时候曾经玩过这个小游戏,如今长大了,有了一定的知识就可以实现一些小时候未曾想过的事情,或者说梦想去做的事情!虽然这次实现的小游戏比较简单,但是也算游戏吧,比较自己还不是这方面的大神. 如果想要用Win32项目制作一个小游戏,那么首先你要对对C/C++语言熟悉,对Windows编程有一定的了解.其实还有一点就是你在开始制作小游戏之前,你要知道你的游戏的逻辑结构.对于一般的小游戏结构可以用下图的结构表示. Game_main()是游戏的主体函数,不过它在主事件循环每次处理windows消息

Win32游戏制作之---SwordsMan

前言   今天是NBA总决赛的最后一场,还是抢七大战,伟大的James终于圆梦了,比赛之中突然发现詹姆斯胡子都有点白了,原来原先那些陪伴自己众多篮球明星都已经老了,Kobe也退役了,他们每个人都有梦想并且为之奋斗,詹姆斯为了自己的梦想奋斗了这么多年才圆梦,那么自己也应该努力实现自己心中的梦想,当然只是想实现自己心中的一个小小的梦想而已,不是每个人都可以说出为自己家乡带来总冠军那样的豪言壮语. ---这句话送给伟大的詹姆斯,也送给我自己,更送给所有在梦想道路上前进的人 前段时间由于忙着准备学校的考

Win32游戏制作之---五子棋的设计(一)

想必每个人都玩过五子棋,其实对于我而言,五子棋是小时候玩的最多的棋类游戏,当然小时候也爱玩象棋以及国际象棋之类的,不过由于五子棋比较简单,所以就先实现一个简单的人机五子棋.最近我就在想如今学会了一点编程之后是不是应该把以前小时候特备爱玩的游戏实现一下,毕竟那是一种珍贵的回忆! 好了其他的不多说了,进入到我们的正题,首先呢,我准备分两次实现这个五子棋的内容,因为在制作好之后,个人感觉自己对于AI落子的算法的实现写得不够好,也思考了好久,感觉还是没有达到预期的效果,虽说最近放假了,但是学校又有事情,

简易2D横版RPG游戏制作

Unity学习笔记1 简易2D横版RPG游戏制作 http://m.blog.csdn.net/article/details?id=24601905

游戏制作流程【转】

作为创意产业最具发展潜力的行业——游戏行业,它的发展俨然超过所有人的预想.国家政策大力扶持,游戏市场发展势头迅猛,网游收入规模超越传统三大娱乐产业:电影票房.电视娱乐节目和音像制品. 与此同时,国内网游制作水准也在不断提升,<完美世界>.<梦幻西游>等众多高水平网游逐渐夺回被国外网游占据的市场份额.国产网游的逐步成熟,中国网 游市场的前景一片大好,让很多喜欢游戏的人都想进入游戏行业,但对大多数人来说这一领域还是陌生.空白的.这些高水准的网游是如何制作出来的?怎么才能成 为一名优秀的

程序设计C语言二级考试教程 Java基础视频教程 安卓软件开发教程 Unity3D游戏制作入门教程

热门推荐电脑办公计算机基础知识教程 Excel2010基础教程 Word2010基础教程 PPT2010基础教程 五笔打字视频教程 Excel函数应用教程 Excel VBA基础教程 WPS2013表格教程 更多>平面设计PhotoshopCS5教程 CorelDRAW X5视频教程 Photoshop商业修图教程 Illustrator CS6视频教程 更多>室内设计3Dsmax2012教程 效果图实例提高教程 室内设计实战教程 欧式效果图制作实例教程 AutoCAD2014室内设计 Aut

关于游戏制作的相关细节

网络是一个发展非常快的地方,其中很多东西的更新换代都是非常快的,之前流行的还是一个游戏,可能过一段时间以后,新的游戏出现了,大家的选择自然就不一样了.这一点对棋牌游戏制作来说是非常重要的,在这个过程中,效率是很重要的,先开发出来的平台就是很占优势的,而大雄游戏的成功就是因为它的棋牌游戏制作效率是极高的,玩家很喜欢. 不过大雄游戏认为在这个过程中只重视快是不行的,对于棋牌游戏制作来说,游戏的每一个细节都是要处理好的,这样才会得到大家的认可.很多平台认为一个游戏即使有一些小瑕疵也是没有问题的.而事实

张左峰的分享 网页游戏制作技术 加密的设计思路与手段

网页游戏制作技术 加密的设计思路与手段 必备工具:Doswf 好朋友Laan开发,请自行百度搜索 今天太晚了,明天再更新内容...咔咔咔

游戏制作大致流程粗谈之五

这一次的文章来介绍一下游戏制作非常重要的工具之一游戏引擎 游戏引擎是指一些已编写好的可编辑电脑游戏系统或者一些交互式实时图像应用程序的核心组件.这些系统为游戏设计者提供各种编写游戏所需的各种工具,其目的在于让游戏设计者能容易和快速地做出游戏程式而不用由零开始.大部分都支持多种操作平台,如Linux.Mac OS X.微软Windows.游戏引擎包含以下系统:渲染引擎(即"渲染器",含二维图像引擎和三维图像引擎).物理引擎.碰撞检测系统.音效.脚本引擎.电脑动画.人工智能.网络引擎以及场