Pygame Tutorial Reihe

Gute Links und Tutorials könnt ihr hier posten.
dbGAMES
User
Beiträge: 4
Registriert: Dienstag 29. Januar 2008, 11:14
Kontaktdaten:

Dienstag 29. Januar 2008, 11:24

gleich als erste aktion hier im forum will ich meine pygame tutorial reihe vorstellen.
ich beschäftige mich bereits länger mit dem thema der spieleprogrammierung, mit python erst seit etwa einem 3/4 jahr, deshalb würde ich mich vor allem über tipps zum stil und so freuen ;)
  • Pygame Tutorial

    Teil 1 - Der Einstieg

    Pygame Tutorial von Daniel Baumartz
    Copyrigth (c) 2007 Daniel Baumartz
    Version v0.0.2

1. Inhalt

1. Inhalt
2. Einleitung
2.1 Warum schreibe ich das?
2.2 Was ist Pygame?
2.3 Wo gibts das?
3. Versions-History
3.1 v0.0.1
3.2 v0.0.2
3.3 v0.0.3
4. Pygame einrichten
4.1 Die Entwicklungsumgebung
4.2 Pygame integrieren
4.3 Testen
5. Ein paar Grundlagen
5.1 Das erste Beispiel
5.2 Pygame initialisieren
5.3 Die Nachrichtenschleife
6. Aublick auf Part 2


2. Einleitung

2.1 Warum schreibe ich das?
Bei einem neuen Tutorial stellt sich natürlich immer die Frage, warum es geschrieben wurde. Die Antwort in diesem Fall ist aber ziemlich einfach: Ich habe bisher kein deutsches Pygame Tutorial gefunden. Natürlich, es gibt ein Paar auf Englisch und es gibt die gute Dokumentation, aber viele hält das möglicherweise ab. Außerdem sind mehr Tutorials immer besser ;)

2.2 Was ist Pygame?
Pygame ist eine Sammlung von Python Modulen, die es einem ermöglichen, relativ einfach und schnell Spiele zu programmieren. Basieren tuen die Module auf der SDL (Simple DirectMedia Layer) Bbliothek.
Pygame ist kostenlos zu haben und läuft auf jedem Betriebssystem für das es einen Python-Interpreter gibt, wenn man Platformunabhängig programmiert, was in Python aber nich schwer ist.

2.3 Wo gibts das?
Die offizielle Pygame Seite findet sich unter http://www.pygame.org . Dort gibt es auch die neuste Version, die Doku, Tutorials und vieles mehr. Unter http://www.python.org gibts die Python Interpreter, und alle die Python noch nicht können finden dort alles um es zu lernen. Der Vollständigkeithalber hier noch die SDL Addresse: http://www.libsdl.org .


3. Versions-History

3.1 v0.0.1
Erste Version, Großteil des Textes geschrieben.

3.2 v0.0.2
Diverse, kleine Änderungen

3.3 v0.0.3
Korrektur der URLs, Danke Abrexxes


4. Pygame einrichten

4.1 Die Entwicklungsumgebung (IDE)
Man kann Python Programme ganz einfach mit einem simplen Text-Editor (wie Notepad unter Windows) schreiben, viele spezielle Editoren bieten aber einiges mehr was einem beim Programmieren hilft, wie etwa Syntax-Highlighting, Code-Vervollständigng und vieles mehr. Ich verwende Eclipse dafür mit dem Pydev Plugin. Eclipse gibt es hier: http://www.eclipse.org/ und das Python Plugin hier: http://pydev.sourceforge.net/ . Das Installieren gestaltet sich ziemlich einfach, einfach den entpackten eclipse-Ordner von Pydev in den Eclipse Ordner kopieren. Danach muss unter Window > Preferences > Pydev > Interpreter - Python noch die exe Datei des Python Interpreters angegeben werden, danach können wir in die Pydev Perspective schalten und loslegen.

4.2 Pygame integrieren
Läuft am einfachsten über einen Installer ab, der installiert alle benötigten Dateien (Python Module, SDL DLLs usw) in den Unterordner site-packages der Python Installation, Eclipse sollte das automatisch erkennen.

4.3 Testen
Ein einfaches Skript zum Testen der Installation:
[Code ausgelagert]

