Wie soll ich mein Android-Spiel effizient entwickeln? [geschlossen]

11

Ich habe ein Bild eines Flussdiagramms angehängt, das ich in Farbe erstellt habe. Flussdiagramm des Spielkonzepts

Das Bild zeigt, wie ich mein Spiel entwickeln möchte. Ich möchte ein Spiel, das mit intelligenter Codierung, die einfach zu aktualisieren ist, und Anzeigenfunktionen im Laufe der Zeit großartig läuft. Meine Zielplattform ist das Android-Smartphone und der gesamte Code wird in Java mit XML-aufgeblasenen Ressourcen geschrieben, wenn dies wichtig ist. Ich suche keinen harten Code, obwohl Pseudocode helfen wird, würde ich eher Vorschläge und Ratschläge von den Profis bevorzugen.

Meine Fragen sind:

Ist dies eine gute Möglichkeit, ein Spiel zu programmieren, oder gibt es bessere Möglichkeiten, dies zu tun? Müssen Änderungen vorgenommen werden? Vorschläge wären nützlich, da ich keine Erfahrung in der Spielprogrammierung habe. Daher würde ich den Rat von jemandem bevorzugen, der mehrere Spiele geschrieben hat und aus Erfahrung weiß, wie man seinen Code so einrichten sollte, dass er effizient läuft.

kdavis8
quelle

Antworten:

12

Viele Android-Spiele sind nicht einmal groß genug, um das Speichern / Laden oder Optionen / Einstellungen zu rechtfertigen, egal, welche benutzerdefinierten Charaktere und dergleichen, nur weil sie 10 Minuten lang im Zug nach Hause gespielt werden.

Machen Sie nicht den Fehler, etwas mit einem großen Spielraum für ein erstes Android-Spiel zu beginnen. Machen Sie ein paar kleinere Spiele und entscheiden Sie sich dann für etwas Größeres

Android Besonderheiten weise:

Struktur:

Ich würde empfehlen, fast das gesamte Spiel in einer Aktivitätsklasse zu haben. Android arbeitet mit der Idee, dass jede Aktivität wie eine Mini-App ist, halb unabhängig von den anderen Aktivitäten in der App. Die App ist im Wesentlichen ein Stapel von Aktivitäten, bei denen der Benutzer sieht, welche ganz oben steht.

Wenn Sie eine von oben entfernen, wird sie im Allgemeinen zerstört und beim nächsten Start einer neuen Aktivität neu erstellt (StartActivity Intent). Dies macht es schwierig, Zustände zwischen Aktivitäten aufrechtzuerhalten, und führt zu einer einzigen Aktivitätsarchitektur

Möglicherweise möchten Sie eine Aktivität vom Typ Startbildschirm mit dem Menü "Neues Spiel / Spiel laden / Optionen" haben und diese als Startaktivität festlegen. Am Ende müssen Sie jedoch auch ein Menü im Spiel für Ihre Spielaktivität haben, das die meisten der gleichen Funktionen enthält

In meiner eigenen App habe ich eine "MenuActivity" erstellt, die die Funktionen zum Starten eines neuen Spiels, Speichern, Laden und Ändern von Optionen enthält. Dann erweitert meine HomeActivity das ebenso wie meine GameActivity.

Da sich alles in einer Aktivitätsklasse befindet, würde ich empfehlen, eine Hierarchie von Aktivitätsklassen zu erstellen und private, geschützte und Standardbereichslose zu verwenden. Auf diese Weise können Sie zumindest die Dinge in verschiedene Dateien aufteilen, um zu verhindern, dass eine nicht verwaltbare Aktivitätsdatei vorhanden ist. ZB für meine eigene App:

GraphicsEngine extends MenuActivity.

PhysicsEngine extends GraphicsEngine.

GameLogicActivity extends PhysicsEngine.

UIActivity extends GameLogicActivity.

Da es sich bei meiner App um 3D-Opengl-es handelt, funktionieren viele Dinge, die ich mache, nicht aktivitätsübergreifend, sodass sich alle in derselben Aktivität befinden. Vielleicht bin ich voreingenommen, eine Aktivitätsarchitektur zu verwenden

