Pygame-Tutorial

Aus Spieleprogrammierer-Wiki
(Unterschied zwischen Versionen)
Wechseln zu: Navigation, Suche
[gesichtete Version][gesichtete Version]
K (Tippfehler im Absatz "Die Nachrichtenschleife" korrigiert)
(Zusammenbasteln)
 
(11 dazwischenliegende Versionen von einem Benutzer werden nicht angezeigt)
Zeile 7: Zeile 7:
  
 
=== Wo bekomme ich Pygame? ===
 
=== Wo bekomme ich Pygame? ===
Die offizielle Pygame-Webseite findet sich unter http://www.pygame.org/. Dort gibt es auch immer die jeweils neuste Version, die Dokumentation, Tutorials und vieles mehr. Unter http://www.python.org/ gibt es die Python-Interpreter, und alle, die Python noch nicht kennen, finden dort alles, um es zu lernen.
+
Die offizielle Pygame-Webseite findet sich unter http://www.pygame.org/. Dort gibt es auch immer die jeweils neuste Version, die Dokumentation, Tutorials und vieles mehr. Unter http://www.python.org/ gibt es die Python-Interpreter, und alle, die Python noch nicht kennen, finden dort alles, um es zu lernen. In diesem Tutorial wird Pygame Version 1.9.2 und Python Version 2.7.9 verwendet.
  
 
== Pygame einrichten ==
 
== Pygame einrichten ==
Zeile 208: Zeile 208:
  
 
<sourcecode lang=python>
 
<sourcecode lang=python>
if image.get_alpha() == None:
+
if image.get_alpha() is None:
 
     image = image.convert()
 
     image = image.convert()
 
else:
 
else:
Zeile 228: Zeile 228:
 
<sourcecode lang=python line start=5>
 
<sourcecode lang=python line start=5>
 
# Hilfsfunktion, um ein Bild zu laden:
 
# Hilfsfunktion, um ein Bild zu laden:
def loadImage(filename, colorkey = None):
+
def loadImage(filename, colorkey=None):
 
     # Pygame das Bild laden lassen.
 
     # Pygame das Bild laden lassen.
 
     image = pygame.image.load(filename)
 
     image = pygame.image.load(filename)
Zeile 234: Zeile 234:
 
     # Das Pixelformat der Surface an den Bildschirm (genauer: die screen-Surface) anpassen.
 
     # Das Pixelformat der Surface an den Bildschirm (genauer: die screen-Surface) anpassen.
 
     # Dabei die passende Funktion verwenden, je nach dem, ob wir ein Bild mit Alpha-Kanal haben oder nicht.
 
     # Dabei die passende Funktion verwenden, je nach dem, ob wir ein Bild mit Alpha-Kanal haben oder nicht.
     if image.get_alpha() == None:
+
     if image.get_alpha() is None:
 
         image = image.convert()
 
         image = image.convert()
 
     else:
 
     else:
Zeile 244: Zeile 244:
 
         if colorkey is -1:
 
         if colorkey is -1:
 
             colorkey = image.get_at((0,0))
 
             colorkey = image.get_at((0,0))
 
 
         image.set_colorkey(colorkey, pygame.RLEACCEL)
 
         image.set_colorkey(colorkey, pygame.RLEACCEL)
  
Zeile 294: Zeile 293:
 
     # Im Konstruktor speichern wir den Namen
 
     # Im Konstruktor speichern wir den Namen
 
     # und erstellen das Rect (den Bereich) dieses Typs auf der Tileset-Grafik.
 
     # und erstellen das Rect (den Bereich) dieses Typs auf der Tileset-Grafik.
     def __init__(self, name, startX, startY, width, height):
+
     def __init__(self, name, start_x, start_y, width, height):
         self.__name = name
+
         self.name = name
         self.__rect = pygame.rect.Rect(startX, startY, width, height)
+
         self.rect = pygame.rect.Rect(start_x, start_y, width, height)
 
+
    def getName(self):
+
        return self.__name
+
 
+
    def getRect(self):
+
        return self.__rect
+
 
</sourcecode>
 
</sourcecode>
  
Wir speichern als erstes den Namen bzw. die ID des Tile-Typs in der privaten Variable <tt>__name</tt>. Über die Funktion <tt>getName</tt> können wir ihn wieder auslesen.
+
Wir speichern als erstes den Namen bzw. die ID des Tile-Typs in der Variable <tt>name</tt>.
 
In einem <tt>Rect</tt> speichern wir gleichzeitig die Position und die Größe dieses Types in der Tileset-Grafik.
 
In einem <tt>Rect</tt> speichern wir gleichzeitig die Position und die Größe dieses Types in der Tileset-Grafik.
 
Wir gehen gleich zur nächsten Klasse weiter, der <tt>Tileset</tt>-Klasse, in der deutlich mehr passiert.
 
Wir gehen gleich zur nächsten Klasse weiter, der <tt>Tileset</tt>-Klasse, in der deutlich mehr passiert.
Zeile 313: Zeile 306:
 
Zuletzt wird noch ein Dictionary für die Tile-Typen angelegt, das aber erst einmal leer bleibt.
 
Zuletzt wird noch ein Dictionary für die Tile-Typen angelegt, das aber erst einmal leer bleibt.
  
<sourcecode lang=python line start=8>
+
<sourcecode lang=python line start=7>
 
# Verwaltet die Tileset Grafik und eine Liste mit Tile-Typen.
 
# Verwaltet die Tileset Grafik und eine Liste mit Tile-Typen.
 
class Tileset(object):
 
class Tileset(object):
 
     # Im Konstruktor laden wir die Grafik
 
     # Im Konstruktor laden wir die Grafik
 
     # und erstellen ein leeres Dictionary für die Tile-Typen.
 
     # und erstellen ein leeres Dictionary für die Tile-Typen.
     def __init__(self, image, colorkey, tileWidth, tileHeight):
+
     def __init__(self, image, colorkey, tile_width, tile_height):
         self.__image = Utils.loadImage(image, colorkey)
+
         self.image = Utils.load_image(image, colorkey)
         self.__tileWidth = tileWidth
+
         self.tile_width = tile_width
         self.__tileHeight = tileHeight
+
         self.tile_height = tile_height
 
+
         self.tile_types = dict()
         self.__tileTypes = dict()
+
 
</sourcecode>
 
</sourcecode>
  
 
Die <tt>loadImage</tt>-Funktion haben wir in das Modul <tt>Utils</tt> ausgelagert. Also das <tt>import Utils</tt> am Anfang des Moduls nicht vergessen.
 
Die <tt>loadImage</tt>-Funktion haben wir in das Modul <tt>Utils</tt> ausgelagert. Also das <tt>import Utils</tt> am Anfang des Moduls nicht vergessen.
 
Um das Bild anzeigen zu können, bzw. Ausschnitte daraus, erstellen wir eine Funktion <tt>getImage</tt>, die das Bild zurückliefert. Außerdem ermöglichen wir es, das Bild gegen eine neues auszutauschen. Wenn während des Spiels so ein Tausch des Tileset-Bildes öfter vorkommen soll, ist es aber ratsamer, alle Bilder zum Beispiel in einer Liste zu speichern und nicht jedes Mal neu zu laden.
 
 
<sourcecode lang=python line start=19>
 
    def getImage(self):
 
        return self.__image
 
 
    def setImage(self, image, colorkey):
 
        self.__image = Utils.loadImage(image, colorkey)
 
</sourcecode>
 
 
Ebenfalls sehr einfach sind die drei Funktionen, um die Größe der Tiles zu bekommen:
 
 
<sourcecode lang=python line start=25>
 
    def getTileWidth(self):
 
        return self.__tileWidth
 
 
    def getTileHeight(self):
 
        return self.__tileHeight
 
 
    def getTileSize(self):
 
        return (self.__tileWidth, self.__tileHeight)
 
</sourcecode>
 
  
 
