鬼火(irrlicht)的复燃

来源:互联网 发布:软件发短信 编辑:程序博客网 时间:2024/04/25 19:15

    点此领取楼主。

    我说的“鬼火(irrlicht)“是一个开源的3D渲染引擎,基于C++开发。

    大概3年多以前第一次接触到irrlicht,那时候还有一个“食人魔(OGRE)”,也是基于C++的开源3D渲染引擎,二者之间我选择了前者。虽然OGRE拥有更强大的社区支持,并且拥有更加流畅的结构,但是对于初学者而言整个系统国语复杂(除非你坚持钻研下去直到豁然开朗的那一天,而我则只是浅尝辄止),所以我选择了相对简洁的鬼火引擎。

    大概有半个月的时间零散的学习了irrlicht的一些demo,最后自己仿照官方例程改写了一个完整的3d演示程序,所有数据未做更改。

    期间还附带地学习了irrklang音频处理引擎,与irrlicht啊呸使用相得益彰,irrlicht用于video渲染,irrklang用于audio输出,完美!

    之后诸多杂事(或者只是懒惰的借口?)以至于将此学习搁置一旁,如今重拾,似乎又找回了当初的那种感觉。






























程序结构

App.cpp:

WinMain()

{

new Game();  //SimpleGame.cpp

Game->Run(); //

return;

}


SimpleGame的声明

//#ifndef __SIMPLEGAME_H_INCLUDED__#define __SIMPLEGAME_H_INCLUDED__#include <windows.h>// Irrlicht dependencies#include <irrlicht.h>using namespace irr;using namespace core;using namespace scene;using namespace video;using namespace io;using namespace gui;#pragma comment(lib,"irrlicht.lib")// IrrKlang audio support#include <irrKlang.h>using namespace irrklang;#pragma comment (lib, "irrKlang.lib")typedef struct particleImpact{u32 when;vector3df pos;vector3df outVector;} SParticleImpact;namespace Parameters{namespace FullScreen{enum State{On = 1,Off = 2};}namespace BufferedShadow{enum State{On = 1,Off = 2};}namespace VerticalSync{enum State{On = 1,Off = 2};}namespace AntiAlias{enum State{On = 1,Off = 2};}namespace PlayMusic{enum State{On = 1,Off = 2};}}using namespace Parameters;class Size{public:Size(int w, int h);int Width();int Height();private:int width;int height;};class Game :public IEventReceiver{public:const int CAMERA_COUNT=7;Game(E_DRIVER_TYPE driverType, Size resolution,  FullScreen::State full, BufferedShadow::State shadow,              VerticalSync::State vsync, AntiAlias::State anti, PlayMusic::State music);void SetBkMusic(char* pszMusicFile);~Game();void Run();virtual bool OnEvent(const SEvent& evt);private:void CreateLoadingScreen();void LoadSceneData();void SwitchToNextScene();void Shoot();void CreateParticleImpacts();SIrrlichtCreationParameters params;IrrlichtDevice* irrDevice;IVideoDriver*  videoDriver;ISceneManager* sceneMgr;IGUIEnvironment* guiEnv;IFileSystem* fileSys;ITimer*  timer;PlayMusic::State playMusic;ISoundEngine* sndEngine;ISound* bkMusic;ISoundSource* ballSound;ISoundSource* impactSound;int currentScene;SColor bgColor;IGUIStaticText* statusText;IGUIInOutFader* inOutFader;IQ3LevelMesh* quakeLevelMesh;ISceneNode* quakeLevelNode;ISceneNode* skyboxNode;IAnimatedMeshSceneNode* model1;IAnimatedMeshSceneNode* model2;IParticleSystemSceneNode* campFire;IMetaTriangleSelector* metaSelector;ITriangleSelector* mapSelector;s32 sceneStartTime;s32 timeForThisScene;array<SParticleImpact> Impacts;};#endif


SimpleGame的实现

