Ich versuche, ein Videospiel von Grund auf neu zu machen, aber ich bin wirklich neu in diesem Bereich und stoße immer wieder auf grundlegende Probleme. Wie speichern Videospiele Offscreen-Informationen? Was ich meine ist, woher weiß das Programm, was als nächstes auf dem Bildschirm angezeigt werden soll? Oder sogar, wenn der Player die Umgebung ändert, wie bleibt diese Änderung beim nächsten Laden auf dem Bildschirm erhalten?
Zum Beispiel in New Super Mario Bros, wenn Sie eine? blocken und dann vom Bildschirm gehen, und zurückkommen, es bleibt immer noch getroffen. Wie werden diese Informationen gespeichert und beim nächsten Laden des Blocks ausgeführt? Warum wird es nicht einfach zurückgesetzt?
game-design
architecture
software-engineering
game-mechanics
Nur ein paar Fragen
quelle
quelle
Antworten:
Normalerweise sollten Sie den logischen Zustand Ihrer Spielumgebung von der visuellen Darstellung trennen.
Der Spieler sieht möglicherweise nur einen kleinen Teil davon auf seinem Bildschirm. Sie behalten jedoch den Status des gesamten Levels im Gedächtnis und berechnen in der Regel auch die Spielmechanik für das gesamte Level. Wenn Ihre Welt so groß ist, dass dies zu viel RAM und / oder CPU erfordern würde, können Sie weiter entfernte Bereiche für die Festplatte aussetzen.
Ihre Rendering-Subroutine überprüft, welche Teile der Ebene aktuell auf dem Bildschirm angezeigt werden, und zeichnet dann nur diese. Was außerhalb des Bildschirms ist, wird nicht gezeichnet, aber das bedeutet nicht, dass es nicht aktualisiert wird.
quelle
Sie machen es rückwärts.
Sie beginnen mit dem logischen Zustand Ihres Spiels und modellieren diesen. Der gesamte logische Zustand der gesamten Welt wird mit ziemlicher Sicherheit zu viel sein, um sofort gespeichert zu werden. Sie können ihn also in kleinere Teile aufteilen, die unabhängig voneinander geladen und gespeichert werden können. Diese Teile werden oft als Brocken bezeichnet . Diese Chunks können eine zusammenhängende Welt bilden, sie können aber auch separate Ebenen / Instanzen sein. Die Terminologie variiert stark je nach Genre und gewünschter Technik.
Dann laden Sie die Teile, die von Interesse sind, dh Stücke, die sich in der Nähe des Players befinden. Zu weit entfernte Chunks werden auf der Festplatte / im permanenten Speicher gespeichert und aus dem Speicher entladen.
Und als letzten Schritt bestimmen Sie, was tatsächlich sichtbar ist, und erstellen die visuelle Darstellung des aktuellen Spielstatus und rendern ihn auf dem Bildschirm.
Natürlich würden Sie versuchen, nicht jedes Mal die gesamte visuelle Darstellung neu zu erstellen, sondern sie zwischenzuspeichern und wiederzuverwenden, wenn Sie Teile haben, die bereits konstruiert sind, aber das ist das Hauptprinzip.
Dies gilt für alle Programme, die eine Ausgabe haben. Wenn Sie ein Programm mit einer normalen GUI wie einem Texteditor schreiben, modellieren Sie wahrscheinlich das Dokument, und dann bestimmt die GUI den Status und die sichtbaren Teile des Dokuments und rendert es auf dem Bildschirm. Oder füllen Sie die Formularfelder entsprechend aus.
Das Wichtigste ist: Überlegen Sie sich zuerst, wo und wie Sie die Daten speichern (wahrscheinlich zusammen mit der Darstellung). Fast jedes Programm hat mit Datenspeicherung zu tun. Es gibt nur sehr wenige Fälle, in denen Sie keine Daten speichern.
quelle
Wie andere bereits gesagt haben, behalten Sie eine Karte (z. B. in einem Array) bei, zeichnen den sichtbaren Teil auf den Bildschirm und lesen nicht vom Bildschirm zurück.
In einigen älteren Systemen würden Sie Daten jedoch buchstäblich vom Bildschirm fernhalten. Für eine 320 x 200-Anzeige wären beispielsweise 400 x 300 Pixel Videospeicher vorhanden, und Sie würden ein Ansichtsfenster darin definieren ("Start bei X = 10 Y = 30"). Sie können also den Bildschirm scrollen, indem Sie einfach ein Register anpassen. Sie müssten nicht die hunderttausend Zyklen aufwenden, die erforderlich sind, um die Bytes zu verschieben. Sie ändern lediglich, wo die Video-Hardware mit dem Lesen beginnt.
Das NES kombiniert dies mit einem kachelbasierten System: http://wiki.nesdev.com/w/index.php/PPU_scrolling
Das NES erstellt niemals das vollständige Abbild im Speicher, da es nicht über genügend RAM verfügt. Stattdessen gibt es ein RAM-Array, das einen Kachelsatz mit zwei Bildschirmen definiert. Ein Byte pro Kacheltyp. Die Videohardware durchsucht die Kachel- und X / Y-Versatzkoordinaten, um zu entscheiden, welche Pixel an einem beliebigen Punkt angezeigt werden sollen.
quelle
Nun, wenn Sie diese Art von Frage stellen, werden Sie einen langen Weg zurücklegen müssen, um zu dem Punkt zu gelangen, an dem Sie ein Spiel machen können. Um Ihre Frage auf den Punkt zu bringen, kann das Programm den Status vieler verschiedener Dinge in Variablen speichern, die sich im Back-End Ihres Programms befinden. Schauen wir uns ein paar Beispiele an.
Mario Brothers (oder ähnliches) speichert den Status des Levels, in dem Sie sich befinden. Dies kann beinhalten, wie weit Sie gegangen sind, bevor Sie gestorben sind, ob ein Block getroffen wurde oder nicht. In einem eher objektorientierten Sinn sagt das Spiel nur "sei ein Block hier" und der Block existiert. Wenn Sie dann auf den Block klicken, ändert der Block seinen internen Status und sagt "Ich wurde getroffen". Solche Daten können auf verschiedene Arten gespeichert werden.
Ihr Textverarbeitungsprogramm speichert seine Daten in einer Datenstruktur. Jetzt gibt es viele dieser und viele Möglichkeiten, wie sie implementiert werden können, aber wahrscheinlich wird eine Baumform verwendet. In einem Baum haben Sie mindestens einen Knoten. Alles, was hinzugefügt wird, bevor es nach links geht. Alles, was danach hinzugefügt wird, geht nach rechts. Nachdem Sie drei Knoten hinzugefügt haben, hängen zwei davon am mittleren Knoten. Und der Baum kann noch größer werden, wenn überall neue Teile hinzugefügt werden, und der Baum wird sich selbst wieder aufbauen. Oder denken Sie an Shooter-Spiele, in denen Ihr Feind herumläuft. Jede von ihnen hat Variablen, die ihren Standort, ihr Leben usw. verfolgen, so dass Sie sich erinnern, dass sie verletzt wurden, wenn Sie eine verwunden haben.
All diese Dinge erfordern Kenntnisse über Datenstrukturen. Es geht weit über das hinaus, was Sie auf dem Bildschirm sehen. Ich würde vorschlagen, über Arrays, Listen, Hashes (manchmal als Wörterbücher oder Maps bezeichnet) zu lesen und dann auf Ihr Problem zurückzukommen.
Hier sind einige gute Ausgangsmaterialien:
quelle
In gewissem Maße hängt dies davon ab, wie 3D gerendert wird. OpenGL ermittelt beispielsweise automatisch Geometrien außerhalb des Bereichs -1,0, +1,0 im XY-Bildschirmbereich (Z ist komplexer, aber ähnlich). Ausgeschlossene Geometrie erzeugt niemals Fragmente (ungefähr Pixel) und wird daher niemals in tatsächliche Bilder umgewandelt, obwohl sie zum Rendern an das System gesendet wird. In jedem Fall ist es unmöglich, in einen Bereich außerhalb des Renderfensters zu schreiben (wenn alles so funktioniert, wie es sollte).
In einigen Kontexten reicht es aus, sich auf dieses Verhalten als Optimierung zu verlassen. Sie müssen jedoch noch alle Ihre Spieldaten mindestens eine Rendering-Phase (Vertex-Shader) durchlaufen, bevor die Grafikkarte erkennen kann, was sichtbar ist. In so etwas wie Skyrim wäre das unpraktisch. Nicht nur müssen Sie jede Ecke in der Welt durch die Rendering - Pipeline senden, aber Sie müssen laden jede Ecke in System / Videospeicher. Das ist ineffizient, wenn überhaupt möglich.
Viele Spiele verwenden daher CPU-basiertes Culling. Sie werden in der Regel eine Art LOD-System (Level of Detail) implementieren, bei dem die Qualität und Existenz von Vermögenswerten davon abhängt, wie wichtig sie in einem bestimmten Kontext bewertet werden. Ein pyramidenförmiges Netz ist möglicherweise eine akzeptable Annäherung für einen Berg, wenn Sie 80 km davon entfernt sind. Wenn Sie es überhaupt nicht sehen können (wie es von anderen Bergen blockiert wird), müssen Sie es nicht einmal laden. Es gibt eine Reihe komplexerer Methoden, die meines Erachtens nicht direkt für die von dieser Frage geforderte Tiefe relevant sind. Schauen Sie sich jedoch die Tessellation an, um eines der häufigsten Beispiele zu finden.
Der eigentliche Kern davon ist, dass die Visuals nur das Produkt des Spiels sind. Die tatsächlichen Daten haben nichts direkt mit dem zu tun, was Sie die meiste Zeit sehen oder nicht sehen. Die Daten werden in verschiedenen Schritten gefiltert, um überflüssige Informationen zu entfernen, bevor sie an die Stelle gelangen, an der ein Bild auf den Bildschirm geschrieben wird. Abhängig vom Design der Engine kann die Grafik extrem von der eigentlichen Spielelogik abgekoppelt werden, sofern eine 2D- und 3D-Schnittstelle für dasselbe Spiel möglich ist. Es ist sogar möglich, dass viele Spiele-Engines ohne Ausgabe ausgeführt werden. Manchmal wird dies verwendet, um die KI des Spiels zu testen.
Hier kann es allerdings kompliziert werden. In so etwas Einfachem wie einem Mario-Spiel ist es nicht zu unerschwinglich, die Bewegung aller Feinde im Level zu berechnen, auch wenn sie nicht sichtbar sind. In modernen Kontexten, was geschieht außerhalb des Bildschirms ist eine tatsächliche Frage ernsthaft in Erwägung gezogen. Wenn es mehrere ganze Städte von NPCs gibt, wie gehen Sie damit um, wie sie sich verhalten, wenn sie vollständig ausgesondert wurden - wie wenn sich der Spieler in einer anderen Stadt befindet? Möchten Sie wirklich Hunderte von NPC-Entscheidungen auf der ganzen Karte berechnen? Die Antwort ist normalerweise Nein, aber die genaue Vorgehensweise, um dies nicht zu erreichen, kann variieren und einige Auswirkungen auf das Spiel haben.
Es ist wichtig zu beachten, dass dies jetzt so funktioniert . Die alten Mario-Spiele selbst waren wahrscheinlich auf sehr unterschiedliche Weise programmiert (ich kann nicht genau sagen), da die Hardware zu diesem Zeitpunkt extrem eingeschränkt war. Das Konzept von 3D gab es damals noch nicht; Heutzutage verwenden fast alle Spiele, auch solche, die vollständig aus 2D bestehen, 3D-Rendering in irgendeiner Form, auch wenn sie nicht wissen, dass sie dies tun. Moderne Videohardware ist in erster Linie 3D, und 2D-Rendering (zumindest wenn die Hardware ordnungsgemäß verwendet wird) ignoriert lediglich die 3. Dimension.
quelle
Um Ihre Frage zu beantworten: Videospiele halten den Stand der Spielwelt in einer abstrakten Datenstruktur, die nichts mit dem Bildschirm zu tun hat. Dies wird dann nach Bedarf auf dem Bildschirm angezeigt (dh je nachdem, wo sich der Player befindet).
Spiele, die den Video-RAM direkt für Statuszwecke verwenden, gab es in den 80er Jahren im 8-Bit-Bereich, vielleicht sogar in der 16-Bit-Ära, aber es sei denn, Sie entwickeln für diese Plattform oder für einige µC, die den RAM stattdessen in KB bündeln von GB, vergiss es.
Das heißt, Sie scheinen in allem, was mit Programmierung zu tun hat, sehr neu zu sein, oder die Frage wäre nicht aufgetaucht. Ich schlage vor, Schritt für Schritt vorzugehen und zunächst sehr einfache Dinge zu programmieren. Vielleicht etwas, das nur Texteingabe / -ausgabe enthält (einfache Eingabeaufforderungen und so weiter). Um ehrlich zu sein, die Zeit, in der ich das getan habe, ist um die 30 Jahre vergangen, also habe ich keine wirklich guten Ressourcen für Sie, aber Ihre lokale Bibliothek ist vielleicht besser als das Internet, um Ihnen einen wirklich guten Start in die Programmierung zu ermöglichen.
quelle