Kommen wir zur wichtigsten Funktion: Das Hinzufügen eines Tile-Typen. Das ist im Grunde auch nicht sonderlich kompliziert. Wir fügen einfach eine neue Instanz der <tt>TileType</tt>-Klasse in unser Dictionary ein, mit passenden Parametern:
 
Kommen wir zur wichtigsten Funktion: Das Hinzufügen eines Tile-Typen. Das ist im Grunde auch nicht sonderlich kompliziert. Wir fügen einfach eine neue Instanz der <tt>TileType</tt>-Klasse in unser Dictionary ein, mit passenden Parametern:
  
<sourcecode lang=python line start=34>
+
<sourcecode lang=python line start=17>
 
     # Neuen Tile-Typ hinzufügen.
 
     # Neuen Tile-Typ hinzufügen.
     def addTile(self, name, startX, startY):
+
     def add_tile(self, name, start_x, start_y):
         self.__tileTypes[name] = TileType.TileType(name, startX, startY, self.__tileWidth, self.__tileHeight)
+
         self.tile_types[name] = TileType.TileType(name, start_x, start_y, self.tile_width, self.tile_height)
 
</sourcecode>
 
</sourcecode>
  
 
Auch das Abfragen eines Types ist leicht, einfach über den Key den passenden Wert zurückliefern:
 
Auch das Abfragen eines Types ist leicht, einfach über den Key den passenden Wert zurückliefern:
  
<sourcecode lang=python line start=38>
+
<sourcecode lang=python line start=21>
 
     # Versuchen, einen Tile-Type über seinen Namen in der Liste zu finden.
 
     # Versuchen, einen Tile-Type über seinen Namen in der Liste zu finden.
 
     # Falls der Name nicht existiert, geben wir None zurück.
 
     # Falls der Name nicht existiert, geben wir None zurück.
     def getTile(self, name):
+
     def get_tile(self, name):
 
         try:
 
         try:
             return self.__tileTypes[name]
+
             return self.tile_types[name]
 
         except KeyError:
 
         except KeyError:
 
             return None
 
             return None
Zeile 384: Zeile 353:
 
         # Wir erstellen ein neues Tileset.
 
         # Wir erstellen ein neues Tileset.
 
         # Hier im Tutorial fügen wir manuell vier Tile-Typen hinzu.
 
         # 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.add_tile("grass", 0, 0)
         self.__tileset.addTile("mud", 32, 0)
+
         self.tileset.add_tile("mud", 32, 0)
         self.__tileset.addTile("water", 64, 0)
+
         self.tileset.add_tile("water", 64, 0)
         self.__tileset.addTile("block", 0, 32)
+
         self.tileset.add_tile("block", 0, 32)
 
</sourcecode>
 
</sourcecode>
  
Zeile 396: Zeile 365:
 
<sourcecode lang=python line start=18>
 
<sourcecode lang=python line start=18>
 
         # Festlegen der Startposition der Kamera. Hier (0, 0).
 
         # Festlegen der Startposition der Kamera. Hier (0, 0).
         self.__cameraX = 0
+
         self.camera_x = 0
         self.__cameraY = 0
+
         self.camera_y = 0
 
          
 
          
 
         # Die Größe der Maps in Tiles.
 
         # Die Größe der Maps in Tiles.
         self.__width = 30
+
         self.width = 30
         self.__height = 25
+
         self.height = 25
  
         # Erstellen einer leeren Liste für die Tile-Daten.
+
         # Erstellen einer leeren Liste für die Tile Daten.
         self.__tiles = list()
+
         self.tiles = list()
 
</sourcecode>
 
</sourcecode>
  
 
Wir legen Standardwerte für die Position der Kamera und die Größe der Karte fest. Die Größe der Karten wird in Tiles angegeben, nicht in Pixeln. Auch hier gilt wieder: Die Größe kann flexibler gestaltet werden, etwa durch einen Parameter in dem Konstruktor oder eine Datei. Zudem erstellen wir eine noch leere Liste, in der wir später die Tiles speichern wollen.
 
Wir legen Standardwerte für die Position der Kamera und die Größe der Karte fest. Die Größe der Karten wird in Tiles angegeben, nicht in Pixeln. Auch hier gilt wieder: Die Größe kann flexibler gestaltet werden, etwa durch einen Parameter in dem Konstruktor oder eine Datei. Zudem erstellen wir eine noch leere Liste, in der wir später die Tiles speichern wollen.
  
<sourcecode lang=python line start=23>
+
<sourcecode lang=python line start=29>
 
         # Manuelles Befüllen der Tile-Liste:
 
         # Manuelles Befüllen der Tile-Liste:
 
         # Jedes Feld bekommt ein zufälliges Tile zugewiesen.
 
         # Jedes Feld bekommt ein zufälliges Tile zugewiesen.
         for i in range(0, self.__height):
+
         for i in range(0, self.height):
             self.__tiles.append(list())
+
             self.tiles.append(list())
             for j in range(0, self.__width):
+
             for j in range(0, self.width):
 
                 x = random.randint(0, 4)
 
                 x = random.randint(0, 4)
 
                 if x == 0:
 
                 if x == 0:
                     self.__tiles[i].append("grass")
+
                     self.tiles[i].append("grass")
 
                 elif x == 1:
 
                 elif x == 1:
                     self.__tiles[i].append("water")
+
                     self.tiles[i].append("water")
 
                 elif x == 2:
 
                 elif x == 2:
                     self.__tiles[i].append("mud")
+
                     self.tiles[i].append("mud")
 
                 else:
 
                 else:
                     self.__tiles[i].append("block")
+
                     self.tiles[i].append("block")
 
</sourcecode>
 
</sourcecode>
  
Zeile 433: Zeile 402:
 
     def render(self, screen):
 
     def render(self, screen):
 
         # Zeilenweise durch die Tiles durchgehen.
 
         # 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.tile_height) + 1):
             # Die Kameraposition mit einbeziehen.
+
             # Die Kamera Position mit einbeziehen.
             ty = y + self.__cameraY
+
             ty = y + self.camera_y
             if ty >= self.__height or ty < 0:
+
             if ty >= self.height or ty < 0:
 
                 continue
 
                 continue
 
             # Die aktuelle Zeile zum einfacheren Zugriff speichern.
 
             # Die aktuelle Zeile zum einfacheren Zugriff speichern.
             line = self.__tiles[ty]
+
             line = self.tiles[ty]
 
             # Und jetzt spaltenweise die Tiles rendern.
 
             # 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.tile_width) + 1):
 
                 # Auch hier müssen wir die Kamera beachten.
 
                 # Auch hier müssen wir die Kamera beachten.
                 tx = x + self.__cameraX
+
                 tx = x + self.camera_x
                 if tx >= self.__width or tx < 0:
+
                 if tx >= self.width or tx < 0:
 
                     continue
 
                     continue
 
                 # Wir versuchen, die Daten des Tiles zu bekommen.
 
                 # Wir versuchen, die Daten des Tiles zu bekommen.
 
                 tilename = line[tx]
 
                 tilename = line[tx]
                 tile = self.__tileset.getTile(tilename)
+
                 tile = self.tileset.get_tile(tilename)
 
                 # Falls das nicht fehlschlägt können wir das Tile auf die screen-Surface blitten.
 
                 # 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.image, (x * self.tileset.tile_width, y * self.tileset.tile_height), tile.rect)
 
</sourcecode>
 
</sourcecode>
  
Zeile 473: Zeile 442:
 
<sourcecode lang=python line start=69>
 
<sourcecode lang=python line start=69>
 
     # Tastendrücke verarbeiten:
 
     # Tastendrücke verarbeiten:
     def handleInput(self, key):
+
     def handle_input(self, key):
 
         # Pfeiltaste links oder rechts erhöht bzw. verringert die x-Position der Kamera.
 
         # 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.camera_x += 1
 
         if key == pygame.K_RIGHT:
 
         if key == pygame.K_RIGHT:
             self.__cameraX -= 1
+
             self.camera_x -= 1
 
          
 
          
 
         # Und das gleiche nochmal für die y-Position.
 
         # Und das gleiche nochmal für die y-Position.
 
         if key == pygame.K_UP:
 
         if key == pygame.K_UP:
             self.__cameraY += 1
