使用的IDE:CodeBlocks 10.05
Irrlicht版本:1.8
操作系统:win7
项目结构:
Irrlicht test world-player-war
---Sources
--src
----Faerie.cpp
----World.cpp
----main.cpp
----Headers
--include
----EventReceiver.h
----Faerie.h
----World.h
#include "../include/World.h" #include "../include/Faerie.h" class World world; class Faerie faerie1; class Faerie faerie2; int main(int argc, char* argv[]) { cEventReceiver eventReceiver; // 初始化世界 world.Init(); // 准备地图等场景 world.Prepare(); // 初始化要加载的精灵 faerie1.Initialize(world.device,world.mapSelector,1); faerie2.Initialize(world.device,world.mapSelector,2); // 传入事务接收器 world.device->setEventReceiver(&eventReceiver); // 主程序执行启动 while(world.device->run() && (eventReceiver.Keys[KEY_ESCAPE] == false)) { world.MainLoop(faerie1.faerieNode,&eventReceiver); faerie1.OnAnima(&eventReceiver); } world.Finish(); return 0; }
#ifndef WORLD_H #include <irrlicht.h> #include <sys/time.h> #include <iostream> #define WORLD_H using namespace irr; #include "EventReceiver.h" using namespace core; using namespace scene; using namespace video; using namespace io; enum { // I use this ISceneNode ID to indicate a scene node that is // not pickable by getSceneNodeAndCollisionPointFromRay() ID_IsNotPickable = 0, // I use this flag in ISceneNode IDs to indicate that the // scene node can be picked by ray selection. IDFlag_IsPickable = 1 << 0, //IDFlag_IsPickable = 0, // I use this flag in ISceneNode IDs to indicate that the // scene node can be highlighted. In this example, the // homonids can be highlighted, but the level mesh can't. IDFlag_IsHighlightable = 1 << 1 //IDFlag_IsHighlightable = 1 }; class World { public: World(); virtual ~World(); // 创建鼠标接收结构 struct SMouseState { bool LeftButtonDown; SMouseState() : LeftButtonDown(false) { } } MouseState; const SMouseState & GetMouseState(void) const { return MouseState; } struct SParticleImpact { u32 when; core::vector3df pos; core::vector3df outVector; }; //游戏主函数 void Init(); void Prepare(); void MainLoop(IAnimatedMeshSceneNode* mainNode,cEventReceiver* eventReceiver); void Render(); void Finish(); // Irrlicht vars IVideoDriver* driver; ISceneManager* smgr; //IGUIEnvironment* guienv; IrrlichtDevice *device; gui::IGUIEnvironment* gui; scene::ICameraSceneNode* fps_camera; scene::IParticleSystemSceneNode* ps; scene::ITriangleSelector* mapSelector; scene::ITriangleSelector* cubeSelector; scene::IParticleSystemSceneNode* campFire; scene::ITerrainSceneNode* terrain; scene::ISceneCollisionManager* collMan; scene::ISceneNode * selectedSceneNode; scene::IBillboardSceneNode * bill; scene::IParticleEmitter* em ; core::array<SParticleImpact> Impacts; core::stringw str; protected: private: void Play(); void Shoot(core::vector3df start); void CreateParticleImpacts(); bool hasEmitter; f32 speed;//3.f f32 camera_round; vector3df pFaerie; vector3df pCamera; core::line3d<f32> ray; core::vector3df intersection; }; #endif // WORLD_H
#include "../include/World.h" #include "../include/EventReceiver.h" using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; World::World(): hasEmitter(true) { //ctor } World::~World() { //dtor } //初始化world void World::Init() { //初始化参数 camera_round = -28.f; core::dimension2d<u32> resolution ( 800, 600 ); device = createDevice(EDT_OPENGL, resolution, 32, false, true, false); device->setWindowCaption(L"World!"); driver = device->getVideoDriver(); smgr = device->getSceneManager(); collMan = smgr->getSceneCollisionManager(); gui = device->getGUIEnvironment(); //生成摄像机 fps_camera = smgr->addCameraSceneNodeFPS(); fps_camera->setScale(vector3df(0.1f,0.1f,0.1f)); fps_camera->setPosition(vector3df(5210.f,1000.f,3110.f)); fps_camera->setRotation(vector3df(0.f,180.f,0.f)); device->getCursorControl()->setVisible(false); } //准备 void World::Prepare() { //加载地图 IAnimatedMesh* mesh = smgr->getMesh("../../media/room.3ds"); smgr->getMeshManipulator()->makePlanarTextureMapping(mesh->getMesh(0), 0.004f); ISceneNode* node = 0; scene::IAnimatedMeshSceneNode* animModel = smgr->addAnimatedMeshSceneNode(mesh); node = animModel; node->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(node->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY)); node->setMaterialFlag(EMF_LIGHTING, false); //创建选择器,附加到场景上 mapSelector = smgr->createOctreeTriangleSelector(mesh,node); node->setTriangleSelector(mapSelector); node->setMaterialTexture(0, driver->getTexture("../../media/wall.jpg")); node->getMaterial(0).SpecularColor.set(0,0,0,0); node->setMaterialFlag(EMF_FOG_ENABLE, false); mesh = smgr->addHillPlaneMesh( "waterMesh", dimension2d<f32>(30,30), dimension2d<u32>(30,30), 0, 0, dimension2d<f32>(0,0), dimension2d<f32>(10,10)); node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0), 3.0f, 300.0f, 30.0f); node->setPosition(vector3df(0,9,0)); node->setMaterialTexture(0, driver->getTexture("../../media/stones.jpg")); node->setMaterialTexture(1, driver->getTexture("../../media/water.jpg")); node->setMaterialType(EMT_REFLECTION_2_LAYER); //node->setMaterialFlag(EMF_FOG_ENABLE, true); node->setDebugDataVisible(scene::EDS_OFF); node->setMaterialFlag(EMF_LIGHTING, false); //ISceneNode* terrain = smgr->addMeshSceneNode(smgr->getMesh("../../media/Irr2013123.irr")); //加载场景 IMesh* cubeMesh = smgr->getMesh("../../media/data/smallcube.3ds"); ISceneNode* cubeNode = smgr->addMeshSceneNode(cubeMesh); cubeNode->setMaterialTexture(0, driver->getTexture("../../media/data/crate.jpg")); cubeNode->setPosition(vector3df(140,100,40)); //cubeNode->setScale(vector3df(3,3,2)); cubeNode->setMaterialFlag(video::EMF_LIGHTING, false); cubeNode->setName("cube"); smgr->addTextSceneNode(gui->getBuiltInFont(), L"Cube-1", video::SColor(100,255,255,255), cubeNode); // Add the billboard. bill = smgr->addBillboardSceneNode(); bill->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR ); bill->setMaterialTexture(0, driver->getTexture("../../media/fireball.bmp")); // bill->setMaterialTexture(); bill->setMaterialFlag(video::EMF_LIGHTING, false); bill->setMaterialFlag(video::EMF_ZBUFFER, false); bill->setSize(core::dimension2d<f32>(20.0f, 20.0f)); bill->setID(ID_IsNotPickable); // This ensures that we don't accidentally ray-pick it //cubeNode->; //调试物理碰撞检测网格 //cubeNode->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(cubeNode->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY)); cubeSelector = 0; cubeSelector = smgr->createTriangleSelector(cubeMesh,cubeNode); cubeNode->setTriangleSelector(cubeSelector); //selector->drop(); // We're done with this selector, so drop it now. // some lights /*video::SLight l; scene::ILightSceneNode *light = smgr->addLightSceneNode(gamescene,core::vector3df(50,50,50),video::SColorf(1,1,1,1.f),1000); l = light->getLightData(); l.Type = video::ELT_POINT; l.AmbientColor = video::SColorf(.35,.35,.35); l.SpecularColor = video::SColorf(.7,.7,.5); l.DiffuseColor = video::SColorf(1,1,1); l.CastShadows = true; light->setLightData( l );*/ //node = smgr->addOctreeSceneNode(mesh,0,0); //node->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(node->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY)); //创建地图选择器,附加到地图场景上 //创建精灵碰撞响应动画 scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( mapSelector, cubeNode, cubeNode->getBoundingBox().MaxEdge, core::vector3df(0,-10,0), core::vector3df(0,0,0)); cubeNode->addAnimator(anim); anim->drop(); anim = 0; //创建粒子节点 campFire = smgr->addParticleSystemSceneNode(false); campFire->setPosition(core::vector3df(100,120,600)); campFire->setScale(core::vector3df(2,2,2)); //创建粒子发生器(盒子) em = campFire->createBoxEmitter( core::aabbox3d<f32>(-7,0,-7,7,1,7),// emitter size core::vector3df(0.0f,0.06f,0.0f), // initial direction 80,100, // min and max emit rate video::SColor(1,255,255,255), // darkest color video::SColor(1,255,255,255), // brightest color 800,2000,10, // min and max age, angle dimension2df(10.f,10.f), // min size dimension2df(20.f,20.f) // max size ); em->setMinStartSize(core::dimension2d<f32>(20.0f, 10.0f)); em->setMaxStartSize(core::dimension2d<f32>(20.0f, 10.0f)); campFire->setEmitter(em); em->drop(); em = 0; //附加粒子效果 scene::IParticleAffector* paf = campFire->createFadeOutParticleAffector(); campFire->addAffector(paf); paf->drop(); //设定粒子相关属性 campFire->setMaterialFlag(video::EMF_LIGHTING, false); campFire->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); campFire->setMaterialTexture(0, driver->getTexture("../../media/fireball.bmp")); campFire->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); } //主循环 void World::MainLoop(IAnimatedMeshSceneNode* mainNode,cEventReceiver* eventReceiver) { pCamera= vector3df(mainNode->getPosition().X+sin(PI*fps_camera->getRotation().Y/180)*camera_round, mainNode->getPosition().Y+20.f, mainNode->getPosition().Z+cos(PI*fps_camera->getRotation().Y/180)*camera_round); fps_camera->setPosition(pCamera); str = L"Irrlicht Engine - Walker example ["; str += driver->getName(); str += "] "; str += "P:"; str += fps_camera->getRotation().X; str += ","; str += fps_camera->getRotation().Y; str += ","; str += fps_camera->getRotation().Z; str += "|"; str += mainNode->getPosition().X; str += ","; str += mainNode->getPosition().Y; str += ","; str += mainNode->getPosition().Z; device->setWindowCaption(str.c_str()); /*if(fps_camera->getRotation().X<=6) { fps_camera->setRotation(vector3df(6,fps_camera->getRotation().Y,0)); } if(72<=fps_camera->getRotation().X) { fps_camera->setRotation(vector3df(72,fps_camera->getRotation().Y,0)); }*/ ray.start = fps_camera->getPosition(); ray.end = ray.start + (fps_camera->getTarget()- ray.start).normalize() * 1000.0f; core::triangle3df hitTriangle; Play(); selectedSceneNode = collMan->getSceneNodeAndCollisionPointFromRay( ray, intersection, // This will be the position of the collision hitTriangle, // This will be the triangle hit in the collision IDFlag_IsPickable, // This ensures that only nodes that we have // set up to be pickable are considered 0); // Check the entire scene (this is actually the implicit default) if(selectedSceneNode) { bill->setPosition(ray.end); bill->setRotation(core::vector3df(fps_camera->getRotation().X,fps_camera->getRotation().Y,fps_camera->getRotation().Z)); driver->setTransform(video::ETS_WORLD, core::matrix4()); //driver->setMaterial(material); driver->draw3DTriangle(hitTriangle, video::SColor(0,255,0,0)); //selectedSceneNode->setVisible(false); std::cout<<selectedSceneNode->getName()<<std::endl; std::cout<<selectedSceneNode->getPosition().X<<","<<selectedSceneNode->getPosition().Y<<","<<selectedSceneNode->getPosition().Z<<std::endl; //std::cout<<intersection.X<<","<<intersection.Y<<","<<intersection.Z<<std::endl; //std::cout<<hitTriangle.pointA<<","<<hitTriangle.pointB<<","<<hitTriangle.pointC<<std::endl; if(strcmp(selectedSceneNode->getName(),"cube")==0) { //selectedSceneNode->setPosition(mainNode->getPosition()); std::cout<<"---------------stop-------------"<<std::endl; eventReceiver->Move=false; //mainNode->setMD2Animation(EMAT_STAND); } else { eventReceiver->Move=true; } if(eventReceiver->GetMouseState().LeftButtonDown) { std::cout<<"--------------------war-----------------------"<<std::endl; selectedSceneNode->setPosition(selectedSceneNode->getPosition()+1); } else { } } CreateParticleImpacts(); Render(); } //渲染 void World::Render() { if (device->isWindowActive()) { driver->beginScene(true, true, SColor(255,100,101,140)); smgr->drawAll(); driver->endScene(); /*str = L"Irrlicht Engine - Walker example ["; str += driver->getName(); str += "] "; str += "P:"; str += fps_camera->getRotation().X; str += ","; str += fps_camera->getRotation().Y; str += ","; str += fps_camera->getRotation().Z; device->setWindowCaption(str.c_str());*/ } } //结束 void World::Finish() { device->drop(); } void World::Play() { //鼠标事件 if(GetMouseState().LeftButtonDown) { std::cout<<"click mouse"<<std::endl; Shoot(pFaerie); } } void World::Shoot(core::vector3df start) { scene::ISceneManager* sm = device->getSceneManager(); scene::ICameraSceneNode* camera = sm->getActiveCamera(); if (!camera ) return; SParticleImpact imp; imp.when = 0; // get line of camera //core::vector3df start = faerieNode->getPosition(); core::vector3df end = (camera->getTarget() - start); end.normalize(); start += end*8.0f; end = start + (end * camera->getFarValue()); core::triangle3df triangle; core::line3d<f32> line(start, end); // get intersection point with map scene::ISceneNode* hitNode; if (sm->getSceneCollisionManager()->getCollisionPoint( line, mapSelector, end, triangle, hitNode)) { // collides with wall core::vector3df out = triangle.getNormal(); out.setLength(0.03f); imp.when = 1; imp.outVector = out; imp.pos = end; } else { // doesnt collide with wall //core::vector3df start = faerieNode->getPosition(); core::vector3df end = (camera->getTarget() - start); end.normalize(); start += end*8.0f; end = start + (end * camera->getFarValue()); } // create fire ball scene::ISceneNode* node = 0; node = sm->addBillboardSceneNode(0, core::dimension2d<f32>(25,25), start); node->setMaterialFlag(video::EMF_LIGHTING, false); node->setMaterialTexture(0, device->getVideoDriver()->getTexture("../../media/fireball.bmp")); node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); f32 length = (f32)(end - start).getLength(); const f32 speed = 0.2f; u32 time = (u32)(length / speed); scene::ISceneNodeAnimator* anim = 0; // set flight line anim = sm->createFlyStraightAnimator(start, end, time); node->addAnimator(anim); anim->drop(); anim = sm->createDeleteAnimator(time); node->addAnimator(anim); anim->drop(); if (imp.when) { // create impact note imp.when = device->getTimer()->getTime() + (time - 100); Impacts.push_back(imp); } } void World::CreateParticleImpacts() { u32 now = device->getTimer()->getTime(); scene::ISceneManager* sm = device->getSceneManager(); for (s32 i=0; i<(s32)Impacts.size(); ++i) if (now > Impacts[i].when) { // create smoke particle system scene::IParticleSystemSceneNode* pas = 0; pas = sm->addParticleSystemSceneNode(false, 0, -1, Impacts[i].pos); pas->setParticleSize(core::dimension2d<f32>(10.0f, 10.0f)); scene::IParticleEmitter* em = pas->createBoxEmitter( core::aabbox3d<f32>(-5,-5,-5,5,5,5), Impacts[i].outVector, 20,40, video::SColor(50,255,255,255),video::SColor(50,255,255,255), 1200,1600, 20); pas->setEmitter(em); em->drop(); scene::IParticleAffector* paf = campFire->createFadeOutParticleAffector(); pas->addAffector(paf); paf->drop(); pas->setMaterialFlag(video::EMF_LIGHTING, false); pas->setMaterialFlag(video::EMF_ZWRITE_ENABLE, false); pas->setMaterialTexture(0, device->getVideoDriver()->getTexture("../../media/smoke.bmp")); pas->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); scene::ISceneNodeAnimator* anim = sm->createDeleteAnimator(2000); pas->addAnimator(anim); anim->drop(); // delete entry Impacts.erase(i); i--; } }
#ifndef FAERIE_H #define FAERIE_H #include <irrlicht.h> #include "World.h" using namespace irr; #include "EventReceiver.h" using namespace core; //using namespace scene; //using namespace video; //using namespace io; class Faerie { public: Faerie(); void Initialize(IrrlichtDevice *device,scene::ITriangleSelector* mapSelector,s32 n); //void setSelector(scene::ITriangleSelector* mapSelector); virtual ~Faerie(); void OnAnima(cEventReceiver* eventReceiver); scene::IAnimatedMeshSceneNode* faerieNode; protected: private: void Move(); void Turn_face(bool leftOrRight ); f32 speed;//3.f vector3df pFaerie; bool turn_back; bool status; f32 lasttick; f32 pX;// 0.f; f32 pZ;// 0.f; f32 pR;// 0.f; IrrlichtDevice *f_device; }; #endif // FAERIE_H
#ifndef CEVENTRECEIVER_H #define CEVENTRECEIVER_H class cEventReceiver : public IEventReceiver { public: cEventReceiver() { for (int i=0; i<KEY_KEY_CODES_COUNT; i++) { Keys[i] = false; KeysTemp[i] = false; } mouseX=mouseY=mouseDeltaX=mouseDeltaY=0; Move = true; } // 创建鼠标接收结构 struct SMouseState { bool LeftButtonDown; SMouseState() : LeftButtonDown(false) { } } MouseState; const SMouseState & GetMouseState(void) const { return MouseState; } ~cEventReceiver() {} virtual bool OnEvent(const SEvent& event) { if (event.EventType==irr::EET_KEY_INPUT_EVENT) { Keys[event.KeyInput.Key] = false; Keys[event.KeyInput.Key] = event.KeyInput.PressedDown; return true; } if (event.EventType==irr::EET_MOUSE_INPUT_EVENT) { /*mouseX = event.MouseInput.X; mouseY = event.MouseInput.Y; mouseDeltaX = event.MouseInput.X - mouseX; mouseDeltaY = event.MouseInput.Y - mouseY; std::cout<<mouseDeltaX<<std::endl; return true;*/ } if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) { switch(event.MouseInput.Event) { case EMIE_LMOUSE_PRESSED_DOWN: MouseState.LeftButtonDown = true; break; case EMIE_LMOUSE_LEFT_UP: MouseState.LeftButtonDown = false; break; case EMIE_RMOUSE_PRESSED_DOWN: break; case EMIE_MOUSE_WHEEL: if(event.MouseInput.Wheel < 0 ) { } else if(event.MouseInput.Wheel > 0 ) { } break; case EMIE_MOUSE_MOVED: break; default: break; } } return false; } s32 mouseDeltaX; s32 mouseDeltaY; bool Keys[KEY_KEY_CODES_COUNT]; bool KeysTemp[KEY_KEY_CODES_COUNT]; bool Move; s32 mouseX; s32 mouseY; private: }; #endif // EVENTRECEIVER_H
#include "../include/Faerie.h" #include "../include/EventReceiver.h" #include <irrlicht.h> Faerie::Faerie() { //ctor } Faerie::~Faerie() { //dtor } void Faerie::Initialize(IrrlichtDevice *device,scene::ITriangleSelector* mapSelector,s32 n) { //初始化参数 status = true; speed = 3.f; if(!device) return; f_device = device; //场景加入精灵 scene::IAnimatedMesh* mesh; ISceneManager* smgr = f_device->getSceneManager(); mesh = smgr->getMesh("../../media/sydney.md2"); faerieNode = smgr->addAnimatedMeshSceneNode(mesh); smgr->addTextSceneNode(device->getGUIEnvironment()->getBuiltInFont(), L"sydney.md2", video::SColor(255,255,255,255), faerieNode); //角色坐标设定 faerieNode->setPosition(vector3df(-40,150,40)); faerieNode->setScale(vector3df(1,1,1)); IVideoDriver* driver = f_device->getVideoDriver(); pFaerie = faerieNode->getPosition(); faerieNode->setMaterialTexture(0,driver->getTexture("../../media/sydney.BMP")); //调试物理碰撞检测网格 //faerieNode->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(faerieNode->isDebugDataVisible()^scene::EDS_MESH_WIRE_OVERLAY)); faerieNode->setDebugDataVisible((scene::E_DEBUG_SCENE_TYPE)(faerieNode->isDebugDataVisible()^scene::EDS_BBOX)); //faerieNode->setAnimationSpeed(13); //faerieNode->setMD2Animation(EMAT_STAND); //faerieNode->setMD2Animation(EMAT_STAND); //faerieNode->setScale(vector3df(4.8f,4.8f,4.8f)); if(n!=1) { faerieNode->setName((core::stringw)n+"sydney"); } faerieNode->setMaterialFlag(video::EMF_LIGHTING, false); scene::ITriangleSelector* selector = 0; selector = smgr->createTriangleSelector(faerieNode); faerieNode->setTriangleSelector(selector); selector->drop(); // We're done with this selector, so drop it now. //创建精灵碰撞响应动画 scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator( mapSelector, faerieNode, faerieNode->getBoundingBox().MaxEdge, core::vector3df(0,-10,0), core::vector3df(0,-7,0)); faerieNode->addAnimator(anim); anim->drop(); anim = 0; } void Faerie::OnAnima(cEventReceiver* eventReceiver) { //std::cout<<faerieNode->getPosition().X<<","<<faerieNode->getPosition().Y<<","<<faerieNode->getPosition().Z<<std::endl; if(eventReceiver->Keys[KEY_KEY_W]) { if(status) { status = false; faerieNode->setMD2Animation(EMAT_RUN); } if(eventReceiver->Move) { Move(); } } else { status = true; faerieNode->setMD2Animation(EMAT_STAND); } if(eventReceiver->Keys[KEY_KEY_A]) { if (f_device->getTimer()->getTime() > lasttick + 10) { lasttick = f_device->getTimer()->getTime(); Turn_face(true); } } if(eventReceiver->Keys[KEY_KEY_D]) { if (f_device->getTimer()->getTime() > lasttick + 10) { lasttick = f_device->getTimer()->getTime(); Turn_face(false); } } if(eventReceiver->GetMouseState().LeftButtonDown) { std::cout<<"--------------------war-----------------------"<<std::endl; faerieNode->setMD2Animation(EMAT_ATTACK); }else { } /*if(eventReceiver->mouseDeltaX>0) { Turn_face(true); } else if(eventReceiver->mouseDeltaX<0) { Turn_face(false); }*/ } void Faerie::Move() { pFaerie = faerieNode->getPosition(); pX = cos(faerieNode->getRotation().Y*PI/180)*speed; pZ = -sin(faerieNode->getRotation().Y*PI/180)*speed; faerieNode->setPosition(vector3df(pFaerie.X+pX,faerieNode->getPosition().Y,pFaerie.Z+pZ)); } //转向 void Faerie::Turn_face(bool leftOrRight) { pR = faerieNode->getRotation().Y; if(leftOrRight) { pR -=6; if(pR<0) pR = 360 + pR; } else { pR +=6; if(pR>360) pR = pR - 360; } faerieNode->setRotation(vector3df(faerieNode->getRotation().X, pR,faerieNode->getRotation().Z)); }