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.
wondering why the eventReveiver is not a part of the engine
-
- Posts: 10
- Joined: Sun Nov 29, 2015 6:49 pm
Re: wondering why the eventReveiver is not a part of the eng
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.
It provides a larger flexibility.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Re: wondering why the eventReveiver is not a part of the eng
You need fake events? Just send them to your function, it's your function after all.
-
- Posts: 10
- Joined: Sun Nov 29, 2015 6:49 pm
Re: wondering why the eventReveiver is not a part of the eng
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?
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?
Re: wondering why the eventReveiver is not a part of the eng
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.
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
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
-
- Competition winner
- Posts: 688
- Joined: Mon Sep 10, 2012 8:51 am
Re: wondering why the eventReveiver is not a part of the eng
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:
^ This is by no means complete, mind you, but it conveys the idea.
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)"
};