+
             self.camera_y += 1
 
         if key == pygame.K_DOWN:
 
         if key == pygame.K_DOWN:
             self.__cameraY -= 1
+
             self.camera_y -= 1
 
</sourcecode>
 
</sourcecode>
  
Zeile 498: Zeile 467:
  
 
<sourcecode lang=python line start=53>
 
<sourcecode lang=python line start=53>
                 map.handleInput(event.key)
+
                 map.handle_input(event.key)
 
</sourcecode>
 
</sourcecode>
  
Zeile 517: Zeile 486:
  
 
# Hilfsfunktion, um ein Bild zu laden:
 
# Hilfsfunktion, um ein Bild zu laden:
def loadImage(filename, colorkey = None):
+
def load_image(filename, colorkey=None):
 
     # Pygame das Bild laden lassen.
 
     # Pygame das Bild laden lassen.
 
     image = pygame.image.load(filename)
 
     image = pygame.image.load(filename)
Zeile 523: Zeile 492:
 
     # Das Pixelformat der Surface an den Bildschirm (genauer: die screen-Surface) anpassen.
 
     # Das Pixelformat der Surface an den Bildschirm (genauer: die screen-Surface) anpassen.
 
     # Dabei die passende Funktion verwenden, je nach dem, ob wir ein Bild mit Alpha-Kanal haben oder nicht.
 
     # Dabei die passende Funktion verwenden, je nach dem, ob wir ein Bild mit Alpha-Kanal haben oder nicht.
     if image.get_alpha() == None:
+
     if image.get_alpha() is None:
 
         image = image.convert()
 
         image = image.convert()
 
     else:
 
     else:
Zeile 533: Zeile 502:
 
         if colorkey is -1:
 
         if colorkey is -1:
 
             colorkey = image.get_at((0,0))
 
             colorkey = image.get_at((0,0))
 
 
         image.set_colorkey(colorkey, pygame.RLEACCEL)
 
         image.set_colorkey(colorkey, pygame.RLEACCEL)
  
Zeile 549: Zeile 517:
 
     # Im Konstruktor speichern wir den Namen
 
     # Im Konstruktor speichern wir den Namen
 
     # und erstellen das Rect (den Bereich) dieses Typs auf der Tileset-Grafik.
 
     # und erstellen das Rect (den Bereich) dieses Typs auf der Tileset-Grafik.
     def __init__(self, name, startX, startY, width, height):
+
     def __init__(self, name, start_x, start_y, width, height):
         self.__name = name
+
         self.name = name
         self.__rect = pygame.rect.Rect(startX, startY, width, height)
+
         self.rect = pygame.rect.Rect(start_x, start_y, width, height)
 
+
    def getName(self):
+
        return self.__name
+
 
+
    def getRect(self):
+
        return self.__rect
+
 
</sourcecode>
 
</sourcecode>
  
Zeile 565: Zeile 527:
  
 
import pygame
 
import pygame
 
 
import Utils
 
import Utils
 
import TileType
 
import TileType
Zeile 573: Zeile 534:
 
     # Im Konstruktor laden wir die Grafik
 
     # Im Konstruktor laden wir die Grafik
 
     # und erstellen ein leeres Dictionary für die Tile-Typen.
 
     # und erstellen ein leeres Dictionary für die Tile-Typen.
     def __init__(self, image, colorkey, tileWidth, tileHeight):
+
     def __init__(self, image, colorkey, tile_width, tile_height):
         self.__image = Utils.loadImage(image, colorkey)
+
         self.image = Utils.load_image(image, colorkey)
         self.__tileWidth = tileWidth
+
         self.tile_width = tile_width
         self.__tileHeight = tileHeight
+
         self.tile_height = tile_height
 
+
         self.tile_types = dict()
         self.__tileTypes = dict()
+
       
+
    def getImage(self):
+
        return self.__image
+
 
+
    def setImage(self, image, colorkey):
+
        self.__image = Utils.loadImage(image, colorkey)
+
       
+
    def getTileWidth(self):
+
        return self.__tileWidth
+
 
+
    def getTileHeight(self):
+
        return self.__tileHeight
+
 
+
    def getTileSize(self):
+
        return (self.__tileWidth, self.__tileHeight)
+
 
      
 
      
 
     # Neuen Tile-Typ hinzufügen.
 
     # Neuen Tile-Typ hinzufügen.
     def addTile(self, name, startX, startY):
+
     def add_tile(self, name, start_x, start_y):
         self.__tileTypes[name] = TileType.TileType(name, startX, startY, self.__tileWidth, self.__tileHeight)
+
         self.tile_types[name] = TileType.TileType(name, start_x, start_y, self.tile_width, self.tile_height)
 
          
 
          
 
     # Versuchen, einen Tile-Type über seinen Name in der Liste zu finden.
 
     # Versuchen, einen Tile-Type über seinen Name in der Liste zu finden.
 
     # Falls der Name nicht existiert, geben wir None zurück.
 
     # Falls der Name nicht existiert, geben wir None zurück.
     def getTile(self, name):
+
     def get_tile(self, name):
 
         try:
 
         try:
             return self.__tileTypes[name]
+
             return self.tile_types[name]
 
         except KeyError:
 
         except KeyError:
 
             return None
 
             return None
Zeile 612: Zeile 557:
 
# -*- coding: UTF-8 -*-
 
# -*- coding: UTF-8 -*-
  
import pygame
 
 
import random
 
import random
 +
import pygame
 
import Tileset
 
import Tileset
  
Zeile 621: Zeile 566:
 
         # Wir erstellen ein neues Tileset.
 
         # Wir erstellen ein neues Tileset.
 
         # Hier im Tutorial fügen wir manuell vier Tile-Typen hinzu.
 
         # 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.add_tile("grass", 0, 0)
         self.__tileset.addTile("mud", 32, 0)
+
         self.tileset.add_tile("mud", 32, 0)
         self.__tileset.addTile("water", 64, 0)
+
         self.tileset.add_tile("water", 64, 0)
         self.__tileset.addTile("block", 0, 32)
+
         self.tileset.add_tile("block", 0, 32)
 
          
 
          
 
         # Festlegen der Startposition der Kamera. Hier (0, 0).
 
         # Festlegen der Startposition der Kamera. Hier (0, 0).
         self.__cameraX = 0
+
         self.camera_x = 0
         self.__cameraY = 0
+
         self.camera_y = 0
 
          
 
          
 
         # Die Größe der Maps in Tiles.
 
         # Die Größe der Maps in Tiles.
         self.__width = 30
+
         self.width = 30
         self.__height = 25
+
         self.height = 25
  
 
         # Erstellen einer leeren Liste für die Tile Daten.
 
         # Erstellen einer leeren Liste für die Tile Daten.
         self.__tiles = list()
+
         self.tiles = list()
 
          
 
          
 
         # Manuelles Befüllen der Tile-Liste:
 
         # Manuelles Befüllen der Tile-Liste:
 
         # Jedes Feld bekommt ein zufälliges Tile zugewiesen.
 
         # Jedes Feld bekommt ein zufälliges Tile zugewiesen.
         for i in range(0, self.__height):
+
         for i in range(0, self.height):
             self.__tiles.append(list())
+
             self.tiles.append(list())
             for j in range(0, self.__width):
+
             for j in range(0, self.width):
 
                 x = random.randint(0, 4)
 
                 x = random.randint(0, 4)
 
                 if x == 0:
 
                 if x == 0:
                     self.__tiles[i].append("grass")
+
                     self.tiles[i].append("grass")
 
                 elif x == 1:
 
                 elif x == 1:
                     self.__tiles[i].append("water")
+
                     self.tiles[i].append("water")
 
                 elif x == 2:
 
                 elif x == 2:
                     self.__tiles[i].append("mud")
+
                     self.tiles[i].append("mud")
 
                 else:
 
                 else:
                     self.__tiles[i].append("block")
+
                     self.tiles[i].append("block")
 
                      
 
                      
 
      
 
      
