本系列文章由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]; //全局函数声明