I. Prérequis▲
Ok, commençons avec les en-têtes (je pense qu'il n'y a rien à en dire).
#include
<irrlicht.h>
#include
"driverChoice.h"
#ifdef _MSC_VER
#pragma comment(lib,
"Irrlicht.lib"
)
#endif
// Espace de noms pour le moteur.
using
namespace
irr;
using
namespace
core;
using
namespace
video;
using
namespace
scene;
Maintenant, nous allons définir la résolution dans une constante pour l'utiliser dans l'initialisation du moteur et la configuration du « viewport ». De plus, nous définissons une variable globale indiquant si la division d'écran est active ou non.
// Résolution
const
int
ResX=
800
;
const
int
ResY=
600
;
const
bool
fullScreen=
false
;
// Utiliser la division d'écran ?
bool
SplitScreen=
true
;
Maintenant, nous avons besoin de quatre pointeurs sur nos caméras que nous créerons plus tard.
// caméras
ICameraSceneNode *
camera[4
]={
0
,0
,0
,0
}
;
Dans notre receveur d'événements, nous changeons la variable SplitScreen lorsque l'utilisateur presse la touche 'S'. Tous les autres événements sont envoyés à la caméra FPS.
class
MyEventReceiver : public
IEventReceiver
{
public
:
virtual
bool
OnEvent(const
SEvent&
event)
{
// La touche S active/désactive la division de l'écran.
if
(event.EventType ==
irr::
EET_KEY_INPUT_EVENT &&
event.KeyInput.Key ==
KEY_KEY_S &&
event.KeyInput.PressedDown)
{
SplitScreen =
!
SplitScreen;
return
true
;
}
// Envoie tous les autres événements à la caméra 4.
if
(camera[3
])
return
camera[3
]->
OnEvent(event);
return
false
;
}
}
;
OK, maintenant la fonction main : premièrement, nous initialisons le moteur, obtenons le gestionnaire de sources et le pilote vidéo, chargeons un objet animé à partir du fichier .md2 et une carte à partir du fichier .pk3. Parce que ce sont de vieilles choses, je n'expliquerai pas toutes les étapes. Faites juste attention à la position de la carte.
int
main()
{
// Demande à l'utilisateur un pilote.
video::
E_DRIVER_TYPE driverType=
driverChoiceConsole();
if
(driverType==
video::
EDT_COUNT)
return
1
;
// Instance de EventReceiver.
MyEventReceiver receiver;
// Initialise le moteur.
IrrlichtDevice *
device =
createDevice(driverType,
dimension2du(ResX,ResY), 32
, fullScreen,
false
, false
, &
receiver);
if
(!
device)
return
1
;
ISceneManager *
smgr =
device->
getSceneManager();
IVideoDriver *
driver =
device->
getVideoDriver();
// Charge le modèle.
IAnimatedMesh *
model =
smgr->
getMesh("../../media/sydney.md2"
);
if
(!
model)
return
1
;
IAnimatedMeshSceneNode *
model_node =
smgr->
addAnimatedMeshSceneNode(model);
// Charge la texture.
if
(model_node)
{
ITexture *
texture =
driver->
getTexture("../../media/sydney.bmp"
);
model_node->
setMaterialTexture(0
,texture);
model_node->
setMD2Animation(scene::
EMAT_RUN);
// Désactive l'éclairage (nous n'avons pas de lumière).
model_node->
setMaterialFlag(EMF_LIGHTING,false
);
}
// Charge la carte.
device->
getFileSystem()->
addFileArchive("../../media/map-20kdm2.pk3"
);
IAnimatedMesh *
map =
smgr->
getMesh("20kdm2.bsp"
);
if
(map)
{
ISceneNode *
map_node =
smgr->
addOctreeSceneNode(map->
getMesh(0
));
// Définit la position.
map_node->
setPosition(vector3df(-
850
,-
220
,-
850
));
}
II. Création des caméras▲
Maintenant nous créons quatre caméras. L'une regarde vers le modèle en face, une autre d'en haut et une sur un côté. De plus, il y a une caméra FPS qui peut être contrôlée par l'utilisateur.
// Crée trois caméras fixes et une contrôlée par l'utilisateur.
// Devant
camera[0
] =
smgr->
addCameraSceneNode(0
, vector3df(50
,0
,0
), vector3df(0
,0
,0
));
// Dessus
camera[1
] =
smgr->
addCameraSceneNode(0
, vector3df(0
,50
,0
), vector3df(0
,0
,0
));
// Gauche
camera[2
] =
smgr->
addCameraSceneNode(0
, vector3df(0
,0
,50
), vector3df(0
,0
,0
));
// Contrôlée par l'utilisateur.
camera[3
] =
smgr->
addCameraSceneNodeFPS();
// Ne commence pas à la position de Sydney.
if
(camera[3
])
camera[3
]->
setPosition(core::
vector3df(-
50
,0
,-
50
));
Créer une variable pour compter le nombre d'images par secondes et cacher la souris.
// Cacher la souris.
device->
getCursorControl()->
setVisible(false
);
// Nous voulons compter le nombre d'images par secondes.
int
lastFPS =
-
1
;
III. Rendu de l'écran partagé▲
Ce n'était pas nouveau, jusqu'à maintenant ! Définir quatre caméras n'est pas suffisant pour diviser l'écran du jeu. Pour le faire, vous devez suivre quelques étapes :
- mettre le « viewport » sur la totalité de l'écran ;
- commencer une scène (effacer la scène) ;
- les trois étapes suivantes sont répétées pour chaque « viewport » dans la division d'écran :
- mettre le « viewport » là où vous le souhaitez ;
- activer la caméra qui doit être liée au « viewport » ;
- dessiner tous les objets ;
- si vous avez une interface utilisateur :
- mettre le « viewport » sur tout l'écran ;
- afficher l'interface utilisateur ;
- fin de la scène.
Cela paraît un petit peu compliqué, mais vous verrez ça ne l'est pas :
while
(device->
run())
{
// Définit la zone de rendu sur la totalité de l'écran et commence la scène.
driver->
setViewPort(rect<
s32>
(0
,0
,ResX,ResY));
driver->
beginScene(true
,true
,SColor(255
,100
,100
,100
));
// Si la division d'écran est utilisée.
if
(SplitScreen)
{
// Active la caméra 1.
smgr->
setActiveCamera(camera[0
]);
// Définit la zone de rendu sur le premier quart (en haut à gauche).
driver->
setViewPort(rect<
s32>
(0
,0
,ResX/
2
,ResY/
2
));
// Dessine la scène.
smgr->
drawAll();
// Active la caméra 2.
smgr->
setActiveCamera(camera[1
]);
// Définit la zone de rendu sur le deuxième quart (en haut à droite).
driver->
setViewPort(rect<
s32>
(ResX/
2
,0
,ResX,ResY/
2
));
// Dessine la scène.
smgr->
drawAll();
// Active la caméra 3.
smgr->
setActiveCamera(camera[2
]);
// Définit la zone de rendu sur le troisième quart (en bas à gauche).
driver->
setViewPort(rect<
s32>
(0
,ResY/
2
,ResX/
2
,ResY));
// Dessine la scène.
smgr->
drawAll();
// définit la zone de rendu sur le dernier quart (en bas à droite )
driver->
setViewPort(rect<
s32>
(ResX/
2
,ResY/
2
,ResX,ResY));
}
// Active la caméra 4.
smgr->
setActiveCamera(camera[3
]);
// Dessine la scène.
smgr->
drawAll();
driver->
endScene();
Comme vous pouvez le voir, l'image est dessinée séparément pour chaque « viewport ». Ce qui veut dire que vous perdrez de la performance. OK, si vous vous demandez « Comment je dois mettre le « viewport » pour avoir cet écran ou celui-là ? », ne paniquez pas, c'est très simple : dans la fonction rect, vous définissez quatre coordonnées :
- la coordonnée X du coin en haut à gauche ;
- la coordonnée Y du coin en haut à gauche ;
- la coordonnée X du coin en bas à droite ;
- la coordonnée Y du coin en bas à droite ;
Ce qui veut dire que si vous voulez séparer l'écran en deux « viewport », vous donnerez les coordonnées suivantes :
- 1er « viewport » : 0,0,ResX/2,ResY
- 2ème « viewport » : ResX/2,0,ResX,ResY
Si vous n'avez pas tout compris, testez juste l'exemple pour voir ce qu'il se passe.
Maintenant, nous affichons juste le nombre d'images par seconde et arrêtons le moteur quand l'utilisateur le souhaite :
// Obtient et montre le nombre d'images par secondes.
if
(driver->
getFPS() !=
lastFPS)
{
lastFPS =
driver->
getFPS();
core::
stringw tmp =
L"Irrlicht SplitScreen-Example (FPS: "
;
tmp +=
lastFPS;
tmp +=
")"
;
device->
setWindowCaption(tmp.c_str());
}
}
// Supprime le moteur.
device->
drop();
return
0
;
}
Voilà ! Compilez et testez le programme.
Note : la touche 'S' peut être utilisée pour utiliser ou non la division d'écran.
IV. Conclusion▲
Vous pouvez désormais diviser votre écran en plusieurs parties.
Dans le prochain tutoriel Souris et manettes de jeux, nous verrons comment traiter les événements de souris et de manettes de jeux.
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.