image image


image

Ich habe fertig: Alien Attack Stage 3 (final)

Das Spiel »Alien Attack« – ein Space Invaders-Klon –, das ich zur Erkundigung der Möglichkeiten von TigerJython und der mitgelieferten Spielebibliothek GameGrid hier zu programmieren angefangen hatte, ist mittlerweile fertig. Wie angekündigt, habe ich den Aliens Bomben spendiert, mit der sie den Spieler bombardieren können. Dazu habe ich analog zur Klasse Missile eine Klasse Bomb implementiert:

class Bomb(Actor):
    
    def __init__(self):
        Actor.__init__(self, "sprites/creature.gif", 2)
        self.timer = 10
        self.speed = 5
    
    def act(self):
        self.timer -= 1
        ypos = self.getY()
        self.setY(ypos + self.speed)
        if ypos > 600:
            win.removeActor(self)
        if self.timer == 0:
            self.showNextSprite()
            self.timer = 10
    
    def collide(self, actor1, actor2):
        gameover()
        return(0)

Sie ist der Klasse Missile wirklich sehr ähnlich, mit dem Unterschied, daß sie verschwindet, wenn sie den unteren Rand des Fensters erreicht hat. Nur die Methode collide() ist sehr viel einfacher, denn wenn eine Bombe das Raumschiff des Spielers trifft, ist das Spiel zu Ende und die Funktion gameover() wird zum Schluß bemüht.

Doch auch die Methode collide() in Missile hat eine Änderung erfahren. Denn wenn kein Alien mehr lebt, dann hat der Spieler gewonnen und die Funktion winner() wird aufgerufen:

        win.addActor(hit, Location(xpos, ypos))
        if win.getNumberOfActors(Alien) == 0:
            winner()

Zum Schluß mußte ich nur noch die Funktionen gameover() und winner() implementieren:

def gameover():
    hit = Explosion()
    win.addActor(hit, Location(player.getX(), 565))
    win.removeActor(player)
    youLost = Actor("sprites/gameover.gif")
    win.addActor(youLost, Location(300, 300))
    win.doPause()
 
def winner():
    youWin = Actor("sprites/you_win.gif")
    win.addActor(youWin, Location(300, 300))
    win.doPause()

Die Instanzen youLost und youWin habe ich direkt von der Oberklasse Actor abgeleitet, denn Ihre einzige Aufgabe besteht darin, jeweils ein Bild auf das Spielfeld zu bringen, das entweder Game Over oder You Win anzeigt. Dafür jeweils eine eigene Subklasse zu erstellen, erschien mir – trotz meiner Vorliebe für Klassenbildung – doch etwas zu überambitioniert.

Wie man an der Funktion gameover() erkennen kann, explodiert auch das getroffene Raumschiff.

Doch nun den endgültigen und vollständigen Code meines Space-Invaders-Klons, damit Ihr das Skript nachvollziehen und/oder nachprogrammieren könnt:

from gamegrid import *
from random import randint

win = makeGameGrid(600, 600, 1, None, "sprites/town.jpg", False )
win.setTitle("Alien Attack Stage 3")
win.setSimulationPeriod(20)

class SpaceShip(Actor):
    
    def __init__(self):
        Actor.__init__(self, "sprites/spaceship.gif")
        self.timer = 0
        
    def act(self):
        self.timer -= 1
    

class Missile(Actor):
    
    def __init__(self):
        Actor.__init__(self, "sprites/bomb.gif")
        self.speed = 5
    
    def act(self):
        ypos = self.getY()
        self.setY(ypos - self.speed)
        if ypos < 0:
            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 win.getNumberOfActors(Alien) == 0:
            winner()
        return(0)
            
class Alien(Actor):
    
    def __init__(self):
        Actor.__init__(self, "sprites/alien.gif", 2)
        self.ypos = 0
        self.timer = 10
        self.speed = 0.1
    
    def act(self):
        self.ypos += self.speed
        self.setY(int(self.ypos))
        self.timer -= 1
        if self.timer == 0:
            self.showNextSprite()
            self.timer = 10
        if randint(1, 1000) == 500:
            bomb = Bomb()
            bomb.addCollisionActor(player)
            win.addActor(bomb, Location(self.getX(), self.getY() + 10))
        if self.ypos > 580:
            gameover()

class Bomb(Actor):
    
    def __init__(self):
        Actor.__init__(self, "sprites/creature.gif", 2)
        self.timer = 10
        self.speed = 5
    
    def act(self):
        self.timer -= 1
        ypos = self.getY()
        self.setY(ypos + self.speed)
        if ypos > 600:
            win.removeActor(self)
        if self.timer == 0:
            self.showNextSprite()
            self.timer = 10
    
    def collide(self, actor1, actor2):
        gameover()
        return(0)
            
class Explosion(Actor):
    
    def __init__(self):
        Actor.__init__(self, "sprites/hit.gif")
        self.timer = 5
    
    def act(self):
        self.timer -= 1
        if self.timer == 0:
            win.removeActor(self)

def fire():
    if player.timer < 0:
        missile = Missile()
        aliens = win.getActors(Alien)
        for alien in aliens:
            missile.addCollisionActor(alien)
        bombs = win.getActors(Bomb)
        for bomb in bombs:
            missile.addCollisionActor(bomb)
        win.addActor(missile, Location(player.getX(), 550))
        player.timer = 10
    
def keyCallback(keyCode):
    xpos = player.getX()
    if keyCode == 37: #left
        if xpos > 20:
            player.setX(xpos - 5)
    elif keyCode == 39: #right
        if xpos < 580:
            player.setX(xpos + 5)
    elif keyCode == 32: #space
        fire()

def gameover():
    hit = Explosion()
    win.addActor(hit, Location(player.getX(), 565))
    win.removeActor(player)
    youLost = Actor("sprites/gameover.gif")
    win.addActor(youLost, Location(300, 300))
    win.doPause()
 
def winner():
    youWin = Actor("sprites/you_win.gif")
    win.addActor(youWin, Location(300, 300))
    win.doPause()

for row in range(50, 300, 50):
    for col in range(40, 570, 40):
        alien = Alien()
        alien.ypos = row
        win.addActor(alien, Location(col, row))

player = SpaceShip()
win.addActor(player, Location(300, 560))
win.addKeyRepeatListener(keyCallback)

win.show()
win.doRun()

Die Beschäftigugn mit dem GameGrid-Modul hat mir sehr viel Spaß gebracht und ich habe dadurch – dank den Beispielprogramm aus dem Buch Let’s Code Python von Hauke Fehr auch sehr viel gelernt. Ich werde daher als nächstes meine DawnHawk-Implementierung (Stage 1 und Stage 2) den neugewordenen Erkenntnissen anpassen müssen. Ich möchte mit ihr nämlich einige Algorithmen aus der Künstlichen Intelligenz für die Spieleprogrammierung vorstellen, denn dafür scheint mir TigerJython mit GameGrid wirklich ideal geeignet zu sein. 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