Tician Geschrieben 30. Juni 2017 Autor Teilen Geschrieben 30. Juni 2017 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. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Whiz-zarD Geschrieben 1. Juli 2017 Teilen Geschrieben 1. Juli 2017 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. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Tician Geschrieben 1. Juli 2017 Autor Teilen Geschrieben 1. Juli 2017 (bearbeitet) 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 1. Juli 2017 von Tician Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Kleinrechner Geschrieben 3. Juli 2017 Teilen Geschrieben 3. Juli 2017 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. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Whiz-zarD Geschrieben 3. Juli 2017 Teilen Geschrieben 3. Juli 2017 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" Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Tician Geschrieben 3. Juli 2017 Autor Teilen Geschrieben 3. Juli 2017 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. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
arlegermi Geschrieben 3. Juli 2017 Teilen Geschrieben 3. Juli 2017 (bearbeitet) 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 3. Juli 2017 von arlegermi JimTheLion reagierte darauf 1 Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
arlegermi Geschrieben 3. Juli 2017 Teilen Geschrieben 3. Juli 2017 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")); } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Tician Geschrieben 3. Juli 2017 Autor Teilen Geschrieben 3. Juli 2017 Damit kann ich was anfangen, werde ich sobald ich kann ausprobieren! Vielen Dank! Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Tician Geschrieben 4. Juli 2017 Autor Teilen Geschrieben 4. Juli 2017 Events sind ja was richtig feines! Gefällt mir! Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Tician Geschrieben 4. Juli 2017 Autor Teilen Geschrieben 4. Juli 2017 (bearbeitet) 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 4. Juli 2017 von Tician Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
arlegermi Geschrieben 4. Juli 2017 Teilen Geschrieben 4. Juli 2017 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; } Tician reagierte darauf 1 Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Kleinrechner Geschrieben 4. Juli 2017 Teilen Geschrieben 4. Juli 2017 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. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Whiz-zarD Geschrieben 4. Juli 2017 Teilen Geschrieben 4. Juli 2017 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. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Tician Geschrieben 4. Juli 2017 Autor Teilen Geschrieben 4. Juli 2017 (bearbeitet) Edit: Hat sich erledigt (hier stand eine doofe Frage^^) Super, danke Leute! Bearbeitet 4. Juli 2017 von Tician Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Whiz-zarD Geschrieben 4. Juli 2017 Teilen Geschrieben 4. Juli 2017 (bearbeitet) 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 4. Juli 2017 von Whiz-zarD Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Tician Geschrieben 4. Juli 2017 Autor Teilen Geschrieben 4. Juli 2017 (bearbeitet) 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 4. Juli 2017 von Tician Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
arlegermi Geschrieben 4. Juli 2017 Teilen Geschrieben 4. Juli 2017 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). Tician reagierte darauf 1 Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Tician Geschrieben 4. Juli 2017 Autor Teilen Geschrieben 4. Juli 2017 (bearbeitet) 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 4. Juli 2017 von Tician Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Whiz-zarD Geschrieben 4. Juli 2017 Teilen Geschrieben 4. Juli 2017 Du reichst Player und Monster in den Konstruktor der Fight-klasse rein und speicherst diese dann als Membervariable in dieser Klasse ab. Tician reagierte darauf 1 Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
arlegermi Geschrieben 4. Juli 2017 Teilen Geschrieben 4. Juli 2017 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. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Tician Geschrieben 4. Juli 2017 Autor Teilen Geschrieben 4. Juli 2017 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()); } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Whiz-zarD Geschrieben 4. Juli 2017 Teilen Geschrieben 4. Juli 2017 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. Tician reagierte darauf 1 Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Tician Geschrieben 4. Juli 2017 Autor Teilen Geschrieben 4. Juli 2017 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. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Whiz-zarD Geschrieben 4. Juli 2017 Teilen Geschrieben 4. Juli 2017 (bearbeitet) 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 4. Juli 2017 von Whiz-zarD Tician reagierte darauf 1 Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
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.