image image


Ein glücklicher Spaziergänger in Pygame Zero

Nachdem ich gestern die Klasse Walker für die Vektorarithmetik nach Daniel Shiffmans »The Nature of Code« in Pygame Zero erfolgreich implementiert hatte, konnte ich nicht anders, ich mußte einen glücklichen Spaziergänger (Happy Walker) – natürlich ebenfalls mit Pygame Zero – programmieren. Grund war allerdings auch, daß ich über einen Satz freier Hintergrund-Layer gestolpert bin, die nahtlos ineinander übergehen, so daß ich mich mal wieder im Parallax Scrolling üben konnte.

image

Ich verstehe langsam besser als noch im letzten Herbst, wie man dem sich manchmal sträubenden Pygame Zero die Objektorientierung überstülpt, und so habe ich als erstes zwei Klassen definiert. Die Klasse Layer ist für die sechs Hintergrundlayer zuständig:

class Layer(Actor):
    
    def __init__(self, image, xpos, speed):
        Actor.__init__(self, image)
        self.left = xpos
        self.scroll_speed = speed
    
    def update(self):
        self.left -= self.scroll_speed
        if self.right < 0:
            self.left = TILEWIDTH - 1

Bei meinen ersten Versuchen hatte ich, wenn ein Layer resetted, ihn auf die Anfangsposition TILEWIDTH zurückgesetzt. Dann zeigte sich jedoch im Fenster ein häßlicher, ein Pixel breiter Streifen. Setzt man ihn jedoch auf TILEWIDTH - 1 zurück, verschwindet dieser Streifen. Warum das so ist, erschließt sich mir (noch) nicht, speziell weil beim Start dieser Streifen nicht auftritt. Aber wie dem auch sei, TILEWIDTH - 1 löste das Problem.

Die Klasse Walker ist die Blaupause für den Spaziergänger:

class Walker(Actor):
    
    def __init__(self, image, pos):
        Actor.__init__(self, image, pos)
        self.pos = pos
        self.count = 0
        self.speed = 1
    
    def update(self):
        self.count += self.speed
        if self.count > 20:
            self.count = 0
        if self.count < 11:
            self.image = "walk1.png"
        else:
            self.image = "walk2.png"

Nanu, keine draw()- oder show()-Methode? Nein, denn da die beiden Klassen Unterklassen von Actor sind, erben sie natürlich auch die draw()-Methode von Actor. Und da diese ziemlich »magische« Dinge anstellt, sollte man sie nach Möglichkeit nicht überschreiben.

Die meiste Tipparbeit ist das Initialisieren der einzelnen Instanzen der Klasse Layer, da ja jedes Hintergrundbild, das sich bewegt zwei Mal vorhanden sein muß. Aber wenn man die einzelnen Layer in eine Liste packt,

layers = [bg, sky1, sky2, mountain1, mountain2, hill1, hill2,
          fence1, fence2, ground1, ground2]

hat man dann in der Game Loop bedeutend weniger inzutippen:

def draw():
    for layer in layers:
        layer.draw()
    walker.draw()

def update():
    for layer in layers:
        layer.update()
    walker.update()

Das war es dann für heute. Für diejenigen unter Euch, die sich ein Fleißbienchen verdienen und meine kleine Fingerübung nachprogrammieren wollen, hier noch einmal der komplette Quellcode:

import pgzrun

WIDTH = 480
HEIGHT = 320
TITLE = "Happy Walker"
TILEWIDTH = 640

class Layer(Actor):
    
    def __init__(self, image, xpos, speed):
        Actor.__init__(self, image)
        self.left = xpos
        self.scroll_speed = speed
    
    def update(self):
        self.left -= self.scroll_speed
        if self.right < 0:
            self.left = TILEWIDTH - 1

class Walker(Actor):
    
    def __init__(self, image, pos):
        Actor.__init__(self, image, pos)
        self.pos = pos
        self.count = 0
        self.speed = 1
    
    def update(self):
        self.count += self.speed
        if self.count > 20:
            self.count = 0
        if self.count < 11:
            self.image = "walk1.png"
        else:
            self.image = "walk2.png"

bg = Layer("layer-1", 0, 0)
sky1 =Layer("layer-3", 0, 0.05)
sky2 =Layer("layer-3", TILEWIDTH, 0.05)
mountain1 =Layer("layer-4", 0, 0.1)
mountain2 =Layer("layer-4", TILEWIDTH, 0.1)
hill1 =Layer("layer-5", 0, 0.2)
hill2 =Layer("layer-5", TILEWIDTH, 0.2)
fence1 =Layer("layer-6", 0, 0.5)
fence2 =Layer("layer-6", TILEWIDTH, 0.5)
ground1 =Layer("layer-7", 0, 0.5)
ground2 =Layer("layer-7", TILEWIDTH, 0.5)

layers = [bg, sky1, sky2, mountain1, mountain2, hill1, hill2,
          fence1, fence2, ground1, ground2]

walker = Walker("walk1", (100, HEIGHT - 90))

def draw():
    for layer in layers:
        layer.draw()
    walker.draw()

def update():
    for layer in layers:
        layer.update()
    walker.update()

pgzrun.go()

Ihr findet den Quellcode und sämtliche Assets natürlich auch in meinem GitHub-Repositoium.

Ich könnte der kleinen, glücklichen Spielekonsole stundenlang bei ihrem Spaziergang zuschauen. Es ist schon seltsam, womit man in den Tagen der Corona-Pandemie die Zeit totschlägt. 🤓


(Kommentieren) 

image image



Über …

Der Schockwellenreiter ist seit dem 24. April 2000 das Weblog digitale Kritzelheft von Jörg Kantel (Neuköllner, EDV-Leiter Rentner, 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

Diese Spalte wurde absichtlich leergelassen!


Werbung


image  image  image
image  image  image


image