wondering why the eventReveiver is not a part of the engine

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
lordadamson
Posts: 10
Joined: Sun Nov 29, 2015 6:49 pm

wondering why the eventReveiver is not a part of the engine

Post by lordadamson »

Hi all,
I was wondering why isn't the eventReceiver a part of the engine? you know where the engine user would just call the functions like receiver.keydown(KEY_UP) or whatever.

That would make the engine much easier to use.
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: wondering why the eventReveiver is not a part of the eng

Post by Mel »

Because Irrlicht processes already the events, but instead of enabling some inner variables or the like for the user to check, it just passes the message to a user provided routine, that is, the event receiver. that way you have control over how to react to the events, and Irrlicht doesn't have to do anything with the events that just won't matter it.

It provides a larger flexibility.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
hendu
Posts: 2600
Joined: Sat Dec 18, 2010 12:53 pm

Re: wondering why the eventReveiver is not a part of the eng

Post by hendu »

You need fake events? Just send them to your function, it's your function after all.
lordadamson
Posts: 10
Joined: Sun Nov 29, 2015 6:49 pm

Re: wondering why the eventReveiver is not a part of the eng

Post by lordadamson »

you know in theory what you guys say does make sense to me. so the bottom line I believe is: It provides more flexibility and gives me more control.

but you know I'd implement mine with functions like:
is_key_down()
is_key_released()
mouse_button_1_clicked()
mouse_button_2_clicked()
middle_mouse_button_clicked()
get_mouse_x()
get_mouse_y()

and then I'd act accordingly in a different place in my code.

But to get a better understanding of the flexibility the engine provides, could someone give me a little example as to how someone might need to implement the eventreceiver differently?
CuteAlien
Admin
Posts: 9734
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: wondering why the eventReveiver is not a part of the eng

Post by CuteAlien »

You might want to know when the key was pressed (lot's of games timing patterns matter). You might want to ignore keys. You might have different states in which the key means different things. You might want to handle key-repeats as x-clicks or as one click. You might want to handle keys different if they were already pressed when you make the application active (think alt-tab). You might have devices where you want to simulate keys (virtual keyboards). You might need a mode where you have to wait for a key-press (which is very different from testing if a key is pressed down as it has device-run() calls in between).

To give you an example how input handling in a larger game can look like, check my racers sources at https://bitbucket.org/mzeilfelder/trunk_hc1
In src/event_receiver_base.cpp you find the main receiver. From there on it branches out for keyboard and mouse input to src/input_device_manager.cpp. But only after the gui has had a chance to check if it needs the keys maybe first (in which case the game ignores them). And InputDeviceManager also doesn't use it directly but for each input devices I have classes like src/device_keyboard.cpp or src/device_mouse.cpp which offer then the interface which looks a little bit like the one you want. This is a little extreme, but once you want to be able control something with different devices and experiment with settings quickly and allow users to change those settings etc... things can get more and more complicated.

Your case is basically the one you start with - and is enough for many simple games. So maybe it would be good to add such an event-receiver as example to Irrlicht.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
chronologicaldot
Competition winner
Posts: 688
Joined: Mon Sep 10, 2012 8:51 am

Re: wondering why the eventReveiver is not a part of the eng

Post by chronologicaldot »

Interesting. Reminds me of the call-backs methodology of Java, Javascript, and so forth which is rather popular but tedious to do in C++ (at least until lambdas came around).
You could have something like an event receiver with (pseudo code):
void SpecialReceiver::setOnMouseButton1Event( bool doMyMB1Event( const MouseEventAspects& aspects ) )

All in all, though, it just seems like a whole lot more work... to make it conceptually easier?

Maybe it'd be nice if somewhere we had some pre-made IEventReceiver implementations for specific purposes, like FPS, where we have a key map that calls a user-implemented interface with methods like "strafeRight()" and "strafeLeft()". Something like this:

Code: Select all

 
 
// Abstract base class, meant for user implementation
class FPSEventReceiverInterface
{
public:
    // forward key
    virtual void walkForward()=0;
 
    // backward key
    virtual void walkBackward()=0;
 
    // left key
    virtual void strafeLeft()=0;
 
    // right key
    virtual void strafeRight()=0;
 
 
    // Shift + forward key
    virtual void runForward()=0;
 
    // Shift + backward key
    virtual void runBackward()=0;
 
    // Shift + left key
    virtual void runStrafeLeft()=0;
 
    // Shift + right key
    virtual void runStrafeRight()=0;
 
 
    // Fire key
    virtual void fireWeapon()=0;
 
    // Action key (for grabbing items, opening doors, etc.)
    virtual void actOnNearObject()=0;
};
 
 
enum E_FPS_KeyCodes
{
    EFPS_WalkForward=0,
    EFPS_WalkBackward,
    EFPS_StrafeLeft,
    EFPS_StrafeRight,
    EFPS_RunForward,
    EFPS_RunBackward,
    EFPS_RunStrafeLeft,
    EFPS_RunStrafeRight,
    EFPS_FireWeapon,
    EFPS_ActOnNearObject,
 
    EFPS_COUNT
};
 
 
class FPSEventReceiver : public IEventReceiver
{
    FPSEventReceiverInterface* callbacks;
    E_FPS_KeyCodes keyMap[ KEY_KEY_CODES_COUNT ];
 
public:
    FPSEventReceiver() : callbacks(0) {}
 
    void setEventInterface( FPSEventReceiverInterface* pCallbacks )
    {
        callbacks = pCallbacks;
    }
 
    virtual bool OnEvent( const SEvent& event )
    {
        if ( !callbacks ) return;
 
        switch( event.EventType )
        {
        case EET_MOUSE_INPUT_EVENT:
            break;
 
        case EET_KEY_INPUT_EVENT:
            switch( keyMap[ event.KeyInput.Key ] )
            {
            case EFPS_WalkForward: callbacks->walkForward(); return true;
            case EFPS_WalkBackward: callbacks->walkBackward(); return true;
            case EFPS_StrafeLeft: callbacks->strafeLeft(); return true;
            case EFPS_StrafeRight: callbacks->strafeRight(); return true;
            case EFPS_RunForward: callbacks->runForward(); return true;
            case EFPS_RunBackward: callbacks->runBackward(); return true;
            case EFPS_RunStrafeLeft: callbacks->runStrafeLeft(); return true;
            case EFPS_RunStrafeRight: callbacks->runStrafeRight(); return true;
            case EFPS_FireWeapon: callbacks->fireWeapon(); return true;
            case EFPS_ActOnNearObject: callbacks->actOnNearObject(); return true;
            default: break;
            }
            break;
        }
 
        return false;
    }
 
 
    // Other methods might include "setFireKey(EKEY_CODE)" and "setActionKey(EKEY_CODE)"
};
 
^ This is by no means complete, mind you, but it conveys the idea.
Post Reply