I. Prérequis▲
#ifdef _MSC_VER
// Nous définissons ceci pour stopper l'avertissement de MSVC pour sprintf().
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib,
"Irrlicht.lib"
)
#endif
#include
<irrlicht.h>
#include
"driverChoice.h"
using
namespace
irr;
Tout comme nous l'avons fait dans l'exemple 4 : Mouvement, nous stockons l'état de la souris et de la première manette et les mettons à jour quand nous recevons des événements.
class
MyEventReceiver : public
IEventReceiver
{
public
:
// Nous créons une structure pour enregistrer les informations sur l'état de la souris.
struct
SMouseState
{
core::
position2di Position;
bool
LeftButtonDown;
SMouseState() : LeftButtonDown(false
) {
}
}
MouseState;
// Ceci est la méthode que nous devons implémenter.
virtual
bool
OnEvent(const
SEvent&
event)
{
// Se rappelle de l'état de la souris.
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_MOUSE_MOVED:
MouseState.Position.X =
event.MouseInput.X;
MouseState.Position.Y =
event.MouseInput.Y;
break
;
default
:
// Nous n'utiliserons pas la roulette.
break
;
}
}
// L'état de chaque manette connectée nous est envoyé
// à chaque run() du moteur irrlicht. Stockons l'état
// de la première manette, et ignorons les autres.
// Ceci n'est actuellement supporté que sous Windows et Linux.
if
(event.EventType ==
irr::
EET_JOYSTICK_INPUT_EVENT
&&
event.JoystickEvent.Joystick ==
0
)
{
JoystickState =
event.JoystickEvent;
}
return
false
;
}
const
SEvent::
SJoystickEvent &
GetJoystickState(void
) const
{
return
JoystickState;
}
const
SMouseState &
GetMouseState(void
) const
{
return
MouseState;
}
MyEventReceiver()
{
}
private
:
SEvent::
SJoystickEvent JoystickState;
}
;
II. Obtention des informations sur le joystick▲
Le receveur d'événements est prêt pour conserver les touches pressées, la réponse actuelle sera faite dans la boucle de rendu, juste avant de dessiner la scène. Donc créons juste un irr::IrrlichtDevice ainsi que le nœud de scène que nous voulons déplacer. Nous créons aussi d'autres nœuds de scènes supplémentaires, pour montrer qu'il y a aussi d'autres façons de déplacer et d'animer des nœuds de scènes.
int
main()
{
// Demande à l'utilisateur un pilote.
video::
E_DRIVER_TYPE driverType=
driverChoiceConsole();
if
(driverType==
video::
EDT_COUNT)
return
1
;
// Crée le moteur.
MyEventReceiver receiver;
IrrlichtDevice*
device =
createDevice(driverType,
core::
dimension2d<
u32>
(640
, 480
), 16
, false
, false
, false
, &
receiver);
if
(device ==
0
)
return
1
; // Ne peut pas créer le pilote sélectionné.
core::
array<
SJoystickInfo>
joystickInfo;
if
(device->
activateJoysticks(joystickInfo))
{
std::
cout <<
"Joystick support is enabled and "
<<
joystickInfo.size() <<
" joystick(s) are present."
<<
std::
endl;
for
(u32 joystick =
0
; joystick <
joystickInfo.size(); ++
joystick)
{
std::
cout <<
"Joystick "
<<
joystick <<
":"
<<
std::
endl;
std::
cout <<
"
\t
Name: '"
<<
joystickInfo[joystick].Name.c_str() <<
"'"
<<
std::
endl;
std::
cout <<
"
\t
Axes: "
<<
joystickInfo[joystick].Axes <<
std::
endl;
std::
cout <<
"
\t
Buttons: "
<<
joystickInfo[joystick].Buttons <<
std::
endl;
std::
cout <<
"
\t
Hat is: "
;
switch
(joystickInfo[joystick].PovHat)
{
case
SJoystickInfo::
POV_HAT_PRESENT:
std::
cout <<
"present"
<<
std::
endl;
break
;
case
SJoystickInfo::
POV_HAT_ABSENT:
std::
cout <<
"absent"
<<
std::
endl;
break
;
case
SJoystickInfo::
POV_HAT_UNKNOWN:
default
:
std::
cout <<
"unknown"
<<
std::
endl;
break
;
}
}
}
else
{
std::
cout <<
"Joystick support is not enabled."
<<
std::
endl;
}
core::
stringw tmp =
L"Irrlicht Joystick Example ("
;
tmp +=
joystickInfo.size();
tmp +=
" joysticks)"
;
device->
setWindowCaption(tmp.c_str());
video::
IVideoDriver*
driver =
device->
getVideoDriver();
scene::
ISceneManager*
smgr =
device->
getSceneManager();
III. Traitement des événements▲
Nous créons un objet en forme de flèche et le déplaçons selon les axes/chapeaux de la manette, ou lui faisons suivre le curseur de la souris.
scene::
ISceneNode *
node =
smgr->
addMeshSceneNode(
smgr->
addArrowMesh( "Arrow"
,
video::
SColor(255
, 255
, 0
, 0
),
video::
SColor(255
, 0
, 255
, 0
),
16
,16
,
2.
f, 1.3
f,
0.1
f, 0.6
f
)
);
node->
setMaterialFlag(video::
EMF_LIGHTING, false
);
scene::
ICameraSceneNode *
camera =
smgr->
addCameraSceneNode();
camera->
setPosition(core::
vector3df(0
, 0
, -
10
));
// Comme dans l'exemple 04, nous allons utiliser un mouvement indépendant du nombre d'images par seconde.
u32 then =
device->
getTimer()->
getTime();
const
f32 MOVEMENT_SPEED =
5.
f;
while
(device->
run())
{
// Calcul le temps delta d'une image.
const
u32 now =
device->
getTimer()->
getTime();
const
f32 frameDeltaTime =
(f32)(now -
then) /
1000.
f; // Temps en secondes.
then =
now;
bool
movedWithJoystick =
false
;
core::
vector3df nodePosition =
node->
getPosition();
if
(joystickInfo.size() >
0
)
{
f32 moveHorizontal =
0.
f; // La fourchette va de -1.f (tout à gauche) à 1.f (tout à droite).
f32 moveVertical =
0.
f; // -1.f (tout en bas) à +1.f (tout en haut).
const
SEvent::
SJoystickEvent &
joystickData =
receiver.GetJoystickState();
// Nous recevons une fourchette de valeur analogique complète des axes, et donc nous implémentons notre
// propre zone morte. Ceci est une valeur empirique, depuis que certaines manettes ont plus de gigue ou de glissement
// autour du point central que d'autres. Nous utiliserons 5 % de la fourchette comme zone morte,
// mais généralement, vous voudrez donner à l'utilisateur la possibilité de changer cela.
const
f32 DEAD_ZONE =
0.05
f;
moveHorizontal =
(f32)joystickData.Axis[SEvent::SJoystickEvent::
AXIS_X] /
32767.
f;
if
(fabs(moveHorizontal) <
DEAD_ZONE)
moveHorizontal =
0.
f;
moveVertical =
(f32)joystickData.Axis[SEvent::SJoystickEvent::
AXIS_Y] /
-
32767.
f;
if
(fabs(moveVertical) <
DEAD_ZONE)
moveVertical =
0.
f;
// L'information POV du chapeau est supportée uniquement par Windows, mais sa valeur
// sera obligatoirement 65535 lorsque non-supporté, donc nous pouvons la vérifier.
const
u16 povDegrees =
joystickData.POV /
100
;
if
(povDegrees <
360
)
{
if
(povDegrees >
0
&&
povDegrees <
180
)
moveHorizontal =
1.
f;
else
if
(povDegrees >
180
)
moveHorizontal =
-
1.
f;
if
(povDegrees >
90
&&
povDegrees <
270
)
moveVertical =
-
1.
f;
else
if
(povDegrees >
270
||
povDegrees <
90
)
moveVertical =
+
1.
f;
}
if
(!
core::
equals(moveHorizontal, 0.
f) ||
!
core::
equals(moveVertical, 0.
f))
{
nodePosition.X +=
MOVEMENT_SPEED *
frameDeltaTime *
moveHorizontal;
nodePosition.Y +=
MOVEMENT_SPEED *
frameDeltaTime *
moveVertical;
movedWithJoystick =
true
;
}
}
// Si le nœud de la flèche n'est pas déplacé avec la manette, alors il suit le curseur de la souris.
if
(!
movedWithJoystick)
{
// Crée un rayon partant du curseur de la souris.
core::
line3df ray =
smgr->
getSceneCollisionManager()->
getRayFromScreenCoordinates(
receiver.GetMouseState().Position, camera);
// Ainsi qu'une intersection du rayon avec un plan proche d'un nœud faisant face à la caméra.
core::
plane3df plane(nodePosition, core::
vector3df(0
, 0
, -
1
));
core::
vector3df mousePosition;
if
(plane.getIntersectionWithLine(ray.start, ray.getVector(), mousePosition))
{
// Nous avons maintenant une position de souris dans un espace 3D; déplaçons-la autour.
core::
vector3df toMousePosition(mousePosition -
nodePosition);
const
f32 availableMovement =
MOVEMENT_SPEED *
frameDeltaTime;
if
(toMousePosition.getLength() <=
availableMovement)
nodePosition =
mousePosition; // Saute à la position finale
else
nodePosition +=
toMousePosition.normalize() *
availableMovement; // Move towards it
}
}
node->
setPosition(nodePosition);
// Active ou désactive l'éclairage selon que le bouton gauche de la souris est pressé ou non.
node->
setMaterialFlag(video::
EMF_LIGHTING, receiver.GetMouseState().LeftButtonDown);
driver->
beginScene(true
, true
, video::
SColor(255
,113
,113
,133
));
smgr->
drawAll(); // Dessine la scène 3D.
driver->
endScene();
}
À la fin, nous supprimons le moteur Irrlicht.
device->
drop();
return
0
;
}
IV. Conclusion▲
Vous pouvez désormais traiter les événements souris et de manettes avec Irrlicht.
Dans le prochain tutoriel Gestion de lumières, nous verrons comment utiliser le gestionnaire de lumières d'Irrlicht.
V. Remerciements▲
Merci à Nikolaus Gebhardt de nous permettre de traduire ce tutoriel.
Merci à LittleWhite pour sa relecture technique ainsi qu'à ced pour sa relecture orthographique.