Creare Videogiochi - Game Developer
Tutorial 19 - Mouse and Joystick - Versione stampabile

+- Creare Videogiochi - Game Developer (https://www.making-videogames.net/giochi)
+-- Forum: Altri Programmi per la Creazione di Videogames (https://www.making-videogames.net/giochi/Forum-Altri-Programmi-per-la-Creazione-di-Videogames)
+--- Forum: Irrlicht Engine (https://www.making-videogames.net/giochi/Forum-Irrlicht-Engine)
+--- Discussione: Tutorial 19 - Mouse and Joystick (/thread-Tutorial-19-Mouse-and-Joystick)



Tutorial 19 - Mouse and Joystick - Chip - 21-08-2015

Tutorial 19: Mouse and Joystick

[Immagine: 019shot.jpg]

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 joystickaggiornandolo 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 SEventevent)
    {
        
// 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.event.MouseInput.X;
                
MouseState.Position.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;
}; 
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.
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;

    
IrrlichtDevicedevice createDevice(driverType,
            
core::dimension2d<u32>(640480), 16falsefalsefalse, &receiver);

    if (
device == 0)
        return 
1// could not create selected driver.


    
core::array<SJoystickInfojoystickInfo;
    if(
device->activateJoysticks(joystickInfo))
    {
        
std::cout << "Joystick support is enabled and " << joystickInfo.size() << " joystick(s) are present." << std::endl;

        for(
u32 joystick 0joystick 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::IVideoDriverdriver device->getVideoDriver();
    
scene::ISceneManagersmgr device->getSceneManager(); 
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).
Codice PHP:
scene::ISceneNode node smgr->addMeshSceneNode(
        
smgr->addArrowMesh"Arrow",
                
video::SColor(25525500),
                
video::SColor(25502550),
                
16,16,
                
2.f1.3f,
                
0.1f0.6f
                
)
        );
    
node->setMaterialFlag(video::EMF_LIGHTINGfalse);

    
scene::ICameraSceneNode camera smgr->addCameraSceneNode();
    
camera->setPosition(core::vector3df(00, -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 && 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(moveHorizontal0.f) || !core::equals(moveVertical0.f))
            {
                
nodePosition.+= MOVEMENT_SPEED frameDeltaTime moveHorizontal;
                
nodePosition.+= 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().Positioncamera);

            
// Intersezione con un piano rivolto alla camera che segue la mesh.
            
core::plane3df plane(nodePositioncore::vector3df(00, -1));
            
core::vector3df mousePosition;
            if(
plane.getIntersectionWithLine(ray.startray.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_LIGHTINGreceiver.GetMouseState().LeftButtonDown);

        
driver->beginScene(truetruevideo::SColor(255,113,113,133));
        
smgr->drawAll(); // draw the 3d scene
        
driver->endScene();
    } 
Alla fine cancelliamo il device di Irrlicht.
Codice PHP:
device->drop();

    return 
0;


Versione pdf scaricabile da QUI