VC++游戏开发随记之二十二.docx

上传人:b****1 文档编号:1680263 上传时间:2023-05-01 格式:DOCX 页数:16 大小:216.94KB
下载 相关 举报
VC++游戏开发随记之二十二.docx_第1页
第1页 / 共16页
VC++游戏开发随记之二十二.docx_第2页
第2页 / 共16页
VC++游戏开发随记之二十二.docx_第3页
第3页 / 共16页
VC++游戏开发随记之二十二.docx_第4页
第4页 / 共16页
VC++游戏开发随记之二十二.docx_第5页
第5页 / 共16页
VC++游戏开发随记之二十二.docx_第6页
第6页 / 共16页
VC++游戏开发随记之二十二.docx_第7页
第7页 / 共16页
VC++游戏开发随记之二十二.docx_第8页
第8页 / 共16页
VC++游戏开发随记之二十二.docx_第9页
第9页 / 共16页
VC++游戏开发随记之二十二.docx_第10页
第10页 / 共16页
VC++游戏开发随记之二十二.docx_第11页
第11页 / 共16页
VC++游戏开发随记之二十二.docx_第12页
第12页 / 共16页
VC++游戏开发随记之二十二.docx_第13页
第13页 / 共16页
VC++游戏开发随记之二十二.docx_第14页
第14页 / 共16页
VC++游戏开发随记之二十二.docx_第15页
第15页 / 共16页
VC++游戏开发随记之二十二.docx_第16页
第16页 / 共16页
亲,该文档总共16页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

VC++游戏开发随记之二十二.docx

《VC++游戏开发随记之二十二.docx》由会员分享,可在线阅读,更多相关《VC++游戏开发随记之二十二.docx(16页珍藏版)》请在冰点文库上搜索。

VC++游戏开发随记之二十二.docx

VC++游戏开发随记之二十二

 

【VisualC++】游戏开发笔记二十二游戏基础物理建模(四)粒子系统模拟

(一)

 

本节内容主要讲解了在GDI中粒子的运用,为后续DirectX中粒子系统的讲解提供一个初步的认识。

一.基础知识讲解

1.基本概念

粒子是一种微小的物体,在数学上通常用点来表示其模型。

我们可以把粒子想象成颗粒状的物体,如雪花,雨滴,沙尘,烟雾

等特殊的事物。

又比如游戏中的怪物,晶体,材料,在需要的时候,也可以通过粒子来实现。

俗话说“不积跬步,无以至千里,

不积小流,何以成江海”,单个的粒子是比较平凡的存在,但是如果将大量的粒子聚到一起,就可以实现很多神奇的效果了。

 

在C/C++中想要定义一个粒子是非常容易的。

基本功扎实的朋友们肯定马上就可以想到,“结构体“是用来定义粒子类型的绝

佳武器。

原则上用“类”也可以实现,但是在这里采用“结构体”将更加合适。

2.实现方法

如下面的这个结构体snow便是用来定义“雪花”粒子的:

[cpp] viewplaincopyprint?

1.struct snow  

2.{  

3.       int x;        //雪花的 X坐标  

4.       int y;        //雪花的 Y坐标  

5.       BOOL exist; //雪花是否存在  

6.};  

可以看出,上述结构体中有3个成员,分别是代表X坐标的x,代表Y坐标的y,与表示雪花是否存在的布尔型变量exist。

定义完粒子的结构体后,便可以实例化一个粒子数组了。

 如果我们需要一个大小为50的snowfly数组,则可用一下两种方法来进行:

<1>在结构体的尾部加上我们需要实例化的对象

[cpp] viewplaincopyprint?

1.struct snow  

2.{  

3.       int x;        //雪花的 X坐标  

4.       int y;        //雪花的 Y坐标  

5.       BOOL exist; //雪花是否存在  

6.}snowfly[50];  

 

<2>单独定义

[cpp] viewplaincopyprint?

1.snow snowfly[50];  

定义完之后,就可以在这个粒子数组的基础上,用代码进行相关功能的实现了。

以上就是粒子系统概念的一个简明扼要的讲解。