Zeile 657: Zeile 602:
 
     def render(self, screen):
 
     def render(self, screen):
 
         # Zeilenweise durch die Tiles durchgehen.
 
         # 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.tile_height) + 1):
 
             # Die Kamera Position mit einbeziehen.
 
             # Die Kamera Position mit einbeziehen.
             ty = y + self.__cameraY
+
             ty = y + self.camera_y
             if ty >= self.__height or ty < 0:
+
             if ty >= self.height or ty < 0:
 
                 continue
 
                 continue
 
             # Die aktuelle Zeile zum einfacheren Zugriff speichern.
 
             # Die aktuelle Zeile zum einfacheren Zugriff speichern.
             line = self.__tiles[ty]
+
             line = self.tiles[ty]
 
             # Und jetzt spaltenweise die Tiles rendern.
 
             # 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.tile_width) + 1):
 
                 # Auch hier müssen wir die Kamera beachten.
 
                 # Auch hier müssen wir die Kamera beachten.
                 tx = x + self.__cameraX
+
                 tx = x + self.camera_x
                 if tx >= self.__width or tx < 0:
+
                 if tx >= self.width or tx < 0:
 
                     continue
 
                     continue
 
                 # Wir versuchen, die Daten des Tiles zu bekommen.
 
                 # Wir versuchen, die Daten des Tiles zu bekommen.
 
                 tilename = line[tx]
 
                 tilename = line[tx]
                 tile = self.__tileset.getTile(tilename)
+
                 tile = self.tileset.get_tile(tilename)
 
                 # Falls das nicht fehlschlägt können wir das Tile auf die screen-Surface blitten.
 
                 # 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.image, (x * self.tileset.tile_width, y * self.tileset.tile_height), tile.rect)
 
                      
 
                      
 
      
 
      
 
     # Tastendrücke verarbeiten:
 
     # Tastendrücke verarbeiten:
     def handleInput(self, key):
+
     def handle_input(self, key):
 
         # Pfeiltaste links oder rechts erhöht bzw. verringert die x-Position der Kamera.
 
         # 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.camera_x += 1
 
         if key == pygame.K_RIGHT:
 
         if key == pygame.K_RIGHT:
             self.__cameraX -= 1
+
             self.camera_x -= 1
 
          
 
          
 
         # Und das gleiche nochmal für die y-Position.
 
         # Und das gleiche nochmal für die y-Position.
 
         if key == pygame.K_UP:
 
         if key == pygame.K_UP:
             self.__cameraY += 1
+
             self.camera_y += 1
 
         if key == pygame.K_DOWN:
 
         if key == pygame.K_DOWN:
             self.__cameraY -= 1
+
             self.camera_y -= 1
 
</sourcecode>
 
</sourcecode>
  
Zeile 697: Zeile 642:
 
# -*- coding: UTF-8 -*-
 
# -*- coding: UTF-8 -*-
  
# Pygame-Modul importieren.
+
# Pygame Modul importieren.
 
import pygame
 
import pygame
  
# Unser Tilemap-Modul ebenfalls importieren.
+
# Unser Tilemap Modul ebenfalls importieren.
 
import Tilemap
 
import Tilemap
  
Zeile 718: Zeile 663:
 
     pygame.key.set_repeat(1, 30)
 
     pygame.key.set_repeat(1, 30)
  
     # Clock-Objekt erstellen, das wir benötigen, um die Framerate zu begrenzen.
+
     # Clock Objekt erstellen, das wir benötigen, um die Framerate zu begrenzen.
 
     clock = pygame.time.Clock()
 
     clock = pygame.time.Clock()
 
      
 
      
Zeile 747: Zeile 692:
 
                  
 
                  
 
                 # Alle Tastendrücke auch der Tilemap mitteilen.
 
                 # Alle Tastendrücke auch der Tilemap mitteilen.
                 map.handleInput(event.key)
+
                 map.handle_input(event.key)
 
          
 
          
 
         # Die Tilemap auf die screen-Surface rendern.
 
         # Die Tilemap auf die screen-Surface rendern.
 
         map.render(screen)
 
         map.render(screen)
 
          
 
          
         # Inhalt von screen anzeigen.
+
         # Inhalt von screen anzeigen
 
         pygame.display.flip()
 
         pygame.display.flip()
  
Zeile 776: Zeile 721:
 
# Die Klasse kümmert sich um eine einfache Animation:
 
# Die Klasse kümmert sich um eine einfache Animation:
 
class Animation(object):
 
class Animation(object):
     def __init__(self, image, startX, startY, num, width, height, duration):
+
     def __init__(self, image, start_x, start_y, num, width, height, duration):
 
         # Die Surface speichern,
 
         # Die Surface speichern,
 
         # alle Einzelbilder müssen in einer Reihe liegen.
 
         # alle Einzelbilder müssen in einer Reihe liegen.
         self.__image = image
+
         self.image = image
 
          
 
          
 
         # Dazu müssen wir wissen, an welcher Position die Frames beginnen,
 
         # Dazu müssen wir wissen, an welcher Position die Frames beginnen,
 
         # wie viele Frames die Animation hat,
 
         # wie viele Frames die Animation hat,
 
         # sowie die Breite und Höhe der Animation kennen.
 
         # sowie die Breite und Höhe der Animation kennen.
         self.__startX = startX
+
         self.start_x = start_x
         self.__startY = startY
+
         self.start_y = start_y
         self.__num = num
+
         self.num = num
         self.__width = width
+
         self.width = width
         self.__height = height
+
         self.height = height
 
          
 
          
         # Und natürlich auch, nach welchem Zeitraum wir das nächste Frame anzeigen sollen.
+
         # Und natürlich auch, nach welchem Zeitraum wir das nächsten Frame anzeigen sollen.
         self.__duration = duration
+
         self.duration = duration
 
          
 
          
         # Die aktuelle Zeit und das aktuelle Frame speichern wie ebenfalls.
+
         # Die aktuelle Zeit und das aktuellen Frame speichern wir ebenfalls.
         self.__time = 0
+
         self.time = 0
         self.__current = 0
+
         self.current = 0
 
</sourcecode>
 
</sourcecode>
  
Im Konstruktor passiert nicht viel. Um die Animation darstellen zu können, benötigen wir ein paar Daten: Natürlich das Bild, wir erwarten hier aber keinen Dateinamen sondern, direkt eine Surface mit den Bilddaten. Das hat den Vorteil, dass wir in einem Bild mehrere Animationen unterbringen können und nicht unnötigerweise das Bild für jede Animation komplett geladen wird. Aus diesem Grund müssen wir auch wissen, an welcher Position im Bild die Animation beginnt: <tt>startX</tt> und <tt>startY</tt>. Dazu brauchen wir die Abmessungen der Animation (<tt>width</tt>, <tt>height</tt>) und die Anzahl der Einzelbilder (<tt>num</tt>). Jetzt fehlt noch die Zeitspanne, für die ein Frame angezeigt, wird bevor zum nächsten gewechselt wird: <tt>duration</tt>.
+
Im Konstruktor passiert nicht viel. Um die Animation darstellen zu können, benötigen wir ein paar Daten: Natürlich das Bild, wir erwarten hier aber keinen Dateinamen sondern, direkt eine Surface mit den Bilddaten. Das hat den Vorteil, dass wir in einem Bild mehrere Animationen unterbringen können und nicht unnötigerweise das Bild für jede Animation komplett geladen wird. Aus diesem Grund müssen wir auch wissen, an welcher Position im Bild die Animation beginnt: <tt>start_x</tt> und <tt>start_y</tt>. Dazu brauchen wir die Abmessungen der Animation (<tt>width</tt>, <tt>height</tt>) und die Anzahl der Einzelbilder (<tt>num</tt>). Jetzt fehlt noch die Zeitspanne, für die ein Frame angezeigt, wird bevor zum nächsten gewechselt wird: <tt>duration</tt>.
  
 
Das Rendern der Animation erledigen wir in einer Zeile:
 
