Hier hatte ich geschrieben, daß ich gerne einmal einen Side-Scroller mit Bewegungsparallaxe programmieren möchte. Ursprünglich hatte ich dafür Pygame Zero vorgesehen, aber nachdem ich schon ein erstes Tutorial mit Algorithmen für Spieleprogrammierer (Tile Based Movement) in Processing.py geschrieben hatte, dachte ich, daß solch ein Side-Scroller auch in die Kategorie »Algorithmen für Spieleprogrammierer« gehöre und habe ihn daher ebenfalls in Processing.py implementiert.
In diesem ersten Teil geht es nur darum, die Bewegungsparallaxe vorzustellen. Ich möchte Euch zeigen, wie diese funktioniert. Dazu habe ich drei Ebenen erschaffen, erstens die Ebene mit den Wolken, dann eine Hintergrundebene mit großen Hügeln und eine letzte Ebene mit kleinen, dunkelgrünen Hügelchen. Der Einfachheit halber habe ich diese Hügel als (Halb-) Kreise implementiert. Sie leiten sich alle von einer Klasse ab:
class Hill(object): def __init__(self, x, r, s, c): self.xpos = x self.radius = r self.step = s self.col = c def update(self): self.xpos += self.step if self.xpos <= -self.radius: self.xpos = width + self.radius def show(self): fill(self.col) circle(self.xpos, 400, 2*self.radius)
Auch die Wolken (eigentlich gibt es nur eine, die immer wieder über den Hintergrund geschoben wird) setzt sich aus Kreisen zusammen:
class Cloud(object): def __init__(self, x, s): self.xpos = x self.step = s def update(self): self.xpos += self.step if self.xpos <= -200: self.xpos = width + 200 def show(self): fill("#ffffff") circle(self.xpos, 150, 100) circle(self.xpos, 200, 100) circle(self.xpos - 50, 200, 100) circle(self.xpos + 50, 200, 100)
Der Clou ist hierbei, daß die Wolke nur eine Koordinate (xpos
) für den Hauptkreis benötigt, die anderen Koordinaten werden davon abgeleitet.
Der Eindruck einer Bewegungsparallaxe entsteht dadurch, daß sich die Ebenen mit unterschiedlichen, gestaffelten Geschwindigkeiten von rechts nach links über den Bildschirm bewegen. Der Hintergrund schiebt sich langsam mit einem Pixel per Frame durch das Bild, die großen, hellgrünen Hügel bewegen sich mit zwei Pixeln pro Frame und die kleinen Hügel vorne rasen mit sagenhaften drei Pixeln per Frame vorbei:
Ganz vorne ist dann noch die Ebene, auf der sich der Spieler bewegt. Diese habe ich einfach durch ein passendes, hellbraunes Rechteck in voller Fensterbreite dargestellt, das sich – genau wie der Spieler – nicht bewegt:
for cloud in clouds: cloud.update() cloud.show() # Große Hügel im Hintergrund for hill in bighills: hill.update() hill.show() # Kleine Hügel im Vordergrund for hill in smallhills: hill.update() hill.show() # Erdboden fill("#ffd05e") rect(0, 400, width, 50) # Sprites (erst einmal nur das rosa Alien) for sprite in sprites: sprite.update() sprite.show()
Der Spieler klebt tatsächlich an einer festen Position. Der Eindruck der Bewegung entsteht nur durch die vorbeigleitenden Hintergründe.
Der Screenshot kann natürlich nur einen Hauch des Eindrucks der Tiefe vermitteln, den die Animationen tatsächlich dem Zuschauer vorgaukelt.
Zur Unterstützung dieses Bewegungseindrucks lasse ich den Spieler – ein kleines rosa Alien aus der freien Sprite-Sammlung von Kenney.nl, daß ich hier auch schon mal verwendet hatte – ein wenig zappeln (ich tausche zwei Bildchen in regelmäßigen Abständen aus):
def show(self): if self.status == "walking": self.count += 1 if self.count > 15: self.count = 0 if self.count < 8: image(self.im1, self.x, self.y) else: image(self.im2, self.x, self.y)
Den kompletten Code habe ich – wie man dem Headerbild entnehmen kann – auf drei Reiter aufgeteilt. Der erste enthält das Hauptprogramm:
# Side Scroller 1 from backgrounds import Hill, Cloud from sprites import Alien FPS = 60 clouds = [] bighills = [] smallhills = [] sprites = [] def setup(): size(800, 450) this.surface.setTitle("Side Scroller 1") clouds.append(Cloud(400, -1)) for i in range(3): bighills.append(Hill(i*400, 200, -2, "#63e06b")) for i in range(6): smallhills.append(Hill(i*200, 100, -3, "#217424")) sprites.append(Alien(66, 320)) frameRate(FPS) noStroke() def draw(): background(64, 176, 226) # Wolke(n) im Hintergrund for cloud in clouds: cloud.update() cloud.show() # Große Hügel im Hintergrund for hill in bighills: hill.update() hill.show() # Kleine Hügel im Vordergrund for hill in smallhills: hill.update() hill.show() # Erdboden fill("#ffd05e") rect(0, 400, width, 50) # Sprites (erst einmal nur das rosa Alien) for sprite in sprites: sprite.update() sprite.show()
Der zweite Reiter backgrounds.py
exportiert die Klassen Hill()
und Cloud
, wobei ich die Klasse Hill()
, wie oben schon kurz erwähnt, so allgemein gehalten habe, daß sie sowohl als Blaupause für die großen wie auch für die kleinen Hügel herhalten kann:
# coding=utf-8 class Hill(object): def __init__(self, x, r, s, c): self.xpos = x self.radius = r self.step = s self.col = c def update(self): self.xpos += self.step if self.xpos <= -self.radius: self.xpos = width + self.radius def show(self): fill(self.col) circle(self.xpos, 400, 2*self.radius) class Cloud(object): def __init__(self, x, s): self.xpos = x self.step = s def update(self): self.xpos += self.step if self.xpos <= -200: self.xpos = width + 200 def show(self): fill("#ffffff") circle(self.xpos, 150, 100) circle(self.xpos, 200, 100) circle(self.xpos - 50, 200, 100) circle(self.xpos + 50, 200, 100)
Mit diesen beiden Reitern läßt sich die Simualtion der Bewegungsparallaxe schon sehr schön zeigen. Der letzte Reiter ist noch sehr unvollständig und hübscht mit dem rosa Alien die Szene nur ein wenig auf:
# coding=utf-8 class Sprite(object): def __init__(self, x, y): self.x = x self.y = y def update(self): pass def show(self): pass class Alien(Sprite): def __init__(self, x, y): Sprite.__init__(self, x, y) self.status = "walking" self.im1 = loadImage("alienwalk1.png") self.im2 = loadImage("alienwalk2.png") self.count = 0 def show(self): if self.status == "walking": self.count += 1 if self.count > 15: self.count = 0 if self.count < 8: image(self.im1, self.x, self.y) else: image(self.im2, self.x, self.y)
Später sollen hier noch die Gegner des Spielers wie auch Hindernisse und andere Objekte hinzukommen, die dann alle von der (momentan noch sehr rudimentären) Klasse Sprite()
abgeleitet werden.
Und damit Ihr den Sketch nicht nur nachvollziehen, sondern auch nachprogrammieren könnt, hier die beiden Bildchen des Alien:
In einem nächsten Beitrag werde ich dieses Alien auch noch hüpfen lassen, damit es Hindernissen und Gegnern ausweichen kann. Und vielleicht wird es auch noch einen dritten Teil geben, in dem ich die Hügel und Wolken mit weiteren Bildern aus dem unerschöpflichen Fundes von Kenney.nl aufhübsche. Still digging!
Ü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