Wer jetzt keine Ahnung von Python hat sollte sich erstmal ein Tutorial zu Gemüte führen, allen anderen wird der größte Teil keine Probleme bereiten. Starten können wir mit Run > Run > Python Run > Ok, Beenden über ESC oder das X. Es sollte ein Fenster mit schwarzem Hintergrund zu sehen sein, nicht mehr aber auch nicht weniger.


5. Ein paar Grundlagen

Schauen wir uns das erste Beispiel mal etwas genauer an...

5.1 Das erste Beispiel
Zuerst importieren wir die benötigten Pygame Module. Wenig Aufregendes, über

Code: Alles auswählen

import pygame
from pygame.locals import *
holen wir alles was wir fürs Programmieren mit Pygame benötigen. zusätzlich können wir noch Testen, ob die Module für die Sound- und die Font-Bibliothek korrekt geladen wurden:

Code: Alles auswählen

if not pygame.font: print 'Fehler! pygame.font'
if not pygame.mixer: print 'Fehler! pygame.mixer'
Zusätzlich dazu wird jeder die Module inportieren müssen die er benötigt ;)

5.2 Pygame initialisieren
Als nächstes initialisieren wir Pygame und erstellen eine Surface die wir als Bildschirm verwende, mit einer festen Auflösung von 800x600 Pixeln.

Code: Alles auswählen

pygame.init()
screen = pygame.display.set_mode((800, 600))
Der set_mode Funktion können wir noch zusätzliche Parameter übergeben, aber ohne sie sucht SDL die für den PC Besten Einstellungen heraus, was in den meisten Fällen der bessere Weg ist. Wer ein Bestimmtes Format benötigt schaut hier nach: http://www.pygame.org/docs/ref/display. ... y.set_mode .
Das Festlegen des Fenstertitels und das Anzeigen der Maus ist selbserklärend. Als Letztes schalten wir noch die Tasten-Wiederholung ein. Dadurch weisen wir Pygame an, trotzdem eine Taste-gedrückt-Nachricht zu senden, obwohl die Taste noch nicht losgelassen wurde.

Code: Alles auswählen

pygame.display.set_caption("Pygame Tutorial - listing 4.3")
pygame.mouse.set_visible(1)
pygame.key.set_repeat(1, 30)
5.3 Die Nachrichtenschleife
Damit ist Pygame grundlegend initialisiert. Jetzt müssen wir nur noch dafür sorgen, dass das Fenster auch länger als ein Frame angezeigt wird. Dafür verwenden wir, logischerweise eine Nachrichtenschleife. Um Probleme mit der Geschwindigkeit der verschiedenen PCs zu vermeiden, legen wir fest, dass wir maximal 30 Frames pro Sekunde haben wollen:

[Code ausgelagert]

Zuerst erstellen wir ein time.Cock-Objekt welches sich um die Frame Begrenzung kümmern soll. Um die Schleife bequem wieder verlassen zu können, verwenden wir die running Variable. Solange sie 1
ist bleiben wir in der Schleife. In der Schleife lassen wir das time.Clock-Objekt erstmal berechnen wie lange wir warten müssen um maximal 30 Frames zu erhalten. Danach überschreiben wir den gesamten Bildschirm mit der Farbe Schwarz.

Code: Alles auswählen

    for event in pygame.event.get():
        if event.type == QUIT:
           running = 0
Hier haben wir die erste Abbruchsbedingung. Wir holen uns per pygame.event.get() sämtliche Events die Pygame empfangen / generiert hat. Finden wir eines vom Typ QUIT setzten wir die running Variable auf 0, sodass wir die Schleife verlassen können.
Als nächstes Interessiert uns, welche Tasten der User gedrückt hat, diese werden durch den Typ KEYDOWN abgefangen.

Code: Alles auswählen

        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                pygame.event.post(pygame.event.Event(QUIT))
Wir testen hier nur auf die Escape-Taste. Wurde sie gedrückt, posten wir ein Event vom Typ QUIT, was dafür sorgt, das wir die Schleife verlassen (wir erinnern uns: auf dieses Event reagieren wir ja etwas weiter oben).
Nachdem wir alle Events durchgesehen habe, können wir endlich den Bildschirm anzeigen:

Code: Alles auswählen

    pygame.display.flip()
