Das Projekt zeigt auf, wie man ein 2D-Spiel auf dem STM32F429 selbst erstellen kann.
Screenshot vom Spiel :
MAP :
Die MAP (Karte vom Spielfeld) wird am PC mit dem kostenlosen Mapeditor “Tiled” gezeichnet. Diese MAP besteht aus einzelnen Kacheln (Tiles) die alle die gleiche Größe haben (z.B. 32 x 32 Pixel). Abgespeichert in der CPU wird zum Schluss nicht die ganze MAP sondern nur das Tileset (das ist ein Bild von allen Kacheln die benutzt werden) konvertiert als C-File und die Daten der MAP (das ist ein Array das per Copy&Paste in das C-File übertragen werden kann.
Link zum Mapeditor : http://www.mapeditor.org/
Hier ein Beispiel einer MAP mit 40 x 30 Tiles:
und hier das Tileset dazu :
Während dem Programmlauf wird der Kartenausschnitt der auf dem Display angezeigt werden muss von der CPU aus den einzelnen Tiles zusammengebaut.
Player-Sprite :
Für den Spieler muss auch ein Tileset in Form eines Bildes (konvertiert als C-File) vorhanden sein und zwar eines in dem alle Bewegungsrichtungen mit Animation abgebildet sind.
hier ein Beispiel :
Die CPU muss dann nur wissen, wieviele Bilder pro Richtung vorhanden sind und welche die Startbilder von “hoch”, “runter”, “rechts”, “links” sind.
Terrain-Daten :
Damit der Spieler nicht durch Wände laufen kann, muss die Software wissen, welche Tiles in der MAP vom Spieler begehbar sind und welche nicht. Dafür ist das Terrain-File da (das wird von Tiled.exe aus dem Tileset der MAP erstellt und kann (gewandelt als Binärfile) in das Flash kopiert werden. Die Software parst die Daten daraus automatisch.
Gegner-Sprites :
Diese werden genau wie der Spieler-Sprite als Tileset hinzugefügt. Die Anzahl ist beliebig und nur durch den Speicherplatz begrenzt.
hier ein minimal Beispiel für einen Magier und einen Ritter :
in diesen Tilesets gibt es pro Richtung nur zwei Bilder, die Bewegungs-Animation ist damit nicht besonders gut. Es soll hier aber nur als Beispiel dienen und kann auch mit einem anderen Tileset entsprechend verbessert werden.
Die Anzahl der Objekte die das Tileset benutzen kann auch beliebig hoch sein. Es ist also möglich z.B. 10 Ritter und 20 Magier über die MAP laufen zu lassen.
Waypoints :
Wegpunkte dienen zum bewegen der Gegner-Sprites über die Karte. Jeder Wegpunkt sagt dem Objekt in welche Richtung es sich bewegen soll (wie weit und wie schnell) und welcher Wegpunkt als nächstes benutzt werden soll, wenn das Ziel erreicht ist.
Mit zwei Wegpunkten kann man also eine unendliche rechts/links Bewegung realisieren :
1. MOVE_RIGHT, Distance=100, Speed=5, Next=2 2. MOVE_LEFT, Distance=100, Speed=5, Next=1
Es können beliebig viele Wegpunkte gesetzt werden und mehrere Sprites können die gleichen Wegpunkte benutzen. Durch verschiedene Startpunkte werden diese dann unterschiedliche Gebiete ablaufen.
User-Einstellungen :
Ich habe alle Stellen in denen der User Änderungen vornehmen kann/muss
z.B. wenn er eine eigene MAP benutzen will mit dem Kommantar : ”[USER_xxx]” gekennzeichnet
hier eine Liste davon und in welchen Files diese stehen :
stm32_ub_tiled_map.c // USER_M01 = Array von MAP_DATA stm32_ub_tiled_map.h // USER_M02 = Tileset der MAP // USER_M03 = Einstellung der MAP // USER_M04 = Einstellung vom Screen // USER_M05 = Startpositionen der MAP // USER_M06 = Minimum Abstand vom Player zum Rand // USER_M07 = Hintergrundfarbe vom Display stm32_ub_tiled_obj.c // USER_O01 = Tilesets aller Objekt-Typen // USER_O02 = Animations-Daten aller Objekt-Typen // USER_O03 = Collision-Typ aller Objekt-Typen // USER_O04 = Liste aller Objekte // USER_O05 = Startpositionen aller Objekte // USER_O06 = Liste aller Wegpunkte stm32_ub_tiled_obj.h // USER_O07 = Aufzaehlung der verschiedenen Objekt-Typen // USER_O08 = Images der Tileset aller Objekt-Typen // USER_O09 = Anzahl aller Objekte stm32_ub_tiled_player.c // USER_P01 = Tileset vom Player // USER_P02 = Animations-Daten vom Player stm32_ub_tiled_player.h // USER_P03 = Image vom Tileset vom Player // USER_P04 = Startposition vom Player // USER_P05 = Zielposition vom Player stm32_ub_tiled_terrain.c // USER_T01 = Terrain Daten fuer Player stm32_ub_tiled_terrain.h // USER_T02 = Terrain-File der MAP
ich habe alles mit Kommentaren versehen und hoffe das man damit zurechtkommt
User-Programm :
Das Hauptprogramm vom User kommt mit wenigen Zeilen aus :
1 2 3 4 | UB_Tiled_Init(true); while(1) { UB_Tiled_Do(); } |
Die “Init-Funktion” liefert ein “Success” wenn beim internen Check kein Fehler gefunden wurde. Und die “Tiled_Do” kümmert sich um das anzeigen vom Spiel und bewegen aller Objekte.
User-Callbacks :
Es gibt 4 CallBack-Funktionen die unter bestimmten Bedingungen aufgerufen werden und die vom User ausprogrammiert werden müssen.
1. "UB_Tiled_1ms_ISR_CallBack" : diese Funktion wird jede ms aufgerufen 2. "UB_Tiled_Input_Device_CallBack" : diese Funktion wird zyklisch alle 30ms aufgerufen 3. "UB_Tiled_LCD_CallBack" : diese Funktion wird vor dem ScreenRefresh aufgerufen 4. "UB_Tiled_Event_CallBack" : diese Funktion wird beim eintreten eines "Events" aufgerufen
UB_Tiled_1ms_ISR_CallBack :
Der User kann diese Funktion nutzen um zeitgesteuerte Ereignisse zu realisieren.
Im Beispiel wird hier das USB-Keyboard gepollt.
UB_Tiled_Input_Device_CallBack :
Diese Funkion ist dazu da ein Eingabegerät auszulesen und z.B. die Spielerbewegung damit zu steuern.
Im Beispiel wird je nach Tastendruck die “MovePlayer” Funktion gestartet um den Spielen ein paar Pixel zu bewegen.
UB_Tiled_LCD_CallBack :
Weil der Screen von Tiled verwaltet wird, muss diese Funktion benutzt werden, wenn der User auch was auf dem Bildschirm darstellen will. Zugriffe auf das Display außerhalb dieser Funktion funktionieren nicht richtig.
UB_Tiled_Event_CallBack :
Das ist die wichtigste Funktion für die Spielmechanik. Sie wird immer aufgerufen wenn ein “Event” aufgetreten ist. Welches Event der Grund für den Aufruf war, steht in der Variabeln : “TILED.event” und kann 4 Ursachen haben :
TILED_EVENT_COLLECTABLE_COLLISION : Der Spieler ist mit einem Sammelbaren Objekt kollidiert TILED_EVENT_DEADLY_COLLISION : Der Spieler ist mit einem tödlichen Objekt kollidiert TILED_EVENT_DEADLY_TERRAIN : Der Spieler steht auf einem tödlichen Terrain-Tile TILED_EVENT_GOAL : Der Spieler hat das Ziel-Tile erreicht
Je nach Event muss programmiert werden was passieren soll.
Bei Kollisionen kann über die Funktionen :
“UB_Tiled_CheckCollectableCollision” bzw “UB_Tiled_CheckDeadlyCollision”
die Objekt-Nummer und der Objekt-Typ ermittelt werden.
User-Funktionen :
hier eine Liste von ein paar nützlichen Funktionen, die der User aufrufen kann :
UB_Tiled_MovePlayer() : bewegt den Player ein paar Pixel in eine Richtung UB_Tiled_DisableObjekt() : deaktiviert ein Objekt UB_Tiled_EnableObjekt() : enabled ein Objekt
Die Funktion “DisbaleObjekt” kann z.B. bei Sammelbaren Objekten benutzt werden damit sie nach dem “einsammeln” vom Spielfeld verschwinden.
Software :
Aktuelle Version : 1.00 (vom 21.09.2014)
Hier der komplette CooCox-Projektordner zum download :
Hier die benutzten Tilesets als Bilder und die MAP als TMX-File :