- -

Einfädeln

Für die Spielaktivität haben Sie zwei Threads (oder 3, wenn Sie 3D-OpenGL-Sachen machen). Ein Thread ist der UI / Haupt-Thread. Dies ist der Thread, in dem die Aktivität gestartet und ausgeführt wird und der Ihnen von Android zur Verfügung gestellt wird.

Dieser UI-Thread ist der einzige, in dem Sie UI-Elemente (Ansichten, Layouts usw.) aktualisieren können. Er ist auch derjenige, in dem Listener für Benutzereingaben ausgeführt werden. Sie sehen keine Mechanik des UI-Threads, nur dass er irgendwo in einer Schleife im Hintergrund ausgeführt wird.

Den zweiten Thread machen Sie selbst (ich würde die Verwendung von AsyncTask empfehlen trotz aller Mängel zu verwenden). Dies erledigt alle Nicht-UI-Aufgaben, die Sie in einer normalen Spielschleife ausführen, z. B. das Aktualisieren von Bewegungen, das Berechnen von Kollisionen, Kampfberechnungen usw.

Sie machen diesen AsyncTask-Thread / diese AsyncTask-Klasse zu einer inneren Klasse Ihrer Aktivität. Auf diese Weise können Sie über einige aktivitätsweite Objekte ( Vector<Spaceship>) verfügen , auf die sowohl der UI-Thread als auch der Game-Loop-Thread zugreifen können.

Da die Spielelogik im Game-Loop-Thread ausgeführt wird, ist dies der einzige Thread, der die Werte von Variablen tatsächlich ändern muss (Tankgeschwindigkeit aktualisieren, Spieler-HP reduzieren). Der UI-Thread liest nur Werte, daher sollte es nur minimale Probleme mit der Parallelität geben.

Das Knifflige ist, dass der UI-Thread auf Anfrage des Game-Loop-Threads Aktualisierungen vornimmt. Es gibt verschiedene Möglichkeiten, dies zu tun. Wenn Sie die AsyncTask-Dokumentation lesen, verfügt sie über die Methode PublishProgress () / onProgressUpdate (). Dies fügt der Warteschlange des UI-Threads tatsächlich Dinge hinzu, die in der nächsten Schleife zu erledigen sind.

Handler macht genau das Gleiche, wenn Sie die handleMessage () -Methode implementieren und diese Methode tatsächlich von der nächsten Schleife des UI-Threads ausgeführt wird.

Schließlich können Sie bei jeder Benutzereingabe im UI-Thread die UI-Elemente sofort aktualisieren (also innerhalb der Implementierung aller onClick / onTouch-Listener). Wenn Sie die Spielobjekte aktualisieren müssen, können Sie entweder Synchronisierung verwenden oder eine eigene Warteschlange mit Aktualisierungen in AsyncTask implementieren, die wie der UI-Thread beim nächsten Ausführen der Spielschleife durchlaufen wird

Android Threading-Anleitung .

- -

Benutzeroberfläche

Für die eigentliche UI-Struktur innerhalb der einzelnen Aktivität empfehle ich, ein Rahmenlayout als Basislayout zu verwenden. Die untergeordneten Elemente in einem Rahmenlayout funktionieren wie eine Warteschlange. Das erste Element wird zuerst gezeichnet, das zweite wird über das erste, das dritte über das zweite gezeichnet.

Auf diese Weise können Sie über mehrere XML-Layoutdateien verfügen und durch Verwalten der untergeordneten Elemente des Rahmenlayouts problemlos Ansichten in und aus austauschen.

Wenn Sie die Oberflächenansicht immer unten haben (erstes untergeordnetes Element im Rahmenlayout), können Sie alle üblichen Android-Ansichten / Widgets (Schaltflächen, Textansichten, Bildlaufansichten) usw. über der Oberflächenansicht verwenden der grafische Teil des Spiels.