Intern arbeitet Pygame mit einem Buffer für den Bildschrim, der erst mit diesem Befehl angezeigt wird. Würde man direkt auf den Bildschirm rendern würde man den Bildaufbau sehen können.
Damit sind wir auch fast schon am Ende des Beispiels. Das vorige Besprochene haben wir in eine Funktion main gesteckt, die wir jetzt einfach aufrufen, falls diese Datei nicht als Modul importiert wird.

Code: Alles auswählen

if __name__ == '__main__':
    main()

6. Ausblick auf Teil 2

Hier in dem Tutorial gabs nur die allerersten Grundlagen zum Theme Pygame zu sehen. Im Teil 2 werde ich genauer auf alle Verwendeten Module innerhalb von Pygame eingehen, soweit dass am Ende ein kleines Spiel entstehen kann.

Edit (Leonidas): Code ausgelagert.
[url=http://www.dbaumartz.de]dbaumartz[/url]
[url=http://blog.dbaumartz.de]blog.dbaumartz[/url]

Neue Urls!
dbGAMES
User
Beiträge: 4
Registriert: Dienstag 29. Januar 2008, 11:14
Kontaktdaten:

Dienstag 29. Januar 2008, 11:25

und gleich weiter mit teil 2:
  • Pygame Tutorial

    Teil 2 - Bilder am Beispiel einer Tilemap

    Pygame Tutorial von Daniel Baumartz
    Copyrigth (c) 2007 Daniel Baumartz
    Version v0.0.3
1. Inhalt

1. Inhalt
2. Einleitung
2.1 Teil 2?
2.2 Über diesen Teil
3. Versions-History
3.1 v0.0.1
3.2 v0.0.2
3.3 v0.0.3
4. Beschreibung der Tilemap
4.1 Was ist das?
4.2 Wie gehen wir vor?
5. Bilder in Pygame
5.1 Los gehts
5.2 Surfaces
5.3 Format-Konvertierung
5.4 Kreise?
5.5 Bild anzeigen
5.6 Mehr zu Surfaces
6. Programmieren einer Tilemap
6.1 Die Klasse: TileType
6.2 Die Klasse: Tileset
6.3 Die Klasse: Tilemap
6.4 Fertig
7. Aublick auf Teil 3
8. Bilder und Daten


2. Einleitung

2.1 Teil 2?
Den ersten Teil findet ihr hier im selben Post.

2.2 Über diesen Teil
Hier im zweiten Teil werden wir, am praktischen Beispiel einer Tilemap für ein 2D-Spiel, die Pygame Funktionen für das Laden und Anzeigen von Bildern kennenlernen.
Ich habe diesen Teil gekürzt, Bild-Modifizierung und das Font-Modul werden erst im nächsten Teil behandelt.


3. Versions-History

3.1 v0.0.1
Erste Version, Großteil des Textes geschrieben.

3.2 v0.0.2
Viele Änderungen vorgenommen, praktisches Beispiel geändert.

3.3 v0.0.3
Es gab einen Anzeige-Bug bei der Tilemap, das habe ich behoben und die Beschreibung des Codes angepasst. Außerdem habe ich noch ein paar Daten hinzugefügt. *Danke Shade*


4. Beschreibung der Tilemap

4.1 Was ist das?
Bevor wir uns an das Implementieren der Tilemap machen, klären wir noch ganz kurz was genau das ist und wie wir sie hier in dem Tutorial bauen werden.
Tilemaps werden häufig in 2D-Spielen verwendet, sie sind eine einfache und schnelle Lösung, eine Landschaft oder ähnliches in einem Spiel darzustellen. Die Landschaft ist dabei aus zumeist gleich großen, quadratischen Kacheln (= Tiles) zusammengesetzt, daher der Name. Mehrere, verschiedene Tile-Grafiken fasst man zu sogenannten Tilesets zusammen, damit kann man zum Beispiel während dem Spiel einfach und schnell den Grafikstiländern (etwa eine normale Gras-Grafik in eine Gras-mit-Schnee-Grafik) ändern. Um Platz zu sparen und um die Übersicht zu erhöhen werden Tiles aus einem Set oftmals in einer Bilddatei gespeichert. Eine Tilemap speichert jetzt einfach eine Liste von Informationen, an welcher Position welches Tile liegt (zum Beispiel über den Namen eines Tiles in einem 2D-Array).

4.2 Wie gehen wir vor?
Unsere Tilemap wird folgendermaßen arbeiten: Wir verwenden eine Klasse names TileType, welche exakt einen Tile-Typ repräsentiert. Sie speichert die Position dieses Typs auf der Grafik und seinen Namen. Hier ist außerdem der passende Ort, um weitere Informationen, wie etwa
Begehbarkeit, Ereignisse usw. zu speichern. Die Klasse Tileset speichert in einem Dictionary (Python-Pendant zu std::map<x, y> in C++) alle Tile-Typen, sowie die einheitliche Größe der Tiles. Und dazu noch eine Grafik, auf der sämtliche Tiles vorhanden sind. Außerdem ermöglichen wir es, dass man diese Grafik einfach gegen eine Andere tauschen kann. Ein Tile-Typ muss per Hand hinzugefügt werden, eine gute Gelegenheit um den Umgang mit den Datei-Funktionen von Python zu lernen ;)
Zu guter Letzt habe wir noch eine Klasse namens Tilemap, die sich hauptsächlich um das Anzeigen der Tiles kümmert. Hier wird ein Tileset gespeichert, und natürlich eine Liste von Tiles. Die Liste verwenden wir als 2D-Array in denen die ID eines Tile-Types gespeichert ist.


5. Bilder in Pygame

5.1 Los gehts
Bevor wir uns an das Programmieren machen, schauen wir, wie Pygame uns mit den Bildern helfen kann. Mittels Pygame können wir sehr schnell und sehr einfach ein Bild laden:

Code: Alles auswählen

_image = pygame.image.load("tolles_bild.bmp")
Unterstützt werden dabei folgende Formate: (Auszug aus der Dokumentation, http://www.pygame.org/docs/ref/image.html )
* JPG
* PNG
* GIF (non animated)
* BMP
* PCX
* TGA (uncompressed)
* TIF
* LBM (and PBM)
* PBM (and PGM, PPM)
* XPM
Da sollte jeder "sein" Format finden.
Mit dem fertig geladenen Bild könnten wir jetzt bereits arbeiten, aber für den Einsatz in einem Spiel / Programm sollte das Bild noch optimiert werden. Vorher schauen wir aber noch, wie das geladene Bild in Pygame repräsentiert wird.

5.2 Surfaces
Pygame speichert alles, was irgendwie Angezeigt werden könnte, in sogenannten Surfaces. Auch Bilder und der Bildschirm werden als Surface repräsentiert. Für jetzt ist erstmal wichtig, dass ganze bzw Teile einer Surface auf andere Surfaces bzw den Bildschirm kopiert werden können.
Details dazu kommen später.

5.3 Format-Konvertierung
Beim Erstellen der Bildschirm-Surface können wir, falls gewünscht, die Farbtiefe des Fensters angeben, bzw wird dies von Pygame automatisch erledigt. Wenn wir jetzt ein Bild anzeigen lassen wollen welche nicht in diesem Format gespeichert ist, muss Pygame das Bild bei jedem Anzeige-Vorgang konvertieren - und das dauert unter Umständen recht lange, je mehr Bilder desto mehr leidet die Performance. Deshalb werden wir direkt nach dem Laden das Bild in das passende Format konvertieren.
Dazu bietet Pygame gleich zwei Funktionen, eine für Bilder mit einem Alpha-Kanal und eine für Bilder ohne und da es auch eine Funktion gibt die prüft ob das Bild einen Alpha-Kanal hat, können wir das ohne Probleme automatisieren:

[Code ausgelagert]

5.4 Kreise?
Wer die bisherige Ladefunktion schon getestet hat, wird festgestellt haben, dass wir immer nur Rechtecke anzeigen können. Das ist für ein echtes Spiel natürlich zuwenig da die wenigsten Figuren rechteckig aussehen ;) Um dieses Problem zu lösen bietet Pygame natürlich die bekannte Colorkey-Methode, in der eine bestimmte Farbe beim Anzeigen eines Bildes einfach ausgelassen wird. Das festlegen des Colorkeys unter Pygame ist auch sehr einfach realisierbar:

Code: Alles auswählen

_image.set_colorkey((rot, grün, blau), RLEACCEL)
Sehr oft wird als Colorkey die Farbe (255, 0, 255) verwendet, da man sie selten in einem Bild benötigt.

5.5 Bild anzeigen
Ein Bild können wir, wie bereits erwähnt, entweder direkt auf die Bildschirm rendern oder auf ein andere Surface, diese Methode nennt sich Bit Block Transfer. Jede Surface besitzt eine Funktion namens blit mit der eine andere Surface auf sie kopiert werden kann.
In der Standard-Variante wird eine komplette Surface an eine bestimmte Position geblittet:

Code: Alles auswählen

screen.blit(_image, (0, 10))
Damit wird die Surface _image an der Position x=0 und y=10 auf die Surface screen geblittet (screen ist meistens die Surface, die zum Anzeigen auf dem Bildschirm verwendet wird).

5.6 Mehr zu Surfaces
Jetzt können wir Bilder laden und optimieren und anzeigen, wem das reicht der kann gleich zum nächsten abschnitt weitergehen. Alle anderen bekommen jetzt noch ein paar Details zu Surfaces ( http://www.pygame.org/docs/ref/surface.html ). In den meisten Fällen erstellt man eine Surface durch laden eines Bildes, falls nötig, kann man aber auch eine "per Hand" erstellen (etwa um einen Buffer zu haben). Dafür stehen zwei Funktionen zur Verfügung:

[Code ausgelagert]

Als Flags können wir "anfragen" (das heißt, unter Umständen ignoriert SDL diese Anfrage wenn es Probleme geben könnte), dass die Surface im Grafikkartenspeicher abgelegt werden soll (Flag HWSURFACE) und / oder dass wir "per-pixel alpha" Unterstützung wollen (Flag SRCALPHA).
Letzteres ist nicht empfohlen, da es langsam ist, in den meinsten Fällen ist es aber zum Glück nicht nötig, da man ja Colorkeys und einen Transparents-Wert für die komplette Surface angeben kann.
Die wichtigste Funktion einer Surface ist wohl die blit-Funktion ( http://www.pygame.org/docs/ref/surface. ... rface.blit ), sie ermöglicht es, andere Surfaces, bzw Ausschnitte daraus, auf diese zu kopieren:

Code: Alles auswählen

Surface.blit(source, dest, area=None, special_flags = 0): return Rect
Der Parameter source muss eine weitere Surface sein die kopiert werden soll. Über den zweiten Parameter, dest, kann der Zielbereich angegeben werden in den kopiert wird. Entweder als ein Tupel von Zahlen (posX, posY) oder als eine Rect-Variable. Um nur Ausschnitte von einer Surface zu kopieren (unerlässlich für unsere Tilemap) benötigt man den dritten Parameter, area. Er erwartet eine Rect-Variable die den kleineren Ausschnit definiert. Über den special_flags-Parameter kann man Überblendungs-Effekte beim Kopieren einbauen (BLEND_ADD, BLEND_SUB, BLEND_MULT, BLEND_MIN, BLEND_MAX).
Weitere wichtige Funktionen sind get_width und get_height zum ermitteln der Größe der Surface, sowie fill um die Surface mit einer Farbe komplett zu füllen.
Dass soll erstmal genug sein, jetzt kommen wir zum Programmieren der Tilemap.


6. Programmieren einer Tilemap

6.1 Die Klasse: TileType
Dies ist die einfachste und kleinste Klasse. Deshalb zuerst der Code:

[Code ausgelagert]

Wir speichern als erstes den Namen, bze die ID des Types in der privaten Variable __name, über die Funktion getName können wir ihn wieder auslesen.
In einem Rect speichern wir gleichzeitig die Position und die Größe dieses Types.
Wir gehen gleich zur nächsten Klasse weiter, der Tileset-Klasse in der deutlich mehr passiert.

6.2 Die Klasse: Tileset
Hier in der Tileset-Klasse müssen wir vor allem die Tile-Typen speichern. Der Konstruktor der Klasse erwartet einen Dateinamen für das Bild der Tiles, dazu einen Colorkey für das Bild und die Breite und Höhe eines Tiles (alle Tiles haben die gleiche Größe).
Zuletzt wird noch ein Dictionary für die Tile-Typen angelegt, der erstmal leer bleibt.

[Code ausgelagert]

Die verwendete loadImage Funktion zum Laden eines Bildes besteht aus dem oben besprochenen Code.
Hier nochmal im Überblick:

[Code ausgelagert]

Um das Bild anzeigen zu können, bzw Ausschnitte daraus, erstellen wir eine Funktion die das Bild zurückliefert. Außerdem ermöglichen wir es, das Bild gegen eine neues auszutauschen. Wenn während dem Spiel so ein Tausch des Tileset-Bildes öfter vorkommen soll, ist es aber ratsamer, alle Bilder zum Beispiel in einer Liste zu speichern und nicht jedesmal neu zu laden.

[Code ausgelagert]

Ebenfalls sehr einfach sind die drei Funktionen um die Größe der Tiles zu bekommen:

[Code ausgelagert]

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 TileType Klasse in unserem Dictionary hinzu, mit passenden Parametern:

[Code ausgelagert]

Auch das rausholen eines Types ist leicht, einfach über den Key den passenden Wert zurückliefern:

[Code ausgelagert]

Existiert dieser Schlüssel nicht: Wir fangen die mögliche Exception, die geworfen wird wenn ein Schlüssel übergeben wird der nicht existiert ab, und geben dann einfach None zurück.
Damit kommen wir zu der eigentlichen Tilemap-Klasse.

6.3 Die Klasse: Tilemap
Wir beginnen wieder mit dem Konstruktor:

[Code ausgelagert]

Es fällt natürlich sofort auf, das das ziemlich unflexibel ist. Ein deutlich besserer Weg wäre, sämtliche Informationen aus einer Datei zu lesen. Aufgrund der Einfachheit dieses Tutorials werde ich aber davon absehen und überlasse ihnen die Verbesserung ;)
Was passiert: Wir erstellen eine neue Instanz der Tileset-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.

[Code ausgelagert]

Wir legen Standard Wete 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: Gestalten sie die Größe flexibler, 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.

[Code ausgelagert]

Mit diesem Code endet der Konstruktor. Wir befüllen hier die Liste der Tiles. Dazu verwendenwir zwei for-Schleifen, die die Breite bzw Höhe der Karte durchlaufen. Für jedes i (= eine Zeile) erstellen wir eine neue Liste, in der wir die Spalten mit einem Zufalls-Wert füllen (hier gibt es eine Auswahl zwischen den vier hinzugefügten Tiles). Standardmäßig sollte hier jedes Feld auf " " oder None gesetzt werden, oder man ließt gleich alle Positions-Daten aus einer Datei.
Schauen wir uns die komplizierteste, aber auch wichtigste Funktion an: Die Funktion, die die Karte auf den Bildschirm (oder eine beliebige andere Surface rendert):

[Code ausgelagert]

Wir werden die Funktion Zeile für zeile durchgehen.
1) Wir wollen nur soviele 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.
2) Die Y-Position auf dem Bildschirm ist nicht gleich der Position in unserer Tile-Liste, diese Position speichern wir in der Variable ty. Um den korrekten Wert zu erhalten, müssen wir nur die Kamera-Position hinzuaddieren.
3) Wir testen, ob wir uns überhaupt noch innerhalb der Map-Grenze befinden. Wenn nicht überspringen wir dieses Teil.
5) Die Tiles werden spaltenweise gerendert, hier speichern wir die aktuelle Spalte.
6) In der zweiten for-Schleife durchlaufen wie die Breite des Bildschrims.
7) Auch die X-Position wird berechnet, genau wie die Y-Position.
8) Natürlich muss auch hier getestet werden, ob wir die Grenzen der Map einhalten.
9) Als nächstes holen wir uns den Namen des Tiles welches wir rendern wollen aus der aktuellen Spalte.
10) Über das Tileset erhalten wir das Tile, oder None wenn keines existiert.
11) Und wenn wir ein Tile haben, wird das auf den Bildschrim gerendert.
12) In der Tilemap ist das Bild mit allen Tiles gespeichert, das ist unsere Quelle für die blit-Funktion. Die Positionen multiplizieren wir noch mit der Größe der Tiles um keine Überschneidung mit dem vorigen Tile zu bekommen. Zuletzt der wichtigste Parameter: Der Ausschnitt, der von dem Bild verwendet werden soll, ist in der Tile-Klasse gespeichert.
Damit snd wir fast fertig.
Die Veränderung der Kamera-Position ist im Gegensatz zur letzten Funktion absolut kein Ding mehr:

[Code ausgelagert]

6.4 Fertig
Für das Tutorial sind wir jetzt mit der Tilemap fertig. Für ein kleines 2D-Spiel kann man sie gut als Grundlage verwenden und noch etwas verbessern. Etwa durch mehrere Layer, weitere Informationen der einzelne Tiles (eine eigene Tile-Klasse zum Beispiel) und natürlich Auslesen der Map-Daten aus einer Datei.
Wer dazu Fragen hat knn sich gerne an mich wenden.
Zum Schluss bauen wir die Tilemap noch in das Skript aus dem letzten Tutorial ein (falls sie noch Probleme haben und nicht wissen, wie sie da Vorgehen sollen). Die alten Kommentare habe ich entfernt, die Map-klassen liegen in einer Python-Datei namens Map.py.

[Code ausgelagert]


7. Aublick auf Teil 3

Teil 3 wird das Thema Animation bearbeiten. Eine animierte Spielfigur, die über die hier entwickelte Tilemap läuft ist der nächste logische Schritt und den wollen wir gehen. Außerdem wird dabei die Tastatur- / Maus-Abfrage wieder wichtiger werden die in diesem Teil nicht mehr behandelt werden konnte. Dazu wird es um Bild-Modifizierng über SDL_gfx, etwa Spiegelung, und Verwendung des Font-Modules zum Anzeigen von TTF-Fonts gehen.