而下面我们依旧是通过一个实例来巩固本节所学。

 

 

 

二、详细注释的源代码欣赏

 

在贴出全部的源代码之前,我们先把最关键的部分提出来先剖析一下,下面是本节实例的核心代码:

 

[cpp] viewplaincopyprint?

1.//全局变量声明  

2.HINSTANCE hInst;  

3.HBITMAP bg,snow,mask;  //用于贴图的三个HBITMAP变量  

4.HDC hdc,mdc,bufdc;  

5.HWND    hWnd;  

6.RECT    rect;  

7.int i,count; //定义count用于计数  

8.  

9.//****自定义绘图函数*********************************  

10.// 1.窗口贴图  

11.// 2.实现雪花纷飞的效果  

12.void MyPaint(HDC hdc)  

13.{  

14.  

15.//创建粒子  

16.    if(count<50)  //当粒子数小于50时,产生新的粒子,设定每个粒子的属性值  

17.    {  

18.        drop[count].x = rand()%rect.right; //将粒子的X坐标设为窗口中水平方向上的任意位置  

19.        drop[count].y = 0;    //将每个粒子的Y坐标都设为"0",即从窗口上沿往下落  

20.        drop[count].exist = true; //设定粒子存在  

21.        count++;   //每产生一个粒子后进行累加计数  

22.    }  

23.  

24.  

25.//贴上背景图到mdc中  

26.    SelectObject(bufdc,bg);  

27.    BitBlt(mdc,0,0,640,480,bufdc,0,0,SRCCOPY);  

28.  

29.//首先判断粒子是否存在,若存在,进行透明贴图操作  

30.    for(i=0;i<50;i++)  

31.    {  

32.          

33.        Sleep

(1);  

34.        if(drop[i].exist)  

35.        {  

36.            SelectObject(bufdc,mask);  

37.            BitBlt(mdc,drop[i].x,drop[i].y,20,20,bufdc,0,0,SRCAND);  

38.  

39.            SelectObject(bufdc,snow);  

40.            BitBlt(mdc,drop[i].x,drop[i].y,20,20,bufdc,0,0,SRCPAINT);  

41.            if(rand()%2==0)  

42.                drop[i].x+=5;  

43.            else   

44.                drop[i].x-=5;  

45.            drop[i].y+=10;  

46.            if(drop[i].y > rect.bottom)  

47.            {  

48.                drop[i].x = rand()%rect.right;  

49.                drop[i].y = 0;  

50.            }  

51.        }  

52.      

53.    }  

54.      

55.  

56.//将mdc中的全部内容贴到hdc中  

57.    BitBlt(hdc,0,0,640,480,mdc,0,0,SRCCOPY);  

58.  

59.}  

MyPaint函数的书写思路是,先初始化每个粒子,这里是共50个粒子。

然后贴上背景图到mdc中,再用循环将各个粒子也贴

到mdc中,循环完成之后,再统一将mdc中的内容直接贴到hdc中。

这样做的优点是比较直观,提高了贴图的效率。

 

 

 

下面就贴出全部详细注释的源代码,供大家学习,需要在自己机器上运行并学习提高的朋友,请点击文章末尾处贴出的地址进

行下载。

源代码依旧是分为VC6.0和VS2010两个版本。

这里贴出的是VC6.0版的:

[cpp] viewplaincopyprint?

1.#include "stdafx.h"  

2.#include   

3.  

4.//全局变量声明  

5.HINSTANCE hInst;  

6.HBITMAP bg,snow,mask;  //用于贴图的三个HBITMAP变量  

7.HDC hdc,mdc,bufdc;  

8.HWND    hWnd;  

9.RECT    rect;  

10.int i,count; //定义count用于计数  

11.  

12.  

13.  

14.  

15.struct snow  

16.{  

17.    int x;  

18.    int y;  

19.    BOOL exist;  

20.}drop[50];  

21.  

22.  

23.//全局函数声明  

24.ATOM                MyRegisterClass(HINSTANCE hInstance);  

25.BOOL                InitInstance(HINSTANCE, int);  

26.LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);  

27.void                MyPaint(HDC hdc);  

