Site under construction!
Events explained
Introduction
This tutorial is a detailed list of window events. It describes them, and shows how to (and how not to) use them.
The Event type
Before dealing with events, it is important to understand what the
Event type is,
and how to correctly use it. Event
is a union, which means that only one of its members is
valid at a time (remember your C/C++/D lessons: all the members of a
union share the same memory space). The valid member is the one that
matches the event type, for example event.key
for a KeyPressed
event. Trying to read any
other member will result in an undefined behavior (most likely:
random or invalid values). It it important to never try to use an
event member that doesn't match its type.
Event
instances are filled by the pollEvent
(or waitEvent
) function of the
Window
class. Only these two functions can produce valid events, any
attempt to use an Event
which was not returned by successful call to pollEvent
(or waitEvent
) will result in the same
undefined behavior that was mentioned above.
To be clear, here is what a typical event loop looks like:
Event event;
while(window.pollEvent(event))
{
// check the type of the event
switch(event.type)
{
// window closed
case Event.EventType.Closed:
window.close();
break;
// key pressed
case Event.EventType.KeyPressed:
...
break;
// we don't process other types of events
default:
break;
}
}
Read the above paragraph once again and make sure that you fully understand it, the Event union is the cause of many problems for inexperienced programmers.
Alright, now we can see what events DSFML supports, what they mean and how to use them properly.
The Closed event
The Event.EventType.Closed
event is triggered
when the user wants to close the window, through any of the possible
methods the window manager provides ("close" button, keyboard shortcut,
etc.). This event only represents a close request, the window is not yet
closed when the event is received.
Typical code will just call window.close()
in
reaction to this event, to actually close the window. However, you may
also want to do something else first, like saving the current
application state or asking the user what to do. If you don't do
anything, the window remains open.
There's no member associated with this event in the Event union.
if (event.type == Event.EventType.Closed)
window.close();
The Resized event
The Event.EventType.Resized
event is triggered
when the window is resized, either through user action or
programmatically by calling window.setSize
.
You can use this event to adjust the rendering settings: the viewport if you use OpenGL directly, or the current view if you use dsfml-graphics.
The member associated with this event is event.size
,
it contains the new size of the window.
if (event.type == Event.EventType.Resized)
{
writeln("new width: ", event.size.width);
writeln("new height: ", event.size.height);
}
The LostFocus and GainedFocus events
The Event.EventType.Resized
event is triggered
when the window is resized, either through user action or
programmatically by calling window.setSize
.
The Event.EventType.LostFocus
and
Event.EventType.GainedFocus
events are triggered
when the window loses/gains focus, which happens when the user switches
the currently active window. When the window is out of focus, it doesn't
receive keyboard events.
This event can be used e.g. if you want to pause your game when the window is inactive.
There's no member associated with this event in the Event union.
if (event.type == Event.EventType.LostFocus)
myGame.pause();
if (event.type == Event.EventType.GainedFocus)
myGame.resume();
The TextEntered event
The Event.EventType.TextEntered
event is
triggered when a character is typed. This must not be confused with the
KeyPressed
event: TextEntered
interprets the user input and produces the appropriate printable
character. For example, pressing '^' then 'e' on a French keyboard will
produce two KeyPressed
events, but a single
TextEntered
event containing the 'ê' character.
It works with all the input methods provided by the operating system,
even the most specific or complex ones.
This event is typically used to catch user input in a text field.
The member associated with this event is event.text
,
it contains the Unicode value of the entered character as a dchar
.
if (event.type == Event.EventType.TextEntered)
{
writeln("Character typed: ", event.text.unicode);
}
Note that, since they are part of the Unicode standard, some non-printable characters such as backspace are generated by this event. In most cases you'll need to filter them out.
Many programmers use the KeyPressed
event to get
user input, and start to implement crazy algorithms that try to
interpret all the possible key combinations to produce correct
characters. Don't do that!
The KeyPressed and KeyReleased events
The Event.EventType.KeyPressed
and
Event.EventType.KeyReleased
events are triggered
when a keyboard key is pressed/released.
If a key is held, multiple KeyPressed
events
will be generated, at the default operating system delay (ie. the same
delay that applies when you hold a letter in a text editor). To disable
repeated KeyPressed
events, you can call
window.setKeyRepeatEnabled(false)
. On the flip
side, it is obvious that KeyReleased
events can
never be repeated.
This event is the one to use if you want to trigger an action exactly once when a key is pressed or released, like making a character jump with space, or exiting something with escape.
Sometimes, people try to react to KeyPressed
events directly to implement smooth movement. Doing so will not produce
the expected effect, because when you hold a key you only get a few
events (remember, the repeat delay). To achieve smooth movement with
events, you must use a boolean that you set on KeyPressed
and clear on KeyReleased
; you can then move
(independently of events) as long as the boolean is set.
The other (easier) solution to produce smooth movement is to use
real-time keyboard input with Keyboard
(see the dedicated tutorial).
The member associated with these events is event.key
,
it contains the code of the pressed/released key, as well as the current
state of the modifier keys (alt, control, shift, system).
if (event.type == Event.EventType.KeyPressed)
{
if (event.key.code == Keyboard.Key.Escape)
{
writeln("the escape key was pressed");
writeln("control:", event.key.control);
writeln("alt:", event.key.alt);
writeln("shift:", event.key.shift);
writeln("system:", event.key.system);
}
}
Note that some keys have a special meaning for the operating system, and will lead to unexpected behavior. An example is the F10 key on Windows, which "steals" the focus, or the F12 key which starts the debugger when using Visual Studio. This will probably be solved in a future version of SFML, which will fix it in DSFML.
The MouseWheelMoved event
The Event.EventType.MouseWheelMoved
event is
deprecated since SFML 2.3, use the
MouseWheelScrolled
event instead.
The MouseWheelScrolled event
The Event.EventType.MouseWheelScrolled
event is
triggered when a mouse wheel moves up or down, but also laterally if the
mouse supports it.
The member associated with this event is event.mouseWheelScroll
,
it contains the number of ticks the wheel has moved, what the
orientation of the wheel is and the current position of the mouse
cursor.
if (event.type == Event.EventType.MouseWheelScrolled)
{
if (event.mouseWheelScroll.wheel == Mouse.Wheel.VerticalWheel)
writeln("wheel type: vertical");
else if (event.mouseWheelScroll.wheel == Mouse.Wheel.HorizontalWheel)
writeln("wheel type: horizontal");
else
writeln("wheel type: unknown");
writeln("wheel movement: ", event.mouseWheelScroll.delta);
writeln("mouse x: ", event.mouseWheelScroll.x);
writeln("mouse y: ", event.mouseWheelScroll.y);
}
The MouseButtonPressed and MouseButtonReleased events
The Event.EventType.MouseButtonPressed
and
Event.EventType.MouseButtonReleased
events are
triggered when a mouse button is pressed/released.
DSFML supports 5 mouse buttons: left, right, middle (wheel), extra #1 and extra #2 (side buttons).
The member associated with these events is event.mouseButton
, it
contains the code of the pressed/released button, as well as the current
position of the mouse cursor.
if (event.type == Event.EventType.MouseButtonPressed)
{
if (event.mouseButton.button == Mouse.Button.Right)
{
writeln("the right button was pressed");
writeln("mouse x: ", event.mouseButton.x);
writeln("mouse y: ", event.mouseButton.y);
}
}
The MouseMoved event
The Event.EventType.MouseMoved
event is
triggered when the mouse moves within the window.
This event is triggered even if the window isn't focused. However, it is triggered only when the mouse moves within the inner area of the window, not when it moves over the title bar or borders.
The member associated with this event is event.mouseMove
,
it contains the current position of the mouse cursor relative to the
window.
if (event.type == Event.EventType.MouseMoved)
{
writeln("new mouse x: ", event.mouseMove.x);
writeln("new mouse y: ", event.mouseMove.y);
}
The MouseEntered and MouseLeft events
The Event.EventType.MouseEntered
and
Event.EventType.MouseLeft
events are triggered
when the mouse cursor enters/leaves the window.
There's no member associated with these events in the Event union.
if (event.type == Event.EventType.MouseEntered)
writeln("the mouse cursor has entered the window");
if (event.type == Event.EventType.MouseLeft)
writeln("the mouse cursor has left the window");
The JoystickButtonPressed and JoystickButtonReleased events
The Event.EventType.JoystickButtonPressed
and
Event.EventType.JoystickButtonReleased
events
are triggered when a joystick button is pressed/released.
DSFML supports up to 8 joysticks and 32 buttons.
The member associated with these events is event.joystickButton
,
it contains the identifier of the joystick and the index of the
pressed/released button.
if (event.type == Event.EventType.JoystickButtonPressed)
{
writeln("joystick button pressed!");
writeln("joystick id: ", event.joystickButton.joystickId);
writeln("button: ", event.joystickButton.button);
}
The JoystickMoved event
The Event.EventType.JoystickMoved
event is
triggered when a joystick axis moves.
Joystick axes are typically very sensitive, that's why DSFML uses a
detection threshold to avoid spamming your event loop with tons of
JoystickMoved
events. This threshold can be
changed with the Window::setJoystickThreshold
function, in case you want to receive more or less joystick move events.
DSFML supports 8 joystick axes: X, Y, Z, R, U, V, POV X and POV Y. How they map to your joystick depends on its driver.
The member associated with this event is event.joystickMove
,
it contains the identifier of the joystick, the name of the axis, and
its current position (in the range [-100, 100]).
if (event.type == Event.EventType.JoystickMoved)
{
if (event.joystickMove.axis == Joystick.X)
{
writeln("X axis moved!");
writeln("joystick id: ", event.joystickMove.joystickId);
writeln("new position: ", event.joystickMove.position);
}
}
The JoystickConnected and JoystickDisconnected events
The Event.EventType.JoystickConnected
and
Event.EventType.JoystickDisconnected
events are
triggered when a joystick is connected/disconnected.
The member associated with this event is event.joystickConnect
,
it contains the identifier of the connected/disconnected joystick.
if (event.type == Event.EventType.JoystickConnected)
writeln("joystick connected: ", event.joystickConnect.joystickId);
if (event.type == Event.EventType.JoystickDisconnected)
writeln("joystick disconnected: ", event.joystickConnect.joystickId);