8. Bilder und Daten

Eine Tilemap mit 10x10 Tiles, im Durchschnitt 450FPS:
Bild

Eine Tilemap mit 10000x10000 Tiles, im Durchschnitt 300FPS, Ladezeit bis die Zufall-Tiles erstellt waren ~2 Minuten:
Bild

Die verwendete Tileset-Grafik:
Bild

den dritten teil werde ich nach den klausuren die jetzt anstehen erstellen.

und jetzt spart nicht mit kritik ;)

Edit (Leonidas): Code ausgelagert, restlichen Code in Tags gesetzt.
[url=http://www.dbaumartz.de]dbaumartz[/url]
[url=http://blog.dbaumartz.de]blog.dbaumartz[/url]

Neue Urls!
Leonidas
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Dienstag 29. Januar 2008, 14:22

Hallo dbGAMES, willkommen im Forum,
dbGAMES hat geschrieben:und jetzt spart nicht mit kritik ;)
Ok - erstmal an der Form. Ich musste fast jeden Codesnippsel ins LodgeIt auslagern, da hier sonst das phpBB aufgrund eines Bugs blokiert. Dann finde ich es auch sinnlos das Tutorial ins Forum zu schreiben - verschiebe es doch ins Wiki, das hat meiner Meinung nach *wesentlich* mehr Sinn. Dafür sind Wikis da.

Zweitens, was mir so beim überfliegen aufgefallen ist: Zahlen mit ``is`` vergleichen ist nicht gut, da sie nicht immer die gleiche Identität besitzen müssen, wenn sie den gleichen Wert haben. Die Zahlen von 0 - 100 (oder so) sind in CPython im Cache, aber das muss nicht so sein. Einzig None sollte man mit ``is`` vergleichen, weil ``None`` ein Singleton ist.

Ansonsten: schau dir mal PEP8 an. Die Namensgebung deiner Funktionen ist falsch, die Leerzeichen falsch gesetzt.

Zuallerletzt: werd die *-Importe los. Das das sie in jedem Totorial auftauchen ist dumm, aber das muss man nicht zu allem Überfluss übernehmen. Sonst gibts das gleiche Problem, wo wir schon mit den Tkinter-Einsteigern kämpfen müssen. Also schlechten Stil gar nicht erst angewöhnen.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
dbGAMES
User
Beiträge: 4
Registriert: Dienstag 29. Januar 2008, 11:14
Kontaktdaten:

Dienstag 29. Januar 2008, 15:06

erstmal danke fürs auslagern des codes. das mit dem wiki ist eine gute idee, das werde ich machen sobald ich alle kritikpunkte beseitigt habe wie die "is" vergleiche und die *-exporte ;)