Das Rendern der Animation erledigen wir in einer Zeile:
Zeile 808: Zeile 753:
 
         # Die x-Position können wir aus der Breite und der Start-Position berechnen,
 
         # Die x-Position können wir aus der Breite und der Start-Position berechnen,
 
         # die restlichen Werte kennen wir bereits.
 
         # die restlichen Werte kennen wir bereits.
         screen.blit(self.__image, pos, pygame.Rect(self.__startX + (self.__width * self.__current), self.__startY, self.__width, self.__height))
+
         screen.blit(self.image, pos, pygame.Rect(self.start_x + (self.width * self.current), self.start_y, self.width, self.height))
 
</sourcecode>
 
</sourcecode>
  
Wir benötigen hier wieder eine Surface, auf die wir zeichnen sollen, und dazu eine Positionsangabe. Diese beiden Parameter geben wir so direkt an die <tt>blit</tt>-Methode weiter. Fehlt nur noch die Information, welcher Bereich des Bilds genau dargestellt werden soll. Dazu basteln wir ein Rechteck (<tt>pygame.Rect</tt>) mit den folgenden Daten: Der Beginn unserer Animation ist in <tt>__startX</tt> und <tt>__startY</tt> gespeichert. Da wir festgelegt haben, dass sich unsere Frames alle in einer Reihe befinden müssen, addieren wir die Breite des Einzelbildes multipliziert mit der Nummer des aktuellen Einzelbild zur x-Position dazu. Das bringt uns exakt zu dem Einzelbild, das wir anzeigen wollen. Die Größe der Animation kennen wir bereits.
+
Wir benötigen hier wieder eine Surface, auf die wir zeichnen sollen, und dazu eine Positionsangabe. Diese beiden Parameter geben wir so direkt an die <tt>blit</tt>-Methode weiter. Fehlt nur noch die Information, welcher Bereich des Bilds genau dargestellt werden soll. Dazu basteln wir ein Rechteck (<tt>pygame.Rect</tt>) mit den folgenden Daten: Der Beginn unserer Animation ist in <tt>start_x</tt> und <tt>start_y</tt> gespeichert. Da wir festgelegt haben, dass sich unsere Frames alle in einer Reihe befinden müssen, addieren wir die Breite des Einzelbildes multipliziert mit der Nummer des aktuellen Einzelbild zur x-Position dazu. Das bringt uns exakt zu dem Einzelbild, das wir anzeigen wollen. Die Größe der Animation kennen wir bereits.
  
 
Jetzt müssen wir die Animation nur noch aktualisieren, denn momentan würde immer nur das gleiche Bild (das erste) angezeigt.
 
Jetzt müssen wir die Animation nur noch aktualisieren, denn momentan würde immer nur das gleiche Bild (das erste) angezeigt.
Zeile 817: Zeile 762:
 
<sourcecode lang=python line start=29>
 
<sourcecode lang=python line start=29>
 
     # Die update-Methode rufen wir einmal pro Frame auf:
 
     # Die update-Methode rufen wir einmal pro Frame auf:
     def update(self, time = 1):
+
     def update(self, time=1):
         # Die vergangene Zeit addieren.
+
         # Die vergangene Zeit addieren
         self.__time += time
+
         self.time += time
 
          
 
          
         # Falls wir die Anzeigedauer überschreiten, ...
+
         # Falls wir den Anzeige-Zeitraum überschreiten, ...
         if self.__time > self.__duration:
+
         if self.time > self.duration:
             # ... setzen wir die Zeit zurück und gehen zum nächsten Frame.
+
             # ... setzten wir die Zeit zurück und gehen zum nächsten Frame.
             self.__time = 0
+
             self.time = 0
             self.__current += 1
+
             self.current += 1
 
             # Sicherstellen, dass das aktuelle Frame auch verfügbar ist.
 
             # Sicherstellen, dass das aktuelle Frame auch verfügbar ist.
             if self.__current >= self.__num:
+
             if self.current >= self.num:
                 self.__current = 0
+
                 self.current = 0
 
</sourcecode>
 
</sourcecode>
  
Ein Einzelbild der Animation soll immer nur eine bestimmte Zeit lang angezeigt werden. Der <tt>update</tt>-Methode übergeben wir einfach die Zeit, die seit dem letzten Aufruf der Methode vergangen ist. Hier in dem Tutorial machen wir das auf Frame-Basis, deshalb erhöhen wir standardmäßig die Zeit um 1 und rufen die <tt>update</tt>-Methode später in jedem Frame genau einmal auf. Ab Zeile 22 überprüfen wir, ob genügend viel Zeit vergangen ist und wir ein neues Frame anzeigen müssen. Wenn die Zeit größer als die Anzeigedauer für ein Einzelbild ist, setzen wir zuerst die Zeit zurück auf 0 und erhöhen die Nummer des aktuellen Einzelbildes. Im Tutorial lassen wir unsere Animation einfach am Anfang weiterspielen wenn sie fertig ist (Looping), deshalb sorgen wir noch dafür, dass <tt>__current</tt> im erlaubten Wertebereich bleibt.
+
Ein Einzelbild der Animation soll immer nur eine bestimmte Zeit lang angezeigt werden. Der <tt>update</tt>-Methode übergeben wir einfach die Zeit, die seit dem letzten Aufruf der Methode vergangen ist. Hier in dem Tutorial machen wir das auf Frame-Basis, deshalb erhöhen wir standardmäßig die Zeit um 1 und rufen die <tt>update</tt>-Methode später in jedem Frame genau einmal auf. Ab Zeile 22 überprüfen wir, ob genügend viel Zeit vergangen ist und wir ein neues Frame anzeigen müssen. Wenn die Zeit größer als die Anzeigedauer für ein Einzelbild ist, setzen wir zuerst die Zeit zurück auf 0 und erhöhen die Nummer des aktuellen Einzelbildes. Im Tutorial lassen wir unsere Animation einfach am Anfang weiterspielen wenn sie fertig ist (Looping), deshalb sorgen wir noch dafür, dass <tt>current</tt> im erlaubten Wertebereich bleibt.
  
 
Und damit ist unsere Animations-Klasse schon fertig. Den Rest erledigt die <tt>Player</tt>-Klasse.
 
Und damit ist unsere Animations-Klasse schon fertig. Den Rest erledigt die <tt>Player</tt>-Klasse.
Zeile 843: Zeile 788:
 
     def __init__(self):
 
     def __init__(self):
 
         # Bild laden und erste Animation erstellen:  
 
         # Bild laden und erste Animation erstellen:  
         self.__anim_image_right = Utils.loadImage("tileset.png", (255, 0, 255))
+
         self.anim_image_right = Utils.loadImage("tileset.png", (255, 0, 255))
         self.__anim_right = Animation.Animation(self.__anim_image_right, 32, 32, 2, 32, 64, 15)
+
         self.anim_right = Animation.Animation(self.anim_image_right, 32, 32, 2, 32, 64, 15)
 
</sourcecode>
 
</sourcecode>
  
Zeile 860: Zeile 805:
 
         # Die Grafik spiegeln und in einer neuen Surface speichern,
 
         # Die Grafik spiegeln und in einer neuen Surface speichern,
 
         # dann können wir die linke Animation erstellen.
 
         # dann können wir die linke Animation erstellen.
         self.__anim_image_left = pygame.transform.flip(self.__anim_image_right, True, False)
+
         self.anim_image_left = pygame.transform.flip(self.anim_image_right, True, False)
         self.__anim_left = Animation.Animation(self.__anim_image_left, 32, 32, 2, 32, 64, 15)
+
         self.anim_left = Animation.Animation(self.anim_image_left, 32, 32, 2, 32, 64, 15)
 
</sourcecode>
 
</sourcecode>
  
Zeile 869: Zeile 814:
 
         # Startposition des Players festlegen und
 
         # Startposition des Players festlegen und
 
         # merken, in welche Richtung wir schauen, und ob wir überhaupt laufen.
 
         # merken, in welche Richtung wir schauen, und ob wir überhaupt laufen.
         self.__posX = 10*32
