• Benvenuto in Making Videogames!
  • Dai sfogo alla tua fantasia!
  • Crea il tuo Videogioco!
Benvenuto ospite! Login Registrati




Valutazione discussione:
  • 1 voto(i) - 5 media
  • 1
  • 2
  • 3
  • 4
  • 5
Tutorial 24 - CursorControl
#1
Tutorial 24: CursorControl

[Immagine: 024shot.jpg]

Mostriamo come modificare il cursore del mouse e offriamo alcune utili funzioni per crearne di nuovi.
Possiamo anche usare l'esempio per fare sperimentare la manipolazione de mouse in generale.
Codice PHP:
#include <irrlicht.h>
#include "driverChoice.h"

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#endif

const int DELAY_TIME 3000;

enum ETimerAction
{
    
ETA_MOUSE_VISIBLE,
    
ETA_MOUSE_INVISIBLE,
}; 
La struttura permette l'esecuzione ritardata di alcune azioni.
Codice PHP:
struct TimerAction
{
    
u32 TargetTime;
    
ETimerAction Action;
};
struct SAppContext
{
    
SAppContext()
    : 
Device(0), InfoStatic(0), EventBox(0), CursorBox(0), SpriteBox(0)
    , 
ButtonSetVisible(0), ButtonSetInvisible(0), ButtonSimulateBadFps(0)
    , 
ButtonChangeIcon(0)
    , 
SimulateBadFps(false)
    {
    }

    
void update()
    {
        if (!
Device)
            return;
        
u32 timeNow Device->getTimer()->getTime();
        for ( 
u32 i=0TimerActions.size(); ++)
        {
            if ( 
timeNow >= TimerActions[i].TargetTime )
            {
                
runTimerAction(TimerActions[i]);
                
TimerActions.erase(i);
            }
            else
            {
                ++
i;
            }
        }
    }

    
void runTimerAction(const TimerActionaction)
    {
        if (
ETA_MOUSE_VISIBLE == action.Action)
        {
            
Device->getCursorControl()->setVisible(true);
            
ButtonSetVisible->setEnabled(true);
        }
        else if ( 
ETA_MOUSE_INVISIBLE == action.Action)
        {
            
Device->getCursorControl()->setVisible(false);
            
ButtonSetInvisible->setEnabled(true);
        }
    } 
Aggiungiamo un altra icona che l'utente può cliccare e selezionare come cursore futuro.
Codice PHP:
void addIcon(const stringwname, const SCursorSprite &spritebool addCursor=true)
    {
        
// Sprites are just icons - not yet cursors. They can be displayed by 
        // Irrlicht sprite functions and be used to create cursors.
        
SpriteBox->addItem(name.c_str(), sprite.SpriteId);
        
Sprites.push_back(sprite);

        
// create the cursor together with the icon?
        
if ( addCursor )
        { 
Qui creiamo un cursore da uno sprite
Codice PHP:
Device->getCursorControl()->addIcon(sprite);

            
// ... e lo aggiungo alla listbox per la scelta dei cursori.
            
CursorBox->addItem(name.c_str());
        }
    }

    
IrrlichtDevice Device;
    
gui::IGUIStaticText InfoStatic;
    
gui::IGUIListBox EventBox;
    
gui::IGUIListBox CursorBox;
    
gui::IGUIListBox SpriteBox;
    
gui::IGUIButton ButtonSetVisible;
    
gui::IGUIButton ButtonSetInvisible;
    
gui::IGUIButton ButtonSimulateBadFps;
    
gui::IGUIButton ButtonChangeIcon;
    array<
TimerActionTimerActions;
    
bool SimulateBadFps;
    array<
SCursorSpriteSprites;
}; 
Funzione di aiuto, serve a mostrare gli eventi passandoli in una stringw che vedremo
Codice PHP:
void PrintMouseEventName(const SEventeventstringw &result)
{
    switch ( 
event.MouseInput.Event )
    {
        case 
EMIE_LMOUSE_PRESSED_DOWN:  result += stringw(L"EMIE_LMOUSE_PRESSED_DOWN"); break;
        case 
EMIE_RMOUSE_PRESSED_DOWN:  result += stringw(L"EMIE_RMOUSE_PRESSED_DOWN"); break;
        case 
EMIE_MMOUSE_PRESSED_DOWN:  result += stringw(L"EMIE_MMOUSE_PRESSED_DOWN"); break;
        case 
EMIE_LMOUSE_LEFT_UP:       result += stringw(L"EMIE_LMOUSE_LEFT_UP"); break;
        case 
EMIE_RMOUSE_LEFT_UP:       result += stringw(L"EMIE_RMOUSE_LEFT_UP"); break;
        case 
EMIE_MMOUSE_LEFT_UP:       result += stringw(L"EMIE_MMOUSE_LEFT_UP"); break;
        case 
EMIE_MOUSE_MOVED:          result += stringw(L"EMIE_MOUSE_MOVED"); break;
        case 
EMIE_MOUSE_WHEEL:          result += stringw(L"EMIE_MOUSE_WHEEL"); break;
        case 
EMIE_LMOUSE_DOUBLE_CLICK:  result += stringw(L"EMIE_LMOUSE_DOUBLE_CLICK"); break;
        case 
EMIE_RMOUSE_DOUBLE_CLICK:  result += stringw(L"EMIE_RMOUSE_DOUBLE_CLICK"); break;
        case 
EMIE_MMOUSE_DOUBLE_CLICK:  result += stringw(L"EMIE_MMOUSE_DOUBLE_CLICK"); break;
        case 
EMIE_LMOUSE_TRIPLE_CLICK:  result += stringw(L"EMIE_LMOUSE_TRIPLE_CLICK"); break;
        case 
EMIE_RMOUSE_TRIPLE_CLICK:  result += stringw(L"EMIE_RMOUSE_TRIPLE_CLICK"); break;
        case 
EMIE_MMOUSE_TRIPLE_CLICK:  result += stringw(L"EMIE_MMOUSE_TRIPLE_CLICK"); break;
        default:
        break;
    }

Funzione di aiuto, per mostrare tutti gli stati del mouse in una stringw che vedremo
Codice PHP:
void PrintMouseState(const SEventeventstringw &result)
{
    
result += stringw(L"X: ");
    
result += stringw(event.MouseInput.X);
    
result += stringw(L"\n");

    
result += stringw(L"Y: ");
    
result += stringw(event.MouseInput.Y);
    
result += stringw(L"\n");


    
result += stringw(L"Wheel: ");
    
result += stringw(event.MouseInput.Wheel);
    
result += stringw(L"\n");

    
result += stringw(L"Shift: ");
    if ( 
event.MouseInput.Shift )
        
result += stringw(L"true\n");
    else
        
result += stringw(L"false\n");

    
result += stringw(L"Control: ");
    if ( 
event.MouseInput.Control )
        
result += stringw(L"true\n");
    else
        
result += stringw(L"false\n");

    
result += stringw(L"ButtonStates: ");
    
result += stringw(event.MouseInput.ButtonStates);
    
result += stringw(L"\n");

    
result += stringw(L"isLeftPressed: ");
    if ( 
event.MouseInput.isLeftPressed() )
        
result += stringw(L"true\n");
    else
        
result += stringw(L"false\n");

    
result += stringw(L"isRightPressed: ");
    if ( 
event.MouseInput.isRightPressed() )
        
result += stringw(L"true\n");
    else
        
result += stringw(L"false\n");

    
result += stringw(L"isMiddlePressed: ");
    if ( 
event.MouseInput.isMiddlePressed() )
        
result += stringw(L"true\n");
    else
        
result += stringw(L"false\n");

    
result += stringw(L"Event: ");

    
PrintMouseEventName(eventresult);

    
result += stringw(L"\n");

Il tipico event receiver.
Codice PHP:
class MyEventReceiver : public IEventReceiver
{
public:
    
MyEventReceiver(SAppContext context) : Context(context) { }

    
virtual bool OnEvent(const SEventevent)
    {
        if (
event.EventType == EET_GUI_EVENT )
        {
            switch ( 
event.GUIEvent.EventType )
            {
                case 
EGET_BUTTON_CLICKED:
                {
                    
u32 timeNow Context.Device->getTimer()->getTime();
                    
TimerAction action;
                    
action.TargetTime timeNow DELAY_TIME;
                    if ( 
event.GUIEvent.Caller == Context.ButtonSetVisible )
                    {
                        
action.Action ETA_MOUSE_VISIBLE;
                        
Context.TimerActions.push_back(action);
                        
Context.ButtonSetVisible->setEnabled(false);
                    }
                    else if ( 
event.GUIEvent.Caller == Context.ButtonSetInvisible )
                    {
                        
action.Action ETA_MOUSE_INVISIBLE;
                        
Context.TimerActions.push_back(action);
                        
Context.ButtonSetInvisible->setEnabled(false);
                    }
                    else if ( 
event.GUIEvent.Caller == Context.ButtonSimulateBadFps )
                    {
                        
Context.SimulateBadFps Context.ButtonSimulateBadFps->isPressed();
                    }
                    else if ( 
event.GUIEvent.Caller == Context.ButtonChangeIcon )
                    { 
Sostituisco l'icona del cursore esistente con un'altra icona. L'utente deve selezionarli entrambe, l'icona da cambiare e quella nuova.
Codice PHP:
s32 selectedCursor Context.CursorBox->getSelected();
                        
s32 selectedSprite Context.SpriteBox->getSelected();
                        if ( 
selectedCursor >= && selectedSprite >= )
                        { 
Qui sostituiamo le icone.
Codice PHP:
Context.Device->getCursorControl()->changeIcon((ECURSOR_ICON)selectedCursorContext.Sprites[selectedSprite] ); 
E mostriamo l'icona.
Codice PHP:
Context.Device->getCursorControl()->setActiveIconECURSOR_ICON(selectedCursor) );
                        }
                    }
                }
                break;
                case 
EGET_LISTBOX_CHANGED:
                case 
EGET_LISTBOX_SELECTED_AGAIN:
                {
                    if ( 
event.GUIEvent.Caller == Context.CursorBox )
                    { 
Mostriamo quale cursore ha scelto l'utente
Codice PHP:
s32 selected Context.CursorBox->getSelected();
                        if ( 
selected >= )
                        { 
Qui impostiamo il nuovo cursore per essere usato nella nostra finestra.
Codice PHP:
Context.Device->getCursorControl()->setActiveIconECURSOR_ICON(selected) );
                        }
                    }
                }
                break;
                default:
                break;
            }
        }

        if (
event.EventType == EET_MOUSE_INPUT_EVENT)
        {
            
stringw infoText;
            
PrintMouseState(eventinfoText);
            
Context.InfoStatic->setText(infoText.c_str());
            if ( 
event.MouseInput.Event != EMIE_MOUSE_MOVED && event.MouseInput.Event != EMIE_MOUSE_WHEEL // no spam
            
{
                
infoText L"";
                
PrintMouseEventName(eventinfoText);
                
Context.EventBox->insertItem(0infoText.c_str(), -1);
            }
        }

        return 
false;
    }

private:
    
SAppContext Context;
}; 
Usiamo diversi files con immagini come frame per le animazioni nelle icone come cursori.
Le immagini in questi file devono essere tutte della stessa dimensione.
In caso di successo ritorniamo l'indice dello sprite Return sprite altrimenti -1
Codice PHP:
s32 AddAnimatedIconToSpriteBankgui::IGUISpriteBank spriteBankvideo::IVideoDriverdriver,  
 const 
io::pathfile, const array< rect<s32> >& rectsu32 frameTime )
{
    if ( !
spriteBank || !driver || !rects.size() )
        return -
1;

    
video::ITexture tex driver->getTexturefile );
    if ( 
tex )
    {
        array< 
rect<s32> >& spritePositions spriteBank->getPositions();
        
u32 idxRect spritePositions.size();
        
u32 idxTex spriteBank->getTextureCount();
        
spriteBank->addTexturetex );

        
SGUISprite sprite;
        
