hge引擎登陆器 锻造参数怎么改

3198人阅读
大概三个月前,我在试着用几款2D游戏引擎。
&&& 第一款是SDL,这是同事推荐给我的一款跨平台的2D游戏引擎。这款引擎评价很高,总的来说是因为它够底层,实现的功能非常基本,又提供了一套平台无关的接口。所以开发人员在此之上可以天马行空的开发。不过我不是那么热衷底层&&于是我在写了几个实验性的程序之后放弃了他。呵呵,当时研究它主要是因为自己也在做嵌入式,对跨平台很感兴趣。但是当时看一个老外,好像叫lazyfoo,写的开发教程让我学到了很多游戏开发方面基本的知识。
&&& 然后第二款是HGE,它是基于driectX的一款开源2D游戏引擎,也是提供较底层的功能。最核心的大概是它提供基于帧的逻辑和渲染回调,开发人员来实现每帧进行的操作。HGE还提供了一套我觉得非常不好的教程,对于新手是绝对的误导&&它的教程里的代码都乱七八糟,感觉就像个C++新手写的代码一样,各种全局变量,各种魔数,各种乱命名,可读性和框架性都较差。(可能也是HGE的开发者为了求简,不过我觉得这个教程可以做的更好。)
&&& 这时,我自己做的一套简单的游戏,已经简单的设计好UI接口。于是我用HGE来实现这套接口。
&&& 我觉得HGE很恶心的地方就是它基于每帧的回调(当然你可以修改HGE内核来去除这一点,不过将带来更多麻烦,因为HGE很多函数就是基于帧回调机制的。)所以你不能像使用一个Canvas一样来进行实时绘制。于是我在游戏里自己实现了一套消息机制,把整个HGE框架跑在另一个线程中,游戏数据核心线程通过发消息的方式去通知界面更新,或者获取玩家操作。
这是当时自己弄的设计,DirectX or Ddraw改成HGE,后来自己也实现了。
刚开始的时候感觉还好,后来代码稍微上规模的话,就觉得很吃力了。因为我是基于具体游戏功能来封装HGE的接口。在之后又重构了几次,整体架构还算清晰,但是界面和代码之间的耦合度实在太大。最后可以实现一定的界面功能,但是还是太不爽了,所以决定放弃使用HGE。在此总结一下自己的想法,如果要用HGE真正开发一款稍微上规模的游戏,应该怎么做,可能也有很多不正确的地方,欢迎指正。
1. 实现页面栈、控件树
我也不知道该怎么定义这个名称,姑且叫它页面栈和控件树吧,其实就类似于WINDOWS的窗口系统,建立起树状结构的控件系统。对于每一个页面记录各种状态如焦点控件等。并通过栈维护各页面的层次关系。可以从配置文件或者页面脚本载入页面。比如游戏中的主角属性页面、装备页面等,框架都是一定的,使用的一些图片资源什么的也是一定的,应该写成配置文件,直接从文件读入。
2. 在页面树的基础上实现消息路由
消息的路由机制必须实现。
3. 建立资源管理器及配置管理器
专门的资源管理器用来加载和卸载各种图片、特效、音乐资源。同理配置管理器,管理整个HGE的配置。
4. 定义界面文件格式并使用界面文件生成具体画面,同时配套开发界面编辑器
如使用XML来定义具体界面,界面编辑器生成XML。
在1,2,3,4条满足的情况下,再进行具体游戏功能性的接口开发。甚至应该把1,2,3,4这部分抽成 引擎无关、平台无关的中间层,向下提供移植接口,用HGE来port。&& 那么整个游戏界面部分以上应该是高度可移植的。
HGE 的 gui 工具是个好东西,特别是里面的 hgeGUIObject,要多用。说个要注意的点,官网上面貌似都没给详细说明&&
hgeGUIObject 的 rect 成员是该控件的操作响应作用域&&不是显示的。让一个控件disable只要rect.Set(0,0,0,0)就行了。注意有时控件莫名其妙的不响应鼠标操作了,也可能是这个冲突导致的。这问题曾经让我崩溃的调了半天。。。
总结一下。
HGE完全开源、基于directX,功能较为基础。我觉得很适合个人学习和开发小型游戏,但是如果要做稍微大型的游戏的话,必须将整个UI的调度机制设计、封装好(我觉得这个工作量挺大),然后整以相关的开发工具。
OK,HGE就告一段落。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:285540次
积分:5052
积分:5052
排名:第1865名
原创:202篇
评论:284条
(2)(1)(1)(1)(1)(3)(1)(1)(1)(1)(1)(3)(1)(1)(2)(2)(2)(3)(3)(3)(3)(4)(1)(8)(8)(5)(5)(9)(8)(5)(6)(5)(10)(7)(17)(25)(16)(11)(8)(2)(7)更多频道内容在这里查看
爱奇艺用户将能永久保存播放记录
过滤短视频
暂无长视频(电视剧、纪录片、动漫、综艺、电影)播放记录,
使用您的微博帐号登录,即刻尊享微博用户专属服务。
使用您的QQ帐号登录,即刻尊享QQ用户专属服务。
使用您的人人帐号登录,即刻尊享人人用户专属服务。
方式2:免费发送短信到手机
请输入正确的手机号
此短信不收取任何费用,保证您的手机号安全不被泄露
下载APP到本机
当前浏览器仅支持手动复制代码
视频地址:
flash地址:
html代码:
收藏成功,可进入查看所有收藏列表
爸爸去哪儿2游戏 立即参与
30秒后自动关闭
木剑相逢辅助过HGE合击引擎登陆器教程
发布时间:
播放量数据:
木剑相逢辅助过HGE合击引擎登陆器教程
木剑相逢辅助过HGE合击引擎登陆器教程
你可能还想订阅他们:
周围人都在搜-百度搜索提供
&正在加载...
由于版权原因,此视频暂不支持播放
Sorry,due to copyright issues
you can’t watch the video
这些视频最近很火,赶紧看看吧
很抱歉,您所观看的视频已经下线
这些视频最近很火,赶紧看看吧
呃......网络出错了
Hi,{{username}}:
,请继续享受影片无限看、全站无广告等特权。
您的会员还有{{_remainDays}}天就要到期了
VIP还有{{_remainDays}}天到期
您的会员已经过期{{_remainDays}}天
VIP已过期{{_remainDays}}天
您使用浏览器不支持直接复制的功能,建议您使用Ctrl+C或右键全选进行地址复制
色情低俗内容
血腥暴力内容
广告或欺诈内容
侵犯了我的权力
还可以输入300字
&li data-elem="tabtitle" data-seq="{{seq}}"&
&a href="javascript:void(0);"&
&span>{{start}}-{{end}}&/span&
&li data-downloadSelect-elem="item" data-downloadSelect-selected="false" data-downloadSelect-tvid="{{tvid}}"&
&a href="javascript:void(0);"&{{pd}}&/a&
选择您要下载的《》剧集:
安装爱奇艺视频客户端,
马上开始为您下载本片
5秒后自动消失
免费发送到手机,下载手机APP
请输入正确的手机号
此短信不收取任何费用,保证您的手机号安全不被泄露时间:&&&&&&
内容简介:最近在做捕鱼游戏,使用到了HGE引擎,下面让我来介绍一下HGE引擎中的粒子系统。本文章由棋牌休闲游戏中心(www.36qp.net)搜集整理,讲述一段棋牌故事,传授一个游戏技巧,提供一份快乐的心情。希望HGE引擎的粒子系统这篇文章能给你提供帮助。
最近在做捕鱼游戏,使用到了HGE引擎,下面让我来介绍一下HGE引擎中的粒子系统。
首先还是让我们从头文件开始:
& 类名 :hgeParticle
& 功能 :单个粒子的属性结构
& 头文件 :hge/hge181/include/hgeParticle.h
& 实现文件 : 无
struct hgeParticle
&&& // 粒子所在的位置
&&&&&& hgeVector&&&&&& vecL
&&& // 粒子的速度(Velocity)
&&&&&& hgeVector&&&&&& vecV
&&& // 粒子的重力
&&&&&& float&&&&&&& fG
&&& // 粒子的线加速度
&&&&&& float&&&&&&& fRadialA
&&& // 粒子的角加速度
&&&&&& float&&&&&&& fTangentialA
&&& // 粒子的旋转角度
&&&&&& float&&&&&&& fS
&&& // 粒子旋转角度偏移量
&&&&&& float&&&&&&& fSpinD
&&& // 粒子的大小
&&&&&& float&&&&&&& fS
&&& // 粒子的大小偏移量
&&&&&& float&&&&&&& fSizeD
&&& // 粒子的颜色(带alpha值)
&&&&&& hgeColor colC&&&&&&& // + alpha
&&& // 粒子的颜色偏移量
&&&&&& hgeColor colColorD
&&& // 粒子的生存时间
&&&&&& float&&&&&&& fA
&&& // 粒子的死亡时间
&&&&&& float&&&&&&& fTerminalA
& 仅一个简单的数据集合而已,各中变量相信大家一目了然 :)
& 类名 :hgeParticleSystemInfo
& 功能 :粒子系统的相关信息结构
& 头文件 :hge/hge181/include/hgeParticle.h
& 实现文件 : 无
struct hgeParticleSystemInfo
&&& // 粒子贴图
&&& hgeSprite*&&&& // texture + blend mode
&&& // 每秒的粒子数
&&& int&&&&&&&& nE // particles per sec
&&& // 生命周期
&&& float&&&&&& fL
&&& // 最小生命周期
&&& float&&&&&& fParticleLifeM
&&& // 最大生命周期
&&& float&&&&&& fParticleLifeM
&&& // 方向
&&& float&&&&&& fD
&&& // 偏移角度
&&& float&&&&&& fS
&&& // 绝对值还是相对值,用以计算生成粒子的初始速度
&&& bool&&&&&&& bR
&&& // 最低速度
&&& float&&&&&& fSpeedM
&&& // 最高速度
&&& float&&&&&& fSpeedM
&&& // 最小重力
&&& float&&&&&& fGravityM
&&& // 最大重力
&&& float&&&&&& fGravityM
&&& // 最低线加速度
&&& float&&&&&& fRadialAccelM
&&& // 最高线加速度
&&& float&&&&&& fRadialAccelM
&&& // 最低角加速度
&&& float&&&&&& fTangentialAccelM
&&& // 最高角加速度
&&& float&&&&&& fTangentialAccelM
&&& // 起始大小
&&& float&&&&&& fSizeS
&&& // 最终大小
&&& float&&&&&& fSizeE
&&& // 大小变化值
&&& float&&&&&& fSizeV
&&& // 起始旋转角度
&&& float&&&&&& fSpinS
&&& // 最终旋转角度
&&& float&&&&&& fSpinE
&&& // 角度变化值
&&& float&&&&&& fSpinV
&&& // 起始颜色
&&& hgeColor&&& colColorS // + alpha
&&& // 最终颜色
&&& hgeColor&&& colColorE
&&& // 颜色变化值
&&& float&&&&&& fColorV
&&& // alpha变化值
&&& float&&&&&& fAlphaV
& 仍然是一个数据集合而已:)
& 接着让我们看一看hgeParticleSystem这个类型:
& 类名 :hgeParticleSystem
& 功能 :粒子系统
& 头文件 :hge/hge181/include/hgeParticle.h
& 实现文件 : hge/hge181/src/helpers/hgeparticle.cpp
class hgeParticleSystem
&&& // 用于存储粒子系统的相关信息(详见hgeParticleSystemInfo的定义)
&&&&&& hgeParticleSystemI
&&&&&& // 构造函数&析构函数
&&& hgeParticleSystem(const char *filename, hgeSprite *sprite);
&&&&&& hgeParticleSystem(hgeParticleSystemInfo *psi);
&&&&&& hgeParticleSystem(const hgeParticleSystem &ps);
&&&&&& ~hgeParticleSystem() { hge-&Release(); }
&&& // 重载赋值运算符
&&&&&& hgeParticleSystem&&&&&& operator= (const hgeParticleSystem &ps);
&&& // 渲染粒子系统
&&&&&& void&&&&&&&&&&&&&&&&&&&&& Render();
&&& // 在指定位置启动粒子系统
&&&&&& void&&&&&&&&&&&&&&&&&&&&& FireAt(float x, float y);
&&& // 启动粒子系统
&&&&&& void&&&&&&&&&&&&&&&&&&&&& Fire();
&&& // 停止粒子系统
&&&&&& void&&&&&&&&&&&&&&&&&&&&& Stop(bool bKillParticles=false);
&&& // 更新粒子系统
&&&&&& void&&&&&&&&&&&&&&&&&&&&& Update(float fDeltaTime);
&&& // 移动粒子系统的位置
&&&&&& void&&&&&&&&&&&&&&&&&&&&& MoveTo(float x, float y, bool bMoveParticles=false);
&&& // 设定粒子系统的位置偏移量
&&&&&& void&&&&&&&&&&&&&&&&&&&&& Transpose(float x, float y) { fTx=x; fTy=y; }
&&& // 设置粒子系统的缩放比例
&&&&&& void&&&&&&&&&&&&&&&&&&&&& SetScale(float scale) { fScale = }
&&& // 设置是否跟踪粒子系统的边界盒
&&&&&& void&&&&&&&&&&&&&&&&&&&&& TrackBoundingBox(bool bTrack) { bUpdateBoundingBox=bT }
&&& // 获取当前粒子系统中活动的粒子个数
&&&&&& int&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& GetParticlesAlive() const { return nParticlesA }
&&& // 获得粒子系统的生命值
&&&&&& float&&&&&&&&&&&&&&&&&&&&& GetAge() const { return fA }
&&& // 获取粒子系统位置
&&&&&& void&&&&&&&&&&&&&&&&&&&&& GetPosition(float *x, float *y) const { *x=vecLocation.x; *y=vecLocation.y; }
&&& // 获取位置偏移量
&&&&&& void&&&&&&&&&&&&&&&&&&&&& GetTransposition(float *x, float *y) const { *x=fTx; *y=fTy; }
&&& // 获取缩放比例
&&&&&& float&&&&&&&&&&&&&&&&&&&&& GetScale() { return fS }
&&& // 获取边界盒
&&&&&& hgeRect*&&&&&&&&&&&&&& GetBoundingBox(hgeRect *rect)
&&& // 私有化默认构造函数,达到屏蔽默认构造的作用
&&&&&& hgeParticleSystem();
&&&&&& // HGE静态指针
&&& static HGE&&&&&&&&&&&&&&&&&&& *
&&& // 生命值
&&&&&& float&&&&&&&&&&&&&&&&&&&&& fA
&&& // 剩余未有发射(生成)的粒子数量
&&&&&& float&&&&&&&&&&&&&&&&&&&&& fEmissionR
&&& // 前一个位置
&&&&&& hgeVector&&&&&&&&&&&&&&&&&&&& vecPrevL
&&& // 当前位置
&&&&&& hgeVector&&&&&&&&&&&&&&&&&&&& vecL
&&& // 偏移量
&&&&&& float&&&&&&&&&&&&&&&&&&&&& fTx, fTy;
&&& // 缩放因子
&&&&&& float&&&&&&&&&&&&&&&&&&&&& fS
&&& // 活动的粒子个数
&&&&&& int&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& nParticlesA
&&& // 粒子系统的边界盒
&&&&&& hgeRect&&&&&&&&&&&&&&&&&&&&&&& rectBoundingB
&&& // 是否更新边界盒
&&&&&& bool&&&&&&&&&&&&&&&&&&&&& bUpdateBoundingB
&&& // hgeParticle数组,用以存储所有的粒子
&&&&&& hgeParticle&&&&&&&&&&&&&&&&&& particles[MAX_PARTICLES];
& 总的来说,hgeParticleSystem封装了一个相对简洁的粒子系统的各项功能,其头文件声明的数据及函数成员并未有十分费解的地方,下面就让我们看一看其的实现源码:
& 首先自然是他的构造函数:
hgeParticleSystem::hgeParticleSystem(const char *filename, hgeSprite *sprite)
&&&&&& void *
&&& // 创建HGE,以获得其提供的底层接口
&&&&&& hge=hgeCreate(HGE_VERSION);
&&& // 使用Resource_Load加载文件
&&&&&& psi=hge-&Resource_Load(filename);
&&&&&& if(!psi)
&&& // 将文件中的内容拷贝至info(hgeParticleSystemInfo)中
&&&&&& memcpy(&info, psi, sizeof(hgeParticleSystemInfo));
&&& // 释放资源
&&&&&& hge-&Resource_Free(psi);
&&& // 设置粒子精灵类
&&&&&& info.sprite=
&&& // 初始化粒子系统的位置
&&&&&& vecLocation.x=vecPrevLocation.x=0.0f;
&&&&&& vecLocation.y=vecPrevLocation.y=0.0f;
&&& // 初始化粒子系统的偏移位置
&&&&&& fTx=fTy=0;
&&& // 初始化缩放因子,1.0f代表不做缩放
&&&&&& fScale = 1.0f;
&&& // 初始化未发射(生成)粒子数量
&&&&&& fEmissionResidue=0.0f;
&&& // 初始化活动粒子数
&&&&&& nParticlesAlive=0;
&&& // 初始化粒子生命值
&&&&&& fAge=-2.0;
&&& // 初始化边界盒
&&&&&& rectBoundingBox.Clear();
&&& // 默认不更新边界盒
&&&&&& bUpdateBoundingBox=
& 各项操作还是相当易解的,剩下的两个构造函数如出一辙,在此不再赘述,只是就其中的复制构造函数,在这里我想说上一说:
& 源代码中,关于复制构造函数的实现很简单:
hgeParticleSystem::hgeParticleSystem(const hgeParticleSystem &ps)
&&&&&& memcpy(this, &ps, sizeof(hgeParticleSystem));
&&&&&& hge=hgeCreate(HGE_VERSION);
& 由于hgeParticleSystem并不涉及资源的管理(关于HGE的资源管理,可以看看这篇),所以结构内容基本可以按照POD数据的方式进行复制,这也是该函数中大胆使用memcpy的一个原因,但是令我比较意外的是,虽然hgeParticleSystem的头文件中声明了重载赋值运算符函数:
&&& / / 重载赋值运算符
&&&&&& hgeParticleSystem&&&&&& operator= (const hgeParticleSystem &ps);
& 但是却没有加以实现,所以当使用时必然引起链接错误,如果这是作者的初衷的话,我想将其变为私有(private)将更为妥当,而且按照C++中公认的编程规范,一旦你定义了复制构造函数,那么你也应该定义赋值构造函数。对于这个类别,我想比较妥当的定义方法也许可以是这个样子:
hgeParticleSystem::hgeParticleSystem(const hgeParticleSystem &ps)
&&& memcpy(this, &ps, sizeof(hgeParticleSystem));
&&& hge=hgeCreate(HGE_VERSION);
hgeParticleSystem&&&&&& hgeParticleSystem::operator= (const hgeParticleSystem &ps)
&&& if( this == &ps )
&&& memcpy(this, &ps, sizeof(hgeParticleSystem));
& 另外一提的便是fAge这个成员变量,在构造函数中他被设置成了-2.0:
// 初始化粒子生命值
fAge=-2.0;
& 相信不少朋友对于这个-2.0的由来应该比较奇怪,其实他是一个“魔数”,代表着粒子系统尚未启动(使用FireAt或者Fire来启动粒子系统),不过这种编程技巧我个人是比较不赞同的,我的建议是至少使用枚举之类明显的变量值进行代替,最低限度也可以使用粗糙的宏定义来简单的包装一下,譬如:
#define PARTICLE_SYSTEM_NOT_START (-2.0)
& 好了,闲话少叙,接着让我们来看看其他的成员函数:
// 移动粒子系统的位置
void hgeParticleSystem::MoveTo(float x, float y, bool bMoveParticles)
&&&&&& float dx,
&&& // 如果移动所有活动粒子的话
&&&&&& if(bMoveParticles)
&&&&&&& // 计算目标坐标与当前坐标的偏移量
&&&&&&&&&&&&& dx=x-vecLocation.x;
&&&&&&&&&&&&& dy=y-vecLocation.y;
&&&&&&& // 重新设置所有活动粒子的位置
&&&&&&&&&&&&& for(i=0;i&nParticlesAi++)
&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&& particles[i].vecLocation.x +=
&&&&&&&&&&&&&&&&&&&& particles[i].vecLocation.y +=
&&&&&&&&&&&&& }
&&&&&&& // 重新计算先前所在坐标的位置
&&&&&&&&&&&&& vecPrevLocation.x=vecPrevLocation.x +
&&&&&&&&&&&&& vecPrevLocation.y=vecPrevLocation.y +
&&& // 否则仅移动即将发射的粒子
&&&&&& else
&&&&&&& // 如果粒子系统尚未启动
&&&&&&&&&&&&& if(fAge==-2.0) { vecPrevLocation.x=x; vecPrevLocation.y=y; }
&&&&&&&&&&&&& else { vecPrevLocation.x=vecLocation.x;&&&& vecPrevLocation.y=vecLocation.y; }
&&& // 设置当前位置坐标
&&&&&& vecLocation.x=x;
&&&&&& vecLocation.y=y;
& 可以看到,相关的代码并不复杂,值得注意一下的是代码中对于vecPrevLocation的设置 :)
& 接着是FireAt、Fire以及对应的Stop:
// 在指定位置启动粒子系统&&
void hgeParticleSystem::FireAt(float x, float y)
&&& // 简单三部曲:首先停止,接着移动,最后启动
&&&&&& Stop();
&&&&&& MoveTo(x,y);
&&&&&& Fire();
// 启动粒子系统
void hgeParticleSystem::Fire()
&&& // 注意fAge的设置
&&&&&& if(info.fLifetime==-1.0f) fAge=-1.0f;
&&&&&& else fAge=0.0f;
// 停止粒子系统
void hgeParticleSystem::Stop(bool bKillParticles)
&&& // 注意fAge的设置
&&&&&& fAge=-2.0f;
&&& // 如果需要清除粒子的话
&&&&&& if(bKillParticles)
&&&&&&& // 重新设置活动粒子数量为0
&&&&&&&&&&&&& nParticlesAlive=0;
&&&&&&& // 重置粒子系统的边界盒
&&&&&&&&&&&&& rectBoundingBox.Clear();
& 再者让我们看看如何渲染粒子系统:
// 渲染粒子系统
void hgeParticleSystem::Render()
&&&&&& DWORD
&&&&&& hgeParticle *par=
&&& // 获取粒子精灵的颜色
&&&&&& col=info.sprite-&GetColor();
&&& // 对于每一个活动的粒子
&&&&&& for(i=0; i&nParticlesA i++)
&&&&&&& // 设置粒子精灵的颜色
&&&&&&&&&&&&& if(info.colColorStart.r & 0)
&&&&&&&&&&&&&&&&&&&& info.sprite-&SetColor(SETA(info.sprite-&GetColor(),par-&colColor.a*255));
&&&&&&&&&&&&& else
&&&&&&&&&&&&&&&&&&&& info.sprite-&SetColor(par-&colColor.GetHWColor());
&&&&&&& // 渲染粒子精灵,注意各个参数的设置
&&&&&&&&&&&&& info.sprite-&RenderEx(par-&vecLocation.x*fScale+fTx, par-&vecLocation.y*fScale+fTy, par-&fSpin*par-&fAge, par-&fSize*fScale);
&&&&&&& // 移动到下一活动粒子
&&&&&&&&&&&&& par++;
&&& // 还原先前的粒子精灵颜色
&&&&&& info.sprite-&SetColor(col);
& 边界盒的获取也并不复杂:
hgeRect *hgeParticleSystem::GetBoundingBox(hgeRect *rect) const
&&&&&& *rect = rectBoundingB
&&& // 根据缩放因子缩放坐标
&&&&&& rect-&x1 *= fS
&&&&&& rect-&y1 *= fS
&&&&&& rect-&x2 *= fS
&&&&&& rect-&y2 *= fS
& 最后,让我们来看一看稍有些复杂的Update函数:
void hgeParticleSystem::Update(float fDeltaTime)
&&&&&& hgeParticle *
&&&&&& hgeVector vecAccel, vecAccel2;
&&& // 如果粒子系统生命值大于0
&&&&&& if(fAge &= 0)
&&&&&&& // 累计生命值
&&&&&&&&&&&&& fAge += fDeltaT
&&&&&&& // 如果超过系统生命周期时间,则重新设置为未启动
&&&&&&&&&&&&& if(fAge &= info.fLifetime) fAge = -2.0f;
&&&&&& // 更新所有活动粒子
&&& // 更新粒子系统边界盒
&&&&&& if(bUpdateBoundingBox) rectBoundingBox.Clear();
&&&&&& par=
&&& // 对于每一个活动粒子
&&&&&& for(i=0; i&nParticlesA i++)
&&&&&&& // 更新生命值
&&&&&&&&&&&&& par-&fAge += fDeltaT
&&&&&&& // 如果达到死亡时间
&&&&&&&&&&&&& if(par-&fAge &= par-&fTerminalAge)
&&&&&&&&&&&&& {
&&&&&&&&&&& // 递减活动粒子数目
&&&&&&&&&&&&&&&&&&&& nParticlesAlive--;
&&&&&&&&&&& // 将最后一个活动粒子拷贝至此处
&&&&&&&&&&&&&&&&&&&& memcpy(par, &particles[nParticlesAlive], sizeof(hgeParticle));
&&&&&&&&&&& // 递减计数值,以达到下次继续处理该位置粒子的目的
&&&&&&&&&&&&&&&&&&&& i--;
&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&& }
&&&&&&& // 计算粒子的线加速度
&&&&&&&&&&&&& vecAccel = par-&vecLocation-vecL
&&&&&&&&&&&&& vecAccel.Normalize();
&&&&&&&&&&&&& vecAccel2 = vecA
&&&&&&&&&&&&& vecAccel *= par-&fRadialA
&&&&&&&&&&&&& // vecAccel2.Rotate(M_PI_2);
&&&&&&&&&&&&& // the following is faster
&&&&&&& // 计算线加速度方向的切线方向
&&&&&&&&&&&&& ang = vecAccel2.x;
&&&&&&&&&&&&& vecAccel2.x = -vecAccel2.y;
&&&&&&&&&&&&& vecAccel2.y =
&&&&&&& // 计算角角速度
&&&&&&&&&&&&& vecAccel2 *= par-&fTangentialA
&&&&&&& // 计算粒子的实际速度
&&&&&&&&&&&&& par-&vecVelocity += (vecAccel+vecAccel2)*fDeltaT
&&&&&&& // 考虑到重力的影响
&&&&&&&&&&&&& par-&vecVelocity.y += par-&fGravity*fDeltaT
&&&&&&& // 计算粒子的位置
&&&&&&&&&&&&& par-&vecLocation += par-&vecVelocity*fDeltaT
&&&&&&& // 计算粒子的旋转角度
&&&&&&&&&&&&& par-&fSpin += par-&fSpinDelta*fDeltaT
&&&&&&& // 计算粒子的大小
&&&&&&&&&&&&& par-&fSize += par-&fSizeDelta*fDeltaT
&&&&&&& // 计算粒子的颜色
&&&&&&&&&&&&& par-&colColor += par-&colColorDelta*fDeltaT
&&&&&&& // 更新粒子边界盒
&&&&&&&&&&&&& if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(par-&vecLocation.x, par-&vecLocation.y);
&&&&&&& // 移动到下一个粒子
&&&&&&&&&&&&& par++;
&&&&&& // 生成新的粒子
&&& // 如果粒子系统已经启动的话
&&&&&& if(fAge != -2.0f)
&&&&&&& // 计算需要生成的粒子数
&&&&&&&&&&&&& float fParticlesNeeded = info.nEmission*fDeltaTime + fEmissionR
&&&&&&& // 强制装换为无符号整数
&&&&&&&&&&&&& int nParticlesCreated = (unsigned int)fParticlesN
&&&&&&& // 计算遗留下来未有生成的粒子,等待下一次更新生成
&&&&&&&&&&&&& fEmissionResidue=fParticlesNeeded-nParticlesC
&&&&&&&&&&&&& par=&particles[nParticlesAlive];
&&&&&&& // 对于每一个需要生成的粒子
&&&&&&&&&&&&& for(i=0; i&nParticlesC i++)
&&&&&&&&&&&&& {
&&&&&&&&&&& // 如果活动粒子已经超过上界,则不在生成
&&&&&&&&&&&&&&&&&&&& if(nParticlesAlive&=MAX_PARTICLES)
&&&&&&&&&&&
&&&&&&&&&&& // 设置粒子的各项属性
&&&&&&&&&&& // 生命值
&&&&&&&&&&&&&&&&&&&& par-&fAge = 0.0f;
&&&&&&&&&&&&&&&&&&&& par-&fTerminalAge = hge-&Random_Float(info.fParticleLifeMin, info.fParticleLifeMax);
&&&&&&&&&&&
&&&&&&&&&&& // 设置粒子的位置
&&&&&&&&&&&&&&&&&&&& par-&vecLocation = vecPrevLocation+(vecLocation-vecPrevLocation)*hge-&Random_Float(0.0f, 1.0f);
&&&&&&&&&&&&&&&&&&&& par-&vecLocation.x += hge-&Random_Float(-2.0f, 2.0f);
&&&&&&&&&&&&&&&&&&&& par-&vecLocation.y += hge-&Random_Float(-2.0f, 2.0f);
&&&&&&&&&&&&&&&&&&& // 设置粒子的速度值,注意角度的计算&&&&&&&&&&&& ang=info.fDirection-M_PI_2+hge-&Random_Float(0,info.fSpread)-info.fSpread/2.0f;
&&&&&&&&&&&&&&&&&&&& if(info.bRelative) ang += (vecPrevLocation-vecLocation).Angle()+M_PI_2;
&&&&&&&&&&&&&&&&&&&& par-&vecVelocity.x = cosf(ang);
&&&&&&&&&&&&&&&&&&&& par-&vecVelocity.y = sinf(ang);
&&&&&&&&&&&&&&&&&&&& par-&vecVelocity *= hge-&Random_Float(info.fSpeedMin, info.fSpeedMax);
&&&&&&&&&&&
&&&&&&&&&&& // 设置粒子的重力、线角速度以及角加速度
&&&&&&&&&&&&&&&&&&&& par-&fGravity = hge-&Random_Float(info.fGravityMin, info.fGravityMax);
&&&&&&&&&&&&&&&&&&&& par-&fRadialAccel = hge-&Random_Float(info.fRadialAccelMin, info.fRadialAccelMax);
&&&&&&&&&&&&&&&&&&&& par-&fTangentialAccel = hge-&Random_Float(info.fTangentialAccelMin, info.fTangentialAccelMax);
&&&&&&&&&&& // 设置粒子的大小及偏移量
&&&&&&&&&&&&&&&&&&&& par-&fSize = hge-&Random_Float(info.fSizeStart, info.fSizeStart+(info.fSizeEnd-info.fSizeStart)*info.fSizeVar);
&&&&&&&&&&&&&&&&&&&& par-&fSizeDelta = (info.fSizeEnd-par-&fSize) / par-&fTerminalA
&&&&&&&&&&& // 设置粒子的旋转角度及偏移量
&&&&&&&&&&&&&&&&&&&& par-&fSpin = hge-&Random_Float(info.fSpinStart, info.fSpinStart+(info.fSpinEnd-info.fSpinStart)*info.fSpinVar);
&&&&&&&&&&&&&&&&&&&& par-&fSpinDelta = (info.fSpinEnd-par-&fSpin) / par-&fTerminalA
&&&&&&&&&&&&&&&&&&&& // 设置粒子颜色
par-&colColor.r = hge-&Random_Float(info.colColorStart.r, info.colColorStart.r+(info.colColorEnd.r-info.colColorStart.r)*info.fColorVar);
&&&&&&&&&&&&&&&&&&&& par-&colColor.g = hge-&Random_Float(info.colColorStart.g, info.colColorStart.g+(info.colColorEnd.g-info.colColorStart.g)*info.fColorVar);
&&&&&&&&&&&&&&&&&&&& par-&colColor.b = hge-&Random_Float(info.colColorStart.b, info.colColorStart.b+(info.colColorEnd.b-info.colColorStart.b)*info.fColorVar);
&&&&&&&&&&&&&&&&&&&& par-&colColor.a = hge-&Random_Float(info.colColorStart.a, info.colColorStart.a+(info.colColorEnd.a-info.colColorStart.a)*info.fAlphaVar);
&&&&&&&&&&& // 设置粒子颜色偏移量
&&&&&&&&&&&&&&&&&&&& par-&colColorDelta.r = (info.colColorEnd.r-par-&colColor.r) / par-&fTerminalA
&&&&&&&&&&&&&&&&&&&& par-&colColorDelta.g = (info.colColorEnd.g-par-&colColor.g) / par-&fTerminalA
&&&&&&&&&&&&&&&&&&&& par-&colColorDelta.b = (info.colColorEnd.b-par-&colColor.b) / par-&fTerminalA
&&&&&&&&&&&&&&&&&&&& par-&colColorDelta.a = (info.colColorEnd.a-par-&colColor.a) / par-&fTerminalA
&&&&&&&&&&& // 更新粒子系统边界盒
&&&&&&&&&&&&&&&&&&&& if(bUpdateBoundingBox) rectBoundingBox.Encapsulate(par-&vecLocation.x, par-&vecLocation.y);
&&&&&&&&&&& // 递增活动粒子数目
&&&&&&&&&&&&&&&&&&&& nParticlesAlive++;
&&&&&&&&&&& // 移动到下一个待生成粒子
&&&&&&&&&&&&&&&&&&&& par++;
&&&&&&&&&&&&& }
&&& // 设置先前粒子系统位置
&&&&&& vecPrevLocation=vecL
& 好了,至此,我们完全可以使用hgeParticleSystem来生成不错的粒子特效了,不过在这之前,让我们继续来看一下HGE对于hgeParticleSystem的更进一步封装:hgeParticleManager
& 类名 :hgeParticleManager
& 功能 :粒子系统管理类
& 头文件 :hge/hge181/include/hgeParticle.h
& 实现文件 : hge/hge181/src/helpers/hgepmanager.cpp
& 头文件如下:
class hgeParticleManager
&&& // 构造函数&析构函数
&&&&&& hgeParticleManager();
&&&&&& ~hgeParticleManager();
&&& // 更新函数
&&&&&& void&&&&&&&&&&&&&&&&&&&&& Update(float dt);
&&& // 渲染函数
&&&&&& void&&&&&&&&&&&&&&&&&&&&& Render();
&&& // 生成粒子系统
&&&&&& hgeParticleSystem*&&&&&& SpawnPS(hgeParticleSystemInfo *psi, float x, float y);
&&& // 粒子系统是否活动
&&&&&& bool&&&&&&&&&&&&&&&&&&&&& IsPSAlive(hgeParticleSystem *ps)
&&& // 设置粒子系统偏移
&&&&&& void&&&&&&&&&&&&&&&&&&&&& Transpose(float x, float y);
&&& // 获取粒子系统位移
&&&&&& void&&&&&&&&&&&&&&&&&&&&& GetTransposition(float *dx, float *dy) const {*dx=tX; *dy=tY;}
&&& // 销毁指定的粒子系统
&&&&&& void&&&&&&&&&&&&&&&&&&&&& KillPS(hgeParticleSystem *ps);
&&& // 销毁所有粒子系统
&&&&&& void&&&&&&&&&&&&&&&&&&&&& KillAll();
&&& // 私有化复制构造函数及赋值操作符函数,已达到屏蔽作用
&&&&&& hgeParticleManager(const hgeParticleManager &);
&&&&&& hgeParticleManager&&&& operator= (const hgeParticleManager &);
&&& // 粒子系统数量
&&&&&& int&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& nPS;
&&& // 偏移位置坐标
&&&&&& float&&&&&&&&&&&&&&&&&&&&& tX;
&&&&&& float&&&&&&&&&&&&&&&&&&&&& tY;
&&& // 粒子系统指针数组
&&&&&& hgeParticleSystem*&&&&&& psList[MAX_PSYSTEMS];
& hgeParticleManager看来还是相对简单的 :)
& 首先自然是构造函数和析构函数:
hgeParticleManager::hgeParticleManager()
&&& // 设定初始值,使用成员列表更好一些
&&&&&& nPS=0;
&&&&&& tX=tY=0.0f;
hgeParticleManager::~hgeParticleManager()
&&& // 遍历指针数组依次删除
&&&&&& for(i=0;i&nPS;i++) delete psList[i];
& 没有什么奇特的地方,那么接着让我们来看一看SpawnPS:
hgeParticleSystem* hgeParticleManager::SpawnPS(hgeParticleSystemInfo *psi, float x, float y)
&&& // 如果粒子系统超过上界,则返回
&&&&&& if(nPS==MAX_PSYSTEMS) return 0;
&&& // 生成粒子系统
&&&&&& psList[nPS]=new hgeParticleSystem(psi);
&&& // 启动
&&&&&& psList[nPS]-&FireAt(x,y);
&&& // 设置偏移
&&&&&& psList[nPS]-&Transpose(tX,tY);
&&& // 递增粒子系统数目
&&&&&& nPS++;
&&&&&& return psList[nPS-1];
& 函数很简单,生成粒子系统而已 :)
& 接下来的几个成员函数也并不困难:
bool hgeParticleManager::IsPSAlive(hgeParticleSystem *ps) const
&&& // 依次遍历数组查找指定的粒子系统
&&&&&& for(i=0;i&nPS;i++) if(psList[i]==ps)
void hgeParticleManager::Transpose(float x, float y)
&&& // 依次遍历并设置粒子系统偏移
&&&&&& for(i=0;i&nPS;i++) psList[i]-&Transpose(x,y);
&&& // 更新tX和tY
&&&&&& tX=x; tY=y;
void hgeParticleManager::KillPS(hgeParticleSystem *ps)
&&& // 依次遍历指针数组
&&&&&& for(i=0;i&nPS;i++)
&&&&&&& // 如果找到
&&&&&&&&&&&&& if(psList[i]==ps)
&&&&&&&&&&&&& {
&&&&&&&&&&& // 删除这个粒子系统
&&&&&&&&&&&&&&&&&&&& delete psList[i];
&&&&&&&&&&& // 并将其指向最后一个活动的粒子系统
&&&&&&&&&&&&&&&&&&&& psList[i]=psList[nPS-1];
&&&&&&&&&&& // 递减粒子系统数目
&&&&&&&&&&&&&&&&&&&& nPS--;
&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&& }
void hgeParticleManager::KillAll()
&&& // 遍历并删除所有粒子系统
&&&&&& for(i=0;i&nPS;i++) delete psList[i];
&&&&&& nPS=0;
& 最后,让我们来看一看Update和Render:
void hgeParticleManager::Render()
&&& // 依次遍历并渲染每个粒子系统
&&&&&& for(i=0;i&nPS;i++) psList[i]-&Render();
& Render相当简单,那么Update如何呢:
void hgeParticleManager::Update(float dt)
&&& // 对于每个存在的粒子系统
&&&&&& for(i=0;i&nPS;i++)
&&&&&&& // 更新该粒子系统
&&&&&&&&&&&&& psList[i]-&Update(dt);
&&&&&&& // 如果该粒子系统尚未启动并且活动粒子数目为0
&&&&&&&&&&&&& if(psList[i]-&GetAge()==-2.0f && psList[i]-&GetParticlesAlive()==0)
&&&&&&&&&&&&& {
&&&&&&&&&&& // 删除这个粒子系统
&&&&&&&&&&&&&&&&&&&& delete psList[i];
&&&&&&&&&&& // 将其指向最后一个活动粒子系统
&&&&&&&&&&&&&&&&&&&& psList[i]=psList[nPS-1];
&&&&&&&&&&& // 更新粒子系统数目
&&&&&&&&&&&&&&&&&&&& nPS--;
&&&&&&&&&&& // 递减计数值,已达到下次循环继续处理该位置粒子系统的目的
&&&&&&&&&&&&&&&&&&&& i--;
&&&&&&&&&&&&& }
& 呼,至此,HGE的粒子系统终算泛泛的讲解完毕了,虽然篇幅不短,但也还算简单,平心而论,HGE的粒子系统虽说并不十分复杂,但也提供了非常不错的显示效果和可扩展性,对于我们关于粒子系统的学习还是很有助益的,有兴趣的朋友远可以进一步使用或者扩展,说不定可以搞出令人惊奇的东西(到时务必告知一下,以便观摩学习)!好了好了,我想我废话也够多了,是时候说ByeBye了,那么,下次再见吧 :)
你可能感兴趣的:
没有相关文章
我们向您推荐的:
7727542770195136365300426385737364227383
&&&&&&&&&&
942322769042075483153441241596
?[]?[]?[]?[]?[]?[]
& 棋牌休闲游戏中心
增值电信业务经营许可证:浙B2- 文网文编号:浙网文[4号

我要回帖

更多关于 hge引擎登陆器 的文章

 

随机推荐