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

1

01.07.2014, 09:26

C# Event's und Delegaten. Screen Manager Problem.

Guten Morgen,

ich komme leider nicht weiter wenn es um Delegaten und Events geht auch wenn ich schon etliche Tutorials angeguckt habe.

Ich habe es eben geschafft mit einem Event meine Exit Methode auszuführen aber irgendwie fühlt sich mein Aufbau falsch an.

In dieser Klasse habe ich das Event deklariert und die Methode von OnExit von ScreenManager abonniert.

Dann habe ich in der Update Methode das Event aufgerufen und es hat auch geklappt.

Aber wieso brauche ich Event's? ich könnte auch einfach screenManager.OnExit() aufrufen bzw. würde schon ein Delegate reichen.

Was übersehe ich?


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
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.GamerServices;

namespace TeamPlatformer
{
    public delegate void ScreenChangeEventHandler();

    public class TeamPlatformer : Game
    {
        public event ScreenChangeEventHandler ExitHandler;

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        ScreenManager screenManager;

        public TeamPlatformer()
            : base()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            screenManager = new ScreenManager(this);
            ExitHandler += screenManager.onExit;

            base.Initialize();
        }

        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
        }

        protected override void UnloadContent()
        {

        }

        protected override void Update(GameTime gameTime)
        {
            if (Keyboard.GetState().IsKeyDown(Keys.Escape))
                ExitHandler();

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);

            base.Draw(gameTime);
        }
    }
}


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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace TeamPlatformer
{

    class ScreenManager : DrawableGameComponent
    {
        public ScreenManager(Game game): base(game)
        {
        }

        protected override void LoadContent()
        {
            base.LoadContent();
        }

        protected override void UnloadContent()
        {
            base.UnloadContent();
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);
        }

        public void onExit()
        {
            Game.Exit();
        }

        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
        }
    }
}

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

2

01.07.2014, 09:38

In deinem Fall scheint das Event-Handling unnötig zu sein (und auch mit Delegates muss man da gar nichts anfangen). Du prüfst im Spiel, ob die Taste zum Beenden gedrückt wurde, löst ggf. das Event aus und der ScreenManager beendet dann das Spiel, statt das das Spiel es selbst erledigt.
Außerdem sollten (wenn möglich) Objekte sich selbst für Events registrieren, in deinem Fall macht es aber die erzeugende Stelle.

In dem Fall wäre es besser, wenn das Spiel im Fall der Fälle (das Spiel wird beendet) die entsprechende Methode des Screenmanagers aufruft und sich dann selbst beendet. Der Screenmanager könnte dan noch Dinge machen, bevor das Spiel tatsächlich beendet wird.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

3

01.07.2014, 11:59

Letztendlich sind Events nichts anderes als Funktionsaufrufe durch denjenigen, der das Event bereitstellt. Im Prinzip kannst du dir merken, dass Events und Listener optional sind und nicht zwingend notwendig sind, sich anzumelden. Außerdem kann sich auf einem Event immer mehrere Anmelden.
Wenn du nur einen Listener hast, der auf ein Event reagieren soll, dann ist ein direkter Funktionsaufruf auf ein referenziertes Objekt besser an statt Events zu verwenden. Beim Screenwechsel hast du ja genau genommen immer nur ein aktives Objekt, nämlich den aktiven Screen: Der aktive Screen wird verlassen und ein neuer wird betreten.
Ich verwende Events gegen 0 in meinem Spielecode, weil es einfach zu wenig Anwendungsfälle gibt.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

01.07.2014, 13:02

Ich finde es gibt sogar sehr viele Anwendungsfälle für Events bei Spielen:
- reagiere auf UI-Controls
- reagiere auf Keyboard-Input
- reagiere auf Physik-Events (Kollisionen z.B.)
- reagiere auf Timer
- ...
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

5

01.07.2014, 13:45

Was ich auch schon hatte war, dass die KI und das Pathfinding Events auslösen, wenn:
- Monster/Spieler in Sichtweite kommt
- Monster/Spieler einen Wegpunkt erreichen
- Ein Weg spontan blockiert wird
- Monster/Spieler stirbt
- Monster/Spieler Schaden nimmt
- Monster/Spieler spawnt
- Monster/Spieler gewisse Skills oder Items einsetzt
- ...

