Wie trennt man Logik & Grafik sinnvoll?



  • Wie trennt man Logik & Grafik sinnvoll? (Bitte nicht auf das MVC Pattern verweisen, den Quatsch kann man fast nie umsetzen)

    Kollisionserkennung ist zwar Logik, aber hängt stark von der Grafik ab.
    (Ohne die Information über das Sprite kann man schlecht raten...)

    Ist eine richtige Trennung überhaupt möglich? Langsam kommen mir die Zweifel.

    Bei meinem letzten Spiel habe ich Grafik und Logik einfach vermischt. Der Code war zwar grässlich, ich bin aber schnell ans Ziel gekommen. Und es hat auch wunderbar funktioniert.

    Diesmal versuche ich Grafik & Logik zu trennen, aber komme einfach nicht voran, da ich die ganze Zeit am überlegen bin wie ich die Trennung durchführen soll.

    Nehmen wir mal an, wir haben eine Klasse Player. Sie soll keine Informationen über Grafik enthalten (wegen der Trennung). Schön und gut. Aber wo soll ich nun die Kollisionserkennung durchführen? Ich hatte bisher in einem Polygon die Eckpunkte gespeichert und das Polygon in der Player-Klasse als Instanzvariable gespeichert. Das ist zwar keine Information über die Grafik, jedoch kann ich dieses Polygon erst dann erzeugen, wenn ich das der fertige Sprite sehe.

    Somit hängt die Kollisionserkennung unmittelbar mit der Grafik zusammen. Wie soll man das Trennen?

    Mittlerweile hab ich das (zur Kollisionserkennung notwendige) Polygon aus Player verlagert nach außen. Und nun weise ich irgendwo später im code dem Player das Polygon zu (im Sinne von: Polygon auf Kollision testen und dann das Kollisions-flag(bool) in der Playerklasse setzen ) Das hat den Effekt, dass ich absolut KEINEN VORTEIL daraus gewinne und mein Code sich nur unnötig aufbläht.

    Wie soll man in solch einem Fall überhaupt verfahren? Wie Trenne ich sinnvoll? Soll man überhaupt trennen? Bis jetzt hat mir das Kopfzerbrechen nur Zeit und Nerven geraubt und ich hab mich kein Stück vorwärts bewegt. Ich komme langsam zu dem Punkt, dass ich der Einfachheit halber Logik & Grafik wieder vermischen möchte. Mein Code würde erheblich an Länge verlieren. Langsam komme ich mir vor wie ein Dogmatiker, dessen Grundsätze einem im Wegstehen.

    Mir wurde zwar mal das Model-View-Controller-Pattern empfohlen, aber das ist sowas von "praxisferne Lehrbuch-Theorie", das kann man doch kaum umsetzen.



  • Wie mans am besten trennt kann ich nicht sagen. Aber zu deiner Argumentation: Die Kollisionserkennung hängt doch nicht von der Grafik, sondern von der *Physik* ab. Wie genau der Spieler aussieht ist unwichtig. Die Form der Spielers ist wichtig.



  • The-Kenny schrieb:

    Wie mans am besten trennt kann ich nicht sagen. Aber zu deiner Argumentation: Die Kollisionserkennung hängt doch nicht von der Grafik, sondern von der *Physik* ab. Wie genau der Spieler aussieht ist unwichtig. Die Form der Spielers ist wichtig.

    Nach der Definition kann ich ja mein Polygon wieder beruhigt in die Player-Klasse stecken.

    Somit ist die Form des Spielers keine "Grafik" mehr? (da ich nebenbei die Kontur des Spielersprites in Player speichern wollte in einem anderen Polygon xD)



  • Nimm MVC.


  • Administrator

    Schneewittchen schrieb:

    Mir wurde zwar mal das Model-View-Controller-Pattern empfohlen, aber das ist sowas von "praxisferne Lehrbuch-Theorie", das kann man doch kaum umsetzen.

    Kam mir bisher nicht so vor. Es braucht aber im allgemeinen ein ziemliches Umdenken.

    Aber The-Kenney hat schon recht. Mit der Graphik, bzw. der View, hat die Kollisionserkennung nichts zu tun. Für das MVC prinzipt gilt ja:
    Die Daten werden im Model gespeichert. Dazu gehören auch die Daten über das Aussehen: Farbe, Material, Grösse, Position, usw. usf.
    Die View erstellt aus den Daten des Model eine Graphik. Die View speichert also keine Daten über das Aussehen ab, sondern Optionen wie die Daten verarbeitet werden.
    Der Controller kontrolliert den Datenaustausch und sonstiges, knüpft Model und View zusammen.

    Wichtig ist zu erkennen, was die Aufgabe von Model und View ist. Die View zeichnet und speichert daher nur Optionen für das Zeichnen, kennt aber keine Daten über das Objekt, welches gezeichnet werden soll, diese bekommt es alle mit dem Model. Im Model befinden sich die Daten des Körpers.
    Viele MVC Anfänger machen den Fehler, dass sie probieren Daten über das Aussehen des Körpers in die View zu packen, was aber falsch ist.

    Grüssli



  • Man muss ja nicht gleich MVC in reinkultur implementieren. Wichtig ist nur, dass die View nichts anderes tut als den aktuellen Zustand anzuzeigen, wobei Formen von Objekten und kollisionen dazwischen für mich eindeutig zum Zustand des Spiels gehören. Ob dieser sich nun selber ändert oder das durch einen Kontroller gemacht wird ist hierfür ja erstmal egal



  • Okay, dann habe ich die Trennung etwas missverstanden.

    Ich dachte immer, dass nur View Informatonen (animation, sprite) haben darf.

    Muss wohl alles wieder umwurschteln.


  • Administrator

    Vielleicht noch eine kleine Ergänzung für ein besseres Verständnis von MVC:
    MVC ist keine Trennung von Daten, sondern ist eine Trennung von Funktionalität. Durch die Trennung von der Funktionalität hat man natürlich automatisch auch eine Trennung von Daten, da diese an die Funktionalität gebunden sind, aber diese Trennung ist zweitrangig, bzw. passiert implizit. Man sollte sich also auf die Trennung der Funktionalität konzentrieren.

    Das Model speichert Informationen über den Körper.
    Der Controller arbeitet oder kommuniziert.
    Die View zeichnet.

    Auch kann ein Controller mehrere Models und Views verwalten. Eine View kann mehrere Models zeichnen, usw. Es besteht meistens keine 1 zu 1 zu 1 Beziehung.

    Gewisse Funktionalitäten können auch nicht explizit einem einzigen Teil im MVC Muster zugeordnet werden. Oft gibt es streit über die Funktionalitättrennung zwischen Model und Controller. Ich habe schon Artikel gelesen, welche vorgeschlagen haben, Model und Controller zu vereinigen.

    Aber ich glaube, dass der wichtige Punkt eben ist, dass man erkennt, dass es um Funktionalitätstrennung geht.

    Grüssli


  • Mod

    Schneewittchen schrieb:

    Kollisionserkennung ist zwar Logik, aber hängt stark von der Grafik ab.
    (Ohne die Information über das Sprite kann man schlecht raten...)

    Kollision haengt ueberhaupt nicht von der graphik ab, auch blinde koennen irgendwo gegenrennen.

    Nehmen wir mal an, wir haben eine Klasse Player. Sie soll keine Informationen über Grafik enthalten (wegen der Trennung). Schön und gut.

    garnicht schoen, zum einen macht man kaum eine klasse die player heisst. meistens gibt es einfach nur objekte die auf verschiedenen wegen kontrolliert werden.

    du hast also generische objekte, diese beinhalten keine daten, sie verweisen auf daten. diese daten generiert man am besten ausserhalb vom spiel/engine (z.b. resource compiler), dann kannst du ein bsp fuer collisionen generieren und ein dreiecksmesh fuers rendern, von was auch immer deine ausgangsdaten waren: patches, voxel, splines, polygone, csg....

    Aber wo soll ich nun die Kollisionserkennung durchführen? Ich hatte bisher in einem Polygon die Eckpunkte gespeichert und das Polygon in der Player-Klasse als Instanzvariable gespeichert. Das ist zwar keine Information über die Grafik, jedoch kann ich dieses Polygon erst dann erzeugen, wenn ich das der fertige Sprite sehe.

    was wenn es ein server ist der die kollisionen berechnet und nie etwas "sehen" wird?

    Somit hängt die Kollisionserkennung unmittelbar mit der Grafik zusammen. Wie soll man das Trennen?

    graphik ist reine ausgabe, sie liest den momentanen status der logischen darstellung ab und zeichnet entsprechendes. viele dinge die gezeichnet werden sind ueberhaupt garnicht in der logik vorhanden (z.b. grass auf dem terrain) und es sind dinge vorhanden die nie gezeichnet werden (z.b. soundquellen, invisible walls, trigger)

    Mittlerweile hab ich das (zur Kollisionserkennung notwendige) Polygon aus Player verlagert nach außen. Und nun weise ich irgendwo später im code dem Player das Polygon zu (im Sinne von: Polygon auf Kollision testen und dann das Kollisions-flag(bool) in der Playerklasse setzen ) Das hat den Effekt, dass ich absolut KEINEN VORTEIL daraus gewinne und mein Code sich nur unnötig aufbläht.

    das liegt daran dass du alles spezialisierst und wenig wiederbenutzt, vermutlich hast du pro gegner eine klasse und die kollisionsklasse heisst nicht zufaellig "playercollision"?

    Wie soll man in solch einem Fall überhaupt verfahren? Wie Trenne ich sinnvoll? Soll man überhaupt trennen? Bis jetzt hat mir das Kopfzerbrechen nur Zeit und Nerven geraubt und ich hab mich kein Stück vorwärts bewegt. Ich komme langsam zu dem Punkt, dass ich der Einfachheit halber Logik & Grafik wieder vermischen möchte. Mein Code würde erheblich an Länge verlieren. Langsam komme ich mir vor wie ein Dogmatiker, dessen Grundsätze einem im Wegstehen.

    bevor du saubere trennung einfuehren kannst, solltest du erstmal generalisieren. mach eine einzige class (was eigentlich auch zu sehr idealisiert ist) die alle objekte in deinem spiel representiert. sie zeigt dann auf graphik, sound, collisiondaten, input-objekt und ein paar einstellungen.

    Mir wurde zwar mal das Model-View-Controller-Pattern empfohlen, aber das ist sowas von "praxisferne Lehrbuch-Theorie", das kann man doch kaum umsetzen.

    es liegt nicht an der theorie, sondern eventuell daran, dass viele pattern runterbeten koennen, aber ihre umsetzungen davon sehr schlecht (eigentlich nur ein runterschrieben der theorie) sind. das funktioniert dann nur an ihrem hello-world beispiel.



  • Schneewittchen schrieb:

    Wie trennt man Logik & Grafik sinnvoll? (Bitte nicht auf das MVC Pattern verweisen, den Quatsch kann man fast nie umsetzen)

    Doch 😃

    Wenn du mal zu dem Thema im Internet suchst, findest du bestimmt auch Seiten, die das Thema genauer beleuchten.

    Ich würde das mal "MVC-Flavours" nennen.
    Flavour deshalb, weil es unterschiedliche Gründe gibt, warum man an welchen Stellen eine Trennung vornimmt. Siehe MVP.

    Der klassische Vorteil ist die Austauschbarkeit von M,V und C.
    Beispiel: Will man den Renderer wechseln muss man nur etwas an den internen Mechanismen von V tun. M+C bleiben so wie sie sind.

    Ein weiterer wichtiger Aspekt dabei ist die lose Kopplung. (->Events?)
    Mit einem falschen Klassen-Design und schlechter Hierarchie ist eine Trennung auch nicht möglich.

    In dem MVC-Fall muss man meiner Meinung nach grundsätzlich "top-down" denken und die strukturelle Trennung konsequent durchziehen.

    Dann klappt das auch ...

    Bleibt noch die spannende Frage: Warum sollte man sich MVC überhaupt antun ?
    Meine Meinung: Gewisse Requirements führen a priori in MVC-Richtung.



  • nurf schrieb:

    In dem MVC-Fall muss man meiner Meinung nach grundsätzlich "top-down" denken und die strukturelle Trennung konsequent durchziehen.

    Nö. Vielmehr schadet es grundsätzlich, grundsätzlich nur eine Denkweise zu betreiben.


Anmelden zum Antworten