image image


image

Killer-Kürbisse? Wir schießen zurück! (Happy Halloween Stage 2)

Ich hatte es mir vorgenommen, Männergrippe hin oder her, bis zum Wochenende mein kleines – in TigerJython (mit GameGrid) programmiertes – Halloween-Spiel mit gefährlichen Kürbissen, denen der Spieler entweder ausweichen oder die er abschießen muß, fertigzustellen. Wer von meinen Leserinnen oder Lesern meint, dies hätte aber gewaltige Ähnlichkeit mit der »Attacke der Killer-Pizzen«, die oder der haben natürlich recht: Ballerspiele sind nun einmal Ballerspiele, die Variationsmöglichkeiten sind da eher begrenzt.

Ich betrachte es daher auch eher als Fingerübung. Einmal, um mehr über die Möglichkeiteiten von TigerJython und der GameGrid-Bibliothek zu lernen, und zum anderen, um trotz Männergrippe bis Halloween ein wenig Spaß zu haben.

Daher geht es nun erst einmal darum, den Spieler ins Spiel zu bringen, ihn über das Spielfeld zu scheuchen und ihm die Möglichkeit zu geben, Kürbisse abzuschießen.

Der Spieler ist eine kleine, blaue Rakete (sein Bildchen habe ich – wie das der Kürbisse – von Twitters Twemojis geklaut und ein wenig bearbeitet). Im Gegensatz zu den Kürbissen soll er aber nicht nur die Richtung ändern können, sondern mit der Raketenspitze auch in die Richtung zeigen, in die er fliegt oder seine Raketen verschießt. Dafür muß im Konstruktor der zweite Parameter (nach self) auf True gesetzt sein:

    def __init__(self):
        Actor.__init__(self, True, os.path.join(DATAPATH, "rocket1.png"))

Mit den Pfeiltasten »Rechts« und »Links« kann ich nun den Spieler jeweils um fünf Grad seine Richtung ändern lassen:

    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

Mit der Leertaste kann der Spieler Raketen abschießen. Die dafür benutzte Klasse Missile() ist der gleichnamigen Klasse aus dem Pizza-Spiel sehr ähnlich, mit der Ausnahme, daß die Richtung der Raketen natürlich mit der Richtung des Spielers übereinstimmen muß:

class Missile(Actor):
    
    def __init__(self):
        Actor.__init__(self, True, os.path.join(DATAPATH, "missile.png"))
        self.speed = 15
        self.direction = player.dir

Mit der Pfeiltaste nach oben wird der Spieler in seine aktuelle Richtung bewegt, und mit ein wenig Zauberei mit den Konstanten RIGHTMARGIN, LEFTMARGIN, BOTTOMMARGIN und TOPMARGIN habe ich dem Umstand Rechnung getragen, daß das Spielfeld im Fenster eingemittet ist, das Spielefenster also größer ist als das Spielfeld:

        elif isKeyPressed(38):     # UP
            self.move(self.speed)
            if self.getX() >= RIGHTMARGIN - 10:
                self.setX(RIGHTMARGIN -10)
            elif self.getX() <= LEFTMARGIN + 10:
                self.setX(LEFTMARGIN + 10)
            if self.getY() >= BOTTOMMARGIN - 10:
                self.setY(BOTTOMMARGIN - 10)
            elif self.getY() <= TOPMARGIN + 10:
                self.setY(TOPMARGIN + 10)

Den Rand habe ich gebastelt, weil ich oben ein wenig Platz für den Spielstand haben möchte. Wie ich die Punkte dahinzaubere, weiß ich noch nicht genau, aber GameGrid besitzt die Klasse TextActor(), die das können sollte.

Die Behandlung der Geschosse wie auch die der Explosionen läuft ansonsten genauso wie bei den bösen Pizzen ab, daher hier erst einmal der komplette Quellcode zum Nachlesen und Nachprogrammieren:

# title: Pumpkin Attack Stage 2
# 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")

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
        
    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)
            elif self.getX() <= LEFTMARGIN + 10:
                self.setX(LEFTMARGIN + 10)
            if self.getY() >= BOTTOMMARGIN - 10:
                self.setY(BOTTOMMARGIN - 10)
            elif self.getY() <= TOPMARGIN + 10:
                self.setY(TOPMARGIN + 10)
        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))
        # win.doPause()         # Für Screenshot
        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, Color(color("#2b3e50")), True)
win.setPosition(1300, 40)
win.setTitle("Pumpkin Attack, Stage 2 🎃")   # 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()

Wie immer gibt es den Quellcode (wie auch die bisher verwendeten Assets) in meinem GitLab-Repositorium zu TigerJython. Und damit Ihr nicht ständig die Suchmaschine Eures Vertrauens bemühen müßt, gibt es hier eine Übersicht über die bisher veröffentlichten Folgen:

Je mehr ich mit TigerJython spiele und je besser ich das Framework kennenlerne, um so mehr Ideen gehen mir durch den Kopf. Denn es ist erstaunlich, was man alles entdecken kann, wenn man sich durch die etwas versteckten Features wühlt. Im wahrsten Sinne des Wortes: 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 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!


Werbung


image  image  image
image  image  image


image