Zum Inhalt springen

C# kleines Spiel, bitte um Hilfe


Tician

Empfohlene Beiträge

brauche ich wirklich 'virtual', 'abstract', 'interface' und weißnichtwasnoch für sachen? Wie gesagt ich wollte mich Unterrichtsnah halten und wenn ich das dann nicht erklären kann wirds doof :/

Mein größtes Problem ist das ich gerne ein "Player.Attack" hätte, aber mir kommt die behämmerten Form1-Dinger in die Quere.

Vielleicht erkennt man das an meinem Code. Wenn ich sage das der Player schaden bekommt, dann kann ich in der Player-Klasse natürlich eine Methode "TakeDamage" machen, vielleicht auch einen Rückgabewert geben. Aber dann muss sich das Label verändern (string), dann muss sich der Balken verändern (int) und natürlich im Spieler-Objekt slebst die HP-variable verändern, außerdem muss noch eine textAusgabe erfolgen. Ich kann das also nicht so einfach aufrufen. Wenn jemand dazu eine Idee hat wäre ich schon um einiges glücklicher.

vor 7 Minuten schrieb Whiz-zarD:

Ansonsten ist da noch sehr viel, was man anders machen sollte aber darüber zu reden bringt wohl nichts.

Warum schreibst du dann überhaupt? Solche Kommentare sind genau das was ich nicht brauche und die mich ständig in die Verzweiflung treiben. Manchmal versteh ich überhaupt nicht was du sagst, aber diese 2 Dinge oben habe ich verstanden. Ich würde die erstere gerne durchziehen, es sieht sauber aus und es ist auch nicht wirklich neu. Ich setze mich morgen mal an den Code und hoffe bis dahin eine Lösung für meine Problematik mit den Form-Elemente gefunden zu haben.

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 16 Stunden schrieb Tician:

brauche ich wirklich 'virtual', 'abstract', 'interface' und weißnichtwasnoch für sachen? Wie gesagt ich wollte mich Unterrichtsnah halten und wenn ich das dann nicht erklären kann wirds doof :/

Wenn du es vernünftig machen willst, dann ja, denn das sind die Grundkonzepte der Objektorientierung.
Wenn du fehlerhaften, unwartbaren, unübersichtlichen, komplizierten und verdoppelten Code produzieren willst, dann nein. 

vor 16 Stunden schrieb Tician:

Warum schreibst du dann überhaupt? Solche Kommentare sind genau das was ich nicht brauche und die mich ständig in die Verzweiflung treiben. Manchmal versteh ich überhaupt nicht was du sagst, aber diese 2 Dinge oben habe ich verstanden. Ich würde die erstere gerne durchziehen, es sieht sauber aus und es ist auch nicht wirklich neu. Ich setze mich morgen mal an den Code und hoffe bis dahin eine Lösung für meine Problematik mit den Form-Elemente gefunden zu haben.

Weil du dich strikt weigerst, etwas neues zu lernen:

Am 26.6.2017 um 11:33 schrieb Tician:

@arlegermi Danke für deine vielen Verbesserungsvorschläge! Ich würde das Programm aber gerne erstmal zum laufen bringen und die Verbesserungen hinterher umsetzen. Ich wollte keine Unterrichts-fremden Dinge einsetzen (IEnumerate) weil ich sie nicht erklären kann. Was ich jetzt alles gemacht habe verstehe ich noch und kann es auch nachvollziehen.

Man könnte dir von Patterns, etc. erzählen aber das ist einfach vergeudete Mühe, weil du die sowieso nicht einsetzen willst.

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 2 Stunden schrieb Whiz-zarD:

Man könnte dir von Patterns, etc. erzählen aber das ist einfach vergeudete Mühe, weil du die sowieso nicht einsetzen willst.

Ich will etwas einsetzen das ich verstehe. Nehmen wir mal den Schulunterricht. Wir lernen etwas direkt anhand der Praxis und der Lehrer ist geschult und kennt unseren momentanen Wissensstand und kann gut erklären. ier habe ich das nicht. Du hattest mir mal versucht zu erklären was ein interface ist, aber ich habe nicht ein einziges Wort verstanden.