+
         self.pos_x = 10*32
         self.__posY = 13*32         
+
         self.pos_y = 13*32         
         self.__dir = 0
+
         self.dir = 0
         self.__walking = False
+
         self.walking = False
 
</sourcecode>
 
</sourcecode>
  
Diese Werte kann der Spieler später über die Pfeiltasten beeinflussen. Das wird in der <tt>handleInput</tt>-Methode erledigt:
+
Diese Werte kann der Spieler später über die Pfeiltasten beeinflussen. Das wird in der <tt>handle_input</tt>-Methode erledigt:
  
 
<sourcecode lang=python line start=46>
 
<sourcecode lang=python line start=46>
     def handleInput(self, key):
+
     def handle_input(self, key):
 
         # Linke Pfeiltaste wird gedrückt:
 
         # Linke Pfeiltaste wird gedrückt:
 
         if key == pygame.K_LEFT:
 
         if key == pygame.K_LEFT:
 
             # x-Position der Spielfigur anpassen,
 
             # x-Position der Spielfigur anpassen,
 
             # die Blickrichtung festlegen
 
             # die Blickrichtung festlegen
             # und den "Laufen"-Zustand einschalten.
+
             # und den Laufen-Zustand einschalten.
             self.__posX -= 1
+
             self.pos_x -= 1
             self.__dir = -1
+
             self.dir = -1
             self.__walking = True
+
             self.walking = True
 
          
 
          
 
         # Und nochmal für die rechte Pfeiltaste.
 
         # Und nochmal für die rechte Pfeiltaste.
 
         if key == pygame.K_RIGHT:
 
         if key == pygame.K_RIGHT:
             self.__posX += 1
+
             self.pos_x += 1
             self.__dir = 1
+
             self.dir = 1
             self.__walking = True
+
             self.walking = True
 
</sourcecode>
 
</sourcecode>
  
Das ist sehr ähnlich zur <tt>handleInput</tt>-Methode unserer <tt>Tilemap</tt>-Klasse. Je nach dem, welche Pfeiltaste gedrückt wird, erhöhen bzw. verringern wir die x-Position des Spielers (damit kann er nach rechts und links laufen) und passen die Blickrichtung an: -1 für links und +1 für rechts. Außerdem sind wir in beiden Fällen am laufen, setzen <tt>__walking</tt> also auf <tt>True</tt>. Diese Information benötigen wir zum Rendern:
+
Das ist sehr ähnlich zur <tt>handle_input</tt>-Methode unserer <tt>Tilemap</tt>-Klasse. Je nach dem, welche Pfeiltaste gedrückt wird, erhöhen bzw. verringern wir die x-Position des Spielers (damit kann er nach rechts und links laufen) und passen die Blickrichtung an: -1 für links und +1 für rechts. Außerdem sind wir in beiden Fällen am laufen, setzen <tt>walking</tt> also auf <tt>True</tt>. Diese Information benötigen wir zum Rendern:
  
 
<sourcecode lang=python line start=27>
 
<sourcecode lang=python line start=27>
 
     def render(self, screen):
 
     def render(self, screen):
 
         # Die Blickrichtung ist links:
 
         # Die Blickrichtung ist links:
         if self.__dir == -1:
+
         if self.dir == -1:
 
             # Wenn der Spieler die linke oder rechte Pfeiltaste gedrückt hat sind wir am laufen,
 
             # Wenn der Spieler die linke oder rechte Pfeiltaste gedrückt hat sind wir am laufen,
             if self.__walking:                 
+
             if self.walking:                 
 
                 # nur dann die Animation updaten.
 
                 # nur dann die Animation updaten.
                 self.__anim_left.update()
+
                 self.anim_left.update()
 
             # Blickrichtung links rendern.
 
             # Blickrichtung links rendern.
             self.__anim_left.render(screen, (self.__posX, self.__posY))   
+
             self.anim_left.render(screen, (self.pos_x, self.pos_y))   
 
         else:
 
         else:
 
             # Und das gleiche nochmal für rechts:
 
             # Und das gleiche nochmal für rechts:
             if self.__walking:
+
             if self.walking:
                 self.__anim_right.update()
+
                 self.anim_right.update()
             self.__anim_right.render(screen, (self.__posX, self.__posY))
+
             self.anim_right.render(screen, (self.pos_x, self.pos_y))
 
          
 
          
 
         # De Laufen-Zustand zurücksetzen, im nächsten Frame bleiben wir stehen.
 
         # De Laufen-Zustand zurücksetzen, im nächsten Frame bleiben wir stehen.
         self.__walking = False
+
         self.walking = False
 
</sourcecode>
 
</sourcecode>
  
Die <tt>render</tt>-Methode sieht komplizierter aus als sie es ist. Wir haben drei mögliche Zustände, in denen sich der Spieler befinden kann: Stehen, links gehen und rechts gehen. Dafür haben wir vorher die Blickrichtung gespeichert. Schauen wir zuerst mal, was passiert, wenn der Spieler weder die rechte noch die linke Pfeiltaste gedrückt hat: <tt>__dir </tt> ist 0 (das haben wir im Konstruktor so festgelegt), wir kommen also zu Zeile 26. Der Einfachheit halber lassen wir in diesem Fall den Spieler einfach immer nach rechts schauen, später wird die Blickrichtung erhalten bleiben. Da <tt>__walking = False</tt> ist, aktualisieren wir die Animation nicht, das Einzelbild verändert sich also nicht. Am Ende der Methode setzen wir <tt>__walking</tt> wieder auf <tt>False</tt>, damit wir im nächsten Frame stehen (natürlich nur falls, der Spieler keine Pfeiltaste mehr drückt). Die Blickrichtung setzen wir nicht zurück, damit wissen wir im nächsten Frame noch, welche Animation wir anzeigen sollen, auch wenn der Spieler keine Pfeiltaste gedrückt hat. Der Zustand für "rechts gehen" (mit <tt>__dir</tt> ist 1) ist exakt der gleiche wie der, den wir eben angesehen haben, und für die Variante "links gehen" (<tt>__dir</tt> ist -1) aktualisieren und zeichnen wir anstatt der rechten Animation eben die linke.
+
Die <tt>render</tt>-Methode sieht komplizierter aus als sie es ist. Wir haben drei mögliche Zustände, in denen sich der Spieler befinden kann: Stehen, links gehen und rechts gehen. Dafür haben wir vorher die Blickrichtung gespeichert. Schauen wir zuerst mal, was passiert, wenn der Spieler weder die rechte noch die linke Pfeiltaste gedrückt hat: <tt>dir </tt> ist 0 (das haben wir im Konstruktor so festgelegt), wir kommen also zu Zeile 26. Der Einfachheit halber lassen wir in diesem Fall den Spieler einfach immer nach rechts schauen, später wird die Blickrichtung erhalten bleiben. Da <tt>walking = False</tt> ist, aktualisieren wir die Animation nicht, das Einzelbild verändert sich also nicht. Am Ende der Methode setzen wir <tt>walking</tt> wieder auf <tt>False</tt>, damit wir im nächsten Frame stehen (natürlich nur falls, der Spieler keine Pfeiltaste mehr drückt). Die Blickrichtung setzen wir nicht zurück, damit wissen wir im nächsten Frame noch, welche Animation wir anzeigen sollen, auch wenn der Spieler keine Pfeiltaste gedrückt hat. Der Zustand für "rechts gehen" (mit <tt>dir</tt> ist 1) ist exakt der gleiche wie der, den wir eben angesehen haben, und für die Variante "links gehen" (<tt>dir</tt> ist -1) aktualisieren und zeichnen wir anstatt der rechten Animation eben die linke.
  
 
Jetzt fehlt nur noch die Einbindung der <tt>Player</tt>-Klasse in unser Beispielspiel.
 
Jetzt fehlt nur noch die Einbindung der <tt>Player</tt>-Klasse in unser Beispielspiel.
Zeile 925: Zeile 870:
  
 
<sourcecode lang=python line start=15>
 
<sourcecode lang=python line start=15>
         self.__tileset.addTile("grass-mud", 0, 64)