sprite.frameTime frameTime;

        array< 
SGUISprite >& sprites spriteBank->getSprites();
        for ( 
u32 i=0rects.size(); ++)
        {
            
spritePositions.push_backrects[i] );

            
gui::SGUISpriteFrame frame;
            
frame.rectNumber idxRect+i;
            
frame.textureNumber idxTex;
            
sprite.Frames.push_backframe );
        }

        
sprites.push_backsprite );
        return 
sprites.size()-1;
    }

    return -
1;

Creiamo una icone non animata dalla posizione e dal file forniti e lo mettiamo nell'archivio degli sprite.
Potremo usare queste icone come cursori in seguito.
Codice PHP:
s32 AddIconToSpriteBankgui::IGUISpriteBank spriteBankvideo::IVideoDriverdriver,  const io::pathfile, const core::rect<s32>& rect )
{
    if ( !
spriteBank || !driver )
        return -
1;

    
video::ITexture tex driver->getTexturefile );
    if ( 
tex )
    {
        
core::array< core::rect<irr::s32> >& spritePositions spriteBank->getPositions();
        
spritePositions.push_backrect );
        array< 
SGUISprite >& sprites spriteBank->getSprites();
        
spriteBank->addTexturetex );

        
gui::SGUISpriteFrame frame;
        