Versteh mich nicht falsch, ich möchte nicht sagen das es an dir liegt, im Gegenteil, ich kann nachvollziehen, dass du es als "vergeudete Mühe" betrachtest. Ich bin vielleicht schwierig, aber vorallem bin ich ein visuell veranlagter Mensch, du kannst mir so viel erzählen wie du willst, die Wahrscheinlichkeit das ich es verstehe ist gering. Ich kann mir keine Namen, Fachbegriffe, etc merken (nach 2 Jahren kenne ich etwa 7 Namen meiner  27 Klassenkameraden!), erst recht nicht wenn ich nicht jeden Tag damit zu tun habe.

Microsofts Beispiele sind furchtbar und oft fehlt mir das Verständnis um das was ich sehe auf das was ich brauche zu übertragen. Ich möchte mich hiermit bei dir für die vergeudete Zeit entschuldigen, es tut mir leid.

Außerdem ist jeder freizeitlich hier, ich erwarte nicht das sich jemand die Mühe macht eine Bilderbuch-ANleitung zu schreiben, aber vielleicht zumindest etwas Verständnis entgegen zu bringen das es ohne wohl bei mir nicht geht.

Bearbeitet von Tician
Link zu diesem Kommentar
Auf anderen Seiten teilen

Quote

Vielleicht erkennt man das an meinem Code. Wenn ich sage das der Player schaden bekommt, dann kann ich in der Player-Klasse natürlich eine Methode "TakeDamage" machen, vielleicht auch einen Rückgabewert geben. Aber dann muss sich das Label verändern (string), dann muss sich der Balken verändern (int) und natürlich im Spieler-Objekt slebst die HP-variable verändern, außerdem muss noch eine textAusgabe erfolgen. Ich kann das also nicht so einfach aufrufen. Wenn jemand dazu eine Idee hat wäre ich schon um einiges glücklicher.

Diesen fall würde ich versuchen über ein eigenes Event zu lösen, so wie du dich an ein Click_Event von einem Button hängen kannst, kannst du auch eigene Events definieren und dich da dran hängen. Eigene Events zu implementieren sieht auf den ersten Blick evtl etwas kompliziert aus, ist aber auch im Endeffekt nichts anderes, als eine Methode, die aufgerufen wird.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 18 Minuten schrieb Kleinrechner:

Diesen fall würde ich versuchen über ein eigenes Event zu lösen, so wie du dich an ein Click_Event von einem Button hängen kannst, kannst du auch eigene Events definieren und dich da dran hängen. Eigene Events zu implementieren sieht auf den ersten Blick evtl etwas kompliziert aus, ist aber auch im Endeffekt nichts anderes, als eine Methode, die aufgerufen wird.

INotifyPropertyChanged

Ein anderes Stichwort wäre "Data Binding"

Link zu diesem Kommentar
Auf anderen Seiten teilen

Data Binding wurde mir auch schon als Stichwort genannt, aber nur in Verbindung mit WPF - ich habe ja nur eine Form-Anwendung. Oder habe ich das falsch verstanden und ich kann es irgendwie auch so benutzen?

Das Beispiel von Microsoft sieht aus wie eine ganz normale Methode und wird ja auch aufgerufen, ich frage mich was der Unterschied ist ob ich nun eine herkömmliche Methode in der Setter aufrufe oder ein Event benutze.

Wenn ich das richtig sehe ist das Event aber auch nicht Klassenübergreifen oder sowas. Ich kann das Puzzle nicht zusammensetzen, weil damit das Problem nicht gelöst wird. Ich kann das Event nicht in die Setter-Methode der Player.curHP Variable setzen weil ich von da aus trotzdem nicht auf die Elemente in Form zugreifen kann (sollte), aber das wäre das logischste, weil das die "Haupt-Variable" ist, die die Form1-Elemente grafisch wiederspiegeln sollen.

