Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: SFML.Net Event Handling  (Read 19487 times)

0 Members and 1 Guest are viewing this topic.

The New Guy

  • Newbie
  • *
  • Posts: 15
    • View Profile
    • Email
SFML.Net Event Handling
« on: December 08, 2013, 10:38:18 am »
Hey guys, I was wondering if anyone could help me out with Event Handling/Processing with SFML.Net, Maybe direct me to a guide or even just help me out with a post! I can't seem to wrap my head around how to do event handling in SFML.Net, It might be because a lack of knowledge in C#, but it makes perfect sense for me in C++.

void Game::processEvents()
{
    sf::Event event;
    while (mWindow.pollEvent(event))
    {
        if (event.type == sf::Event::Closed)
            mWindow.close();
    }
}

For example, the above example makes perfect sense to me,  You create an event you poll that event and when a event is done by the user, you check the type of the event and if it matches then you perform an action. I can't seem to find out through the resources and SFML.Net API Documentation how to recreate this or go about event handling.

 static void OnClose(object sender, EventArgs e)
        {
            // Close the window when OnClose event is received
            RenderWindow window = (RenderWindow)sender;
            window.Close();
        }

        static void Main()
        {

            // Create the main window
            RenderWindow window = new RenderWindow(new VideoMode(800, 600), "SFML window");
            window.Closed += new EventHandler(OnClose);

I have seen this code multiple times, and I assume this is trying to lead me in the right direction, but I can't seem to figure out  how to perform this action for lets say key strokes or anything else beyond this example. Any help would be great!

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: SFML.Net Event Handling
« Reply #1 on: December 08, 2013, 02:21:22 pm »
This is the event and delegate system of CLR/.NET. Just a little of googling these keywords will show you lots of examples.

window.Closed += new EventHandler(OnClose);

This assigns a method that will be fired when the window.Closed event happens. The ".Closed" is the event. The "EventHandler" is the delegate (method signature) that the Closed event confirms to. "OnClose" is the name of your method that will be fired (that also must match the delegate signature).

You could also write this as

window.Closed += OnClose;

Or using a lambda expression

window.Closed += (sender, e) => { ((Window)sender).Close(); };


Now to handle any of time of event just assign the appropriate event from the window class to any handler. (And of course call window.DispatchEvents() every frame.)
« Last Edit: December 08, 2013, 02:26:33 pm by zsbzsb »
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Re: SFML.Net Event Handling
« Reply #2 on: December 08, 2013, 03:38:30 pm »
I thought the bindings were supposed to be as similar as possible to the C++ SFML? Why is the .net version using such a contrived callback system then although the C++ version got such a nice, clean way of handling events?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: SFML.Net Event Handling
« Reply #3 on: December 08, 2013, 03:49:21 pm »
I thought the bindings were supposed to be as similar as possible to the C++ SFML?
No, the bindings are supposed to look as natural as possible in the target language. There's no point in applying C++ idioms to C# when things are handled differently.

Why is the .net version using such a contrived callback system then although the C++ version got such a nice, clean way of handling events?
"Contrived"? I think you should read up a bit on callbacks in general and event handling in C#. Many OOP design patterns (most notably Observer and Command) are built on top of callbacks, because they provide a very elegant way of decoupling software components.

And the C++ way of polling is not nice, it's very unflexible. I have even built an abstraction around it in Thor -- and guess what -- it uses callbacks ;)
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Re: SFML.Net Event Handling
« Reply #4 on: December 08, 2013, 07:48:11 pm »
When calling a library function the programmer can decide how to structure his code. In C++ SFML its no problem to put the event loop where its convenient and have access to some member variables that are needed to further process the data in any imaginable way the programmer likes, for example, explicitly calling one or many of those functions that look like callbacks or calling some methods to change some objects.

The problem of callbacks is that they are very inflexible. With frameworks and their callbacks its pretty much fixed already how the user code has to be written. One has to fill in all those many callbacks exactly as they are requested and then find a way to work around them because its too much decoupled (one has to be happy if even a user data pointer is provided that then needs to be casted back with an ugly typecast to have a way of doing more than a trivial fixed reaction to the callback). The only way in GLFW to get the data out of the mandatory callbacks is to add some global variables (which is something I like to avoid) for communicating with the rest of the program and thats one important reason why I was choosing to use SFML instead.
C++11 lambdas would make it possible to capture some data with the function and that helps to make callbacks a little more tolerable, but then its still more complicated than it needs to. In Ruby its nicely implemented with blocks getting access to outside local variables. It could be there is a similar mechanism in .net, but I think keeping the library similar to C++ is better than having it completely different. This question would not have to be asked if callbacks were really more intuitive.

Btw, I looked at your link and instead of explicitly writing a switch (that often gets compiled into a jump table automatically) you just hide it inside a map (that contains a call table) where a method emulates the switch. It may look nicer to you, but its basically the same (besides the programmer having more work to search the whole application for additions to the map to be able to follow the program flow). You being able to easily make this addition proves that its flexible how the polling is done, not that its inflexible.
« Last Edit: December 08, 2013, 07:53:46 pm by wintertime »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: SFML.Net Event Handling
« Reply #5 on: December 08, 2013, 08:48:58 pm »
C++11 lambdas would make it possible to capture some data with the function and that helps to make callbacks a little more tolerable, but then its still more complicated than it needs to.
It's only more complicated in small examples. As soon as your project grows bigger, you'll be glad if you don't have a massive switch statement with hardcoded case constants and all the dependencies in one place.

but I think keeping the library similar to C++ is better than having it completely different. This question would not have to be asked if callbacks were really more intuitive.
It would not have been asked if The New Guy had been more familiar with C# event handling. This is the standard way of using events/delegates in .NET, you'll find a lot of resources on MSDN. And again, there is no point in forcefully adopting a C++ idiom that confuses C# users, just to make the transition easier for C++ programmers. A C# API should be designed for C# developers, therefore it is standing to reason to use their native paradigms and idioms.

Btw, I looked at your link and instead of explicitly writing a switch (that often gets compiled into a jump table automatically) you just hide it inside a map (that contains a call table) where a method emulates the switch. It may look nicer to you, but its basically the same
Yes of course, did you expect Thor to magically call the functions? The implementation is completely irrelevant, important is the API that allows users to bind arbitrary callables to actions. This is not directly possible with SFML, people would have to handcraft their own callback system.

besides the programmer having more work to search the whole application for additions to the map to be able to follow the program flow
You seem to not understand the advantages such a callback mechanism brings. I suggest you have a look at the Command or Observer pattern to get the basic idea. The poll approach may be simple, but it's not scalable in bigger software architectures. Especially not if one wants to make things more dynamic (e.g. key binding, connecting/disconnecting listeners at runtime, ...).
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

The New Guy

  • Newbie
  • *
  • Posts: 15
    • View Profile
    • Email
Re: SFML.Net Event Handling
« Reply #6 on: December 08, 2013, 11:48:22 pm »
Hey guys, I appreciate all the info. Although a lot of what you guys are talking about is way over my head.

namespace TESTSFML2
{
    class Game
    {
        private RenderWindow mWindow;
        public CircleShape mPlayer =  new CircleShape();

        public Game()
        {
            mWindow = new RenderWindow(new VideoMode(640, 480), "SFML Application");
            mWindow.KeyPressed += new EventHandler<KeyEventArgs>(myKeyHandler);
            mPlayer.Radius = 40.0f;
            mPlayer.Position = new Vector2f(400.0f, 100.0f);
            mPlayer.FillColor = Color.Cyan;

        }


        public void Run()
        {
            while (mWindow.IsOpen())
            {
                processEvents();
                update();
                render();
            }
        }

         

        private void myKeyHandler(object sender, KeyEventArgs e)
        {
       
            if (e.Code == Keyboard.Key.Right)
            {
                this.mPlayer.FillColor = Color.Red;
            }

        }

        private void processEvents()
        {
       
            mWindow.DispatchEvents();
           
        }
        private void update()
        {
        }
        private void render()
        {
            mWindow.Clear();
            mWindow.Draw(mPlayer);
            mWindow.Display();
        }

    }
}
 

This is where I am at, So lets say for example and I am trying to test for the user who is pressing the right key, I kind of hit a stopping point on where to go from here, again I realize this is most likely a lack of my knowledge of my understanding of event handling in .NET, any help would be appreciated on how to set up something like just testing for the event of the right key.

Thanks!

Edit 1: I have edited my code, and tried making a little bit of progress.

Edit 2: Well, with the help of a great friend I was able to get something going, I was still running into a problem and noticed I was changing the color to cyan so I wasn't seeing the effect, so I am just going to go work at Taco Bell.  Regardless, if you guys could look over my solution here and see if I am doing everything correctly that would be great! Thanks for the help guys.
« Last Edit: December 09, 2013, 12:10:49 am by The New Guy »

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Re: SFML.Net Event Handling
« Reply #7 on: December 09, 2013, 04:10:24 pm »
You seem to not understand the advantages such a callback mechanism brings. I suggest you have a look at the Command or Observer pattern to get the basic idea.
Sorry, but repeating the authority argument is not gonna win me over. There is no silver bullet and other people may have other opinions.
These links show a bit of the philosophy I try to follow:
- http://mollyrocket.com/873
- http://perl.plover.com/yak/design/

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: SFML.Net Event Handling
« Reply #8 on: December 09, 2013, 08:10:56 pm »
There is no silver bullet and other people may have other opinions.
That's fine, but your post makes the impression that you have never had a deeper look at either C# events/delegates, the Command/Observer design patterns or C++ functionals and lambda expressions. Your arguments were that callbacks are unintuitive (which is 1. subjective and 2. the apparent initial complexity is justified by their power), that one would have to search the whole application for map additions (which is wrong, you can as well register callbacks in one place) and that one should work against native C# idioms and adopt C++ (despite being unintuitive).

I'm not a big fan of applying design patterns 1:1 either, partially because they result in masses of boilerplate code and because they sometimes overengineer simple problems. But that's exactly a problem that C++ solved extremely elegantly with std::function. This class template allows arbitrary functions to be stored in objects, which opens a whole new programming paradigm. And it is super easy to use, especially in combination with lambda expressions.

Callbacks are not an academic construct some OOP purists came up with (actually they originate from a completely different world, namely functional programming languages), they do provide practical benefits. If you're not convinced by the theoretical definitions on Wikipedia, please have a look at some other parts of Thor where I use callbacks, e.g. Particles (emitters and affectors are functors) or Animation. If you can tell me how to implement the same functionality as powerful as now, but simpler, I would be really interested -- I have not found a way. In fact, the current design is a result of refactoring more traditional approaches, all of which were not flexible enough and too complicated to use (see Thor 1.1 for comparison).
« Last Edit: December 09, 2013, 08:35:14 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Re: SFML.Net Event Handling
« Reply #9 on: December 11, 2013, 07:00:44 pm »
We're reaching into offtopic here (sorry), but I did look at your links.

Such animation classes I would not use personally, because imho its the responsibility of the game code to glue library code together (use provided classes, call provided helper functions). As this is making game code into framework code and frameworks need to be in a very generalized form to be used by many applications, its automatically getting overengineered for simple things like changing color of a sprite, but it still seems too specialized for general use (only usable for some changes on sprites). Often a gameobject would need more data than just the sprite+predefined animation, so instead of having that extra layer the gameobject can just manipulate the sprite directly.
How I would code a game is, I provide some generalized code to calculate gameticks in the game loop (not have N objects repeatedly calculate times). Then on each tick iterate through all needed gameobjects in a vector or shortened vector with only pointers to relevant objects (or different data structure when its more appropriate for the current game), then call update on each of those objects, where inside it it does whats needed, by explicitely calling appropriate helpers depending on current data. No need to precreate maps for those function calls inside all objects then, as its easily done in code.
For a more advanced game I would have an ECS and just have some component types for some types of animation, then for needed entities such component would have been created (at initialization or when needed) and then it calls all systems in a predefined order each logic tick and lets each system iterate all components of its corresponding type each tick (or maybe as an optimization every x ticks for some) to update them.

I did not look that much at the particle systems, but some of those things, where you added extra classes for callbacks, could maybe get folded into the particlesystem, which could get some data at initialization like particle-weight, lifetime as they are probably needed most of the time anyway. Maybe it could also get simplified by not having variable amounts of emitters per system and just creating a new system when needed by the user.
« Last Edit: December 11, 2013, 07:27:42 pm by wintertime »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: SFML.Net Event Handling
« Reply #10 on: December 11, 2013, 08:19:01 pm »
As this is making game code into framework code and frameworks need to be in a very generalized form to be used by many applications, its automatically getting overengineered for simple things like changing color of a sprite, but it still seems too specialized for general use (only usable for some changes on sprites).
I see what you mean, and it's indeed not always easy to have a good trade-off between genericity and simplicity. Thor.Animation may be a bit unconventional at first (especially if one is used to other animation systems), and it won't fit in every design, but I think overall it does a good job at serving a diversity of use cases with a simple API.

Concerning the animations themselves, they are just functors defining some modification of anything for a given progress in [0,1] -- you're not limited to SFML or Thor objects being animated. Some of the most often used animations (like fading in/out) have been predefined, and they have been defined in a generic way to be also applicable to particles, for example. Apart from those animations, I developed thor::Animator as a "player" for animations. Animations have some constraints and requirements (only one can be active at a time, animations are referenced by an ID, animations automatically stop or loop when ending) that require considerable amount of code, mostly including boring boilerplate like handling time/frames correctly and accounting for special cases. These are the parts I tried to factor out in Thor.

When you browse the forum and the wiki, you'll see a lot of AnimatedSprite classes that are similar to sf::Sprite. That's a design I didn't want, because it is way too limited: The user is forced to use this class (instead of his own objects), he can only use predefined animations such as changing frames, and higher-level functionality (like managing different animations, as provided by thor::Animator) must still be handcrafted.

How I would code a game is, I provide some generalized code to calculate gameticks in the game loop (not have N objects repeatedly calculate times). Then on each tick iterate through all needed gameobjects in a vector or shortened vector with only pointers to relevant objects (or different data structure when its more appropriate for the current game), then call update on each of those objects, where inside it it does whats needed, by explicitely calling appropriate helpers depending on current data.
You can't handle everything inside the entities, for many tasks there is still need for a centralized object that has an overview of everything. The collision thread here is a good example.

When the game grows more complex, there will be several data structures that maintain some kind of state, e.g. graphs for pathfinding, list of targets, a queue of orders, a selection of units, whatever. All these data structures require unit registering and unregistering, for example a unit that dies must notice all the lists where it's referenced. This is a typical use case for the Observer pattern. You have to implement this functionality somehow, and if you want to do it generically (simply register a function that is called upon destruction), you will always end up with something like callbacks or a list of polymorphic listener objects. Hardcoding everything in the entity's destructor does not scale: It creates a dependency bottleneck (suddenly the entity must know about all kinds of lists) and you need to create a different entity class everytime the unregister actions differ.

I did not look that much at the particle systems, but some of those things, where you added extra classes for callbacks, could maybe get folded into the particlesystem, which could get some data at initialization like particle-weight, lifetime as they are probably needed most of the time anyway. Maybe it could also get simplified by not having variable amounts of emitters per system and just creating a new system when needed by the user.
That would be a way, but I prefer to keep the responsibilities of storing and creating particles separate, thus the emitter concept. A list of emitters provides the advantage that you can easily attach them to different positions, for example 4 engines of an airplane -- especially if one writes an emitter that integrates to a scene graph, which is very easy to achieve with the current API.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

wintertime

  • Sr. Member
  • ****
  • Posts: 255
    • View Profile
Re: SFML.Net Event Handling
« Reply #11 on: December 11, 2013, 09:57:17 pm »
How I would code a game is, I provide some generalized code to calculate gameticks in the game loop (not have N objects repeatedly calculate times). Then on each tick iterate through all needed gameobjects in a vector or shortened vector with only pointers to relevant objects (or different data structure when its more appropriate for the current game), then call update on each of those objects, where inside it it does whats needed, by explicitely calling appropriate helpers depending on current data.
You can't handle everything inside the entities, for many tasks there is still need for a centralized object that has an overview of everything. The collision thread here is a good example.

When the game grows more complex, there will be several data structures that maintain some kind of state, e.g. graphs for pathfinding, list of targets, a queue of orders, a selection of units, whatever. All these data structures require unit registering and unregistering, for example a unit that dies must notice all the lists where it's referenced. This is a typical use case for the Observer pattern. You have to implement this functionality somehow, and if you want to do it generically (simply register a function that is called upon destruction), you will always end up with something like callbacks or a list of polymorphic listener objects. Hardcoding everything in the entity's destructor does not scale: It creates a dependency bottleneck (suddenly the entity must know about all kinds of lists) and you need to create a different entity class everytime the unregister actions differ.
The quoted paragraph was about a simple game only. Inside the paragraph below this I wrote I would use an Entity-Component-System for a more advanced game. The point of an ECS is to make interactions explicit and avoid the entangled calls from typical OOP: http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1/
Entities would just be IDs and not classes. There will also not be any registering, because either a component exists and gets processed or it gets deleted immediately by telling the Component-Table/Cache/Storage. If an Entity needs to be removed the System which kills it calls the Entity-Table/Manager which would delete the ID from its list and let all the Component-Storages know to delete any associated component (if it does not exist the request is ignored). Deletion of whole entities will not happen that often and a binary search or lookup in a few hash tables is fast enough and spares one from constantly updating extraneous callback data.
The common case is each system just iterating one, maybe 2 component tables and explicitly doing the same thing on all of them. There is no need to observe single components, because some later called system can and will explicitly read all components of a formerly written-to-type when needed to do its work. Most logic will be in the systems and not the components and each different system can have access to some specialized game modules with their own specialized data structures or just store some of that data in its associated component type. Coincidentally, that makes for a nice, simple Data-Oriented Design (http://gamesfromwithin.com/data-oriented-design).

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: SFML.Net Event Handling
« Reply #12 on: December 12, 2013, 02:36:25 pm »
If an Entity needs to be removed the System which kills it calls the Entity-Table/Manager which would delete the ID from its list and let all the Component-Storages know to delete any associated component
The notification of the component-storages has to be implemented somehow. Whether you use boost::signal, a container of abstract listener objects or simply a list of components for each of which a member function is called, is not too relevant -- what I want to say is that you'll end up with a concept similar to the Observer pattern, even if the implementation differs.

Deletion of whole entities will not happen that often and a binary search or lookup in a few hash tables is fast enough and spares one from constantly updating extraneous callback data.
But this approach forces components to refer to other components always via centralized ID table. It's not possible to store direct pointers, since they may become invalid if they're not unregistered upon destruction of the pointee. Furthermore, the component that queries the centralized table has to perform manual case differentiation:
for (all target IDs)
    if (ID still exists)
        get reference and do something with target
// as opposed to
for (all target pointers)
    do something with target

There are of course also advantages of a centralized ID table, besides the ones you mentioned e.g. debugging can be easier. Performance can be an important aspect for complex games: One has to compare the overhead of access (in the centralized table) against the overhead of notification (for observer-like systems). Typically, removal notifications occur less frequently than access patterns, but when one begins to transmit all kinds of events via notifications, things will look differently.

By the way, thanks for the links, they're quite interesting. I think we should not fall in the typical "OOP vs. components" discussion, in my opinion the view that these concepts are contradictory is a misunderstanding. Often, OOP is associated with overused inheritance and unflexible class hierarchies, and people forget that a entity component system is built on top of most OOP features, too (purists could even consider ECS as a sort of design pattern, but probably there's already another name for it). I'm aware of the benefits of ECS and I'm also planning to employ them more in future projects.
« Last Edit: December 12, 2013, 02:38:03 pm by Nexus »
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

 

anything