frame.rectNumber spritePositions.size()-1;
        
frame.textureNumber spriteBank->getTextureCount()-1;

        
SGUISprite sprite;
        
sprite.frameTime 0;
        
sprite.Frames.push_backframe );

        
sprites.push_backsprite );

        return 
sprites.size()-1;
    }

    return -
1;
}

int main()
{
    
video::E_DRIVER_TYPE driverType driverChoiceConsole();
    if (
driverType==video::EDT_COUNT)
        return 
1;

    
IrrlichtDevice device createDevice(driverTypedimension2d<u32>(640480));
    if (
device == 0)
        return 
1// could not create selected driver.

    // It's sometimes of interest to know how the mouse behaves after a resize
    
device->setResizable(true);

    
device->setWindowCaption(L"Cursor control - Irrlicht engine tutorial");
    
video::IVideoDriverdriver device->getVideoDriver();
    
IGUIEnvironmentenv device->getGUIEnvironment();

    
gui::IGUISpriteBank SpriteBankIcons;

    
SAppContext context;
    
context.Device device;

    
rects32 rectInfoStatic(10,10200200);
    
env->addStaticText (L"Cursor state information"rectInfoStatictruetrue);
    
rectInfoStatic.UpperLeftCorner += dimension2di(015);
    
context.InfoStatic env->addStaticText (L""rectInfoStatictruetrue);
    
rects32 rectEventBox(10,210200400);
    
env->addStaticText (L"click events (new on top)"rectEventBoxtruetrue);
    
rectEventBox.UpperLeftCorner += dimension2di(015);
    
context.EventBox env->addListBox(rectEventBox);
    
rects32 rectCursorBox(210,10400250);
    
env->addStaticText (L"cursors, click to set the active one"rectCursorBoxtruetrue);
    
rectCursorBox.UpperLeftCorner += dimension2di(015);
    
context.CursorBox env->addListBox(rectCursorBox);
    
rects32 rectSpriteBox(210,260400400);
    
env->addStaticText (L"sprites"rectSpriteBoxtruetrue);
    
rectSpriteBox.UpperLeftCorner += dimension2di(015);
    
context.SpriteBox env->addListBox(rectSpriteBox);

    
context.ButtonSetVisible env->addButtonrect<s32>( 4102056040 ), 0, -1L"set visible (delayed)" );
    
