关于2D游戏编程-粒子系统(雪)的实现

本文介绍了一个简单的雪花粒子系统的实现过程,包括如何利用随机函数生成逼真的雪花效果,并提供了详细的代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

读了那篇文章后自己也去动手,嘿嘿,没想到真的做出来了,可惜不是很好,但是还算可以看的过去……

下雪,对于我们北方的朋友来说一定很熟悉了,南方的朋友也一定从电视等等看过了吧,嘿嘿,下雪的时候还是挺美的,这么大了,还没有仔细的看过下雪呢,=。=,请勿见笑!好了开始正题了……

(-)特征描述

(1)雪花有不同的形状或大小
(2)雪花不是直线落下的,受空气阻力会到处飘荡
(3)雪花受空气阻力不同,其下落速度也不同
(4)雪花因视觉关系,离我们越远看起来感觉越小
(5)雪有时下得大,有时下得小
(6)下雪时,有时会刮风
要使雪花具备以上特征,这样会真实点,有的时候根据地图的不同等等因素也需要适当的改变(随机应变了^_^)

(二)着手写代码

先写头文件,CGame_ParticleSnow.h

#ifndef _CGAME_PARTICLESNOW_H
#define _CGAME_PARTICLESNOW_H

#pragma message("This File Have Load Bitmap!")

#i nclude <stdlib.h>
#i nclude <math.h>
#i nclude <time.h>
#i nclude "CGame_Engine.h"

typedef struct{
int  x,y; //粒子坐标
int  z;  //雪,粒子层次

int  vx,vy; //粒子在X,Y轴的速度
RECT rect; //粒子图片格子
bool bDeath; //粒子已死亡?
}PARTICLE_SNOW; //粒子体

typedef struct PARTICLE_SNOW_NODE{
PARTICLE_SNOW *snow;  //一个层次的雪
int  snow_num;   //改层次雪的数目

PARTICLE_SNOW_NODE *next;
}PARTICLE_SNOW_NODE; //粒子节点(其实这里可以不用链表的,比如数组就可以解决问题了)

class CGame_ParticleSnow
{
private:
PARTICLE_SNOW_NODE *first_node;    //头节点
PARTICLE_SNOW_NODE *cur_node;    //当前节点
PARTICLE_SNOW_NODE *arragement_node[5];  //用于保存每个层次的节点,为了更快的速度
LPDIRECTDRAWSU***CE7 lpDDSPic;

bool bShowSnow; //下雪?
int  s_width; //下雪区域宽度 默认800×600
int  s_height; //下雪区域高度
DWORD beg_time; //用于延时计算
DWORD cur_time;
char wind_dir; //当前雪的方位
public:
CGame_ParticleSnow(void); //构造
~CGame_ParticleSnow(void); //析构

BOOL Init(void); //初始化
BOOL Draw(LPDIRECTDRAWSU***CE7 lpDDSTemp); //画雪花
BOOL Restore(void); //恢复
void Release(void); //释放

void Enshow(bool val = true); //可见?
void SetSize(int &width, int &height); //设定屏幕大小

private:
void CreateNode(void);     //创建节点
PARTICLE_SNOW CreateParticle(void);  //创建雪花
void GetPoint(PARTICLE_SNOW &tmp);  //得到改雪花的下一个坐标
void GetSpeed(int &vx, int &vy, int &z); //雪花速度
void GetArrangement(int &ar);    //雪花层次
int Random(int min, int max);    //随机函数
};

#endif

呵呵,粒子系统真的很充分利用随机函数了,原以为没什么用rand()终于排上用场喽,关于随机函数我是这样写的:

int Random(int min, int max)

{

   int back = -1;

   while ((back = rand()*max/MAX_RAND) < min);

   return back;

} 可以得到min-(max-1)之间的随机数,更好的可以在执行该函数前执行srand((unsigned int)time(NULL)); 逝每次随机数不相同……

接下来是源文件了:

#i nclude "CGame_ParticleSnow.h"

#define _MAX_SNOW_PARTICLE 100  //每个层次的最大雪花数
#define _MAX_H_RESTISTANCE 10  //水平阻力
#define _MAX_V_RESTISTANCE 10  //垂直阻力
#define _MAX_ARRANGEMENT 5  //层次数
#define _MAX_SPEED 100    //最大速度
#define _DELAY_TIME 40    //延时
#define _MAX_SNOW_PIC 4    //雪花类型的数量,依源图片文件而定

CGame_ParticleSnow::CGame_ParticleSnow(void)
{
lpDDSPic = NULL;
first_node = NULL;
cur_node = NULL;
}

CGame_ParticleSnow::~CGame_ParticleSnow(void)
{
Release();
}

BOOL CGame_ParticleSnow::Init(void)
{
s_width = 800;
s_height = 600;

if (!CreateSu***ce(&lpDDSPic, 5, 20)){
  return -1;
}

if (!LoadBitmap(lpDDSPic, "Pic//GSnowPic.bmp", TRUE, 0)){
  return -2;
}

srand((unsigned)time(NULL));

CreateNode();

bShowSnow = true;
beg_time = 0;
cur_time = 0;

return TRUE;
}

