Pygame-Tutorial

Aus Spieleprogrammierer-Wiki
(Unterschied zwischen Versionen)
Wechseln zu: Navigation, Suche
[gesichtete Version][unmarkierte Version]
K
(Die Klasse Tilemap: Kommentare)
Zeile 377: Zeile 377:
  
 
<sourcecode lang=python line start=7>
 
<sourcecode lang=python line start=7>
 +
# Die Tilemap Klasse verwaltet die Tile-Daten, die das Aussehen der Karte beschreiben.
 
class Tilemap(object):
 
class Tilemap(object):
     def __init__(self):      
+
     def __init__(self):
 +
        # Wir erstellen ein neues Tileset.
 +
        # Hier im Tutorial fügen wir manuell vier Tile-Typen hinzu.
 
         self.__tileset = Tileset.Tileset("tileset.png", (255, 0, 255), 32, 32)
 
         self.__tileset = Tileset.Tileset("tileset.png", (255, 0, 255), 32, 32)
 
         self.__tileset.addTile("grass", 0, 0)
 
         self.__tileset.addTile("grass", 0, 0)
Zeile 389: Zeile 392:
 
Was passiert: Wir erstellen eine neue Instanz der <tt>Tileset</tt>-Klasse, übergeben ein passendes Bild, den Colorkey und die Größe eines einzelne Tiles (32x32 Pixel). Danach fügen wir per Hand vier Tile-Typen hinzu.
 
Was passiert: Wir erstellen eine neue Instanz der <tt>Tileset</tt>-Klasse, übergeben ein passendes Bild, den Colorkey und die Größe eines einzelne Tiles (32x32 Pixel). Danach fügen wir per Hand vier Tile-Typen hinzu.
  
<sourcecode lang=python line start=15>
+
<sourcecode lang=python line start=18>
 +
        # Festlegen der Startposition der Kamera. Hier (0, 0).
 
         self.__cameraX = 0
 
         self.__cameraX = 0
 
         self.__cameraY = 0
 
         self.__cameraY = 0
           
+
       
         self.__width = 10
+
        # Die Größe der Maps in Tiles.
         self.__height = 10
+
         self.__width = 30
 +
         self.__height = 25
  
 +
        # Erstellen einer leeren Liste für die Tile Daten.
 
         self.__tiles = list()
 
         self.__tiles = list()
 
</sourcecode>
 
</sourcecode>
Zeile 402: Zeile 408:
  
 
<sourcecode lang=python line start=23>
 
<sourcecode lang=python line start=23>
         for i in range(0, self.__width):
+
        # Manuelles befüllen der Tile-Liste:
 +
        # Jedes Feld bekommt ein zufälliges Tile zugewiesen.
 +
         for i in range(0, self.__height):
 
             self.__tiles.append(list())
 
             self.__tiles.append(list())
             for j in range(0, self.__height):
+
             for j in range(0, self.__width):
 
                 x = random.randint(0, 4)
 
                 x = random.randint(0, 4)
 
                 if x == 0:
 
                 if x == 0:
Zeile 416: Zeile 424:
 
</sourcecode>
 
</sourcecode>
  
Mit diesem Code endet der Konstruktor. Wir befüllen hier die Liste der Tiles. Dazu verwenden wir zwei <tt>for</tt>-Schleifen, die die Breite bzw. Höhe der Karte durchlaufen. Für jedes <tt>i</tt> (eine Zeile) erstellen wir eine neue Liste, in der wir die Spalten mit einem Zufallswert füllen (hier gibt es eine Auswahl zwischen den vier hinzugefügten Tiles). Standardmäßig sollte hier jedes Feld auf <tt>""</tt> oder <tt>None</tt> gesetzt werden, oder man liest gleich alle Positionsdaten aus einer Datei.
+
Mit diesem Code endet der Konstruktor. Wir befüllen hier die Liste der Tiles. Dazu verwenden wir zwei <tt>for</tt>-Schleifen, die die Höhe bzw. Breite der Karte durchlaufen. Für jedes <tt>i</tt> (eine Zeile) erstellen wir eine neue Liste, die wir mit Zufallswerten füllen (hier gibt es eine Auswahl zwischen den vier hinzugefügten Tiles). Standardmäßig sollte hier jedes Feld auf <tt>""</tt> oder <tt>None</tt> gesetzt werden, oder man liest gleich alle Positionsdaten aus einer Datei.
 