28.  

29.//****WinMain函数,程序入口点函数**************************************   

30.int APIENTRY WinMain(HINSTANCE hInstance,  

31.                     HINSTANCE hPrevInstance,  

32.                     LPSTR     lpCmdLine,  

33.                     int       nCmdShow)  

34.{  

35.    MSG msg;  

36.  

37.    MyRegisterClass(hInstance);  

38.  

39.    //初始化  

40.    if (!

InitInstance (hInstance, nCmdShow))   

41.    {  

42.        return FALSE;  

43.    }  

44.  

45.           

46.    //消息循环    

47.    while (GetMessage(&msg, NULL, 0, 0))     

48.    {    

49.        TranslateMessage(&msg);    

50.        DispatchMessage(&msg);    

51.    }    

52.  

53.    return msg.wParam;  

54.}  

55.  

56.//****设计一个窗口类,类似填空题,使用窗口结构体*********************   

57.ATOM MyRegisterClass(HINSTANCE hInstance)  

58.{  

59.    WNDCLASSEX wcex;  

60.  

61.    wcex.cbSize = sizeof(WNDCLASSEX);   

62.    wcex.style          = CS_HREDRAW | CS_VREDRAW;  

63.    wcex.lpfnWndProc    = (WNDPROC)WndProc;  

64.    wcex.cbClsExtra     = 0;  

65.    wcex.cbWndExtra     = 0;  

66.    wcex.hInstance      = hInstance;  

67.    wcex.hIcon          = NULL;  

68.    wcex.hCursor        = NULL;  

69.    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);  

70.    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);  

71.    wcex.lpszMenuName   = NULL;  

72.    wcex.lpszClassName  = "maple";  

73.    wcex.hIconSm        = NULL;  

74.  

75.    return RegisterClassEx(&wcex);  

76.}  

77.  

78.//****初始化函数*************************************    

79.// 1.加载位图资源  

80.// 2.取得内部窗口区域信息    

81.BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)  

82.{  

83.    HBITMAP bmp;  

84.    hInst = hInstance;  

85.  

86.    hWnd = CreateWindow("maple", "浅墨的绘图窗口" , WS_OVERLAPPEDWINDOW,  

87.        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);  

88.  

89.    if (!

hWnd)  

90.    {  

91.        return FALSE;  

92.    }  

93.  

94.    MoveWindow(hWnd,10,10,600,450,true);  

95.    ShowWindow(hWnd, nCmdShow);  

96.    UpdateWindow(hWnd);  

97.  

98.    hdc = GetDC(hWnd);  

99.    mdc = CreateCompatibleDC(hdc);  

100.  

101.    bufdc = CreateCompatibleDC(hdc);  

102.    bmp = CreateCompatibleBitmap(hdc,640,480);  

103.  

104.    SelectObject(mdc,bmp);  

105.  

106.  

107.      

108.  

109.    bg = (HBITMAP)LoadImage(NULL,"bg.bmp",IMAGE_BITMAP,rect.right,rect.bottom,LR_LOADFROMFILE);   

110.    snow = (HBITMAP)LoadImage(NULL,"snow.bmp",IMAGE_BITMAP,20,20,LR_LOADFROMFILE);   

111.    mask = (HBITMAP)LoadImage(NULL,"mask.bmp",IMAGE_BITMAP,20,20,LR_LOADFROMFILE);   

112.    GetClientRect(hWnd,&rect);  

113.  

114.  

115.      

116.    SetTimer(hWnd,1,0,NULL);  

117.  

118.    MyPaint(hdc);  

119.  

120.    return TRUE;  

121.}  

122.  

123.//****自定义绘图函数*********************************  

124.// 1.窗口贴图  

125.// 2.实现雪花纷飞的效果  

126.void MyPaint(HDC hdc)  

