Voici une camera FPS que je trouve un peut optimisé. La différence avec celle intégré à Irrlicht:
-On peut lui indiquer des vitesses différente pour avancé, reculé et le déplacement latérale.
-elle se déplace parfaitement horizontalement, c'est à dire que contrairement a celle d'Irrlicht, elle ne saute pas sur place lorsque regarde vers le haut, ni se déplace 2 fois moins vite lorsqu'on regarde vers le bas (bien que l'on peut très facilement changer ce mode de déplacement et revenir au classique).
Dans ce code, pour la simplicité, je n'est pas fait une classe "cameraFPS" mais intégrer son fonctionnement directement dans un code de base.
Aussi, j'ai laisser le curseur visible pour voir comment il réagit.
Voilà la bête:
Code c++ :
#include <irrlicht.h>
using namespace std
;using namespace irr;using namespace core;using namespace scene;using namespace video;using namespace gui;class MyEventReceiver
: public IEventReceiver{public: virtual bool OnEvent
(const SEvent& event
) { if (event
.EventType
== irr::EET_KEY_INPUT_EVENT
) KeyIsDown
[event
.KeyInput
.Key
] = event
.KeyInput
.PressedDown
; return false; } virtual bool IsKeyDown
(EKEY_CODE keyCode
) const { return KeyIsDown
[keyCode
]; } MyEventReceiver
() { for (u32 i
=0; i
<KEY_KEY_CODES_COUNT
; ++i
) KeyIsDown
[i
] = false; }private: bool KeyIsDown
[KEY_KEY_CODES_COUNT
];};void moveCamera
(irr::scene::ISceneNode *node
, vector3df unite
){ matrix4 m
; m
.setRotationDegrees
(vector3df
(0, node
->getRotation
().Y
, 0)); m
.transformVect
(unite
); node
->setPosition
(node
->getPosition
() + unite
); node
->updateAbsolutePosition
();}void targetCamera
(ICameraSceneNode* camera
){ vector3df rotCam
= camera
->getRotation
(); vector3df pos
(0.0f,0.0f,1000.0f); matrix4 mat
; mat
.setRotationDegrees
(rotCam
); mat
.transformVect
(pos
); camera
->setTarget
(camera
->getAbsolutePosition
() + pos
);}int main
(){ int Lwindows
= 640; int Hwindows
= 480; IrrlichtDevice *device
= createDevice
(EDT_DIRECT3D9
, core::dimension2d<u32
>(Lwindows
,Hwindows
),32,false,false,false); IVideoDriver* driver
= device
->getVideoDriver
(); ISceneManager* sceneMgr
= device
->getSceneManager
(); MyEventReceiver myReceiver
; device
->setEventReceiver
(&myReceiver
); device
->getCursorControl
()->setVisible
(true); ICameraSceneNode* myCamera
= sceneMgr
->addCameraSceneNode
(); myCamera
->setPosition
(vector3df
(1000,2000,1000)); scene::ITerrainSceneNode* terrain
= sceneMgr
->addTerrainSceneNode
( "media/terrain-heightmap.bmp", 0, -1, core::vector3df
(0.f
, 0.f
, 0.f
), core::vector3df
(0.f
, 0.f
, 0.f
), core::vector3df
(20.f
, 1.0f, 20.f
), video::SColor ( 255, 255, 255, 255 ), 5, scene::ETPS_17
, 4 ); terrain
->setMaterialFlag
(video::EMF_LIGHTING
, false); terrain
->setMaterialTexture
(0,driver
->getTexture
("media/terrain-texture.jpg")); terrain
->setMaterialTexture
(1,driver
->getTexture
("media/detailmap3.jpg")); terrain
->setMaterialType
(video::EMT_DETAIL_MAP
); terrain
->scaleTexture
(1.0f, 20.0f); ITriangleSelector* selector
= sceneMgr
->createTerrainTriangleSelector
(terrain
, 0); terrain
->setTriangleSelector
(selector
); ISceneNodeAnimator
* anim
= sceneMgr
->createCollisionResponseAnimator
( selector
, myCamera
, vector3df
(60,200,60), vector3df
(0,-10,0), vector3df
(10,10,10), 0.0001f); selector
->drop
(); myCamera
->addAnimator
(anim
); anim
->drop
(); ICursorControl* curseur
= device
->getCursorControl
(); curseur
->setPosition
(Lwindows
/2,Hwindows
/2); f32 move_speed_front
= 600; f32 move_speed_back
= 200; f32 move_speed_latt
= 300; f32 rot_speed
= 100; u32 then
= device
->getTimer
()->getTime
(); u32 now
= device
->getTimer
()->getTime
(); f32 frameDeltaTime
; int fps
; int lastFPS
; while(device
->run
()) { now
= device
->getTimer
()->getTime
(); frameDeltaTime
= (f32
)(now
- then
) / 1000.f
; then
= now
; vector2d<f32
> posMouse
= curseur
->getRelativePosition
(); myCamera
->setRotation
(myCamera
->getRotation
()+ vector3df
( (posMouse
.Y
- 0.5f)*rot_speed
, (posMouse
.X
- 0.5f) * rot_speed
, 0)); if(myCamera
->getRotation
().X
> 89.0f) { myCamera
->setRotation
(vector3df
(89, myCamera
->getRotation
().Y
, 0.0f)); } if(myCamera
->getRotation
().X
< -89.0f) { myCamera
->setRotation
(vector3df
(-89.0f, myCamera
->getRotation
().Y
, 0.0f)); } targetCamera
(myCamera
); curseur
->setPosition
(Lwindows
/2,Hwindows
/2); if(myReceiver
.IsKeyDown
(KEY_UP
)) { f32 unit
= move_speed_front
*frameDeltaTime
; moveCamera
(myCamera
, vector3df
(0,0.01,unit
)); } if(myReceiver
.IsKeyDown
(KEY_DOWN
)) { f32 unit
= move_speed_back
*frameDeltaTime
; moveCamera
(myCamera
, vector3df
(0,0.01,-unit
)); } if(myReceiver
.IsKeyDown
(KEY_LEFT
)) { f32 unit
= move_speed_latt
*frameDeltaTime
; moveCamera
(myCamera
, vector3df
(-unit
,0.01,0)); } if(myReceiver
.IsKeyDown
(KEY_RIGHT
)) { f32 unit
= move_speed_latt
*frameDeltaTime
; moveCamera
(myCamera
, vector3df
(unit
,0.01,0)); } if(myReceiver
.IsKeyDown
(KEY_ESCAPE
)) { device
->closeDevice
(); } driver
->beginScene
(true, true, SColor(0,0,255,255)); sceneMgr
->drawAll
(); driver
->endScene
(); fps
= driver
->getFPS
(); if (lastFPS
!= fps
) { core::stringw str
= L
"TEST CAMERA_FPS ["; str
+= driver
->getName
(); str
+= "] FPS:"; str
+= fps
; device
->setWindowCaption
(str
.c_str
()); lastFPS
= fps
; } } device
->drop
(); return 0;}
J'ai commenté les lignes les plus importantes.
Et pour ceux que veulent la tester directement, l'exemple est téléchargeable ici:
une camera FPS
A+