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

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

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

      之前已经创建了一个简单的粒子系统(点这里 ),但是使用起来还是不是很方便,这次的任务就是为这个系统增加脚本支持。使用脚本来定义粒子系统的各项属性,再从主程序中将这些属性读出来,创建粒子系统。我对小巧简洁的东西有种特殊的喜好,因此我选择了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
总结

以上是内存溢出为你收集整理的基于Direct3D实现简单的粒子系统(二) - 增加LUA脚本支持全部内容,希望文章能够帮你解决基于Direct3D实现简单的粒子系统(二) - 增加LUA脚本支持所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1268259.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存