+
         self.tileset.add_tile("grass-mud", 0, 64)
         self.__tileset.addTile("empty", 0, 96)
+
         self.tileset.add_tile("empty", 0, 96)
 
</sourcecode>
 
</sourcecode>
  
Zeile 932: Zeile 877:
  
 
<sourcecode lang=python line start=30>
 
<sourcecode lang=python line start=30>
         for i in range(0, self.__height):
+
         for i in range(0, self.height):
             self.__tiles.append(list())
+
             self.tiles.append(list())
             for j in range(0, self.__width):
+
             for j in range(0, self.width):
 
                 if i == 14:
 
                 if i == 14:
                     self.__tiles[i].append("grass")  
+
                     self.tiles[i].append("grass")  
 
                 elif i == 15:
 
                 elif i == 15:
                     self.__tiles[i].append("grass-mud")                  
+
                     self.tiles[i].append("grass-mud")
 
                 elif i > 15:
 
                 elif i > 15:
                     self.__tiles[i].append("mud")
+
                     self.tiles[i].append("mud")
 
                 else:
 
                 else:
                     self.__tiles[i].append("empty")
+
                     self.tiles[i].append("empty")
 
</sourcecode>
 
</sourcecode>
  
Zeile 948: Zeile 893:
  
 
<sourcecode lang=python line start=43>
 
<sourcecode lang=python line start=43>
         self.__player = Player.Player()
+
         self.player = Player.Player()
 
</sourcecode>
 
</sourcecode>
  
Zeile 954: Zeile 899:
  
 
<sourcecode lang=python line start=70>
 
<sourcecode lang=python line start=70>
         self.__player.render(screen)
+
         self.player.render(screen)
 
</sourcecode>
 
</sourcecode>
  
Und in der <tt>handleInput</tt>-Methode reichen wir die Tastendrücke durch:
+
Und in der <tt>handle_input</tt>-Methode reichen wir die Tastendrücke durch:
  
 
<sourcecode lang=python line start=75>
 
<sourcecode lang=python line start=75>
         self.__player.handleInput(key)
+
         self.player.handle_input(key)
 
</sourcecode>
 
</sourcecode>
  
Zeile 977: Zeile 922:
 
# Die Klasse kümmert sich um eine einfache Animation:
 
# Die Klasse kümmert sich um eine einfache Animation:
 
class Animation(object):
 
class Animation(object):
     def __init__(self, image, startX, startY, num, width, height, duration):
+
     def __init__(self, image, start_x, start_y, num, width, height, duration):
 
         # Die Surface speichern,
 
         # Die Surface speichern,
 
         # alle Einzelbilder müssen in einer Reihe liegen.
 
         # alle Einzelbilder müssen in einer Reihe liegen.
         self.__image = image
+
         self.image = image
 
          
 
          
 
         # Dazu müssen wir wissen, an welcher Position die Frames beginnen,
 
         # Dazu müssen wir wissen, an welcher Position die Frames beginnen,
 
         # wie viele Frames die Animation hat,
 
         # wie viele Frames die Animation hat,
 
         # sowie die Breite und Höhe der Animation kennen.
 
         # sowie die Breite und Höhe der Animation kennen.
         self.__startX = startX
+
         self.start_x = start_x
         self.__startY = startY
+
         self.start_y = start_y
         self.__num = num
+
         self.num = num
         self.__width = width
+
         self.width = width
         self.__height = height
+
         self.height = height
 
          
 
          
 
         # Und natürlich auch, nach welchem Zeitraum wir das nächsten Frame anzeigen sollen.
 
         # Und natürlich auch, nach welchem Zeitraum wir das nächsten Frame anzeigen sollen.
         self.__duration = duration
+
         self.duration = duration
 
          
 
          
 
         # Die aktuelle Zeit und das aktuellen Frame speichern wir ebenfalls.
 
         # Die aktuelle Zeit und das aktuellen Frame speichern wir ebenfalls.
         self.__time = 0
+
         self.time = 0
         self.__current = 0
+
         self.current = 0
 
          
 
          
 
      
 
      
 
     # Die update-Methode rufen wir einmal pro Frame auf:
 
     # Die update-Methode rufen wir einmal pro Frame auf:
     def update(self, time = 1):
+
     def update(self, time=1):
 
         # Die vergangene Zeit addieren
 
         # Die vergangene Zeit addieren
         self.__time += time
+
         self.time += time
 
          
 
          
 
         # Falls wir den Anzeige-Zeitraum überschreiten, ...
 
         # Falls wir den Anzeige-Zeitraum überschreiten, ...
         if self.__time > self.__duration:
+
         if self.time > self.duration:
 
             # ... setzten wir die Zeit zurück und gehen zum nächsten Frame.
 
             # ... setzten wir die Zeit zurück und gehen zum nächsten Frame.
             self.__time = 0
+
             self.time = 0
             self.__current += 1
+
             self.current += 1
 
             # Sicherstellen, dass das aktuelle Frame auch verfügbar ist.
 
             # Sicherstellen, dass das aktuelle Frame auch verfügbar ist.
             if self.__current >= self.__num:
+
             if self.current >= self.num:
                 self.__current = 0
+
                 self.current = 0
 
                  
 
                  
 
      
 
      
Zeile 1.019: Zeile 964:
 
         # Die x-Position können wir aus der Breite und der Start-Position berechnen,
 
         # Die x-Position können wir aus der Breite und der Start-Position berechnen,
 
         # die restlichen Werte kennen wir bereits.
 
         # die restlichen Werte kennen wir bereits.
         screen.blit(self.__image, pos, pygame.Rect(self.__startX + (self.__width * self.__current), self.__startY, self.__width, self.__height))
+
         screen.blit(self.image, pos, pygame.Rect(self.start_x + (self.width * self.current), self.start_y, self.width, self.height))
 
</sourcecode>
 
</sourcecode>
  
Zeile 1.034: Zeile 979:
 
     def __init__(self):
 
     def __init__(self):
 
         # Bild laden und erste Animation erstellen:  
 
         # Bild laden und erste Animation erstellen:  
         self.__anim_image_right = Utils.loadImage("tileset.png", (255, 0, 255))
+
         self.anim_image_right = Utils.load_image("tileset.png", (255, 0, 255))
         self.__anim_right = Animation.Animation(self.__anim_image_right, 32, 32, 2, 32, 64, 15)   
+
         self.anim_right = Animation.Animation(self.anim_image_right, 32, 32, 2, 32, 64, 15)   
 
          
 
          
 
         # Die Grafik spiegeln und in einer neuen Surface speichern,
 
         # Die Grafik spiegeln und in einer neuen Surface speichern,
 
         # dann können wir die linke Animation erstellen.
 
         # dann können wir die linke Animation erstellen.
         self.__anim_image_left = pygame.transform.flip(self.__anim_image_right, True, False)
+
         self.anim_image_left = pygame.transform.flip(self.anim_image_right, True, False)
         self.__anim_left = Animation.Animation(self.__anim_image_left, 32, 32, 2, 32, 64, 15)
+
         self.anim_left = Animation.Animation(self.anim_image_left, 32, 32, 2, 32, 64, 15)
 
          
 
          
 
         # Start-Position des Players festlegen und
 
         # Start-Position des Players festlegen und
 
         # merken in welche Richtung wir schauen und ob wir überhaupt laufen.
 
         # merken in welche Richtung wir schauen und ob wir überhaupt laufen.
         self.__posX = 10*32
+
         self.pos_x = 10*32
         self.__posY = 13*32         
+
         self.pos_y = 13*32         
         self.__dir = 0
+
         self.dir = 0
         self.__walking = False
+
         self.walking = False
 
          
 
          
 
          
 
          
 
     def render(self, screen):
 
     def render(self, screen):
 
         # Die Blickrichtung ist links:
 
         # Die Blickrichtung ist links:
         if self.__dir == -1:
