Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

moritz31

Treue Seele

  • »moritz31« ist der Autor dieses Themas

Beiträge: 259

Wohnort: Hessen

Beruf: Student

  • Private Nachricht senden

1

20.08.2015, 09:54

[SFML]Intelligenter EventManager

Moin Moin,

also erstmal hoffe ich, dass das Thema hier ganz gut herein passt.

Ich habe mich seit langer Zeit mal wieder mit C++ und SFML auseinandergesetzt, und versuche jetzt ein simples Spiel umzusetzten, bei dem ich allerdings sehr auf den Stil und so Dinge achte.
Nun habe ich eine Klasse EventManager, der die SFML Events handeln soll. Die Klasse hat ne Funktion manageEvents(); die quasi den Event Teil bei SFML darstellt. Sprich pollEvent und dann die ganzen if's wenn ein spezielles Event eintritt. Früher habe ich es nun so gemacht das ich mehr oder weniger die Events aus anderen klassen komplett durchgegeben habe, das war allerdings immer ein ganz schönes Chaos, jetzt habe ich mir überlegt das ich ja theoretisch eine registerEvent Funktion schreiben könnte, die einen String und eine Funktion übergeben bekommt und das ganze in eine Map pusht, und an der jeweiligen stelle in manageEvents(); wird dann gerade die Funktion aufgerufen.

Als Beispiel mal, ich will das beim druck von F1 etwas passiert, dann rufe ich

C-/C++-Quelltext

1
eventManager.registerEvent("f1",&dieFunktionhalt)

auf und an der passenden stelle in der Eventabfrage steht dann ein

C-/C++-Quelltext

1
function_map.at("f1")


Jetzt wollte ich mal von euch hören, ob der Ansatz so okay ist oder ob es eine noch bessere Lösung gibt.
Des Weiteren habe ich momentan das Problem, das ich beim registrieren bei der Funktionsübergabe einen Error bekommen.
So wie ich das richtig verstehe liegt das daran das ich ja nicht einfach eine Funktion übergebe sondern da noch eine Klasse mit dran hängt quasi (&klasse.funktion).

Bin mal auf eure antworten gespannt :)

Gruß
Moritz

Lares

1x Contest-Sieger

  • Private Nachricht senden

2

20.08.2015, 11:33

Wenn es um Tasten- und Mauseingabe geht, solltest du eher die von SFML bereitgestellten Funktionen verwenden: http://www.sfml-dev.org/tutorials/2.3/window-inputs.php
Dadurch verringert sich die Menge an Fällen, die der EventManager behandeln muss enorm, wodurch weniger Abhängigkeiten zu bzw. von anderen Klassen bestehen (je nach Implementierung).
Außerdem wird der Code dadurch einfacher zu lesen, da du mit wenigen Zeilen genau das ausdrückst was passiert (wenn Button A gedrückt wurde, gehe nach links), anstatt den großen Umweg darüber zu gehen, welches Event vorliegt, es entsprechend abzuspeichern und irgendwo anders wieder zu entnehmen und zu verarbeiten. Und das alles gewinnst du für genau 0 Aufwand, da die SFML das bereits alles für dich implementiert hat.

Schrompf

Alter Hase

Beiträge: 1 470

Wohnort: Dresden

Beruf: Softwareentwickler

  • Private Nachricht senden

3

20.08.2015, 12:10

Und schau Dir mal boost::signals an. Sehr praktisch für ereignisgesteuerte Programmierung im Allgemeinen. Sei aber gewarnt, dass ereignisgesteuerter Code sehr schwer wartbar wird, wenn man es übertreibt. Wie bei jedem anderen Stilmittel auch.
Häuptling von Dreamworlds. Baut aktuell an nichts konkretem, weil das Vollzeitangestelltenverhältnis ihn fest im Griff hat. Baut daneben nur noch sehr selten an der Open Asset Import Library mit.

4

02.09.2015, 11:01

Die Thor-Library (basiert auf SFML) bietet unter andere ActionMaps an - das wäre vllt. was für dich ;) Das Thema "Marke Eigenbau" ist immer so eine Sache ... wenn du lernen willst, kann ich dir die entsprechende Thor-Implementierung anzusehen ans Herz legen .. zwecks Inspiratio.. Wenn du loslegen willst, kann ich nur empfehlen direkt Thor zu verwenden.