Das einzige was mir einfallen würde wäre in der Form1 ein PropertyChanged-Event auf eines der Elemente zu legen, würde also Pseudomäßig so aussehen:

Form1
{
	Player _player;
	public event PropertyChangedEventHandler HpChanged;
	labelCurHP.Text {set {HpChanged(value)}};
  
	labelCurHP.Text = _player.TakeDamage(value);
	
	HpChanged(...)
    {
	_player.CurHP = value;
	hpBar.Value = value;
    }
}

Ich glaub hier wird man auch sehen das ich gerade den Unterschied zwischen Event und normaler Methode nicht sehe.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Am 30.6.2017 um 22:03 schrieb Tician:

brauche ich wirklich 'virtual', 'abstract', 'interface' und weißnichtwasnoch für sachen? Wie gesagt ich wollte mich Unterrichtsnah halten und wenn ich das dann nicht erklären kann wirds doof :/

"Brauchen" tust du die Sachen nicht, man kann da immer auch drum herum programmieren. Wie @Whiz-zarD schreibt sind das allerdings wirklich einige der Basis-Bausteine von objektorientierter Programmierung.

Zu deinem Problem mit der Verknüpfung von Oberfläche und Player: Da gibt es ein paar unterschiedliche Möglichkeiten

  • Unsauber: Du könntest das Formular im Konstruktor an die Player-Klasse übergeben, so dass diese direkt Änderungen daran vornehmen kann (Texte ändern, Buttons aktivieren, ...). Das ist zwar die schnelle Lösung, wird auf Dauer aber zu sehr unübersichtlichem Code und sehr enger Verknüpfung zwischen Oberfläche und Logik führen, was gemeinhin vermieden werden sollte.
  • Events: Du könntest in der Player-Klasse Events deklarieren (Kurzbeschreibung von Microsoft). Du hättest also irgendwie sowas:
    public event PlayerHandler PlayerAttributesChanged;
    
    // im Formular:
    _player.PlayerAttributesChanged += UpdatePlayerTexts;
    
    public void UpdatePlayerTexts(object sender, PlayerAttributes a)
    {
     	lblHp.Text = a.Hitpoints;
      	// ...
    }
  • INotifyPropertyChanged: Das ist ein von .NET definiertes Interface, das das, was ich drüber mit Events beschrieben habe, generalisiert für sämtliche Änderungen an Objekten. Das ist im Augenblick das Standard-Muster, nach dem Änderungen an Daten an die Oberfläche gelangen. Das zugrundeliegende Konzept nennt sich Databinding (das gibt's nicht nur in C#, das ist in sehr vielen Sprachen vorhanden).
  • Nochmal Inversion of Control: Ich hatte in einem der Beispiele weiter oben schon einmal was ähnliches beschrieben: Du könntest deiner Player-Klasse im Konstruktor ein Objekt übergeben, das sich um sämtliche Oberflächen-Interaktion kümmert. Somit muss die Player-Klasse weiterhin nichts von WinForms wissen und du kannst sie auch in einer Konsolen-Anwendung oder im Web nutzen. Das könnte sehr grob so aussehen:
    public class Output
    {
     	public Output(Form gameForm)
        {
         	this.Form = gameForm; 
        }  
      	
      	public void Print(string msg)
        {
         	this.Form.Output.AppendText(msg); 
        }
      
      	public void DoAction(string action)
        {
         	switch(action)
            {
              case "go north": //...
              case "attack": //...
            }
        }
    }
    
    // in Player:
    
    public Player(Output output)
    {
     	this.Output = output; 
    }
    
    public void Attack(Monster m)
    {
     	m.Hitpoints -= this.Attack;
      	Output.Print("Player attacked monster, monster has " + m.Hitpoints + " left!");
    }

    Das ist auch nicht wirklich sauber (idealerweise löst man das mit Interfaces und abstrakten / virtuellen Methoden), könnte für dich aber ein guter Mittelweg sein.

(Die komische Formatierung bitte verzeihen, irgendwie fügt das Forum die Tabs hier komisch ein und ich habe keinen Nerv damit zu kämpfen ;) )