Schauen wir uns die komplizierteste, aber auch wichtigste Funktion an: Die Funktion <tt>render</tt>, die die Karte auf den Bildschirm (oder eine beliebige andere Surface rendert):
 
Schauen wir uns die komplizierteste, aber auch wichtigste Funktion an: Die Funktion <tt>render</tt>, die die Karte auf den Bildschirm (oder eine beliebige andere Surface rendert):
  
<sourcecode lang=python line start=37>
+
<sourcecode lang=python line start=45>
 +
    # Hier rendern wir den sichtbaren Teil der Karte.
 
     def render(self, screen):
 
     def render(self, screen):
 +
        # Zeilenweise durch die Tiles durchgehen.
 
         for y in range(0, int(screen.get_height() / self.__tileset.getTileHeight()) + 1):
 
         for y in range(0, int(screen.get_height() / self.__tileset.getTileHeight()) + 1):
 +
            # Die Kamera Position mit einbeziehen.
 
             ty = y + self.__cameraY
 
             ty = y + self.__cameraY
 
             if ty >= self.__height or ty < 0:
 
             if ty >= self.__height or ty < 0:
 
                 continue
 
                 continue
             col = self.__tiles[ty]
+
             # Die aktuelle Zeile zum einfacheren Zugriff speichern.
 +
            line = self.__tiles[ty]
 +
            # Und jetzt spaltenweise die Tiles rendern.
 
             for x in range(0, int(screen.get_width() / self.__tileset.getTileWidth()) + 1):
 
             for x in range(0, int(screen.get_width() / self.__tileset.getTileWidth()) + 1):
 +
                # Auch hier müssen wir die Kamera beachten.
 
                 tx = x + self.__cameraX
 
                 tx = x + self.__cameraX
 
                 if tx >= self.__width or tx < 0:
 
                 if tx >= self.__width or tx < 0:
 
                     continue
 
                     continue
                 tilename = col[tx]
+
                # Wir versuchen, die Daten des Tiles zu bekommen.
 +
                 tilename = line[tx]
 
                 tile = self.__tileset.getTile(tilename)
 
                 tile = self.__tileset.getTile(tilename)
 +
                # Falls das nicht fehlschlägt können wir das Tile auf die screen-Surface blitten.
 
                 if tile is not None:
 
                 if tile is not None:
 
                     screen.blit(self.__tileset.getImage(), (x * self.__tileset.getTileWidth(), y * self.__tileset.getTileHeight()), tile.getRect())
 
                     screen.blit(self.__tileset.getImage(), (x * self.__tileset.getTileWidth(), y * self.__tileset.getTileHeight()), tile.getRect())
Zeile 438: Zeile 454:
 
Wir werden die Funktion Zeile für Zeile durchgehen:
 
Wir werden die Funktion Zeile für Zeile durchgehen:
  
