| 
 | 
 
首先来看使用lua语言改写上篇的粒子系统代码. 
(不过鄙人的lua,python都很菜的,其原因就是一直没有练习的机会) 
对于Lua,其扩展有luabind,tolua++,luaplus,前2着都与boost有关 
所以就使用luaplus,简单些 
开始了先上lua脚本代码(我把lua当成了c++,开始书写很不习惯,居然不知道lua中的逻辑符号是not and or 而非 !&& || 呵呵) 
 
lua脚本: 
 
-- 这是盖莫引擎中使用lua脚本的测试粒子 
 
-- 定义粒子池粒子个数 
max_particles = 2400 
 
-- 定义粒子初始位置 
particle_pos_x = 0.0 
particle_pos_y = 0.0 
particle_pos_z = 3.0 
 
-- 定义重力加速度 
gravity = 9.8 
 
-- 定义粒子大小 
particle_size = 0.8 
 
-- 定义粒子寿命 
particle_life = 8.2 
 
-- 定义批处理粒子个数 
batch_particles = 80 
 
-- 定义粒子和地面之间的摩擦力 
friction = 0.75 
 
-- 定义粒子系统发射半径 
fountain_radius = 1.6 
 
-- 定义粒子范围半径 
particle_r = (fountain_radius + particle_size/2)*(fountain_radius + particle_size/2) 
 
-- 初始化随机种子 
function InitRand() 
   math.randomseed(os.time()); 
end 
    
-- 初始化粒子颜色red,green,blue 
function InitColorRed(t) 
    return 0.7 + 0.3 * math.sin(0.34*t + 0.1); 
end 
function InitColorGreen(t) 
    return 0.6 + 0.4 * math.sin(0.63*t + 1.1); 
end 
function InitColorBlue(t) 
    return 0.6 + 0.4 * math.sin(0.91*t + 2.1); 
end 
 
-- 定义粒子速度 
particle_vel = 8.0 
 
-- 获取时间对应的速度值 
function GetVelByTime(t) 
    return particle_vel*(0.8 + 0.1*(math.sin(0.5*t)+math.sin(0.31*t))); 
end 
 
-- 获取粒子初始速度 
function InitZVel() 
    return 0.7 + (0.3/4096.0) * (math.random(1,4095)); 
end 
    
-- 获取xy平面随机转角 
function GetRandRotXY() 
    return (2.0*3.14159265/4096.0) * math.random(1,4095) 
end    
 
-- 获取粒子随机速度x分量 
function InitXVel(t) 
   xy_angle = GetRandRotXY(); 
   vt = GetVelByTime(t); 
   return 0.45 * math.cos(xy_angle)*vt; 
end 
 
-- 获取粒子随机速度y分量 
function InitYVel(t) 
   xy_angle = GetRandRotXY(); 
   vt = GetVelByTime(t); 
   return 0.45 * math.sin(xy_angle)*vt; 
end 
 
-- 定义更新粒子后的全局变量 
new_life = 0; 
new_xpos = 0; 
new_ypos = 0; 
new_zpos = 0; 
new_xvel = 1; 
new_yvel = 1; 
new_zvel = 1; 
 
-- 更新粒子状态 
function UpdateParticles(life,xpos,ypos,zpos,xvel,yvel,zvel,dt) 
    -- 修正粒子生命 
    new_life = life - dt * (1.0 / particle_life); 
    -- 修正粒子速度 
    new_zvel = zvel - gravity  *dt; 
    new_xpos = xpos + xvel*dt; 
    new_ypos = ypos + yvel*dt; 
    new_zpos = zpos + new_zvel*dt;   
    if new_zvel < 0.0 then 
        if new_xpos*new_xpos + new_ypos*new_ypos < particle_r and new_zpos < particle_pos_z + particle_size/2 then 
            new_zvel = -friction * new_zvel; 
            new_zpos  = particle_pos_z + particle_size/2 + friction * (particle_pos_z + particle_size/2 - new_zpos); 
        -- 当粒子碰撞到地面应该跳起来 
        elseif new_zpos < particle_size/2 then 
           new_zvel = -friction * new_zvel; 
           new_zpos  = particle_size/2 + friction * (particle_size/2 - new_zpos); 
        end 
    end          
end 
 
其关联的c++代码如下: 
 
#include <GEngine/Main.hpp> 
#include <luaplus/luaplus.h> 
 
#define WIN_WIDTH  640 
#define WIN_HEIGHT 480 
 
