zoukankan      html  css  js  c++  java
  • D3D中的粒子系统(6)

    14.3.3 例子程序:粒子枪

    本例程实现了一个粒子枪系统,运行效果如图14.4所示:

    下面是粒子枪系统的定义:
        class cParticleGun : public cParticleSystem
        {
        private:
            cCamera* m_camera;
        public:
            cParticleGun(cCamera* camera);
            virtual void reset_particle(sParticleAttribute* attr);
            virtual void update(float time_delta);
        };

    构造函数需要提供一个照相机的位置点,这是因为系统需要知道照相机的位置及朝向,以决定在哪创建一个粒子。
        cParticleGun::cParticleGun(cCamera* camera)
        {
            m_camera        = camera;
            m_size            = 0.8f;
            m_vb_num        = 2048;
            m_vb_offset        = 0;
            m_vb_batch_num    = 512;
        }

    reset_particle方法设置粒子的位置为当前照相机的位置,并且设置粒子运动的速度为照像机方向的100倍。这样,子弹将射向我们正在看的方向,粒子颜色为绿色。
        void cParticleGun::reset_particle(sParticleAttribute* attr)
        {
            attr->is_alive = true;
            D3DXVECTOR3 camera_dir;   
            m_camera->get_look(&camera_dir);
            attr->position      = m_camera->m_pos;    // change to camera position
                attr->position.y -= 1.0f;                // sightly below camera so it looks like we're carrying a gun
            // travels in the direction the camera is looking
                attr->velocity = camera_dir * 100.0f;
            attr->color        = D3DXCOLOR(0.0f, 1.0f, 0.0f, 1.0f);    // green
            attr->age        = 0.0f;
            attr->life_time = 1.0f;    // lives for 1 seconds
        }

    update方法更新粒子的位置,并且杀死超过其生命周期的粒子,然后,我们搜索粒子列表删除已经死了的粒子。
        void cParticleGun::update(float time_delta)
        {
            for(list<sParticleAttribute>::iterator iter = m_particles.begin(); iter != m_particles.end(); iter++)
            {
                iter->position += iter->velocity * time_delta;
                iter->age       += time_delta;
                if(iter->age > iter->life_time)   
                    iter->is_alive = false;    // kill
            }
            remove_dead_particles();
        }

    执行程序:
        #include "d3dUtility.h"
        #include "camera.h"
        #include "ParticleSystem.h"
        #include <cstdlib>
        #include <ctime>
        #pragma warning(disable : 4100)
        const int WIDTH  = 640;
        const int HEIGHT = 480;
        IDirect3DDevice9*    g_device;
        cParticleSystem*    g_gun;
        cCamera                g_camera(AIR_CRAFT);
            ////////////////////////////////////////////////////////////////////////////////////////////////////
        bool setup()
        {   
            srand((unsigned int)time(NULL));
            // create laser
            g_gun = new cParticleGun(&g_camera);
            g_gun->init(g_device, "flare_alpha.dds");
            // setup a basic scnen, the scene will be created the first time this function is called.
                draw_basic_scene(g_device, 1.0f);
            // set the projection matrix
            D3DXMATRIX proj;
            D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI/4.0f, (float)WIDTH/HEIGHT, 1.0f, 1000.0f);
            g_device->SetTransform(D3DTS_PROJECTION, &proj);
            return true;
        }
            ///////////////////////////////////////////////////////////////////////////////////////////////////////
        void cleanup()
        {   
            delete g_gun;
            // pass NULL for the first parameter to instruct cleanup
            draw_basic_scene(NULL, 1.0f);
        }
            ///////////////////////////////////////////////////////////////////////////////////////////////////////
        bool display(float time_delta)
        {
            // update the camera
            if( GetAsyncKeyState(VK_UP) & 0x8000f )
                g_camera.walk(4.0f * time_delta);
            if( GetAsyncKeyState(VK_DOWN) & 0x8000f )
                g_camera.walk(-4.0f * time_delta);
            if( GetAsyncKeyState(VK_LEFT) & 0x8000f )
                g_camera.yaw(-1.0f * time_delta);
            if( GetAsyncKeyState(VK_RIGHT) & 0x8000f )
                g_camera.yaw(1.0f * time_delta);
            if( GetAsyncKeyState('N') & 0x8000f )
                g_camera.strafe(-4.0f * time_delta);
            if( GetAsyncKeyState('M') & 0x8000f )
                g_camera.strafe(4.0f * time_delta);
            if( GetAsyncKeyState('W') & 0x8000f )
                g_camera.pitch(1.0f * time_delta);
            if( GetAsyncKeyState('S') & 0x8000f )
                g_camera.pitch(-1.0f * time_delta);   
            // update the view matrix representing the camera's new position/orientation
            D3DXMATRIX view_matrix;
            g_camera.get_view_matrix(&view_matrix);
            g_device->SetTransform(D3DTS_VIEW, &view_matrix);   
            g_gun->update(time_delta);
            // render now
            g_device->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
            g_device->BeginScene();
            D3DXMATRIX identity_matrix;
            D3DXMatrixIdentity(&identity_matrix);
            g_device->SetTransform(D3DTS_WORLD, &identity_matrix);
            draw_basic_scene(g_device, 1.0f);
            // order important, render firework last.
                g_device->SetTransform(D3DTS_WORLD, &identity_matrix);
            g_gun->render();
            g_device->EndScene();
            g_device->Present(NULL, NULL, NULL, NULL);
            return true;
        }
            ///////////////////////////////////////////////////////////////////////////////////////////////////////
        LRESULT CALLBACK wnd_proc(HWND hwnd, UINT msg, WPARAM word_param, LPARAM long_param)
        {
            switch(msg)
            {
            case WM_DESTROY:
                PostQuitMessage(0);
                break;
            case WM_KEYDOWN:
                if(word_param == VK_ESCAPE)
                    DestroyWindow(hwnd);
                // Note: we use the message system over GetAsyncKeyState because GetAsyncKeyState was adding
                // particles too fast.  The message system is slower and does not add them as fast. 
                // This isn't the best solution, but works for illustration purposes.
                if(word_param == VK_SPACE)
                    g_gun->add_particle();
                break;
            }
            return DefWindowProc(hwnd, msg, word_param, long_param);
        }
            ///////////////////////////////////////////////////////////////////////////////////////////////////////
        int WINAPI WinMain(HINSTANCE inst, HINSTANCE, PSTR cmd_line, int cmd_show)
        {
            if(! init_d3d(inst, WIDTH, HEIGHT, true, D3DDEVTYPE_HAL, &g_device))
            {
                MessageBox(NULL, "init_d3d() - failed.", 0, MB_OK);
                return 0;
            }
            if(! setup())
            {
                MessageBox(NULL, "Steup() - failed.", 0, MB_OK);
                return 0;
            }
            enter_msg_loop(display);
            cleanup();
            g_device->Release();
            return 0;
        }

    下载源程序

  • 相关阅读:
    WPF DelegateCommand 出现Specified cast is not valid
    WPF DelegateCommand 出现Specified cast is not valid
    WPF DelegateCommand 出现Specified cast is not valid
    win10 sdk 是否向下兼容
    win10 sdk 是否向下兼容
    win10 sdk 是否向下兼容
    PHP extract() 函数
    PHP end() 函数
    PHP each() 函数
    PHP current() 函数
  • 原文地址:https://www.cnblogs.com/flying_bat/p/1137673.html
Copyright © 2011-2022 走看看