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).
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:
Ü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!