den style guide werde ich auch versuchen so gut wie möglich umzusetzen, mein jetziger still ist wohl ziemlich stark von c++ beeinflusst.

danke dafür soweit, dann werde ich mich da mal dransetzten.
[url=http://www.dbaumartz.de]dbaumartz[/url]
[url=http://blog.dbaumartz.de]blog.dbaumartz[/url]

Neue Urls!
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Dienstag 29. Januar 2008, 15:22

Noch ein Vorschlag: Stelle es unter eine freie Lizenz, die auch anderen ermöglicht, damit zu arbeiten (MIT, GPL, GFDL, eventuell auch cc-by, cc-by-sa)
EyDu
User
Beiträge: 4871
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Dienstag 29. Januar 2008, 15:35

Also ich sehe da ehrlilch gesagt noch nichts, was man unter irgend eine Lizenz stellen könnte.
Benutzeravatar
lockwood
User
Beiträge: 7
Registriert: Donnerstag 13. Dezember 2007, 14:35
Wohnort: Holland
Kontaktdaten:

Dienstag 29. Januar 2008, 15:40

Du könntest den ganzen code mit bilder in einem archiv machen sodass wir nicht alles kopieren müssen, und dass dann im wiki dazufügen.
sechsrad
User
Beiträge: 173
Registriert: Montag 31. März 2008, 17:09

Donnerstag 3. April 2008, 19:35

also von mir ein grosses lob für diese wunderbare arbeit.
klasse beschrieben, sehr aufschlussreich.

mfg
Yogi
User
Beiträge: 80
Registriert: Montag 21. Januar 2008, 16:35
Wohnort: Bonner

Freitag 4. April 2008, 00:45

Ich möchte mich dem Lob anschliessen. Sobald ich was Luft habe werde ich mir dein Tut noch genauer anschauen.

Was ich noch bekräftigen möchte ist, dass ein Tut eine Art Vorbild-Charakter hat und somit möglichst einen sauberen Coding-Style haben sollte, damit Anfänger wie ich sich nichts falsches angewöhnen.

Bin mal gespannt auf die weiteren Teile!
dbGAMES
User
Beiträge: 4
Registriert: Dienstag 29. Januar 2008, 11:14
Kontaktdaten:

Samstag 5. April 2008, 12:11

schön dass ich doch noch ein paar leuten helfen konnte :)

ich bin grade dabei dass alles zu überarbeiten um einen besseren stil zu bekommen, da ich aber selber noch relativ am anfang mit python stehe wird das leider noch einige zeit dauern.
ein dritter teil ist noch fest geplant ;)
[url=http://www.dbaumartz.de]dbaumartz[/url]
[url=http://blog.dbaumartz.de]blog.dbaumartz[/url]

Neue Urls!
Tayce
User
Beiträge: 56
Registriert: Sonntag 22. April 2007, 18:26
Wohnort: München
Kontaktdaten:

Samstag 5. April 2008, 19:10

Wie schauts mit nem PDF aus?
Jabber: tayce@jaim.at
Luchs
User
Beiträge: 5
Registriert: Samstag 12. April 2008, 15:22

Samstag 12. April 2008, 21:10

Ich kriege das irgendwie nicht hin ein Programm zu starten? Bin auf der Pydev Perspektive in Eclipse und so, erstelle ein "Untitled Text File", kopiere deinen Code rein, drücke "Run", "Python unit-test" (Gibt nur Python unit-test und Jython unit-test) und dann kriege ich die Meldung: "Python Launch failed.
Reason:
Unable to discover launch config for:"

und danach kommt nix mehr. :/
Was hab ich denn da falsch gemacht?
BlackJack

Samstag 12. April 2008, 22:11

Wahrscheinlich ein Problem mit Pydev/Eclipse. Starte das Programm doch einfach mal direkt. Siehe die [wiki]FAQ.[/wiki]
Luchs
User
Beiträge: 5
Registriert: Samstag 12. April 2008, 15:22

Samstag 12. April 2008, 22:23

Dein Link hat mir nicht wirklich weitergeholfen, in der FAQ steht jetzt nichts spezielles darüber, oder hab ich mich verguckt?
BlackJack

Samstag 12. April 2008, 23:07

Ich dachte da an *4. Wie starte ich Skripte*.
Antworten