Bearbeitet von arlegermi
Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 8 Minuten schrieb Tician:

Das einzige was mir einfallen würde wäre in der Form1 ein PropertyChanged-Event auf eines der Elemente zu legen, würde also Pseudomäßig so aussehen:


Form1
{
	Player _player;
	public event PropertyChangedEventHandler HpChanged;
	labelCurHP.Text {set {HpChanged(value)}};
  
	labelCurHP.Text = _player.TakeDamage(value);
	
	HpChanged(...)
    {
	_player.CurHP = value;
	hpBar.Value = value;
    }
}

Ich glaub hier wird man auch sehen das ich gerade den Unterschied zwischen Event und normaler Methode nicht sehe.

Das event "HpChanged" gehört nicht in's Formular, sondern in die Player-Klasse. Das Formular "subscribed" dann auf das Event:

// im Formular:
_player.HpChanged += UpdateHitpointLabel;

public void UpdateHitpointLabel(object sender, PropertyChangedEventArgs e)
{
 	labelCurHp.Text = _player.CurHp;
}

// in Player:
public event PropertyChangedEventHandler HpChanged;

public void TakeDamage(int damage)
{
 	currentHp -= damage;
    HpChanged(this, new PropertyChangedEventArgs("currentHp"));
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Eine Frage zur Logik, weil ich mal wieder nicht weiß wie andere das machen: Wenn der Spieler angreift sieht das momentan so aus:

Form1
        private void Attack(Monster monster)
        {
            _currentMonster.curHP = _player.Attack(_player, _currentMonster);
            richTextBox1.AppendText("\nYou hit the monster!\nIt's remaining health is: " + _currentMonster.curHP);
            if(_currentMonster.curHP == 0)
            {
                MonsterDie();
                return;
            }
            richTextBox1.AppendText("\nIt fights back!");
            Damage(_currentMonster.attack);            
        }
Player
        public int Attack(Player player, Monster monster)
        {
            if(monster.curHP > player.attack)
            {
                monster.curHP = monster.curHP - player.attack;
            }
            else
            {
                monster.curHP = 0;
            }
            return monster.curHP;
        }

Wie gehabt ist das grottenfalsch. Meine Frage ist ob das nun annehmbar ist:

Main
		_player.Attack(_player, _currentMonster);

Player
        public int Attack(Player player, Monster monster)
        {
            //logik? Keine?
			_monster.TakeDamage(monster);
        }
Monster
        public int TakeDamage(Monster monster)
        {
            //logik hier
			Die();
        }

Mein Gott die Formatierung in den Code-Boxen regt mich auf!

Ich kann mir ja vorstellen das die Player-Klasse vielleicht gar nichts von Monster aufrufen sollte. Außerdem bin ich verwirrt weil beides nicht zusammen passt, ich kann entweder sagen "Spieler greift an" oder "Monster nimmt schaden", aber beides hat zu wenig Logik, es passiert ja nichts außer einer text-message in der Main und ein Abzug der Monster-HP.

Heißt im Prinzip gibt es kein "Spieler greift an":

Main
	_monster.TakeDamage(_player.AttackDamage, _currentMonster)
	//textBox-Message blabla (hier vermutlich ein Event)

Monster
        public void TakeDamage(int damage, Monster monster)
        {
            //Logik
            HpChanged(this, new PropertyChangedEventArgs("curHP");
        }

Was ist da die schönere Lösung?

Bearbeitet von Tician
Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 36 Minuten schrieb Tician:

Ich kann mir ja vorstellen das die Player-Klasse vielleicht gar nichts von Monster aufrufen sollte.

Ne, das ist völlig in Ordnung, dazu gibt es ja öffentliche ("public") Methoden, damit sie von außen aufgerufen werden. Ein Punkt von OOP ist ja gerade, dass Klasse nach außen hin bestimmte Methoden bereitstellen, die dann den internen Zustand des jeweiligen Objekts manipulieren (wenn du da nachlesen möchtest, die Stichwörter sind "Encapsulation" und "Information Hiding").

vor 38 Minuten schrieb Tician:

Außerdem bin ich verwirrt weil beides nicht zusammen passt, ich kann entweder sagen "Spieler greift an" oder "Monster nimmt schaden"

Das ist richtig. Das ist erstmal Geschmackssache, wie du das modellierst. Für "richtige" Spiele ist das ganze noch deutlich komplexer und es kann durchaus Sinn machen, eine dritte Klasse einzubeziehen, die solche Kämpfe "koordiniert". Für dich ist es völlig ok, eine "Player.Attack(Monster m)"-Methode zu haben.

vor 39 Minuten schrieb Tician:

aber beides hat zu wenig Logik, es passiert ja nichts außer einer text-message in der Main und ein Abzug der Monster-HP.

Erstmal ist wichtig, dass es völlig ok ist, Methoden mit wenig Logik zu haben. Es gibt im Bereich von OOP durchaus viele Leute, die der Meinung sind, dass Methoden (und Klassen) kurz sein sollen. Bei Klassen gibt's verschiedene Aussagen dazu, die allermeisten sind sich einig, dass eine durchschnittliche Klasse unter 500 Zeilen Code bleiben sollte, vorzugsweise nicht mehr als 200 (wie gesagt: das sind keine empirisch belegbaren Limits, sondern Erfahrungswerte und Geschmackssache).

Zum anderen ist das vllt. in deinem jetzigen Fall so. Aber wenn man mal ein wenig weiterspinnt, kann es bei so einer Methode schon eine ganze Menge Logik geben. Was ist denn mit Ausweichen? Rüstung? Verfehlen? Tageszeit (hat ein Wolf in der Nacht Vorteile? Was ist, wenn der Spieler eine Fackel trägt?)?

Ich würde daher auf jeden Fall bei deiner Implementierung mit Player.Attack und Monster.TakeDamage bleiben. Zum Beispiel könnte es ja sein, dass auf dem Monster gerade ein Effekt ist, der das Sterben verhindert. Oder das Monster trägt Rüstung, die den Schaden halbiert. Oder oder oder...

Ein kleiner Hinweis noch zu deiner Player.Attack-Methode

vor 45 Minuten schrieb Tician:

public int Attack(Player player, Monster monster)

Wieso übergibst du hier den Player nochmal als Parameter? Du rufst die Methode doch auf dem Player-Objekt auf. Du kannst die Methode daher so schreiben:

public int Attack(Monster monster)
{
	//... bspw. Ausgabe "Player attacks monster"  	
  	var attack = // Logik zum Ermitteln der Angriffspunkte; vllt. gibt ein Schwert ja einen Bonus?
  	monster.TakeDamage(attack);
  	return monster.CurrentHitpoints;
}

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wie @arlegermi schon schreibt musst du der Klasse nicht nochmal die Instanz der eigenen Klasse übergeben, also der Klasse Monster, das Monster oder dem Player den Player.

Was du dir überlegen könntest, wäre, dass ja im Prinzip Attack immer das selbe ist, nur die Richtung unterscheidet sich, also das Monster attackiert den Player und der Player attackiert das Monster und beide haben HitPoints und beide können sterben. Im Prinzip sind also beides Player, nur der eine ist ein Player der vom Benutzer gesteuert wird und das andere ist ein Player, der vom Computer gesteuert wird.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 32 Minuten schrieb arlegermi:

Für "richtige" Spiele ist das ganze noch deutlich komplexer und es kann durchaus Sinn machen, eine dritte Klasse einzubeziehen, die solche Kämpfe "koordiniert". 

Das ist eigentlich auch der richtige Weg. Die Attack()-Methode in der Player-Klasse verursacht einige Probleme.
Zum einen vermischt man Datenhaltung mit der Logik. Wenn man es weiterspinnt, dann wird es ja bei der Attack()-Methode nicht bleiben. Dann gibt es vielleicht noch eine Talk()-, eine Walk()-, eine Use()-, etc. Methode. Die Klasse hat dann mehrere Zuständigkeiten. Sie hält also nicht nur die Daten des Spielers, sondern ist auch noch für den Kampf, fürs Reden, fürs Laufen, etc. zuständig.

Darüber hinaus wird die Player-Klasse von der Monster-Klasse abhängig. Das mag vielleicht in einem einigen Projekt nicht so schlimm sein aber wenn man z.B. die Monster in ein separates Projekt auslagert, so wird es schon etwas problematischer, wenn man dann die Player-Klasse einzeln testen möchte. 

Eine Klasse, die den Kampf koordiniert, dient dann als "Verbindungsstück" (Integration) zwischen Spieler, Monster und ggf. der UI und die Player- und Monster-Klassen können als "dumme" Objekte (POCOs) behandelt werden und brauchen dann keinerlei Logik. 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Die Methode ist doch in der Spieler-Klasse definiert, dann kannst du doch die Eigenschaften/Methoden der Klasse aufrufen

public int Attack(Monster monster)
{
    var attack = this.GetDamage();
    monster.TakeDamage(attack);
    return monster.CurrentHitpoints;
}

private int GetDamage()
{
    // Logik
}

 

Bearbeitet von Whiz-zarD
Link zu diesem Kommentar
Auf anderen Seiten teilen

Wenn ich ein Event habe und 2 Subscriber darauf: Welcher zieht zuerst?

Ich bin gerade am refaktorisieren und mir fehlt nur noch der Kampf. Der Ablauf sollte so sein:

- Button wird gedrückt "Angriff"

- Spieler greift an: Berechnung der übrigen Monster HP (und ob Monster tot ist)

- Wenn Monster noch am Leben: Text-Ausgabe über Monster HP

- Monster greift an: Berechnung der übrigen Spieler HP (und ob SPieler tot ist)

- Textausgabe über Monsterangriff and erhaltenen Schaden

- Wiederholung bei jedem Button-Click bis einer von beiden Tot.

------------------

Ausführung:

Form1
        private void attack(object sender, EventArgs e) //Button Click
        {
            _player.Attack(_currentMonster);
            richTextBox1.AppendText("\nYou hit the monster!\nIt's remaining health is: " + _currentMonster.curHP);
        }

Player
        public void Attack(Monster monster)
        {
            monster.TakeDamage(attack);
        }

Monster
        public void TakeDamage(int damage)
        {
            if (curHP > damage)
            {
                curHP = curHP - damage;
                //player.TakeDamage
            }
            else
            {
                //not omplemented^^
            }
        }

Problem: Vermutlich sichtbar, ich wollte von der Monster-Klasse direkt wieder zurück zur Player-Klasse, aber diesmal fehlt mir mein Player-Objekt. Die Schlamperlösung wäre wohl den Player durch zu schleifen. Aber an diesem Punkt wäre wohl doch eine Klasse für den Kampf besser die ich in Form1 aufrufe und einfach sowohl Player als auch Monster mitgebe oder?

Bearbeitet von Tician
Link zu diesem Kommentar
Auf anderen Seiten teilen

vor einer Stunde schrieb Tician:

Aber an diesem Punkt wäre wohl doch eine Klasse für den Kampf besser die ich in Form1 aufrufe und einfach sowohl Player als auch Monster mitgebe oder?

Genau. Das war das, was ich heute morgen geschrieben habe. Du würdest einfach in deinem Formular ein Objekt der Klasse "Fight" (o.ä.) erzeugen, das die Player-Instanz und das Monster mitbekommt und als Methode sowas wie "FightRound()" hat, die dann je 1x den Spieler und das Monster angreifen lässt (sofern noch am Leben).

Link zu diesem Kommentar
Auf anderen Seiten teilen

Bin quasi schon dran, aber ich glaube ich mache es anders als es vorgesehen war, ich brauche nämlich schon wieder eine Starthilfe :(

Form1:
        private void exploreForest(object sender, EventArgs e) //Schritt 1
        {
            case 3:
                    _currentFight = new Fight(_player, _currentMonster);
                    break;
        }

        private void attack(object sender, EventArgs e) //Angriffs-Button. Schritt 4
        {
            _currentFight.FightRound();
        }

        public void MonsterAppearOutput(object sender, EventArgs e)//Schritt 3
        {
            richTextBox1.Text = "A wild " + _currentMonster.name + " level " + _currentMonster.level + " appears!\nIt has "+_currentMonster.curHP+" HP.";
        }

Fight:
        public event EventHandler MonsterAppear;

        public Fight(Player player, Monster monster) //Schritt 2
        {
            player.MoveTo(World.LocationById(World.location_id_fight)); //Spieler bekommt Button für "Angriff"
            MonsterAppear(this, new EventArgs()); 
        }

        public void FightRound() //Schritt 5
        {
            //???
        }

Wenn ich von meiner Fight-Klasse die Methode FIghtRound() aufrufe muss ich nochmal Player und Monster übergeben um etwas zu machen - war das Sinn der Sache?

Bearbeitet von Tician
Link zu diesem Kommentar
Auf anderen Seiten teilen

Genau so wie @Whiz-zarD schreibt. Genau wie du in deiner Form-Klasse Sachen in Variablen abspeicherst (z.B. _player), machst du das auch in "Fight". Wenn du den Spieler und das Monster also im Konstruktor übergibst, speicherst du sie in (private) Variablen und kannst dann in der Methode "FightRound" auf diese zugreifen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

    public class Fight
    {
        Player player;
        Monster monster;

        //Events
        public event EventHandler MonsterAppear;

        public Fight(Player player, Monster monster)
        {
            this.player = player;
            this.monster = monster;
            player.MoveTo(World.LocationById(World.location_id_fight));
            MonsterAppear(this, new EventArgs());
        }

^_^

Link zu diesem Kommentar
Auf anderen Seiten teilen

Konstruktoren sollte keine Logik besitzen. Wie der Name schon sagt, dient er zur Konstruktion eines Objektes. Daher sollte der Konstruktor auch nur dafür verwendet werden. Sprich, die Zeilen:

player.MoveTo(World.LocationById(World.location_id_fight));
MonsterAppear(this, new EventArgs());

Sollten da raus.

 

 

Link zu diesem Kommentar
Auf anderen Seiten teilen

Wow da hat uns unser Lehrer dann aber ziemlichen Mist beigebracht.

Ich lass es bis übermorgen drin, dann schau ich mal was ich damit mache, weil das war die elegante Lösung um diese beiden Dinge nicht wiederholend zu schreiben und sie müssen sowieso jedesmal aufgerufen werden wenn es in einen Fight geht.

Die Alternative wäre dann in der Form1 eine Methode zu basteln die ich stattdessen aufrufe (und in der wiederum mein Fight-Object erstellt wird). Dann bin ich auch gleichzeitig das Event los.

Link zu diesem Kommentar
Auf anderen Seiten teilen

vor 9 Minuten schrieb Tician:

Die Alternative wäre dann in der Form1 eine Methode zu basteln die ich stattdessen aufrufe (und in der wiederum mein Fight-Object erstellt wird). Dann bin ich auch gleichzeitig das Event los.

Das schon eher (auch wenn das auch nicht nicht sauber ist). Ein Hinweis, dass die beiden genannten Zeilen nicht in die Fight-Klasse gehören, ist auch deren Funktion.
Du bewegst den Spieler und ein Monster erscheint. Das ist aber noch vor dem Kampf und somit verletzt man das sog. Single-Responsibility-Prinzip. Sprich, die Klasse hat mehr als eine Zuständigkeit, indem die Klasse den Spieler bewegt, das Ereignis auslöst und den Kampf an sich.

Bearbeitet von Whiz-zarD
Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...