//! 粒子纹理 
static const unsigned char particle_texture[] = 
{ 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x11, 0x22, 0x22, 0x11, 0x00, 0x00, 
    0x00, 0x11, 0x33, 0x88, 0x77, 0x33, 0x11, 0x00, 
    0x00, 0x22, 0x88, 0xff, 0xee, 0x77, 0x22, 0x00, 
    0x00, 0x22, 0x77, 0xee, 0xff, 0x88, 0x22, 0x00, 
    0x00, 0x11, 0x33, 0x77, 0x88, 0x33, 0x11, 0x00, 
    0x00, 0x00, 0x11, 0x33, 0x22, 0x11, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 
}; 
 
//! 粒子纹理大小   
#define P_TEX_WIDTH  8    
#define P_TEX_HEIGHT 8 
 
//////////////////////////////////////////////////////////// 
/// 给出一个初始化粒子的方法 
//////////////////////////////////////////////////////////// 
void G_CALL InitParticle(core: article* p,float t); 
 
//////////////////////////////////////////////////////////// 
/// 更新粒子函数 
//////////////////////////////////////////////////////////// 
void G_CALL UpdateParticle(core::Particle* p,float time); 
 
//////////////////////////////////////////////////////////// 
/// 场景旋转和偏移 
//////////////////////////////////////////////////////////// 
float TransForm(double t); 
 
//////////////////////////////////////////////////////////// 
/// 构造纹理 
////////////////////////////////////////////////////////////   
void BuildTexture(GLuint& texture_id); 
 
//////////////////////////////////////////////////////////// 
/// 渲染场景 
//////////////////////////////////////////////////////////// 
void RenderScene(); 
 
core: evice* device = NULL; 
libmath::TriTable* table = NULL;   
 
LuaPlus: uaStateOwner *state = NULL; 
   
//////////////////////////////////////////////////////////// 
/// 初始化luaplus   
////////////////////////////////////////////////////////////      
void InitLua(const char* lua) 
{    
    state = new  LuaPlus::LuaStateOwner; 
    // 载入Lua脚本 
    (*state)->DoFile(lua);   
    LuaPlus::LuaFunction<void> initrand(*state,"InitRand"); 
    initrand();   
}   
 
void DeinitLua() 
{ 
    delete state; 
} 
 
//////////////////////////////////////////////////////////// 
/// 从脚本载入粒子描述数据 
//////////////////////////////////////////////////////////// 
void LoadData(core::ParticleSystemDesc &desc); 
 
int main(int argc, char **argv) 
{ 
    InitLua("particle.lua"); 
    int        i; 
    double     t0, t; 
    
    core::VideoMode mode; 
    mode.width = WIN_WIDTH; 
    mode.height = WIN_HEIGHT; 
    
    device = core::InitDevice("盖莫引擎粒子系统",false,mode); 
    table = device->GetTriTable(); 
 
    core::ParticleSystemDesc desc; 
    
    GLuint texture_id; 
    BuildTexture(texture_id); 
    desc.texture_id = texture_id;    
    desc.init_fn = &InitParticle; 
    desc.update_fn = &UpdateParticle; 
    LoadData(desc); 
    core::ParticleSystem* ps = device->GetParticleSystem(desc); 
 
    t0 = device->GetTime(); 
    BEGIN_LOOP(device) 
        t = device->GetTime() - t0; 
        RenderScene(); 
        float dt = TransForm(t); 
        ps->Render(); 
    END_LOOP(device) 
    
    device->Close(); 
    device->Drop(); 
    
    DeinitLua(); 
    return 0; 
} 
 
void BuildTexture(GLuint& texture_id) 
{ 
    glGenTextures( 1, &texture_id ); 
    glBindTexture( GL_TEXTURE_2D, texture_id); 
    glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); 
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); 
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); 
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); 
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, P_TEX_WIDTH, P_TEX_HEIGHT, 
                 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, particle_texture);   
} 
 
//////////////////////////////////////////////////////////// 
/// 场景旋转和偏移 
//////////////////////////////////////////////////////////// 
float TransForm(double t) 
{ 
    double xpos, ypos, zpos, angle_x, angle_y, angle_z; 
    static double t_old = 0.0; 
    float  dt = (float)(t-t_old); 
    t_old = t; 
 
    angle_x = 90.0 - 10.0; 
    angle_y = 10.0 * sin( 0.3 * t ); 
    angle_z = 10.0 * t; 
    glRotated( -angle_x, 1.0, 0.0, 0.0 ); 
    glRotated( -angle_y, 0.0, 1.0, 0.0 ); 
    glRotated( -angle_z, 0.0, 0.0, 1.0 ); 
 
    xpos =  15.0 * sin( (M_PI/180.0) * angle_z ) + 
             2.0 * sin( (M_PI/180.0) * 3.1 * t ); 
    ypos = -15.0 * cos( (M_PI/180.0) * angle_z ) + 
             2.0 * cos( (M_PI/180.0) * 2.9 * t ); 
    zpos = 4.0 + 2.0 * cos( (M_PI/180.0) * 4.9 * t ); 
    glTranslated( -xpos, -ypos, -zpos ); 
    return dt; 
} 
 