context.ButtonSetInvisible env->addButtonrect<s32>( 4105056070 ), 0, -1L"set invisible (delayed)" );
    
context.ButtonSimulateBadFps env->addButtonrect<s32>( 41080560100 ), 0, -1L"simulate bad FPS" );
    
context.ButtonSimulateBadFps->setIsPushButton(true);
    
context.ButtonChangeIcon env->addButtonrect<s32>( 410140560160 ), 0, -1L"replace cursor icon\n(cursor+sprite must be selected)" );

    
// set the names for all the system cursors
    
for ( int i=0< (int)gui::ECI_COUNT; ++)
    {
        
context.CursorBox->addItem(stringwGUICursorIconNames[i] ).c_str());
    } 
Create sprites which then can be used as cursor icons.
Codice PHP:
SpriteBankIcons env->addEmptySpriteBank(io::path("cursor_icons"));
    
context.SpriteBox->setSpriteBank(SpriteBankIcons);

    
// create one animated icon from several files
    
array< io::path files;
    
files.push_backio::path("../../media/icon_crosshairs16x16bw1.png") );
    
files.push_backio::path("../../media/icon_crosshairs16x16bw2.png") );
    
files.push_backio::path("../../media/icon_crosshairs16x16bw3.png") );
    
files.push_backio::path("../../media/icon_crosshairs16x16bw3.png") );
    