127.{  

128.  

129.//创建粒子  

130.    if(count<50)  //当粒子数小于50时,产生新的粒子,设定每个粒子的属性值  

131.    {  

132.        drop[count].x = rand()%rect.right; //将粒子的X坐标设为窗口中水平方向上的任意位置  

133.        drop[count].y = 0;    //将每个粒子的Y坐标都设为"0",即从窗口上沿往下落  

134.        drop[count].exist = true; //设定粒子存在  

135.        count++;   //每产生一个粒子后进行累加计数  

136.    }  

137.  

138.  

139.//贴上背景图到mdc中  

140.    SelectObject(bufdc,bg);  

141.    BitBlt(mdc,0,0,640,480,bufdc,0,0,SRCCOPY);  

142.  

143.//首先判断粒子是否存在,若存在,进行透明贴图操作  

144.    for(i=0;i<50;i++)  

145.    {  

146.          

147.        Sleep

(1);  

148.        if(drop[i].exist)  

149.        {  

150.            SelectObject(bufdc,mask);  

151.            BitBlt(mdc,drop[i].x,drop[i].y,20,20,bufdc,0,0,SRCAND);  

152.  

153.            SelectObject(bufdc,snow);  

154.            BitBlt(mdc,drop[i].x,drop[i].y,20,20,bufdc,0,0,SRCPAINT);  

155.            if(rand()%2==0)  

156.                drop[i].x+=5;  

157.            else   

158.                drop[i].x-=5;  

159.            drop[i].y+=10;  

160.            if(drop[i].y > rect.bottom)  

161.            {  

162.                drop[i].x = rand()%rect.right;  

163.                drop[i].y = 0;  

164.            }  

165.        }  

166.      

167.    }  

168.      

169.  

170.//将mdc中的全部内容贴到hdc中  

171.    BitBlt(hdc,0,0,640,480,mdc,0,0,SRCCOPY);  

172.  

173.}  

174.  

175.  

176.  

177.//****消息处理函数***********************************  

178.LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)  

179.{  

180.    switch (message)  

181.    {  

182.        case WM_TIMER:

                      //时间消息    

183.            MyPaint(hdc);                   //在消息循环中加入处理WM_TIMER消息,当接收到此消息时便调用MyPaint()函数进行窗口绘图    

184.            break;    

185.        case WM_KEYDOWN:

                     //按键消息    

186.            if(wParam==VK_ESCAPE)            //按下【Esc】键  

187.                PostQuitMessage(0);  

188.            break;  

189.        case WM_DESTROY:

                     //窗口结束消息   

190.            DeleteDC(mdc);  

191.            DeleteDC(bufdc);  

192.            DeleteObject(bg);  

193.            DeleteObject(snow);  

194.            DeleteObject(mask);  

195.            KillTimer(hWnd,1);             //窗口结束时,删除所建立的定时器         

196.            ReleaseDC(hWnd,hdc);  

197.            PostQuitMessage(0);  

198.            break;  

199.        default:

                            //其他消息  

200.            return DefWindowProc(hWnd, message, wParam, lParam);  

201.   }  

202.   return 0;  

203.}  

下面是运行后的截图效果:

 

 

可以看到窗口中有漫天飞舞的雪花,我们可以调节数组大小,及几处设定的数值的大小,来使雪花来得更猛烈些。

这张背景图是否有些熟悉呢?

哈哈,喜欢打Dota的朋友们应该可以发现,这张图就是Dota的游戏原画(或者说是魔兽争霸Ⅲ

冰封王座的原画,因为Dota其实就是基于这款游戏的一张自定义多人对战地图罢了),左边的显然就是恐怖利刃TerroBlade

(咦,他的双刀呢?

),中间远远在背后摆造型的是召唤师卡尔,而最右边的当然就是目前Dota中的“一姐”蛇发女妖美杜莎

了。

 在文章末尾说点题外话吧。

关于大家提到的总是熬夜的问题,其实浅墨从来都不熬夜的--。

因为浅墨目前是在欧洲,经常是在当地时间晚上10点左右

把最新的文章发表出来,所以大家在中国看到的都是半夜3点4点左右发表的文章,所以不要以为浅墨是熬夜码字啦,那是因为

时差问题~~-o-

 

 

好了,本篇就写到这里吧,谢谢大家的观赏,下面依旧是放出两个版本的源代码供大家下载学习)(当然,必须是零资

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2