#include "SimpleGame.h"Size::Size(int w, int h){width = w;height = h;}int Size::Width(){return width;}int Size::Height(){return height;}Game::Game(E_DRIVER_TYPE driverType, Size resolution, FullScreen::State full,                            BufferedShadow::State shadow, VerticalSync::State vsync,  AntiAlias::State anti, PlayMusic::State music){params.DriverType = driverType;u32 w = resolution.Width();u32 h = resolution.Height();if (driverType == EDT_SOFTWARE){w = 640;h = 480;}params.WindowSize = dimension2d<u32>(w, h);params.Fullscreen = (full == FullScreen::On);params.Bits = 32;params.Stencilbuffer = (shadow == BufferedShadow::On);params.Vsync = (vsync == VerticalSync::On);params.AntiAlias = (anti == AntiAlias::On);params.EventReceiver = this;irrDevice = createDeviceEx(params);if (irrDevice == NULL){MessageBox(NULL, TEXT("Failed to create irrlicht device!"), TEXT("Failure"), MB_OK);return;}videoDriver = irrDevice->getVideoDriver();sceneMgr = irrDevice->getSceneManager();guiEnv = irrDevice->getGUIEnvironment();fileSys = irrDevice->getFileSystem();timer = irrDevice->getTimer();playMusic = music;bkMusic = NULL;ballSound = NULL;impactSound = NULL;currentScene = -2;bgColor = SColor(255, 192, 192, 255);statusText = NULL;inOutFader = NULL;quakeLevelMesh = NULL;quakeLevelNode = NULL;skyboxNode = NULL;model1 = NULL;model2 = NULL;campFire = NULL;metaSelector = NULL;mapSelector = NULL;sceneStartTime = 0;timeForThisScene = 0;Impacts = NULL;if (music == PlayMusic::On){sndEngine = createIrrKlangDevice();}else{sndEngine = NULL;}}Game::~Game(){//}void Game::SetBkMusic(char* pszMusicFile){ISoundSource* bk = sndEngine->getSoundSource(pszMusicFile);sndEngine->setSoundVolume(1.0f);bkMusic = sndEngine->play2D(bk,true,false,false,true);ISoundEffectControl* fx = bkMusic->getSoundEffectControl();//fx->enableDistortionSoundEffect(-10.0f, 5.0f);fx->enableChorusSoundEffect(30.0f,20.0f);fx->enableWavesReverbSoundEffect(0.0f, 0.0f, 200.0f);}void Game::Run(){if (fileSys->existFile("irrlicht.dat")){fileSys->addFileArchive("irrlicht.dat");}else{fileSys->addFileArchive("Assets/irrlicht.dat");}if (fileSys->existFile("map-20kdm2.pk3"))fileSys->addFileArchive("map-20kdm2.pk3");elsefileSys->addFileArchive("Assets/map-20kdm2.pk3");irrDevice->setWindowCaption(L"SimpleGame (Irrlicht Engine)");// set ambient lightsceneMgr->setAmbientLight(video::SColorf(0x00c0c0c0));wchar_t tmp[255];// draw everythings32 now = 0;s32 lastfps = 0;ITimer* timer = irrDevice->getTimer();sceneStartTime = timer->getTime();while (irrDevice->run()){if (irrDevice->isWindowActive()){// update 3D position for sound engineICameraSceneNode* cam = sceneMgr->getActiveCamera();if (cam){sndEngine->setListenerPosition(cam->getAbsolutePosition(), cam->getTarget());}// load next scene if necessarynow = timer->getTime();if (now - sceneStartTime > timeForThisScene && timeForThisScene != -1)SwitchToNextScene();CreateParticleImpacts();videoDriver->beginScene(timeForThisScene != -1, true, bgColor);sceneMgr->drawAll();guiEnv->drawAll();videoDriver->endScene();// write statisticsconst s32 nowfps = videoDriver->getFPS();swprintf(tmp, 255, L"%ls fps:%3d triangles:%0.3f mio/s",videoDriver->getName(), videoDriver->getFPS(),videoDriver->getPrimitiveCountDrawn(1) * (1.f / 1000000.f));statusText->setText(tmp);if (nowfps != lastfps){irrDevice->setWindowCaption(tmp);lastfps = nowfps;}}}sndEngine->drop();irrDevice->drop();}bool Game::OnEvent(const SEvent& evt){if (irrDevice == NULL){return false;}bool bKeyPressed = (evt.EventType == EET_KEY_INPUT_EVENT) &&                               (evt.KeyInput.PressedDown == false);if (bKeyPressed && evt.KeyInput.Key == KEY_ESCAPE){// user wants to quit.if (currentScene < 3){timeForThisScene = 0;}else{irrDevice->closeDevice();}}else{if (bKeyPressed &&evt.KeyInput.Key == KEY_F9){IImage* image = videoDriver->createScreenShot();u32 tm=timer->getRealTime();char fn[256] = { 0 };sprintf(fn, "Screenshot_%d.jpg", tm);if (image){videoDriver->writeImageToFile(image, fn);image->drop();}}else{return true;ICameraSceneNode* camNode = sceneMgr->getActiveCamera();if (camNode){camNode->OnEvent(evt);return true;}}}return false;}void Game::SwitchToNextScene(){++currentScene;if (currentScene > 3)currentScene = 1;ISceneNodeAnimator* sa = 0;ICameraSceneNode* camera = 0;camera = sceneMgr->getActiveCamera();if (camera){sceneMgr->setActiveCamera(0);camera->remove();camera = 0;}switch (currentScene){case -1: // loading screentimeForThisScene = 0;CreateLoadingScreen();break;case 0: // load scenetimeForThisScene = 0;LoadSceneData();break;case 1: // panorama camera{++currentScene;//camera = sceneMgr->addCameraSceneNode(0, vector3df(0,0,0), vector3df(-586,708,52));//camera->setTarget(vector3df(0,400,0));array<core::vector3df> points;points.push_back(vector3df(-931.473755f, 138.300003f, 987.279114f)); // -49873points.push_back(vector3df(-847.902222f, 136.757553f, 915.792725f)); // -50559points.push_back(vector3df(-748.680420f, 152.254501f, 826.418945f)); // -51964points.push_back(vector3df(-708.428406f, 213.569580f, 784.466675f)); // -53251points.push_back(vector3df(-686.217651f, 288.141174f, 762.965576f)); // -54015points.push_back(vector3df(-679.685059f, 365.095612f, 756.551453f)); // -54733points.push_back(vector3df(-671.317871f, 447.360107f, 749.394592f)); // -55588points.push_back(vector3df(-669.468445f, 583.335632f, 747.711853f)); // -56178points.push_back(vector3df(-667.611267f, 727.313232f, 746.018250f)); // -56757points.push_back(vector3df(-665.853210f, 862.791931f, 744.436096f)); // -57859points.push_back(vector3df(-642.649597f, 1026.047607f, 724.259827f)); // -59705points.push_back(vector3df(-517.793884f, 838.396790f, 490.326050f)); // -60983points.push_back(vector3df(-474.387299f, 715.691467f, 344.639984f)); // -61629points.push_back(vector3df(-444.600250f, 601.155701f, 180.938095f)); // -62319points.push_back(vector3df(-414.808899f, 479.691406f, 4.866660f)); // -63048points.push_back(vector3df(-410.418945f, 429.642242f, -134.332687f)); // -63757points.push_back(vector3df(-399.837585f, 411.498383f, -349.350983f)); // -64418points.push_back(vector3df(-390.756653f, 403.970093f, -524.454407f)); // -65005points.push_back(vector3df(-334.864227f, 350.065491f, -732.397400f)); // -65701points.push_back(vector3df(-195.253387f, 349.577209f, -812.475891f)); // -66335points.push_back(vector3df(16.255573f, 363.743134f, -833.800415f)); // -67170points.push_back(vector3df(234.940964f, 352.957825f, -820.150696f)); // -67939points.push_back(vector3df(436.797668f, 349.236450f, -816.914185f)); // -68596points.push_back(vector3df(575.236206f, 356.244812f, -719.788513f)); // -69166points.push_back(vector3df(594.131042f, 387.173828f, -609.675598f)); // -69744points.push_back(vector3df(617.615234f, 412.002899f, -326.174072f)); // -70640points.push_back(vector3df(606.456848f, 403.221954f, -104.179291f)); // -71390points.push_back(vector3df(610.958252f, 407.037750f, 117.209778f)); // -72085points.push_back(vector3df(597.956909f, 395.167877f, 345.942200f)); // -72817points.push_back(vector3df(587.383118f, 391.444519f, 566.098633f)); // -73477points.push_back(vector3df(559.572449f, 371.991333f, 777.689453f)); // -74124points.push_back(vector3df(423.753204f, 329.990051f, 925.859741f)); // -74941points.push_back(vector3df(247.520050f, 252.818954f, 935.311829f)); // -75651points.push_back(vector3df(114.756012f, 199.799759f, 805.014160f));points.push_back(vector3df(96.783348f, 181.639481f, 648.188110f));points.push_back(vector3df(97.865623f, 138.905975f, 484.812561f));points.push_back(vector3df(99.612457f, 102.463669f, 347.603210f));points.push_back(vector3df(99.612457f, 102.463669f, 347.603210f));points.push_back(vector3df(99.612457f, 102.463669f, 347.603210f));timeForThisScene = (points.size() - 3) * 1000;camera = sceneMgr->addCameraSceneNode(0, points[0], vector3df(0, 400, 0));//camera->setTarget(core::vector3df(0,400,0));sa = sceneMgr->createFollowSplineAnimator(timer->getTime(), points);camera->addAnimator(sa);sa->drop();model1->setVisible(false);model2->setVisible(false);campFire->setVisible(false);inOutFader->fadeIn(7000);}break;case 2:// down fly anim cameracamera = sceneMgr->addCameraSceneNode(0, vector3df(100, 40, -80), vector3df(844, 670, -885));sa = sceneMgr->createFlyStraightAnimator(vector3df(94, 1002, 127), vector3df(108, 15, -60), 10000, true);camera->addAnimator(sa);timeForThisScene = 9900;model1->setVisible(true);model2->setVisible(false);campFire->setVisible(false);sa->drop();break;case 3: // interactive, go around{model1->setVisible(true);model2->setVisible(true);campFire->setVisible(true);timeForThisScene = -1;SKeyMap keyMap[9];keyMap[0].Action = EKA_MOVE_FORWARD;keyMap[0].KeyCode = KEY_UP;keyMap[1].Action = EKA_MOVE_FORWARD;keyMap[1].KeyCode = KEY_KEY_W;keyMap[2].Action = EKA_MOVE_BACKWARD;keyMap[2].KeyCode = KEY_DOWN;keyMap[3].Action = EKA_MOVE_BACKWARD;keyMap[3].KeyCode = KEY_KEY_S;keyMap[4].Action = EKA_STRAFE_LEFT;keyMap[4].KeyCode = KEY_LEFT;keyMap[5].Action = EKA_STRAFE_LEFT;keyMap[5].KeyCode = KEY_KEY_A;keyMap[6].Action = EKA_STRAFE_RIGHT;keyMap[6].KeyCode = KEY_RIGHT;keyMap[7].Action = EKA_STRAFE_RIGHT;keyMap[7].KeyCode = KEY_KEY_D;keyMap[8].Action = EKA_JUMP_UP;keyMap[8].KeyCode = KEY_KEY_J;camera = sceneMgr->addCameraSceneNodeFPS(0, 100.0f, .4f, -1, keyMap, 9, false, 3.f);camera->setPosition(vector3df(108, 140, -140));camera->setFarValue(5000.0f);ISceneNodeAnimatorCollisionResponse* collider =sceneMgr->createCollisionResponseAnimator(metaSelector, camera, vector3df(25, 50, 25),vector3df(0, quakeLevelMesh ? -10.f : 0.0f, 0),vector3df(0, 45, 0), 0.005f);camera->addAnimator(collider);collider->drop();}break;}sceneStartTime = timer->getTime();}void Game::LoadSceneData(){// load quake level// Quake3 Shader controls Z-WritingsceneMgr->getParameters()->setAttribute(scene::ALLOW_ZWRITE_ON_TRANSPARENT, true);quakeLevelMesh = (IQ3LevelMesh*)(sceneMgr->getMesh("maps/20kdm2.bsp"));if (quakeLevelMesh){u32 i;//move all quake level meshes (non-realtime)matrix4 m;m.setTranslation(vector3df(-1300, -70, -1249));for (i = 0; i != quake3::E_Q3_MESH_SIZE; ++i)sceneMgr->getMeshManipulator()->transform(quakeLevelMesh->getMesh(i), m);quakeLevelNode = sceneMgr->addOctreeSceneNode(quakeLevelMesh->getMesh(quake3::E_Q3_MESH_GEOMETRY));if (quakeLevelNode){//quakeLevelNode->setPosition(core::vector3df(-1300,-70,-1249));quakeLevelNode->setVisible(true);// create map triangle selectormapSelector = sceneMgr->createOctreeTriangleSelector(quakeLevelMesh->getMesh(0),quakeLevelNode, 128);// if not using shader and no gamma it's better to use more lighting, because// quake3 level are usually darkquakeLevelNode->setMaterialType(EMT_LIGHTMAP_M4);// set additive blending if wantedquakeLevelNode->setMaterialType(EMT_LIGHTMAP_ADD);}// the additional mesh can be quite huge and is unoptimizedIMesh * additional_mesh = quakeLevelMesh->getMesh(quake3::E_Q3_MESH_ITEMS);for (i = 0; i != additional_mesh->getMeshBufferCount(); ++i){IMeshBuffer *meshBuffer = additional_mesh->getMeshBuffer(i);const SMaterial &material = meshBuffer->getMaterial();//! The ShaderIndex is stored in the material parameters32 shaderIndex = (s32)material.MaterialTypeParam2;// the meshbuffer can be rendered without additional support, or it has no shaderconst quake3::IShader *shader = quakeLevelMesh->getShader(shaderIndex);if (0 == shader){continue;}// Now add the MeshBuffer(s) with the current Shader to the ManagersceneMgr->addQuake3SceneNode(meshBuffer, shader);}}// load sydney model and create 2 instancesIAnimatedMesh* mesh = 0;mesh = sceneMgr->getMesh("Assets/sydney.md2");if (mesh){model1 = sceneMgr->addAnimatedMeshSceneNode(mesh);if (model1){model1->setMaterialTexture(0, videoDriver->getTexture("Assets/spheremap.jpg"));model1->setPosition(vector3df(100, 40, -80));model1->setScale(vector3df(2, 2, 2));model1->setMD2Animation(EMAT_STAND);model1->setMaterialFlag(EMF_LIGHTING, false);model1->setMaterialFlag(EMF_NORMALIZE_NORMALS, true);model1->setMaterialType(EMT_SPHERE_MAP);model1->addShadowVolumeSceneNode();}model2 = sceneMgr->addAnimatedMeshSceneNode(mesh);if (model2){model2->setPosition(vector3df(180, 15, -60));model2->setScale(vector3df(2, 2, 2));model2->setMD2Animation(EMAT_RUN);model2->setMaterialTexture(0, videoDriver->getTexture("Assets/sydney.bmp"));model2->setMaterialFlag(EMF_LIGHTING, true);model2->setMaterialFlag(EMF_NORMALIZE_NORMALS, true);model2->addShadowVolumeSceneNode();}}ISceneNodeAnimator* anim = 0;// create sky boxvideoDriver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false);skyboxNode = sceneMgr->addSkyBoxSceneNode(videoDriver->getTexture("Assets/irrlicht2_up.jpg"),videoDriver->getTexture("Assets/irrlicht2_dn.jpg"),videoDriver->getTexture("Assets/irrlicht2_lf.jpg"),videoDriver->getTexture("Assets/irrlicht2_rt.jpg"),videoDriver->getTexture("Assets/irrlicht2_ft.jpg"),videoDriver->getTexture("Assets/irrlicht2_bk.jpg"));videoDriver->setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true);// create walk-between-portals animationvector3df waypoint[2];waypoint[0].set(-150, 40, 100);waypoint[1].set(350, 40, 100);if (model2){anim = sceneMgr->createFlyStraightAnimator(waypoint[0], waypoint[1], 2000, true);model2->addAnimator(anim);anim->drop();}// create animation for portals;array<video::ITexture*> textures;for (s32 g = 1; g < 8; ++g){stringc tmp("Assets/portal");tmp += g;tmp += ".bmp";ITexture* t = videoDriver->getTexture(tmp);textures.push_back(t);}anim = sceneMgr->createTextureAnimator(textures, 100);// create portalsIBillboardSceneNode* bill = 0;for (int r = 0; r < 2; ++r){bill = sceneMgr->addBillboardSceneNode(0, dimension2d<f32>(100, 100),waypoint[r] + vector3df(0, 20, 0));bill->setMaterialFlag(EMF_LIGHTING, false);bill->setMaterialTexture(0, videoDriver->getTexture("Assets/portal1.bmp"));bill->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);bill->addAnimator(anim);}anim->drop();// create cirlce flying dynamic light with transparent billboard attachedILightSceneNode* light = 0;light = sceneMgr->addLightSceneNode(0,vector3df(0, 0, 0), SColorf(1.0f, 1.0f, 1.f, 1.0f), 500.f);anim = sceneMgr->createFlyCircleAnimator(vector3df(100, 150, 80), 80.0f, 0.0005f);light->addAnimator(anim);anim->drop();bill = irrDevice->getSceneManager()->addBillboardSceneNode(light, dimension2d<f32>(40, 40));bill->setMaterialFlag(EMF_LIGHTING, false);bill->setMaterialTexture(0, videoDriver->getTexture("Assets/particlewhite.bmp"));bill->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);// create meta triangle selector with all triangles selectors in it.metaSelector = sceneMgr->createMetaTriangleSelector();metaSelector->addTriangleSelector(mapSelector);// create camp firecampFire = sceneMgr->addParticleSystemSceneNode(false);campFire->setPosition(vector3df(100, 120, 600));campFire->setScale(vector3df(2, 2, 2));IParticleEmitter* em = campFire->createBoxEmitter(aabbox3d<f32>(-7, 0, -7, 7, 1, 7),vector3df(0.0f, 0.06f, 0.0f),80, 100, SColor(1, 255, 255, 255), SColor(1, 255, 255, 255), 800, 2000);em->setMinStartSize(dimension2d<f32>(20.0f, 10.0f));em->setMaxStartSize(dimension2d<f32>(20.0f, 10.0f));campFire->setEmitter(em);em->drop();IParticleAffector* paf = campFire->createFadeOutParticleAffector();campFire->addAffector(paf);paf->drop();campFire->setMaterialFlag(EMF_LIGHTING, false);campFire->setMaterialFlag(EMF_ZWRITE_ENABLE, false);campFire->setMaterialTexture(0, videoDriver->getTexture("Assets/fireball.bmp"));campFire->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);}void Game::CreateLoadingScreen(){dimension2d<u32> size = videoDriver->getScreenSize();irrDevice->getCursorControl()->setVisible(false);// setup loading screenbgColor.set(255, 90, 90, 156);// create in faderinOutFader = guiEnv->addInOutFader();inOutFader->setColor(bgColor, SColor(0, 230, 230, 230));// irrlicht logoguiEnv->addImage(videoDriver->getTexture("Assets/Admin.png"), position2d<s32>(5, 5));// loading textconst int lwidth = size.Width - 20;const int lheight = 16;rect<int> pos(10, size.Height - lheight - 10, 10 + lwidth, size.Height - 10);guiEnv->addImage(pos);statusText = guiEnv->addStaticText(L"Loading...", pos, true);statusText->setOverrideColor(SColor(255, 205, 200, 200));// load bigger fontguiEnv->getSkin()->setFont(guiEnv->getFont("Assets/fonthaettenschweiler.bmp"));// set new font colorguiEnv->getSkin()->setColor(EGDC_BUTTON_TEXT, SColor(255, 100, 100, 100));}void Game::Shoot(){ICameraSceneNode* camera = sceneMgr->getActiveCamera();if (!camera || !mapSelector)return;SParticleImpact impact;impact.when = 0;// get line of cameravector3df start = camera->getPosition();vector3df end = (camera->getTarget() - start);end.normalize();start += end*8.0f;end = start + (end * camera->getFarValue());triangle3df triangle;line3d<f32> line(start, end);// get intersection point with mapISceneNode* hitNode;if (sceneMgr->getSceneCollisionManager()->getCollisionPoint(line,             mapSelector, end, triangle, hitNode)){// collides with wallvector3df out = triangle.getNormal();out.setLength(0.03f);impact.when = 1;impact.outVector = out;impact.pos = end;}else{// doesnt collide with wallvector3df start = camera->getPosition();vector3df end = (camera->getTarget() - start);end.normalize();start += end*8.0f;end = start + (end * camera->getFarValue());}// create fire ballISceneNode* node = 0;node = sceneMgr->addBillboardSceneNode(0, dimension2d<f32>(25, 25), start);node->setMaterialFlag(EMF_LIGHTING, false);node->setMaterialTexture(0, videoDriver->getTexture("Assets/fireball.bmp"));node->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);f32 length = (f32)(end - start).getLength();const f32 speed = 0.6f;u32 time = (u32)(length / speed);ISceneNodeAnimator* anim = 0;// set flight lineanim = sceneMgr->createFlyStraightAnimator(start, end, time);node->addAnimator(anim);anim->drop();anim = sceneMgr->createDeleteAnimator(time);node->addAnimator(anim);anim->drop();if (impact.when){// create impact noteimpact.when = irrDevice->getTimer()->getTime() + (time - 100);Impacts.push_back(impact);}// play soundif (ballSound)sndEngine->play2D(ballSound);}void  Game::CreateParticleImpacts(){u32 now = timer->getTime();int  iSize = Impacts.size();for (int i = 0; i<iSize; ++i){if (now > Impacts[i].when){// create smoke particle systemIParticleSystemSceneNode* ps = 0;ps = sceneMgr->addParticleSystemSceneNode(false, 0, -1, Impacts[i].pos);ps->setParticleSize(dimension2d<f32>(10.0f, 10.0f));aabbox3d<f32> box = aabbox3d<f32>(-5, -5, -5, 5, 5, 5);SColor cmin = SColor(50, 255, 255, 255);SColor cmax = SColor(50, 255, 255, 255);IParticleEmitter* pe = ps->createBoxEmitter(box, Impacts[i].outVector,             20, 40, cmin, cmax, 1200, 1600, 20);ps->setEmitter(pe);pe->drop();IParticleAffector* pf = campFire->createFadeOutParticleAffector();ps->addAffector(pf);pf->drop();ps->setMaterialFlag(EMF_LIGHTING, false);ps->setMaterialFlag(EMF_ZWRITE_ENABLE, false);ps->setMaterialTexture(0, videoDriver->getTexture("Assets/smoke.bmp"));ps->setMaterialType(EMT_TRANSPARENT_ADD_COLOR);ISceneNodeAnimator* anim = sceneMgr->createDeleteAnimator(2000);ps->addAnimator(anim);anim->drop();// play impact soundif (sndEngine){ISound* sound = sndEngine->play3D(impactSound, Impacts[i].pos, false, false, true);if (sound){// adjust max value a bit to make to sound of an impact loudersound->setMinDistance(400);sound->drop();}}// delete entryImpacts.erase(i);--i;}}}

主程序

#include "SimpleGame.h"INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR strCmdLine, INT nCmdShow){Game* myGame = new Game(EDT_DIRECT3D9, Size(900,640), FullScreen::Off, BufferedShadow::Off,                                                     VerticalSync::Off, AntiAlias::Off, PlayMusic::On);myGame->SetBkMusic("Assets/BkMusic.mp3");myGame->Run();return 0;}


这个例子有些复杂,在后续文章中会循序渐进地介绍,最后回来看看,你一定会觉得这算不了什么,小把戏而已。


0 0
原创粉丝点击