files.push_backio::path("../../media/icon_crosshairs16x16bw2.png") );
    
SCursorSprite spriteBw;  // lo sprite + informazioni aggiuntive per il cursore
    
spriteBw.SpriteId AddAnimatedIconToSpriteBankSpriteBankIconsdriverfiles200 );
    
spriteBw.SpriteBank SpriteBankIcons;
    
spriteBw.HotSpot position2d<s32>(7,7);
    
context.addIcon(L"crosshair_bw"spriteBw);

    
// create one animated icon from one file
    
array< rect<s32> > iconRects;
    
iconRects.push_backrect<s32>(0,01616) );
    
iconRects.push_backrect<s32>(16,03216) );
    
iconRects.push_backrect<s32>(0,161632) );
    
iconRects.push_backrect<s32>(0,161632) );
    
iconRects.push_backrect<s32>(16,03216) );
    
SCursorSprite spriteCol;  // lo sprite + informazioni aggiuntive per il cursore
    
spriteCol.SpriteId AddAnimatedIconToSpriteBankSpriteBankIconsdriverio::path("../../media/icon_crosshairs16x16col.png"), iconRects200 );
    
spriteCol.HotSpot position2d<s32>(7,7);
    
spriteCol.SpriteBank SpriteBankIcons;
    
context.addIcon(L"crosshair_colored"spriteCol);

    
// Creo alcune icone non animate
    
rect<s32rectIcon;
    
SCursorSprite spriteNonAnimated(SpriteBankIcons0position2d<s32>(7,7));

    
rectIcon rect<s32>(0,01616);
    
spriteNonAnimated.SpriteId AddIconToSpriteBankSpriteBankIconsdriverio::path("../../media/icon_crosshairs16x16col.png"), rectIcon );
    
context.addIcon(L"crosshair_col1"spriteNonAnimatedfalse);

    
rectIcon rect<s32>(16,03216);
    
spriteNonAnimated.SpriteId AddIconToSpriteBankSpriteBankIconsdriverio::path("../../media/icon_crosshairs16x16col.png"), rectIcon );
    
context.addIcon(L"crosshair_col2"spriteNonAnimatedfalse);

    
rectIcon rect<s32>(0,161632);
    
spriteNonAnimated.SpriteId AddIconToSpriteBankSpriteBankIconsdriverio::path("../../media/icon_crosshairs16x16col.png"), rectIcon );
    
context.addIcon(L"crosshair_col3"spriteNonAnimatedfalse);

    
MyEventReceiver receiver(context);
    
device->setEventReceiver(&receiver);

    while(
device->run() && driver)
    {
        
// if (device->isWindowActive())
        
{
            
u32 realTimeNow device->getTimer()->getRealTime();

            
context.update();

            
driver->beginScene(truetrueSColor(0,200,200,200));

            
env->drawAll();

            
// disegno lo sprite personalizzato con le funzioni di Irrlicht functions per confrontare. 
            //Dovrebbe assomigliare al cursore.
            
if ( context.SpriteBox )
            {
                
s32 selectedSprite context.SpriteBox->getSelected();
                if ( 
selectedSprite >= && context.Sprites[selectedSprite].SpriteId >= )
                {
                    
SpriteBankIcons->draw2DSprite(u32(context.Sprites[selectedSprite].SpriteId), position2di(580140), 0video::SColor(255255255255), 0realTimeNow);
                }
            }

            
driver->endScene();
        }

        
// Simuliamo un cattivo fps per capire se il supporto hardware dei cursori funziona o no. 
        //Se funziona il cursore si muoverà normalmente, altrimenti lo aggiorniamo ogni 2 fps .
        
if ( context.SimulateBadFps )
        {
            
device->sleep(500); // 2 fps
        
}
        else
        {
            
device->sleep(10);
        }
    }

    
device->drop();

    return 
0;

Versione pdf scaricabile da QUI
 
Rispondi
  


Vai al forum:


Browsing: 1 Ospite(i)