image image


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

Mit meiner Hommage an Daniel Shiffmans »Coding Train«, ein Spiel mit einem hüpfenden Einhorn, das den »thisdot«-Zügen ausweichen muß, bin ich letzte Woche weitergekommen. Ich habe eine Kollisionserkennung implementiert und vergebe nun Punkte, die links oben angezeigt werden (Screenshot).

image

Die verwendete Kollisionserkennung hatte ich hier schon einmal implementiert. Ich habe sie als Methode der Klasse Coding Train hinzugefügt:

    def rect_collision(self, other):
        distanceX = (self.pos.x + self.d/2) - (other.x + other.d/2)
        distanceY = (self.pos.y + self.d/2) - (other.y + other.d/2)
        halfW = self.d/2 + other.d/2
        halfH = self.d/2 + other.d/2
        if (abs(distanceX) < halfW):
            if (abs(distanceY) < halfH):
                return True
        return False

Denn dann kann ich alle möglichen Kollisionen im Hauptprogramm in einer Schleife abfragen:

    for train in trains:
        if train.rect_collision(unicorn):
            print("Game Over")
            noLoop()

Da die eigentlich 100 Pixel weiten und hohen Bilder zu früh eine Kollisionserkennung melden, habe ich sie artifiziell verkleinert und sowohl der Klasse UnicornRainbow wie auch der Klasse CodingTrain je ein self.d = 90 spendiert. Dadurch wirkt die Kollisionserkennung doch etwas realistischer.

Für die Punkteanzeige habe ich mir bei Google den Font Ranchers heruntergeladen. Er steht unter einer Open Font Licence und kann daher frei verwendet werden.

Die Punkte hatte ich ja in meiner letzten Version dieses Programmes hochgezählt, nur angzeigt hatte ich sie noch nicht. Um den Font nutzen zu können, muß er erst einmal in das data-Verzeichnis des Sketches kopiert werden. Doch auch der Rest ist straightforward:

In der setup()-Funktion wird der Zeichensatz mit

    font = createFont("Ranchers-Regular.ttf", 30)
    textFont(font)

geladen und als aktueller Font installiert. Und die letzten zwei Zeilen in der draw()-Funktion schreiben den Punktestand in die obere, linke Fensterecke:

    textSize(30)
    text("Score: " + str(unicorn.score), 15, 40)

Die Anzeige erfolgt ganz zum Schluß, damit sie als letztes gerendert wird und eventuelle Trains, die ganz oben fahren, sie nicht überdecken.

So, und nun den kompletten Quellcode für alle, die das nachvollziehen und nachprogrammieren wollen. Zuerst der Reiter mit der Klasse Unicorn Rainbow:

class UnicornRainbow:
    
    def __init__(self):
        self.rainbow = []
        self.side = 6
        self.im = loadImage("unicorn.png")
        self.d = 90 # 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 den Reiter mit der Klasse CoodingTrain:

class CodingTrain:
    
    def __init__(self, x):
        self.im = loadImage("train.png")
        self.d = 90 # Durchmesser
        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
    
    def rect_collision(self, other):
        distanceX = (self.pos.x + self.d/2) - (other.x + other.d/2)
        distanceY = (self.pos.y + self.d/2) - (other.y + other.d/2)
        halfW = self.d/2 + other.d/2
        halfH = self.d/2 + other.d/2
        if (abs(distanceX) < halfW):
            if (abs(distanceY) < halfH):
                return True
        return False

Und zum Schluß – wie immer – der Hauptsketch:

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 3")
    # Font: https://fonts.google.com/specimen/Ranchers
    font = createFont("Ranchers-Regular.ttf", 30)
    textFont(font)
    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()
    for train in trains:
        if train.rect_collision(unicorn):
            print("Game Over")
            noLoop()
    textSize(30)
    text("Score: " + str(unicorn.score), 15, 40)

def keyPressed():
    if (key == " "):
        unicorn.up()

Das Spiel ist schon recht spielbar geworden, ich möchte mir nun »nur« noch ein paar Goodies überlegen, die es optisch und akustisch aufpeppen. Das kann aber ein Weile dauern, da ich mich – wie gestern angekündigt – erst einmal wieder mit Twine und dem Alice-Universum herumschlagen möchte. So viel zu spielen, so wenig Zeit!

Hier noch die Links zu den beiden früheren Beiträgen mit dem hüpfenden und einen Regenbogen hinter sich herziehenden Einhorn:

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

(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