Anyway, so läuft die Sache bei Thor:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <Thor/Input.hpp>
#include <Thor/Graphics/ToString.hpp>
#include <SFML/Window.hpp>
#include <iostream>

// Enumeration for user-defined actions
enum MyAction
{
    Run,
    Jetpack,
    Shoot,
    Quit,
    Resize,
};

// Callback function for Resize, Shoot (mouse click) and Run (joystick axis) actions
void onResize(thor::ActionContext<MyAction> context);
void onShoot(thor::ActionContext<MyAction> context);
void onRun();

int main()
{
    // Create and initialize window
    sf::Window window(sf::VideoMode(400, 300), "Thor Action");
    window.setFramerateLimit(20);
    window.setKeyRepeatEnabled(false);

    // Create thor::ActionMap that maps MyAction values to thor::Action instances
    thor::ActionMap<MyAction> map;
    using thor::Action;

    // Jetpack: Press one of the shift keys and J (realtime input)
    map[Jetpack] = (Action(sf::Keyboard::LShift) || Action(sf::Keyboard::RShift)) && Action(sf::Keyboard::J);

    // Run: Displace X axis of joystick number 0 by more than 30% in either direction
    map[Run] = Action(thor::joystick(0).axis(sf::Joystick::X).above(30.f))
            || Action(thor::joystick(0).axis(sf::Joystick::X).below(-30.f));

    // Shoot: Press left mouse button or button 2 of joystick number 0 (single events)
    map[Shoot] = Action(sf::Mouse::Left, Action::PressOnce) || Action(thor::joystick(0).button(2), Action::PressOnce);

    // Quit: Release the escape key or click the [X] (single events)
    map[Quit] = Action(sf::Keyboard::Escape, Action::ReleaseOnce) || Action(sf::Event::Closed);

    // Resize: Change window size (single event)
    map[Resize] = Action(sf::Event::Resized);
    
    // Create thor::EventSystem to connect Resize and Shoot actions with callbacks
    // Use connect0() instead of connect() when callback has no parameter
    thor::ActionMap<MyAction>::CallbackSystem system;
    system.connect(Resize, &onResize);
    system.connect(Shoot, &onShoot);
    system.connect0(Run, &onRun);

    // Main loop
    for (;;)
    {
        // Generate new actions (calls window.pollEvent(...))
        map.update(window);

        // Check which actions are currently in effect, react correspondingly
        if (map.isActive(Jetpack))
            std::cout << "Jetpack!" << std::endl;
        if (map.isActive(Quit))
            return 0;

        // Forward actions to callbacks: Invokes onResize() in case of sf::Event::Resized events
        map.invokeCallbacks(system, &window);

        // Update window
        window.display();
    }   
}

void onResize(thor::ActionContext<MyAction> context)
{
    // The sf::Event member variable called type has always the value sf::Event::Resized, as specified in the thor::Action
    // constructor. Since the Resize action has been triggered by an sf::Event (and not by a sf::Keyboard, sf::Mouse or
    // sf::Joystick), we can also be sure that context.event is no null pointer.
    sf::Event event = *context.event;
    std::cout << "Resized!   New size = (" << event.size.width << ", " << event.size.height << ")" << std::endl;
}

void onShoot(thor::ActionContext<MyAction> context)
{
    // context.Window is a pointer to the sf::Window passed to the thor::ActionMap constructor. It can
    // be used for mouse input relative to a window, as follows:
    sf::Vector2i mousePosition = sf::Mouse::getPosition(*context.window);
    std::cout << "Shoot: " << thor::toString(mousePosition) << std::endl;
}

void onRun()
{
    // Since no event is associated with a joystick axis action, we access the global sf::Joystick
    float axisPosition = sf::Joystick::getAxisPosition(0, sf::Joystick::X);
    std::cout << "Run at " << axisPosition << "% speed." << std::endl;
}

Quelle: Thor Examples @ Github

Werbeanzeige