+
         if self.dir == -1:
 
             # Wenn der Spieler die linke oder rechte Pfeiltaste gedrückt hat sind wir am laufen,
 
             # Wenn der Spieler die linke oder rechte Pfeiltaste gedrückt hat sind wir am laufen,
             if self.__walking:                 
+
             if self.walking:                 
 
                 # nur dann die Animation updaten.
 
                 # nur dann die Animation updaten.
                 self.__anim_left.update()
+
                 self.anim_left.update()
 
             # Blickrichtung links rendern.
 
             # Blickrichtung links rendern.
             self.__anim_left.render(screen, (self.__posX, self.__posY))   
+
             self.anim_left.render(screen, (self.pos_x, self.pos_y))   
 
         else:
 
         else:
 
             # Und das gleiche nochmal für rechts:
 
             # Und das gleiche nochmal für rechts:
             if self.__walking:
+
             if self.walking:
                 self.__anim_right.update()
+
                 self.anim_right.update()
             self.__anim_right.render(screen, (self.__posX, self.__posY))
+
             self.anim_right.render(screen, (self.pos_x, self.pos_y))
 
          
 
          
 
         # De Laufen-Zustand zurücksetzen, im nächsten Frame bleiben wir stehen.
 
         # De Laufen-Zustand zurücksetzen, im nächsten Frame bleiben wir stehen.
         self.__walking = False
+
         self.walking = False
 
          
 
          
 
      
 
      
     def handleInput(self, key):
+
     def handle_input(self, key):
 
         # Linke Pfeiltaste wird gedrückt:
 
         # Linke Pfeiltaste wird gedrückt:
 
         if key == pygame.K_LEFT:
 
         if key == pygame.K_LEFT:
Zeile 1.075: Zeile 1.020:
 
             # die Blickrichtung festlegen
 
             # die Blickrichtung festlegen
 
             # und den Laufen-Zustand einschalten.
 
             # und den Laufen-Zustand einschalten.
             self.__posX -= 1
+
             self.pos_x -= 1
             self.__dir = -1
+
             self.dir = -1
             self.__walking = True
+
             self.walking = True
 
          
 
          
 
         # Und nochmal für die rechte Pfeiltaste.
 
         # Und nochmal für die rechte Pfeiltaste.
 
         if key == pygame.K_RIGHT:
 
         if key == pygame.K_RIGHT:
             self.__posX += 1
+
             self.pos_x += 1
             self.__dir = 1
+
             self.dir = 1
             self.__walking = True
+
             self.walking = True
 
</sourcecode>
 
</sourcecode>
  
Zeile 1.099: Zeile 1.044:
 
         # Wir erstellen ein neues Tileset.
 
         # Wir erstellen ein neues Tileset.
 
         # Hier im Tutorial fügen wir manuell vier Tile-Typen hinzu.
 
         # 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.add_tile("grass", 0, 0)
         self.__tileset.addTile("mud", 32, 0)         
+
         self.tileset.add_tile("mud", 32, 0)         
         self.__tileset.addTile("grass-mud", 0, 64)
+
         self.tileset.add_tile("grass-mud", 0, 64)
         self.__tileset.addTile("empty", 0, 96)
+
         self.tileset.add_tile("empty", 0, 96)
 
          
 
          
 
         # Festlegen der Startposition der Kamera. Hier (0, 0).
 
         # Festlegen der Startposition der Kamera. Hier (0, 0).
         self.__cameraX = 0
+
         self.camera_x = 0
         self.__cameraY = 0
+
         self.camera_y = 0
 
          
 
          
 
         # Die Größe der Maps in Tiles.
 
         # Die Größe der Maps in Tiles.
         self.__width = 30
+
         self.width = 30
         self.__height = 25
+
         self.height = 25
  
 
         # Erstellen einer leeren Liste für die Tile Daten.
 
         # Erstellen einer leeren Liste für die Tile Daten.
         self.__tiles = list()
+
         self.tiles = list()
       
+
               
 
         # Sehr einfache Karte basteln:
 
         # Sehr einfache Karte basteln:
         for i in range(0, self.__height):
+
         for i in range(0, self.height):
             self.__tiles.append(list())
+
             self.tiles.append(list())
             for j in range(0, self.__width):
+
             for j in range(0, self.width):
 
                 if i == 14:
 
                 if i == 14:
                     self.__tiles[i].append("grass")  
+
                     self.tiles[i].append("grass")  
 
                 elif i == 15:
 
                 elif i == 15:
                     self.__tiles[i].append("grass-mud")                  
+
                     self.tiles[i].append("grass-mud")
 
                 elif i > 15:
 
                 elif i > 15:
                     self.__tiles[i].append("mud")
+
                     self.tiles[i].append("mud")
 
                 else:
 
                 else:
                     self.__tiles[i].append("empty")
+
                     self.tiles[i].append("empty")
 
          
 
          
 
         # Player-Objekt erstellen.
 
         # Player-Objekt erstellen.
         self.__player = Player.Player()
+
         self.player = Player.Player()
 
                      
 
                      
 
      
 
      
Zeile 1.136: Zeile 1.081:
 
     def render(self, screen):
 
     def render(self, screen):
 
         # Zeilenweise durch die Tiles durchgehen.
 
         # 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.tile_height) + 1):
 
             # Die Kamera Position mit einbeziehen.
 
             # Die Kamera Position mit einbeziehen.
             ty = y + self.__cameraY
+
             ty = y + self.camera_y
             if ty >= self.__height or ty < 0:
+
             if ty >= self.height or ty < 0:
 
                 continue
 
                 continue
 
             # Die aktuelle Zeile zum einfacheren Zugriff speichern.
 
             # Die aktuelle Zeile zum einfacheren Zugriff speichern.
             line = self.__tiles[ty]
+
             line = self.tiles[ty]
 
             # Und jetzt spaltenweise die Tiles rendern.
 
             # 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.tile_width) + 1):
 
                 # Auch hier müssen wir die Kamera beachten.
 
                 # Auch hier müssen wir die Kamera beachten.
                 tx = x + self.__cameraX
+
                 tx = x + self.camera_x
                 if tx >= self.__width or tx < 0:
+
                 if tx >= self.width or tx < 0:
 
                     continue
 
                     continue
 
                 # Wir versuchen, die Daten des Tiles zu bekommen.
 
                 # Wir versuchen, die Daten des Tiles zu bekommen.
 
                 tilename = line[tx]
 
                 tilename = line[tx]
                 tile = self.__tileset.getTile(tilename)
+
                 tile = self.tileset.get_tile(tilename)
 
                 # Falls das nicht fehlschlägt können wir das Tile auf die screen-Surface blitten.
 
                 # 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.image, (x * self.tileset.tile_width, y * self.tileset.tile_height), tile.rect)
 
          
 
          
 
         # Und zuletzt den Player rendern.
 
         # Und zuletzt den Player rendern.
         self.__player.render(screen)          
+
         self.player.render(screen)
   
+
 
   
+
       
 
     # Tastendrücke an den Player weiterreichen:
 
     # Tastendrücke an den Player weiterreichen:
     def handleInput(self, key):         
+
     def handle_input(self, key):         
         self.__player.handleInput(key)
+
         self.player.handle_input(key)
 
</sourcecode>
 
</sourcecode>
  
Zeile 1.172: Zeile 1.117:
 
import pygame
 
import pygame
  
# Unser Tilemap Modul ebenfalls importieren.
+
# Unser Tilemap Modul
 
import Tilemap
 
import Tilemap
  
Zeile 1.219: Zeile 1.164:
 
                  
 
                  
 
                 # Alle Tastendrücke auch der Tilemap mitteilen.
 
                 # Alle Tastendrücke auch der Tilemap mitteilen.
                 map.handleInput(event.key)
+
                 map.handle_input(event.key)
 
          
 
          
 
         # Die Tilemap auf die screen-Surface rendern.
 
         # Die Tilemap auf die screen-Surface rendern.

Aktuelle Version vom 13. März 2015, 14:32 Uhr

Klicke hier, um diese Version anzusehen.

Meine Werkzeuge
Namensräume
Varianten
Aktionen
Navigation
Werkzeuge