加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

基于Direct3D实现简单的粒子系统(二) - 增加LUA脚本支持

发布时间:2020-12-14 22:25:15 所属栏目:大数据 来源:网络整理
导读:????? 之前已经创建了一个简单的粒子系统(点这里 ),但是使用起来还是不是很方便,这次的任务就是为这个系统增加脚本支持。使用脚本来定义粒子系统的各项属性,再从主程序中将这些属性读出来,创建粒子系统。我对小巧简洁的东西有种特殊的喜好,因此我选择

????? 之前已经创建了一个简单的粒子系统(点这里 ),但是使用起来还是不是很方便,这次的任务就是为这个系统增加脚本支持。使用脚本来定义粒子系统的各项属性,再从主程序中将这些属性读出来,创建粒子系统。我对小巧简洁的东西有种特殊的喜好,因此我选择了Lua语言。Lua与C的交互需要频繁的操作栈,使用起来并不是很方便,因此先简单的封装一下,可以不用直接操作栈就可以了。

????? 下面的这个类用于加载一个lua脚本,并提供了几个读取变量值的方法。其中GetInt,GetFloat,GetString用于读取变量field,GetTInt,GetTFloat,GetTString用于读取表table中的第idx个字段,ret返回读取到的值。

EpLuaScriptEngine.h:

#ifndef _EPLUASCRIPTENGINE_H_
#define _EPLUASCRIPTENGINE_H_
#include <lua.hpp>

class EpLuaScriptEngine
{
public :
??? EpLuaScriptEngine ();
??? virtual ~ EpLuaScriptEngine ();

??? bool LoadScript ( const char * fileName );
??? bool GetInt ( const char * field , int * ret );
??? bool GetFloat ( const char * field , float * ret );
??? bool GetString ( const char * field , const char ** ret );
??? bool GetTInt ( const char * table , int idx , int * ret );
??? bool GetTFloat ( const char * table , float * ret );
??? bool GetTString ( const char * table , const char ** ret );

protected :
??? lua_State * m_L ;
};
#endif

EpLuaScriptEngine.cpp:

#include "EpLuaScriptEngine.h"
#include <iostream>
using namespace std ;

EpLuaScriptEngine :: EpLuaScriptEngine ()
{
??? m_L = lua_open ();
}

EpLuaScriptEngine ::~ EpLuaScriptEngine ()
{
??? lua_close ( m_L );
}

bool EpLuaScriptEngine :: LoadScript ( const char * fileName )
{
??? if ( luaL_loadfile ( m_L , fileName ) || lua_pcall ( m_L , 0 , 0 ))
??? {
??????? cout << lua_tostring ( m_L , - 1 ) << endl ;
??????? return false ;
??? }
??? return true ;
}

bool EpLuaScriptEngine :: GetInt ( const char * field , int * ret )
{
??? int top = lua_gettop ( m_L );
??? lua_getglobal ( m_L , field );
??? if ( lua_isnumber ( m_L , - 1 ))
??? {
??????? * ret = ( int ) lua_tonumber ( m_L , - 1 );
??????? lua_settop ( m_L , top );
??????? return true ;
??? }
??? else
??? {
??????? lua_settop ( m_L , top );
??????? return false ;
??? }
}

bool EpLuaScriptEngine :: GetFloat ( const char * field , float * ret )
{
??? int top = lua_gettop ( m_L );
??? lua_getglobal ( m_L , - 1 ))
??? {
??????? * ret = ( float ) lua_tonumber ( m_L , top );
??????? return false ;
??? }
}

bool EpLuaScriptEngine :: GetString ( const char * field , const char ** ret )
{
??? int top = lua_gettop ( m_L );
??? lua_getglobal ( m_L , field );
??? if ( lua_isstring ( m_L , - 1 ))
??? {
??????? * ret = lua_tostring ( m_L , top );
??????? return false ;
??? }
}

bool EpLuaScriptEngine :: GetTInt ( const char * table , table );
??? if ( ! lua_istable ( m_L , - 1 ))
??? {
??????? lua_settop ( m_L , top );
??????? return false ;
??? }
??? lua_rawgeti ( m_L , - 1 , idx );
??? if ( ! lua_isnumber ( m_L , top );
??????? return false ;
??? }
??? * ret = ( int ) lua_tonumber ( m_L , - 1 );
??? lua_settop ( m_L , top );
??? return true ;
}

bool EpLuaScriptEngine :: GetTFloat ( const char * table , top );
??????? return false ;
??? }
??? * ret = ( float ) lua_tonumber ( m_L , top );
??? return true ;
}

bool EpLuaScriptEngine :: GetTString ( const char * table , idx );
??? if ( ! lua_isstring ( m_L , top );
??????? return false ;
??? }
??? * ret = lua_tostring ( m_L , top );
??? return true ;
}

有了这个类以后就可以用它读取粒子脚本中的属性。现在需要在之前的粒子系统类中,加入一个静态函数,用于从脚本加载一个粒子系统。