void RenderScene() 
{ 
    glViewport( 0, 0, WIN_WIDTH,WIN_HEIGHT); 
    glClearColor( 0.1f, 0.1f, 0.1f, 1.0f ); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); 
    glMatrixMode( GL_PROJECTION ); 
    glLoadIdentity(); 
    gluPerspective(65.0, 640.0/480.0, 1.0, 60.0 ); 
    glMatrixMode( GL_MODELVIEW ); 
    glLoadIdentity(); 
} 
 
//////////////////////////////////////////////////////////// 
/// 给出一个初始化粒子的方法(t为粒子系统启动时间(单位:秒)) 
//////////////////////////////////////////////////////////// 
void G_CALL InitParticle(core::Particle* p,float t) 
{ 
    //! 初始化粒子位置位置 
    float xpos = (*state)->GetGlobal("particle_pos_x").GetFloat(); 
    float ypos = (*state)->GetGlobal("particle_pos_y").GetFloat(); 
    float zpos = (*state)->GetGlobal("particle_pos_z").GetFloat(); 
    p->position = Vector3f(xpos,ypos,zpos); 
    
    //! 初始化粒子颜色 
    LuaPlus::LuaFunction<float> red(*state,"InitColorRed"); 
    LuaPlus::LuaFunction<float> green(*state,"InitColorGreen"); 
    LuaPlus::LuaFunction<float> blue(*state,"InitColorBlue"); 
    p->color.red = red(t); 
    p->color.green = green(t); 
    p->color.blue = blue(t); 
    
    //! 初始化粒子初始速度 
    LuaPlus::LuaFunction<float> xvel(*state,"InitXVel"); 
    LuaPlus::LuaFunction<float> yvel(*state,"InitYVel"); 
    LuaPlus::LuaFunction<float> zvel(*state,"InitZVel");    
    p->velocity = Vector3f(xvel(t),yvel(t),zvel(t)); 
} 
 
//////////////////////////////////////////////////////////// 
/// 更新粒子函数 
//////////////////////////////////////////////////////////// 
void G_CALL UpdateParticle(core::Particle* p,float time) 
{ 
    LuaPlus::LuaFunction<void> update_fn(*state,"UpdateParticles");   
    float life = p->life; 
    float xpos = p->position.x; 
    float ypos = p->position.y; 
    float zpos = p->position.z; 
    float xvel = p->velocity.x; 
    float yvel = p->velocity.y; 
    float zvel = p->velocity.z; 
    update_fn(life,xpos,ypos,zpos,xvel,yvel,zvel,time); 
    
    //! 获取粒子的更新后数据 
    p->life = (*state)->GetGlobal("new_life").GetFloat();   
    p->position.x = (*state)->GetGlobal("new_xpos").GetFloat(); 
    p->position.y = (*state)->GetGlobal("new_ypos").GetFloat(); 
    p->position.z = (*state)->GetGlobal("new_zpos").GetFloat(); 
    p->velocity.x = xvel; 
    p->velocity.y = yvel;   
    p->velocity.z = (*state)->GetGlobal("new_zvel").GetFloat();   
} 
 
//////////////////////////////////////////////////////////// 
/// 从脚本载入粒子描述数据 
//////////////////////////////////////////////////////////// 
void LoadData(core::ParticleSystemDesc &desc) 
{ 
    desc.batch_particles = (*state)->GetGlobal("batch_particles").GetInteger(); 
    desc.particle_size = (*state)->GetGlobal("particle_size").GetFloat(); 
    desc.life_span = (*state)->GetGlobal("particle_life").GetFloat(); 
    int max_particles = (*state)->GetGlobal("max_particles").GetInteger(); 
    desc.particle_number = max_particles;      
} 
对应的贴图如下: 
 
  
不过刚开始做的时候写lua的时候有点问题其结果变成了下图,看来要熟悉Lua只有多多练习 
 
 
  
那么下一步要做的就是把lua集成进引擎中了 |   
 
 
 
 |