BOOL CGame_ParticleSnow::Draw(LPDIRECTDRAWSU***CE7 lpDDSTemp)
{
if (!bShowSnow){
  return TRUE;
}

PARTICLE_SNOW_NODE *tmp_node = first_node;
PARTICLE_SNOW snow;
wind_dir = Random(0, 3);
int death_snow = 0;
while (tmp_node != NULL){
  for (int i = 0; i<tmp_node->snow_num; i++){
   if (tmp_node->snow.bDeath){
    death_snow++;
   }
  }

  tmp_node = tmp_node->next;
}

bool z[4] = {false, false, false, false};
for (int i = 0; i<death_snow; i++){
  bool isFind = false;
  snow = CreateParticle();

  if (!z[snow.z]){
   for (int j = 0; j<arragement_node[snow.z]->snow_num; j++){
    if (arragement_node[snow.z]->snow[j].bDeath){
     arragement_node[snow.z]->snow[j] = snow;

     isFind = true;

     break;
    }
   }

   if (!isFind){
    z[snow.z] = true;
   }
  }
}


bool isRest = false;
cur_time = timeGetTime();
if ((cur_time-beg_time)>=_DELAY_TIME){
  isRest = true;
  beg_time = cur_time;
}

tmp_node = first_node;
while (tmp_node != NULL){
  for (int i = 0; i<tmp_node->snow_num; i++){
   if (isRest){
    GetPoint(tmp_node->snow);

    if ((tmp_node->snow.x>=(s_width))||(tmp_node->snow.x<0)||(tmp_node->snow.y>=(s_height))||(tmp_node->snow.y<0)){
     tmp_node->snow.bDeath = true;
    }
   }

    
   if (!tmp_node->snow.bDeath){
    if (!Blt(lpDDSTemp, tmp_node->snow.x, tmp_node->snow.y, lpDDSPic, tmp_node->snow.rect, TRUE)){
     return -1;
    }
   }
  }


  tmp_node = tmp_node->next;
}


return TRUE;
}

BOOL CGame_ParticleSnow::Restore(void)
{
return TRUE;
}

void CGame_ParticleSnow::Release(void)
{
ReleaseSu***ce(lpDDSPic);
if (first_node != NULL){
  PARTICLE_SNOW_NODE *tmp = first_node->next;

  while (tmp!=NULL){
   tmp = first_node->next;
   delete []first_node->snow;
   delete first_node;
   first_node = tmp;
  }

  first_node = NULL;
}
}

void CGame_ParticleSnow::CreateNode(void)
{
first_node = new PARTICLE_SNOW_NODE;
cur_node = first_node;
first_node->snow_num = Random(2, _MAX_SNOW_PARTICLE);
first_node->snow = new PARTICLE_SNOW[first_node->snow_num];
for (int i = 0; i<first_node->snow_num; i++){
  first_node->snow = CreateParticle();
}
arragement_node[0] = first_node;

for (i = 0; i<4; i++){
  PARTICLE_SNOW_NODE *tmp = new PARTICLE_SNOW_NODE;
  tmp->next = NULL;
  tmp->snow_num = Random(2, _MAX_SNOW_PARTICLE);
  tmp->snow = new PARTICLE_SNOW[tmp->snow_num];
  for (int j = 0; j<tmp->snow_num; j++){
   tmp->snow[j] = CreateParticle();
  }

  arragement_node = tmp;
  cur_node->next = tmp;
  cur_node = tmp;
}
}

PARTICLE_SNOW CGame_ParticleSnow::CreateParticle(void)
{
PARTICLE_SNOW back;

GetArrangement(back.z);
GetSpeed(back.vx, back.vy, back.z);
int i = Random(0, _MAX_SNOW_PIC);
if (i>=4){
  i = 3;
}
back.rect.left = 0;
back.rect.right = 5;
back.rect.top = i*5;
back.rect.bottom = (i+1)*5;

back.x = Random(0, s_width);
back.y = Random(0, 10);
back.bDeath = false;

return back;
}

void CGame_ParticleSnow::GetPoint(PARTICLE_SNOW &tmp)
{
tmp.x+=tmp.vx;
tmp.y+=tmp.vy;
}

void CGame_ParticleSnow::GetArrangement(int &ar)
{
ar = Random(0, _MAX_ARRANGEMENT);
if (ar>=5){
  ar = 4;
}
}

void CGame_ParticleSnow::GetSpeed(int &vx, int &vy, int &z)
{
int power = Random(1, _MAX_H_RESTISTANCE);
if (wind_dir){
  vx = _MAX_SPEED/power/(z+1);
}else if (wind_dir == 0){
  vx = -(_MAX_SPEED/power/(z+1));
}else if (wind_dir == 3){
  vx = 0;
}

power = Random(1, _MAX_V_RESTISTANCE);
vy = _MAX_SPEED/power/(z+1);
}

void CGame_ParticleSnow::SetSize(int &width, int &height)
{
s_width = width;
s_height = height;
}

void CGame_ParticleSnow::Enshow(bool val)
{
bShowSnow = val;
}

int CGame_ParticleSnow::Random(int min, int max)
{
int back;

while ((back = (rand()*max/RAND_MAX))<min);

return back;
}

自己去动手吧,做出属于自己的粒子系统,为了游戏,去描述奇妙的大自然吧,^_^

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值