21-08-2015, 09:02 PM
(Questo messaggio è stato modificato l'ultima volta il: 21-08-2015, 09:03 PM da Chip.)
Tutorial 19: Mouse and Joystick
Questo tutorial è basato sull'esempio '04.Movement' che mostra come gestire gli eventi da tastiera con Irrlicht. Adesso gestiremo gli eventi del mouse e del joystick, se ne avete di collegati ai vostri device che al momento potrebbero essere Windows, Linux e device SDL.
L'event receiver per controlalre la pressione dei tasti è pronto, la risposta a tali eventi verrà fatta dentro al loop del render, prima il disegno della scena. Quindi creiamo un irr::IrrlichtDevice e il nodo della scena che vogliamo muovere. Creiamo anche altri nodi aggiuntivi, per mostrare altre possibilità di movimento e animazione disponibili in Irrlicht.
Creiamo una mesh a forma di freccia create e muoviamola sia con il mouse che con il puntatore del mouse (c'è proprio un metodo apposito addArrowMesh() che crea un cono e un cilindro ndt).
Alla fine cancelliamo il device di Irrlicht.
Versione pdf scaricabile da QUI
Questo tutorial è basato sull'esempio '04.Movement' che mostra come gestire gli eventi da tastiera con Irrlicht. Adesso gestiremo gli eventi del mouse e del joystick, se ne avete di collegati ai vostri device che al momento potrebbero essere Windows, Linux e device SDL.
Codice PHP:
#ifdef _MSC_VER
// Lo definiamo per evitare i warning di MSVC per l'uso della sprintf().
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "Irrlicht.lib")
#endif
#include <irrlicht.h>
#include "driverChoice.h"
using namespace irr;
Come facevamo per l'sempio '04.Movement', ci salviamo l'ultimo stato del mouse e del primo joystick, aggiornandolo quando riceviamo un evento.
class MyEventReceiver : public IEventReceiver
{
public:
// Creiamo una struct per registrare lo stato del mouse
struct SMouseState
{
core::position2di Position;
bool LeftButtonDown;
SMouseState() : LeftButtonDown(false) { }
} MouseState;
// Il metodo che dobbiamo implementare per gestire gli eventi
virtual bool OnEvent(const SEvent& event)
{
// Remember the mouse state
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:
// We won't use the wheel
break;
}
}
// Lo stato ci ciascun joystick connesso è inviato ad ogni run() al
// device Irrlicht. Registraiamo lo stato del solo primo joystick
// ignorando gli altri.
// Al momento è supportato solo per Windows e 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;
};
Codice PHP:
int main()
{
// ask user for driver
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;
// create device
MyEventReceiver receiver;
IrrlichtDevice* device = createDevice(driverType,
core::dimension2d<u32>(640, 480), 16, false, false, false, &receiver);
if (device == 0)
return 1; // could not create selected driver.
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 << "\tName: '" << joystickInfo[joystick].Name.c_str() << "'" << std::endl;
std::cout << "\tAxes: " << joystickInfo[joystick].Axes << std::endl;
std::cout << "\tButtons: " << joystickInfo[joystick].Buttons << std::endl;
std::cout << "\tHat 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();
Codice PHP:
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.3f,
0.1f, 0.6f
)
);
node->setMaterialFlag(video::EMF_LIGHTING, false);
scene::ICameraSceneNode * camera = smgr->addCameraSceneNode();
camera->setPosition(core::vector3df(0, 0, -10));
// Come per l'esempio 04, usiamo movimenti indipendenti dal framerate.
u32 then = device->getTimer()->getTime();
const f32 MOVEMENT_SPEED = 5.f;
while(device->run())
{
// Codice per la gestione del frame delta time.
const u32 now = device->getTimer()->getTime();
const f32 frameDeltaTime = (f32)(now - then) / 1000.f; // Time in seconds
then = now;
bool movedWithJoystick = false;
core::vector3df nodePosition = node->getPosition();
if(joystickInfo.size() > 0)
{
f32 moveHorizontal = 0.f; // Range is -1.f for full left to +1.f for full right
f32 moveVertical = 0.f; // -1.f for full down to +1.f for full up.
const SEvent::SJoystickEvent & joystickData = receiver.GetJoystickState();
// Ricevendo l'intero range analogico del movimento degli assi,
// dobbiamo implementare la gestione delle zone morte. Si tratta di
// un valore empirico poiché i joystick non sono tutti uguali. Con un
// 5% del range come zona morta ci stiamo dentro ma sarebbe meglio
// dare all'utente la possibilità di cambiarlo.
const f32 DEAD_ZONE = 0.05f;
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;
// Il POV è supportato solo per Windows, in caso contrario è garantito
// debba essere 65535, quindi possiamo prenderlo.
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;
}
}
// Se la freccia non viene mossa con il mouse, lo fa seguendo il cursore.
if(!movedWithJoystick)
{
// Creo un raggio che attraversa il cursore del mouse.
core::line3df ray = smgr->getSceneCollisionManager()->getRayFromScreenCoordinates(
receiver.GetMouseState().Position, camera);
// Intersezione con un piano rivolto alla camera che segue la mesh.
core::plane3df plane(nodePosition, core::vector3df(0, 0, -1));
core::vector3df mousePosition;
if(plane.getIntersectionWithLine(ray.start, ray.getVector(), mousePosition))
{
// Ora abbiamo una posizione mouse nello spazio 3d da seguire.
core::vector3df toMousePosition(mousePosition - nodePosition);
const f32 availableMovement = MOVEMENT_SPEED * frameDeltaTime;
if(toMousePosition.getLength() <= availableMovement)
nodePosition = mousePosition; // Jump to the final position
else
nodePosition += toMousePosition.normalize() * availableMovement; // Seguiamolo
}
}
node->setPosition(nodePosition);
// Accendo/spengo l'illuminazione alla pressione del tasto sx del mouse.
node->setMaterialFlag(video::EMF_LIGHTING, receiver.GetMouseState().LeftButtonDown);
driver->beginScene(true, true, video::SColor(255,113,113,133));
smgr->drawAll(); // draw the 3d scene
driver->endScene();
}
Codice PHP:
device->drop();
return 0;
}
Versione pdf scaricabile da QUI