# Wir wollen nur so viele Tiles rendern, wie auf den Bildschirm passen. Um das herauszufinden, dividieren wir einfach die Höhe des Bildschirms durch die Höhe der Tiles. Um schwarze Rahmen zu vermeiden, addieren wir noch 1 hinzu.
+
* Zeile 48: Wir wollen nur so viele Tiles rendern, wie auf den Bildschirm passen. Um das herauszufinden, dividieren wir einfach die Höhe des Bildschirms durch die Höhe der Tiles. Um schwarze Rahmen zu vermeiden, addieren wir noch 1 hinzu.
# Die y-Position auf dem Bildschirm ist nicht gleich der Position in unserer Tile-Liste, diese Position speichern wir in der Variable <tt>ty</tt>. Um den korrekten Wert zu erhalten, müssen wir nur die Kameraposition hinzuaddieren.
+
* Zeile 50: Die y-Position auf dem Bildschirm ist nicht gleich der Position in unserer Tile-Liste, diese Position speichern wir in der Variable <tt>ty</tt>. Um den korrekten Wert zu erhalten, müssen wir nur die Kameraposition hinzuaddieren.
# Wir testen, ob wir uns überhaupt noch innerhalb der Map-Grenze befinden. Wenn nicht, überspringen wir das aktuelle Tile.
+
* Zeile 51: Wir testen, ob wir uns überhaupt noch innerhalb der Map-Grenze befinden. Wenn nicht, überspringen wir das aktuelle Tile.
# Die Tiles werden spaltenweise gerendert, hier speichern wir die aktuelle Spalte.
+
* Zeile 54: Die Tiles werden gleich spaltenweise gerendert, hier speichern wir die aktuelle Zeile.
# In der zweiten <tt>for</tt>-Schleife durchlaufen wie die Breite des Bildschrims.
+
* Zeile 56: In der zweiten <tt>for</tt>-Schleife durchlaufen wie die Breite des Bildschrims.
# Auch die x-Position wird berechnet, genau wie die y-Position.
+
* Zeile 58: Auch die x-Position wird berechnet, genau wie die y-Position.
# Natürlich muss auch hier getestet werden, ob wir die Grenzen der Map einhalten.
+
* Zeile 59: Natürlich muss auch hier getestet werden, ob wir die Grenzen der Map einhalten.
# Als Nächstes holen wir uns den Namen des Tiles, das wir rendern wollen, aus der aktuellen Spalte.
+
* Zeile 62: Als Nächstes holen wir uns den Namen des Tiles, das wir rendern wollen, aus der aktuellen Zeile.
# Über das Tileset erhalten wir das Tile, oder <tt>None</tt>, wenn keines existiert.
+
* Zeile 63: Über das Tileset erhalten wir das Tile, oder <tt>None</tt>, wenn keines existiert.
# Und wenn wir ein Tile haben, wird dieses auf den Bildschrim gerendert.
+
* Zeile 65: Und wenn wir ein Tile haben, wird dieses auf den Bildschrim gerendert.
# In der Tilemap ist das Bild mit allen Tiles gespeichert, das ist unsere Quelle für die <tt>blit</tt>-Funktion. Die Positionen multiplizieren wir noch mit der Größe der Tiles, um keine Überschneidung mit dem vorherigen Tile zu bekommen. Zuletzt der wichtigste Parameter: Der Ausschnitt, der von dem Bild verwendet werden soll, ist in der Tile-Klasse gespeichert.
+
* Zeile 66: In der Tilemap ist das Bild mit allen Tiles gespeichert, das ist unsere Quelle für die <tt>blit</tt>-Funktion. Die Positionen multiplizieren wir noch mit der Größe der Tiles, um keine Überschneidung mit dem vorherigen Tile zu bekommen. Zuletzt der wichtigste Parameter: Der Ausschnitt, der von dem Bild verwendet werden soll, ist in der Tile-Klasse gespeichert.
  
 
Damit sind wir fast fertig.
 
Damit sind wir fast fertig.
 
Die Veränderung der Kameraposition ist im Gegensatz zur letzten Funktion sehr einfach:
 
Die Veränderung der Kameraposition ist im Gegensatz zur letzten Funktion sehr einfach:
  
<sourcecode lang=python line start=53>
+
<sourcecode lang=python line start=69>
 +
    # Tastendrücke verarbeiten:
 
     def handleInput(self, key):
 
     def handleInput(self, key):
 +
        # Pfeiltaste links oder rechts erhöht bzw. verringert die X-Position der Kamera.
 
         if key == pygame.K_LEFT:
 
         if key == pygame.K_LEFT:
 
             self.__cameraX += 1
 
             self.__cameraX += 1
 
         if key == pygame.K_RIGHT:
 
         if key == pygame.K_RIGHT:
 
             self.__cameraX -= 1
 
             self.__cameraX -= 1
 
+
       
 +
        # Und das gleiche nochmal für die Y-Position.
 
         if key == pygame.K_UP:
 
         if key == pygame.K_UP:
 
             self.__cameraY += 1
 
             self.__cameraY += 1

Version vom 28. Oktober 2011, 17:22 Uhr

Klicke hier, um diese Version anzusehen.

Meine Werkzeuge
Namensräume
Varianten
Aktionen
Navigation
Werkzeuge