Ich arbeite an einem einfachen blockbasierten Puzzlespiel.
Das Spiel besteht so ziemlich aus beweglichen Blöcken im Spielfeld, es ist also eine triviale Physiksimulation. Meine Implementierung ist jedoch meiner Meinung nach alles andere als ideal und ich frage mich, ob Sie mir Hinweise geben können, wie ich es besser machen kann.
Ich habe den Code in zwei Bereiche aufgeteilt: Spielelogik und Benutzeroberfläche, wie ich es bei vielen Puzzlespielen getan habe:
- Die Spiellogik ist verantwortlich für die allgemeinen Spielregeln (zB das formale Regelsystem im Schach)
- Die Benutzeroberfläche zeigt den Spielbereich und die Figuren (z. B. Schachbrett und Figuren) an und ist für Animationen (z. B. animierte Bewegung von Schachfiguren) verantwortlich.
Die Spielelogik stellt den Spielstatus als logisches Raster dar, wobei jede Einheit die Breite / Höhe einer Zelle im Raster darstellt. Bei einem Gitter der Breite 6 können Sie also einen Block der Breite 2 viermal verschieben, bis er mit der Begrenzung kollidiert.
Die Benutzeroberfläche verwendet dieses Raster und zeichnet es, indem sie logische Größen in Pixelgrößen umwandelt (dh mit einer Konstanten multipliziert). Da das Spiel jedoch kaum Spielelogik enthält, hat meine Spielelogik-Ebene [1] außer der Kollisionserkennung nicht viel zu tun. So funktioniert das:
- Der Spieler beginnt, eine Figur zu ziehen
- Die Benutzeroberfläche fragt die Spiellogik nach dem zulässigen Bewegungsbereich dieser Figur und lässt den Spieler sie in diesen Bereich ziehen
- Spieler lässt ein Stück los
- Die Benutzeroberfläche fängt das Teil am Raster (so dass es sich an einer gültigen logischen Position befindet)
- Die Benutzeroberfläche teilt der Spielelogik die neue logische Position mit (über Mutatormethoden, die ich lieber vermeiden möchte).
Damit bin ich nicht ganz zufrieden:
- Ich schreibe Komponententests für meine Spielelogikebene, aber nicht für die Benutzeroberfläche, und es stellte sich heraus, dass der gesamte heikle Code in der Benutzeroberfläche enthalten ist: Verhindern, dass das Teil mit anderen oder der Grenze kollidiert, und Fangen am Raster.
- Die Tatsache, dass die Benutzeroberfläche der Spielelogik den neuen Status mitteilt, gefällt mir nicht. Ich hätte es vorgezogen, eine
movePieceLeft()
Methode oder ähnliches wie in meinen anderen Spielen aufzurufen , aber ich bin mit diesem Ansatz nicht weit gekommen, weil Die Spielelogik weiß nichts über das Ziehen und Fangen, das in der Benutzeroberfläche möglich ist.
Ich denke, das Beste wäre, meine Spielelogik-Ebene loszuwerden und stattdessen eine Physik-Ebene zu implementieren. Ich habe ein paar Fragen dazu:
- Ist eine solche Physik-Ebene üblich oder ist es typischer, dass die Spielelogik-Ebene dies tut?
- Würde der Code zum Fangen von Gittern und Teilen zur Benutzeroberfläche oder zur Physikebene gehören?
- Funktioniert eine solche Physik-Ebene normalerweise mit Pixelgrößen oder mit einer Art logischer Einheit wie meiner Spielelogik-Ebene?
- Ich habe einmal eine ereignisbasierte Kollisionserkennung in der Codebasis eines Spiels gesehen, das heißt, der Spieler hat einfach die Figur gezogen, die Benutzeroberfläche hat das gehorsam gerendert und das Physiksystem benachrichtigt, und das Physiksystem hat eine onCollision () -Methode aufgerufen auf dem Stück, sobald eine Kollision erkannt wird. Was ist häufiger? Diesen Ansatz oder erst nach dem Bereich der legalen Bewegung fragen?
[1] Die Ebene ist wahrscheinlich nicht das richtige Wort für das, was ich meine, aber das Subsystem klingt übertrieben und die Klasse ist irreführend, da jede Ebene aus mehreren Klassen bestehen kann.