Das ließ sich dann prima mit dem Scripting für Quests zusammen nutzen, indem man sehr unterschiedliche Aktionen für KI-gesteuerte Gegner erstellen konnte, einfach nur basierend auf den Aktionen von Spielern oder anderen (oder sogar denselben) NPCs. Für solche Sachen ist Polling eine totale Katastrophe und Events absolut perfekt.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

6

01.07.2014, 14:14

Ich finde es gibt sogar sehr viele Anwendungsfälle für Events bei Spielen:
- reagiere auf UI-Controls
- reagiere auf Keyboard-Input
- reagiere auf Physik-Events (Kollisionen z.B.)
- reagiere auf Timer


Input würde ich bis heute lieber Zustandsabfragen lösen, glaube da bin ich etwas Rückständig :P. Für Timer habe ich auch immer nur eine Action als Parameter im Konstruktor verwendet, weil sich meistens eh nur eine Instanz dafür interessiert hat. Physik mache ich kaum, daher hab ich keine Erfahrung. Selbst auf UI-Control-Events wie Click reagiert doch meist eh nur ein Listener.
Oder Sagen wir mal so: Bei mir ist bisher der nutzen von Events nicht wirklich wichtig gewesen, Action/Func reicht.

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

7

01.07.2014, 14:56

An der Stelle sollte man zwischen dem allgemeinen Mechanismus der Events und der konkreten Umsetzungsmöglichkeit in C# unterscheiden.
Du verwendest in dem Fall Events, die aber auf einen einzigen Callback beschränkt sind. Es sind aber immernoch Events.

Und nochmal allgemein zusammengefasst:
Events werden zu bestimmten Zeitpunkten ausgelöst und haben das Ausführen einer beliebigen Anzahl von Callbacks zur Folge. Wie bereits geschrieben hat das genau den Hintergrund, dass dadurch an anderen Stellen das Polling (ständige Abfragen auf Zustandsänderungen) eingespart wird.

Bzgl. Input hat sich in einem anderen Thread bereits ergeben, dass Man beim Input abhängig von der jeweiligen Situation arbeiten sollte. Hat man etwas, was diskrete Zustände aufweist und somit auch eine abzählbare Menge möglicher Events (Tasten und Buttons), sind Events häufig besser geeignet, hat man aber einen sich potenziell permanent verändernden Input (Analog-Stick), wäre ein Polling besser geeignet. Man muss auch bedenken, dass man sehr wahrscheinlich eine Abstraktionsebene bei der Input-Verarbeitung hat, welche auch aus 2 Tasten (A und D oder W und S) ein anderes Ergebnis errechnen kann (2 Achsen, ggf. mit Interpolation).
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

01.07.2014, 15:16

Selbst auf UI-Control-Events wie Click reagiert doch meist eh nur ein Listener.
Ändert nichts daran, dass es Events sind. In den meisten Anwendungsfällen gibt es tatsächlich nur einen einzigen Interessenten an einem Event.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

9

01.07.2014, 16:26

Es erzeugt auch stärke Bindung zwischen Datentypen, weil der Eventwerfer den Empfänger ja kennen müsste. Das führt oft auch zu zyklischen Abhängigkeiten, die ganz furchtbar sind.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

10

01.07.2014, 16:32

Und wenn man statt dem Event ein Methodenaufruf macht geht einem die Steuerbarkeit, Konsistenz und die bessere Übersichtlichkeit flöten, die man mit Events hat.

Würde ich so allgemein nicht sagen.
Speichert man sich die Callbacks oder den Callback, ohne zu wissen, worauf er verweist: kein Problem
Speichert man sich ein Objekt einer definierten Schnittstelle, wovon eine Methode aufgerufen wird: auch kein Problem (in Java ist das bspw. erforderlich)

Auch sollte auf die Beziehungen geachtet werden. Hat man eine Aggregation oder gar Komposition, wovon der "Container" die Events zur Verfügung stellt (ist im Grunde im Code im ersten Beitrag enthalten), dann muss der Typ zumindest über eine Schnittstelle bekannt sein und es wäre denkbar, entsprechende Methoden direkt aufzurufen.
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Werbeanzeige