EpParticleSystem * EpParticleSystem :: CreateFromFile ( LPDIRECT3DDEVICE9 device , const char * fileName )
{
??? if ( ! fileName ) return NULL ;
??? //初始化lua,加载粒子脚本
??? EpLuaScriptEngine lua ;
??? lua . LoadScript ( fileName );

??? D3DVECTOR position = { 0 }; ??? //粒子系统的位置
??? lua . GetTFloat ( "position" , 1 , & position . x );
??? lua . GetTFloat ( "position" , 2 , & position . y );
??? lua . GetTFloat ( "position" , 3 , & position . z );
??? D3DVECTOR range = { 0 }; ??? //长宽高范围
??? lua . GetTFloat ( "range" , & range . x );
??? lua . GetTFloat ( "range" , & range . y );
??? lua . GetTFloat ( "range" , & range . z );
??? D3DVECTOR accel = { 0 }; ??? //加速度
??? lua . GetTFloat ( "accel" , & accel . x );
??? lua . GetTFloat ( "accel" , & accel . y );
??? lua . GetTFloat ( "accel" , & accel . z );
??? D3DVECTOR emiPosMin = { 0 }; ??? //发射位置的范围
??? lua . GetTFloat ( "emiPosMin" , & emiPosMin . x );
??? lua . GetTFloat ( "emiPosMin" , & emiPosMin . y );
??? lua . GetTFloat ( "emiPosMin" , & emiPosMin . z );
??? D3DVECTOR emiPosMax = { 0 };
??? lua . GetTFloat ( "emiPosMax" , & emiPosMax . x );
??? lua . GetTFloat ( "emiPosMax" , & emiPosMax . y );
??? lua . GetTFloat ( "emiPosMax" , & emiPosMax . z );
??? D3DXVECTOR3 veloMin ;??? //粒子初始速度范围
??? ZeroMemory ( & veloMin , sizeof ( veloMin ));
??? lua . GetTFloat ( "veloMin" , & veloMin . x );
??? lua . GetTFloat ( "veloMin" , & veloMin . y );
??? lua . GetTFloat ( "veloMin" , & veloMin . z );
??? D3DXVECTOR3 veloMax ;
??? ZeroMemory ( & veloMax , sizeof ( veloMax ));
??? lua . GetTFloat ( "veloMax" , & veloMax . x );
??? lua . GetTFloat ( "veloMax" , & veloMax . y );
??? lua . GetTFloat ( "veloMax" , & veloMax . z );
??? D3DCOLORVALUE colorMin = { 0 }; ??????? //粒子颜色范围
??? lua . GetTFloat ( "colorMin" , & colorMin . a );
??? lua . GetTFloat ( "colorMin" , & colorMin . r );
??? lua . GetTFloat ( "colorMin" , & colorMin . g );
??? lua . GetTFloat ( "colorMin" , 4 , & colorMin . b);
??? D3DCOLORVALUE colorMax = { 0 };
??? lua . GetTFloat ( "colorMax" , & colorMax . a );
??? lua . GetTFloat ( "colorMax" , & colorMax . r );
??? lua . GetTFloat ( "colorMax" , & colorMax . g );
??? lua . GetTFloat ( "colorMax" , & colorMax . b);
??? float psizeMin = 0.0f ;??? //粒子大小范围
??? lua . GetFloat ( "psizeMin" , & psizeMin );
??? float psizeMax = 0.0f ;
??? lua . GetFloat ( "psizeMax" , & psizeMax );
??? int maxCount = 0 ;??? //最大粒子数量
??? lua . GetInt ( "maxCount" , & maxCount );
??? int emiCount = 0 ;??? //每次发射数量
??? lua . GetInt ( "emiCount" , & emiCount );
??? float emiInterval = 1.0f ; //发射间隔时间
??? lua . GetFloat ( "emiInterval" , & emiInterval );
??? const char * textureFile = NULL ;
??? lua . GetString ( "texture" , & textureFile );

??? EpParticleSystem * ps = new EpParticleSystem ( position , range , accel , emiPosMin ,
??????? emiPosMax , veloMin , veloMax , colorMin , colorMax , psizeMin , psizeMax , maxCount ,
??????? emiCount , emiInterval , device , textureFile );
??? return ps;
}

这里粒子系统的构造函数稍微有一点变动。因为脚本中只能定义纹理使用的文件名,而真正创建纹理还是要在C++中做,因此把纹理的创建由外部改到了内部。对于字符串textureFile 因为是存在于Lua的栈中,所以在这个函数返回后就会被销毁,因此如果需要在EpParticleSystem的构造函数以外创建纹理的话,在构造函数中就需要复制该字符串。像下面这样:

m_TexFileName = NULL ;
if ( textureFileName )
{
??? int length = strlen ( textureFileName ) + 1 ;
??? m_TexFileName = new char [ length ];
??? strcpy_s ( m_TexFileName , length , textureFileName );
}

对于上次的烟火的粒子,在Lua脚本中就可以这样写:

Firework.lua:

emiRange = 0.05
veloRange = 0.006

position = { 0.0 , 0.0 , 0.0 }
range = { 4.0 , 4.0 , 4.0 }
accel = { 0.0 , - 0.0002 , 0.0 }
emiPosMin = { - emiRange , - 2.0 , - emiRange }
emiPosMax = { emiRange , emiRange }
veloMin = { - veloRange , 0.02 , - veloRange }
veloMax = { veloRange , 0.03 , veloRange }
colorMin = { 0.0 , 0.0 }
colorMax = { 0.0 , 1.0 , 1.0 }
psizeMin = 0.3
psizeMax = 0.5
maxCount = 3000
emiCount = 10
emiInterval = 0.01
texture = " snow.tga"

现在就可以把之前创建粒子系统的那一大段代码改成下面这行了:

g_Firework = EpParticleSystem :: CreateFromFile ( g_D3DDevice , "Firework.lua" );
??? if ( ! g_Firework ) return false ;

?

脱离了硬编码,这个粒子系统变得灵活多了。比如我们可以再写一个雪花的脚本,然后只需要更改上面的文件名就可以了。

snow.lua:

emiRange = 2.0
veloRange = 0.006

position = { 0.0 , 4.0 }
accel = { 0.00005 , - 0.0001 , 2.0 , 0.00 , 1.0 }
colorMax = { 0.0 , 1.0 }
psizeMin = 0.3
psizeMax = 0.5
maxCount = 3000
emiCount = 10
emiInterval = 0.01
texture = " snow.tga"
最新的源代码: http://download.csdn.net/source/1663374

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读