Wenn also etwas geladen wird, können Sie die Spieleschleife anhalten / einfach alles überspringen lassen, einen undurchsichtigen Ladebildschirm als letztes untergeordnetes Element zum Rahmenlayout hinzufügen und der Benutzer sieht, dass das Laden auf seinem Bildschirm angezeigt wird , ganz unbewusst, dass andere Ansichten dahinter stehen. Auf diese Weise müssen Sie Ansichten nicht entfernen, deren Einrichtung lange dauert, oder bei jedem Hinzufügen / Entfernen Komplikationen verursachen.

Ich würde auch empfehlen, View.setVisibility-Lose zu verwenden. Sie können beispielsweise Ihrem Basisrahmen-Layout ein ganzes "Inventar" -Layout hinzufügen und dann einfach "Sichtbarkeit" (View.Visible) darauf setzen, wenn der Benutzer auf klickt, um sein Inventar anzuzeigen, und "Sichtbarkeit" (View.Gone) festlegen, wenn er es wieder schließt. Auf diese Weise verwalten Sie nicht einmal die untergeordneten Elemente des Rahmenlayouts, sondern fügen lediglich alles hinzu und machen Dinge sichtbar / unsichtbar, wenn der Benutzer verschiedene Dinge tut

Dies hilft beim erneuten Einfädeln. Wenn der Benutzer klickt, um sein Inventar zu öffnen, wird der onCLickListener im UI-Thread behandelt, das Inventar wird darin sichtbar gemacht und die updateInventory-Methode wird erneut vom UI-Thread aufgerufen, wobei nur Getter für alle aufgerufenen Spielobjekte verwendet werden

Hier ist das Diagramm, das ich für eine frühere Frage zur Idee der einzelnen Aktivität / des Rahmenlayouts erstellt habe:

Geben Sie hier die Bildbeschreibung ein

Löffel Daumen
quelle
Also sollte ich deiner Meinung nach ein Frame-Layout haben, um alle Game-Loop-Komponenten aufzunehmen, oder? Wenn ich das tun würde, wie würde ich Ansichten in der HUD-Klasse dazu bringen, Interaktivität mit der SurfaceView zu haben, z. B. ein virtuelles D-Pad / virtuelles Analog? Ich habe schon früher versucht, solche Dinge zu tun, und bin auf Fehler gestoßen.
kdavis8
Ich werde meine Antwort neu schreiben, um es ein bisschen klarer zu machen
Spoon Thumb
Ich habe meine Antwort neu geschrieben. Hoffe das macht es klarer
Spoon Thumb
Vielen Dank für die Aufschlüsselung, die die Dinge wirklich beschreibt, es gibt wirklich nicht viele gute Tutorials für die Entwicklung von Android-Spielen
kdavis8
11

Vieles, was ich in Ihrem Diagramm sehe, hängt mit der Benutzeroberfläche zusammen, und das scheint ziemlich vernünftig zu sein. Es gibt nur einen kleinen Teil Ihres Diagramms, der für die eigentliche Spielelogik reserviert ist, und es ist sehr vage.

Ich denke du versuchst es zu sehr. Ich würde vorschlagen, dass Sie einfach anfangen, Code zu schreiben. Wählen Sie ein bestimmtes Problem aus und lösen Sie es. Sie werden so viel lernen, dass Sie, wenn Sie eine bessere Vorstellung von Ihrem Problemraum haben, eine völlig andere (und nützlichere) Perspektive haben werden.

notlesh
quelle
2
Dem konnte ich nicht mehr zustimmen. Wählen Sie eine Designarchitektur, die dem Spiel und Ihren Vorlieben entspricht, und beginnen Sie dann mit dem Codieren. Wenn Sie einen bestimmten Leistungsverlust feststellen, optimieren Sie, bis er funktioniert. Jeder einzelne Mechanismus in Ihrem Spiel wird seine eigenen Leistungsmerkmale und möglichen Optimierungen haben - Sie müssen einzeln und nicht als Ganzes darüber nachdenken.
Polynom
Wo könnte man einen Leitfaden für solche Muster für die Spielarchitektur finden? es wäre wirklich hilfreich für mich.
Bot_bot