人物行走碰撞测试码
使用的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_Husing 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 varsIVideoDriver* 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}//初始化worldvoid 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_Hclass 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));}?