Die Programmierung meines kleinen Halloween-Gimmicks in TigerJython, in dem der Spieler mit einer kleinen Rakete eine Menge herumstreunender Kürbisse jagen und abschießen muß, geht weiter. Wie gestern angekündigt, habe ich dem Spiel nun einen HUD (HUD – nicht Hut!) spendiert, einen »Head-Up-Display«, der den erreichten Punktestand anzeigt.
Dafür mußte ich tief in die Dokumentation eintauchen, denn die (»semi«-) offiziellen Tutorien tun sich schwer mit Erklärungen, wie man denn Texte in ein GameGrid-Fester zaubert. Aber ich wurde fündig: GameGrid besitzt eine Klasse TextActor()
, die genau dafür da ist. Als ersten Parameter bekommt sie den darzustellenden Text, der zweite Parameter ist die Farbe des Textes und der dritte Parameter die Farbe des Hintergrundes. Und schließlich muß noch der Font übergeben werden (der eine Subklasse von jawa.awt.font
ist). In meinem Fall sah der Aufruf daher so aus:
displayScore = TextActor("Score: " + str(self.score), c, BGCOLOR,
Font("ComicHelvetic_Medium", Font.BOLD, 20))
win.addActor(displayScore, Location(40, 20))
Als Font wollte ich die freie Comic Helvetic nutzen, mit der ich hier ja schon einmal herumgespielt hatte. Die Frage war nur: Findet TigerJython sie auch? Ja, einfach die .otf
-Datei in den Data-Folder verfrachten und dann den Font mit vollem Namen (aber ohne Dateiendung) aufrufen.
Ansonsten habe ich gegenüber der letzten Version nur noch eine kleine Änderung vorgenommen. Im Gegensatz zu den chaotischen Kürbissen sollte die Rakete, wenn sie auf den Spielfeldrand trifft, den Gesetzen der Physik gehorchen: Einfallswinkel = Ausfallswinkel. Das ist bei den senkrechten Rändern 180 Grad - Einfallswinkel und bei den waagrechten 360 Grad - Einfallswinkel. Das habe ich in diesen Zeilen berücksichtigt:
if self.getX() >= RIGHTMARGIN - 10:
self.setX(RIGHTMARGIN -10)
newDir = 180 - self.dir
self.setDirection(newDir)
self.dir = newDir
elif self.getX() <= LEFTMARGIN + 10:
self.setX(LEFTMARGIN + 10)
newDir = 180 - self.dir
self.setDirection(newDir)
self.dir = newDir
if self.getY() >= BOTTOMMARGIN - 10:
self.setY(BOTTOMMARGIN - 10)
newDir = 360 - self.dir
self.setDirection(newDir)
self.dir = newDir
elif self.getY() <= TOPMARGIN + 10:
self.setY(TOPMARGIN + 10)
newDir = 360 - self.dir
self.setDirection(newDir)
self.dir = newDir
Einmal in Bewegung wuselt nun die Rakete ganz schön flott über den Bildschirm und das jeweilige self.dir = newDir
sorgt dafür, daß auch die Geschosse in die Richtung feuern, die die Rakete eingeschlagen hat.
So, und hier ist der vollständige Quellcode dieses Zwischenstandes, damit Ihr das Programm bis hierher nachvollziehen und nachprogrammieren könnt:
# title: Pumpkin Attack Stage 3
# Author: Jörg Kantel
from gamegrid import *
from random import randint
import os
WIDTH = 680
HEIGHT = 680
LEFTMARGIN = 40 + 14
RIGHTMARGIN = 640 - 14
TOPMARGIN = 40 + 14
BOTTOMMARGIN = 640 - 14
NOPUMP = 30
DATAPATH = os.path.join(os.getcwd(), "data")
BGCOLOR = Color(color("#2b3e50"))
class Background(Actor):
def __init__(self):
Actor.__init__(self, False, os.path.join(DATAPATH, "moonnight2.jpg"))
class Player(Actor):
def __init__(self):
Actor.__init__(self, True, os.path.join(DATAPATH, "rocket1.png"))
self.dir = 0
self.speed = 5
self.firecount = 0
self.score = 0
c = Color.white
displayScore = TextActor("Score: " + str(self.score), c, BGCOLOR, Font("ComicHelvetic_Medium", Font.BOLD, 20))
win.addActor(displayScore, Location(40, 20))
def fire(self):
if self.firecount < 0:
missile = Missile()
enemyList = win.getActors(Enemy)
for enemy in enemyList:
missile.addCollisionActor(enemy)
win.addActor(missile, Location(self.getX(), self.getY()))
missile.direction = self.dir
self.firecount = 15
def act(self):
if isKeyPressed(37): # LEFT
self.dir -= 5 % 360
self.direction = self.dir
elif isKeyPressed(39): # RIGHT
self.dir += 5 % 360
self.direction = self.dir
elif isKeyPressed(38): # UP
self.move(self.speed)
if self.getX() >= RIGHTMARGIN - 10:
self.setX(RIGHTMARGIN -10)
newDir = 180 - self.dir
self.setDirection(newDir)
self.dir = newDir
elif self.getX() <= LEFTMARGIN + 10:
self.setX(LEFTMARGIN + 10)
newDir = 180 - self.dir
self.setDirection(newDir)
self.dir = newDir
if self.getY() >= BOTTOMMARGIN - 10:
self.setY(BOTTOMMARGIN - 10)
newDir = 360 - self.dir
self.setDirection(newDir)
self.dir = newDir
elif self.getY() <= TOPMARGIN + 10:
self.setY(TOPMARGIN + 10)
newDir = 360 - self.dir
self.setDirection(newDir)
self.dir = newDir
if isKeyPressed(32): # SPACE
self.fire()
self.firecount -= 1
class Missile(Actor):
def __init__(self):
Actor.__init__(self, True, os.path.join(DATAPATH, "missile.png"))
self.speed = 15
self.direction = player.dir
def act(self):
self.move(self.speed)
if self.getX() >= RIGHTMARGIN:
win.removeActor(self)
elif self.getX() <= LEFTMARGIN:
win.removeActor(self)
if self.getY() >= BOTTOMMARGIN:
win.removeActor(self)
elif self.getY() <= TOPMARGIN:
win.removeActor(self)
def collide(self, actor1, actor2):
xpos = actor2.getX()
ypos = actor2.getY()
win.removeActor(self)
win.removeActor(actor2)
hit = Explosion()
win.addActor(hit, Location(xpos, ypos))
# if player.score == 10:
# win.doPause() # Für Screenshot
player.score += 1
c = Color.white
displayScore = TextActor("Score: " + str(player.score), c, BGCOLOR, Font("ComicHelvetic_Medium", Font.BOLD, 20))
win.addActor(displayScore, Location(40, 20))
return 0
class Explosion(Actor):
def __init__(self):
Actor.__init__(self, True, os.path.join(DATAPATH, "explosion.png"))
self.timer = 5
def act(self):
self.timer -= 1
if self.timer <= 0:
win.removeActor(self)
class Enemy(Actor):
def __init__(self):
Actor.__init__(self, False, os.path.join(DATAPATH, "pumpkin.png"))
self.speed = randint(1, 5)
def act(self):
self.move(self.speed)
if self.getX() >= RIGHTMARGIN:
self.setX(RIGHTMARGIN)
self.direction -= randint(90, 270)
elif self.getX() <= LEFTMARGIN:
self.setX(LEFTMARGIN)
self.direction -= randint(90, 270)
if self.getY() >= BOTTOMMARGIN:
self.setY(BOTTOMMARGIN)
self.direction -= randint(90, 270)
elif self.getY() <= TOPMARGIN:
self.setY(TOPMARGIN)
self.direction -= randint(90, 270)
win = makeGameGrid(WIDTH, HEIGHT, 1, BGCOLOR, True)
win.setPosition(1300, 40)
win.setTitle("Pumpkin Attack, Stage 3 🎃") # Titelzeile mit Pumpkin-Emoji (im Editor nicht sichtbar)
win.setSimulationPeriod(20)
bg = Background()
win.addActor(bg, Location(WIDTH//2, HEIGHT//2))
for _ in range(NOPUMP):
p = Enemy()
win.addActor(p, Location(randint(54, 640 - 14), (randint(54, 640 - 14))))
p.setDirection(randint(20, 340))
player = Player()
win.addActor(player, Location(320, 320))
win.show()
win.doRun()
Und hier die Übersicht über die bisher veröffentlichten Folgen:
Ich denke, ich werde dem Spiel noch ein oder zwei Beiträge spendieren. Dann dürfte Halloween auch schon vorbei sein und die Kürbisse ihre Schuldigkeit getan haben. Still digging!
Ü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 ehemaliger 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!