image image


Space Invaders mit Python und PyGlet – Stage 1

Nachdem es mir gestern gelungen war, mit Hilfe von Python und PyGlet ein Fenster auf den Monitor zu zaubern, ist es nun an der Zeit, dieses Fenster mit Leben zu füllen. Wie ich schon ankündigte, möchte ich eine Art Space Invaders programmieren. Als ersten Schritt soll eine kleine, animierte Rakte das Fenster bevölkern:

image

Das Spritesheet für diese Rakete (so wie auch alle übrigen in diesem Tutorium später noch verwendeten Sprites) habe ich diesem freien Set (CC-BY-3.0) von Jacob Zinman-Jeanes entnommen. Das Set besteht aus vier Sprites, jeweils in einer Größe von 64x29 Pixeln. Um dieses Spritesheet zu laden und daraus eine animierte Sprite-Sequenz zu erstellen, habe ich erst einmal die Datei gameobjects.py erstellt und darin eine Klasse GameObject angelegt. Hier der Inhalt dieser Datei:

import pyglet

class GameObject():
    
    def __init__(self, posx, posy, image = None):
        self.posx = posx
        self.posy = posy
        if image is not None:
            image = pyglet.image.load("images/" + image)
            image_seq = pyglet.image.ImageGrid(image, 4, 1, item_width = 64, item_height = 29)
            image_texture = pyglet.image.TextureGrid(image_seq)
            image_anim = pyglet.image.Animation.from_image_sequence(image_texture[:], 0.1, loop = True)
            self.sprite = pyglet.sprite.Sprite(image_anim, self.posx, self.posy)

Noch ist sie relativ klein und übersichtlich, aber wie man in PyGlet Animationen erstellt, ist aus den Zeilen unter if image is not None: zu erkennen: Zuerst wird das Bild geladen und daraus mit ImageGrid() die Sequenz extrahiert. Der erste Parameter ist das Dateihandle, der zweite die Anzahl der Zeilen im Bild und der dritte die Anzahl der Spalten.

image

Die Sequenz des Schiffs besteht aus einer Spalte mit vier Einzelbildern (Zeilen), daher sind 4, 1 der zweite und dritte Parameter. Schließlich wird der Methode noch die Weite und die Höhe der einzelnen Ausschnitte mitgegeben, in diesem Fall 64x29 Pixel.

Systembedingt kann die Sequenz nicht direkt verwendet, sondern muß erst einer Textur zugewiesen werden, die dann in eine animierte Sequenz verwandelt wird. Dabei wird die gesamte Liste der Textur von Anfang bis Ende [:] durchlaufen. Die Dauer der einzelnen Sequenzen habe ich auf 0.1 gesetzt (das war mein erster naiver Versuch und er brachte auf Anhieb ein ansprechendes Ergebnis) und mit loop = True festgelegt, daß die Sequenz in einer Endlosschleife abgespielt werden soll.

Zu guter Letzt habe ich aus der animierten Sequenz ein Sprite gemacht, das im PyGlet-Fenster dargestellt werden kann. Dazu habe ich im Hauptprogramm das Template aus dem ersten Teil dieser Reihe wie folgt erweitert:

import pyglet
from pyglet.window import FPSDisplay
from gameobjects import GameObject
import os

TITLE = "Space Invaders Stage 1"

class GameWindow(pyglet.window.Window):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.set_location(100, 100)
        self.frame_rate = 1/60.0
        self.fps_display = FPSDisplay(self)
        self.fps_display.label.font_size = 24
        
        # Hier wird der Pfad zum Verzeichnis des ».py«-Files gesetzt
        # Erspart einem das Herumgehample in TextMate mit dem os.getcwd()
        # und os.path.join()
        file_path = os.path.dirname(os.path.abspath(__file__))
        os.chdir(file_path)
        
        self.player = GameObject(50, 300, "Spritesheet_64x29.png")
    
    def on_draw(self):
        self.clear()
        self.player.sprite.draw()
        
        self.fps_display.draw()
    
    def update(self, dt):
        pass

win = GameWindow(900, 600, TITLE, resizable = False)
pyglet.clock.schedule_interval(win.update, win.frame_rate)
pyglet.app.run()

Neben dem Herumspielen mit den Pfaden (dazu weiter unten mehr) und dem import des GameObjects sind eigentlich nur zwei Zeilen hinzugekommen. Mit

        self.player = GameObject(50, 300, "Spritesheet_64x29.png")

habe ich den Player initialisiert und mit

        self.player.sprite.draw()

habe ich die Rakete in das Spielefenster eingezeichnet. Der obige Screenshot gibt es ja nicht her, aber glaubt mir (oder programmiert es nach): Die Raktee zieht einen fröhlich flackernden Feuerschweif hinter sich her. (Natürlich weiß ich, daß es in der Leere des Weltalls keinen Feuerschweif gibt, aber es ist nur ein Spiel und mit flackernden Feuerschweif wirkt es viel lebendiger.)

Nun zu den beiden Zeilen

        file_path = os.path.dirname(os.path.abspath(__file__))
        os.chdir(file_path)

für die ich extra noch os importieren mußte. In den meisten Umgebungen sind diese beiden Zeilen nicht notwendig, da das current working directory (cwd) meist mit dem Verzeichnis der Python-Datei gleichgesetzt wird. Einige Editoren – wie zum Beispiel auch TextMate – setzten aber das cwd auf das Wurzelverzeichnis des Projektes und das bei mir nicht immer das Verzeichnis, in dem auch die Python-Skripte liegen (sie liegen oft tiefer). Dahr habe ich mir angewöhnt, mit diesen beiden Zeilen das cwd auf das Verzeichnis der Python-Datei zu legen.

So, in einem nächsten Schritt möchte ich die Rakete auf Nutzereingaben reagieren lassen. Sie soll dann ihre Position verändern und Laserkanonen abschießen können. Still digging!


(Kommentieren) 

image image



Über …

Der Schockwellenreiter ist seit dem 24. April 2000 das Weblog digitale Kritzelheft von Jörg Kantel (Neuköllner, EDV-Leiter, Autor, Netzaktivist und Hundesportler — Reihenfolge rein zufällig). Hier steht, was mir gefällt. Wem es nicht gefällt, der braucht ja nicht mitzulesen. Wer aber mitliest, ist herzlich willkommen und eingeladen, mitzudiskutieren!

Alle eigenen Inhalte des Schockwellenreiters stehen unter einer Creative-Commons-Lizenz, jedoch können fremde Inhalte (speziell Videos, Photos und sonstige Bilder) unter einer anderen Lizenz stehen.

Der Besuch dieser Webseite wird aktuell von der Piwik Webanalyse erfaßt. Hier können Sie der Erfassung widersprechen.

Diese Seite verwendet keine Cookies. Warum auch? Was allerdings die iframes von Amazon, YouTube und Co. machen, entzieht sich meiner Kenntnis.


Werbung


Werbung


image  image  image
image  image  image


image