image image


Coding Train Unicorn Rainbow mit Processing.py (Stage 2)

Mein hüpfendes Einhorn, dessen Programmierung mit Processing.py ich hier begonnen hatte, macht Fortschritte. Es folgt nicht mehr der Maus, sondern wird mit der SPACE-Taste zum Hüpfen animiert, wobei die Schwerkraft das Fabeltier wieder nach unten zwingt. Bei der Implementierung habe ich mich an Fluffy Fish orientiert, einen Flappy Bird-Klon, den ich vor über zwei Jahren schon in Processing.py programmiert hatte.

image

Verabschiedet habe ich mich von der Vorstellung, daß das Spiel zu Ende sei, wenn das Einhorn mit dem oberen oder unteren Bildschirmrand kollidiert. Das Spiel war für mich dann unspielbar (ich bin allerdings auch kein guter Spieler). Jetzt ist der Plan, daß das Einhorn »nur« noch den Lokomotiven ausweichen muß, von denen ich als erstes einfach mal zwei implementiert habe.

Doch genug der Vorrede, jetzt zum Code: Dem Konstruktor der Klasse Einhorn habe ich ein paar neue Variablen verpaßt, speziell self.y, die das mouseY der ersten Version ersetzen soll.

    def __init__(self):
        self.rainbow = []
        self.side = 6
        self.im = loadImage("unicorn.png")
        self.d = 100 # Durchmesser
        self.score = 0
        self.x = 240
        self.y = 100
        self.offset_rainbow = self.x + 30
        
        self.gravity = 0.6
        self.lift = -12
        self.velocity = 0

Dann habe ich noch mit self.gravity, self.velocity und self.lift drei Variablen implementiert, die das Sprung- und Fallverhalten des Einhorns bestimmen. Sie kommen in der Hauptsache in den up()- und update()-Methoden zum Einsatz:

    def up(self):
        self.velocity += self.lift
       
    def update(self):
        self.velocity += self.gravity
        self.velocity *= 0.9
        self.y += self.velocity
        # check borders
        if self.y >= height - self.d:
            self.y = height - self.d
            self.velocity = 0
        elif self.y <= 0:
                self.y = 0
                self.velocity = 0

Wenn die SPACE-Taste gedrückt wird, schnellt das Einhorn ein wenig nach oben um dann wieder sanft zu fallen. Damit die velocity-Werte nicht zu groß werden, habe ich ihnen noch eine Reibungskonstante von 0.9 spendiert, mit der sie multipliziert werden. Der Rest der Klasse ist unverändert geblieben.

Auch die Klasse CodingTrain hat sich fast nichts verändert, außer das ich dem Konstruktor nun noch ein x mitgebe, daß die Startposition des jeweiligen Zuges bestimmt. Lediglich im Hauptprogramm habe ich noch ein paar Veränderungen vorgenommen: Die setup()-Funktion füllt nun die Liste trains[] mit Zügen,

    for i in range(NO_TRAINS):
        train = CodingTrain((i*400) + 200)
        trains.append(train)

die in der draw()-Methode ausgelesen wird, um für jeden Zug ein update() und ein show() aufzurufen.

    global unicorn, trains
    background(64)
    for train in trains:
        train.update()
        if train.reset:
            unicorn.score += 1
            print(unicorn.score)
    unicorn.add_rainbow_stripes()
    unicorn.update()
    for train in trains:
        train.show()
    unicorn.show()

Für alle, die das nachprogrammieren möchten, hier der vollständige Sketch, zuerst die Klasse UnicornRainbow:

class UnicornRainbow:
    
    def __init__(self):
        self.rainbow = []
        self.side = 6
        self.im = loadImage("unicorn.png")
        self.d = 100 # Durchmesser
        self.score = 0
        self.x = 240
        self.y = 100
        self.offset_rainbow = self.x + 30
        
        self.gravity = 0.6
        self.lift = -12
        self.velocity = 0
                                
    def add_rainbow_stripes(self):
        rectMode(CENTER)
        self.rainbow.append(([self.offset_rainbow, self.y + (self.side*7), self.side, self.side],
                            color(240, 80, 37)))
        self.rainbow.append(([self.offset_rainbow, self.y + (self.side*8), self.side, self.side],
                            color(248, 158, 80)))
        self.rainbow.append(([self.offset_rainbow, self.y + (self.side*9), self.side, self.side],
                            color(248, 239, 34)))
        self.rainbow.append(([self.offset_rainbow, self.y + (self.side*10), self.side, self.side],
                            color(49, 197, 244)))
        self.rainbow.append(([self.offset_rainbow, self.y + (self.side*11), self.side, self.side],
                            color(240, 99, 164)))
        self.rainbow.append(([self.offset_rainbow, self.y + (self.side*12), self.side, self.side],
                            color(129, 122, 198)))
    
    def delete_stripes(self):
        rainbow_copy = [stripe for stripe in self.rainbow if stripe[0][0] >= 0]
        self.rainbow = rainbow_copy
        # print(len(self.rainbow))
    
    def up(self):
        self.velocity += self.lift
       
    def update(self):
        self.velocity += self.gravity
        self.velocity *= 0.9
        self.y += self.velocity
        # check borders
        if self.y >= height - self.d:
            self.y = height - self.d
            self.velocity = 0
        elif self.y <= 0:
                self.y = 0
                self.velocity = 0
        if self.rainbow:
            self.delete_stripes()
            for stripe in self.rainbow:
                stripe[0][0] -= 2
                
    def show(self):    
        for stripe in self.rainbow:
            col = stripe[1]
            fill(col)
            noStroke()
            rect(stripe[0][0], stripe[0][1], stripe[0][2], stripe[0][3])
        image(self.im, self.x, self.y)

Dann die Klasse CodingTrain:

class CodingTrain:
    
    def __init__(self, x):
        self.im = loadImage("train.png")
        self.pos = PVector(width + x, random(height - 100))
        self.speed = 5
        self.reset = False

    def update(self):
        self.pos.x -= self.speed
        if self.pos.x < -100:
            self.reset = True
            self.pos = PVector(width + 200, random(height - 100))
    
    def show(self):
        image(self.im, self.pos.x, self.pos.y)
        self.reset = False

Und zu guter Letzt das Hauptprogramm:

from unicornrainbow import UnicornRainbow
from codingtrain import CodingTrain

trains = []
NO_TRAINS = 2

def setup():
    global unicorn, trains
    size(720, 360)
    this.surface.setTitle("Coding Train Unicorn Rainbow Stage 2")
    unicorn = UnicornRainbow()
    for i in range(NO_TRAINS):
        train = CodingTrain((i*400) + 200)
        trains.append(train)

def draw():
    global unicorn, trains
    background(64)
    for train in trains:
        train.update()
        if train.reset:
            unicorn.score += 1
            print(unicorn.score)
    unicorn.add_rainbow_stripes()
    unicorn.update()
    for train in trains:
        train.show()
    unicorn.show()
    
def keyPressed():
    if (key == " "):
        unicorn.up()

def mousePressed():
    noLoop() # Für Screenshot

Die Funktion keyPressed ruft, wenn die SPACE-Taste gedrückt wird, die Methode unicorn.up() auf und läßt das Einhorn nach oben schnellen, die Funktion mousePressed() hält immer noch das Spiel an, damit ich einen Screenshot erstellen kann. 🤓

Jetzt muß ich nur noch eine Kollisionserkennung programmieren. Da ich diese vor etwa einem Jahr schon einmal programmiert hatte, sollte dies schnell vonstatten gehen. Danach sollte das Spiel schon beinahe spielbar sein, dann kommen die Special Effects. Darauf freue ich mich besonders. 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 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