游戏开发论坛

 找回密码
 立即注册
搜索
查看: 3578|回复: 2

盖莫游戏引擎粒子系统(使用lua脚本载入数据和处理方法)

[复制链接]

50

主题

69

帖子

69

积分

注册会员

Rank: 2

积分
69
发表于 2010-2-24 19:51:00 | 显示全部楼层 |阅读模式
首先来看使用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集成进引擎中了

23

主题

59

帖子

59

积分

注册会员

Rank: 2

积分
59
发表于 2010-5-9 01:28:00 | 显示全部楼层

Re:盖莫游戏引擎粒子系统(使用lua脚本载入数据和处理方法)

!-!

56

主题

94

帖子

98

积分

注册会员

Rank: 2

积分
98
发表于 2010-5-9 13:21:00 | 显示全部楼层

Re:盖莫游戏引擎粒子系统(使用lua脚本载入数据和处理方法)

有问题吗?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-7-1 19:34

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表