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

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。

作者:毛星云    邮箱: [email protected]    期待着与志同道合的朋友们相互交流





本节在笔记二十二的基础上继续讲解了例子系统的模拟与实际运用,着重讲解和分析了基于例子系统的一个“星光绽放

demo”,最后盘点了史诗级游戏作品《暗黑破坏神3》上市首周所创下的传奇。

一.基础知识讲解

1.    概念与思路

基本的粒子系统概念在笔记二十二中已经讲过了,还不太清楚的朋友请移步前篇:


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

本节讲解的星光绽放demo相当于是一个模拟爆炸(或者说是烟花)特效的demo,浅墨认为这个特效拿出来讲解很多必要性,它可以为很多问题带来的思路的火花。这个demo之中,绽放(爆炸)点为在窗口中由随机数产生的一个位置,绽放(爆炸)后,会出现很多星光以不同的速度向四方飞散而去,当粒子飞出窗口后或者超出时间后便会消失。每一次爆炸所出现的粒子全部消失后,便会重新出现绽放(爆炸)的画面,以产生不断绽放星光的效果。


2.“星光”粒子的构造


首先我们来看一下这次如何用结构体来构造出星光粒子:

struct flystar { 	int x;       //星光所在的x坐标 	int y;       //星光所在的y坐标 	int vx;      //星光x方向的速度 	int vy;      //星光y方向的速度 	int lasted;  //星光存在的时间 	BOOL exist;  //星光是否存在 }flystar[50];


6个成员分别为,粒子坐标两个值,粒子方向两个值,持续时间lasted,和粒子是否存在的标识exist。



3.核心代码讲解


最重要的当然是我们的MyPaint()绘图函数:


//全局变量声明 HINSTANCE hInst; HBITMAP bg,star,mask;  //用于贴图的三个HBITMAP变量 HDC	hdc,mdc,bufdc; HWND	hWnd; RECT	rect; int i,count; //定义count用于计数   //****自定义绘图函数********************************* // 1.窗口贴图 // 2.实现星光绽放的效果 void MyPaint(HDC hdc) {     //创建粒子 	if(count == 0)              //随机设置爆炸点 	{ 	int	x=rand()%rect.right; 	int	y=rand()%rect.bottom; 		for(i=0;i<50;i++)       //产生星光粒子 		{ 			flystar[i].x = x; 			flystar[i].y = y; 			flystar[i].lasted = 0;  //设定该粒子存在的时间为零 			if(i%2==0)       //按粒子编号i来决定粒子在哪个象限运动,且x,y方向的移动速度随机为1―15之间的一个值,由1+rand()%15来完成。 			{ 				flystar[i].vx =  -(1+rand()%15); 				flystar[i].vy =  -(1+rand()%15); 			} 			if(i%2==1) 			{ 				flystar[i].vx = 1+rand()%15; 				flystar[i].vy = 1+rand()%15; 			} 			if(i%4==2) 			{ 				flystar[i].vx = -(1+rand()%15); 				flystar[i].vy = 1+rand()%15; 			} 			if(i%4==3) 			{ 				flystar[i].vx = 1+rand()%15; 				flystar[i].vy = -(1+rand()%15); 			} 			flystar[i].exist = true;  //设定粒子存在 		} 		count = 50;   //50个粒子由for循环设置完成后,我们将粒子数量设为50,代表目前有50颗星光 	} 	 	//先在内存dc中贴上背景图片 	SelectObject(bufdc,bg); 	BitBlt(mdc,0,0,rect.right,rect.bottom,bufdc,0,0,SRCCOPY);   	for(i=0;i<50;i++) 	{ 		if(flystar[i].exist)   //判断粒子是否还存在,若存在,则根据其坐标(flystar[i].x,flystar[i].y)进行贴图操作 		{ 			SelectObject(bufdc,mask); 			BitBlt(mdc,flystar[i].x,flystar[i].y,30,30,bufdc,0,0,SRCAND); 			SelectObject(bufdc,star); 			BitBlt(mdc,flystar[i].x,flystar[i].y,30,30,bufdc,0,0,SRCPAINT);   			//计算下一次贴图的坐标 			flystar[i].x+=flystar[i].vx; 			flystar[i].y+=flystar[i].vy;   			//在每进行一次贴图后,将粒子的存在时间累加1. 			flystar[i].lasted++; 			//进行条件判断,若某粒子跑出窗口区域一定的范围,则将该粒子设为不存在,且粒子数随之递减 			if(flystar[i].x<=-10 || flystar[i].x>rect.right || flystar[i].y<=-10 || flystar[i].y>rect.bottom || flystar[i].lasted>50) 			{ 				flystar[i].exist = false;  //删除星光粒子  				count--;                    //递减星光总数 			} 		} 	} 	 //将mdc中的全部内容贴到hdc中 	BitBlt(hdc,0,0,640,480,mdc,0,0,SRCCOPY);   }





相关的书写思路在代码注释中浅墨已经写得比较清晰了。

这段代码的书写整体思路即:

第一步,判断粒子是否创建,若星光数量count不为0,则直接跳到第四步进行相关贴图操作。否则需按每步顺序完成粒子的初始化。

第二步,随机设置绽放点。

第三步,创建各个粒子(为结构体各属性赋值)。

第四步,在内存dc上贴上背景图片。

第五步,对各个粒子进行贴图操作并

第六步,对某些值,如count,exist进行特殊的处理

第七步,将mdc(内存dc)中的内容贴到hdc中,完成最后在屏幕上的显示。






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


OK,讲解完成,现在我们就贴出详细注释的源代码:



#include "stdafx.h" #include <stdio.h>  //全局变量声明 HINSTANCE hInst; HBITMAP bg,star,mask;  //用于贴图的三个HBITMAP变量 HDC	hdc,mdc,bufdc; HWND	hWnd; RECT	rect; int i,count; //定义count用于计数     struct flystar { 	int x;       //星光所在的x坐标 	int y;       //星光所在的y坐标 	int vx;      //星光x方向的速度 	int vy;      //星光y方向的速度 	int lasted;  //星光存在的时间 	BOOL exist;  //星光是否存在 }flystar[50];   //全局函数声明

你可能感兴趣的:(C++,模拟,粒子系统,物理建模)