image image


Getting Started With PyGame (4): SpaceCute

In diesem vierten Teil meiner kleinen Tutorial-Reihe zu PyGame möchte ich Euch zeigen, wie viele Zeilen Programmcode man einsparen kann, wenn man Sprites in Klassen und SpriteGroups zusammenfaßt. Für die Sprites (und auch das Hintergrundbild) habe ich wieder auf ein (freies) Set von Daniel (Danc) Cook zurückgegriffen, diesmal auf das Set SpaceCute, das Ihr hier herunterladen (.zip, 1,6 MB) könnt. Da die einzelnen Sprites etwas groß geraten waren, habe ich sie im Graphikprogramm meiner Wahl zurechtgeschnitten, eventuell gespiegelt und auf eine Größe von 120x120 Pixeln heruntergerechnet.

image

Das Programm selber ist eine Erweiterung des letzten Tutoriums und soll demonstrieren, wie man mit einer Basisklasse unterschiedliche Sprites erzeugen und sie mit Hilfe der SpriteGroup mit nur einer Zeile Code animieren kann. Dafür habe ich erst einmal eine Basisklasse – ich habe sie Spaceship genannt – erzeugt:

class Spaceship(pygame.sprite.Sprite):
    
    def __init__(self, pic, posx, posy):
        pygame.sprite.Sprite.__init__(self)
        self.pic = pic
        self.posx = posx
        self.posy = posy
        self.image = pygame.image.load(pic).convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.centerx = posx
        self.rect.centery = posy
        self.dx = 0
        self.dy = 0
        
    def update(self):
        self.rect.centerx += self.dx
        if self.rect.left > screen.get_width():
            self.rect.right = 0
            self.rect.centery = random.randrange(50, screen.get_height()-85)
        elif self.rect.right < 0:
            self.rect.left = screen.get_width()
            self.rect.centery = random.randrange(50, screen.get_height()-85)

Wie Ihr seht, habe ich dem »Constructor« __init__() dieses Mal Parameter mitgegeben, einmal die Position, die das Sprite beim Start des Programmes einnehmen soll (posx, posy) und dann den Pfad- und den Dateinamen für das Bild, das das Sprite auf dem Monitor repräsentiert. Da ich die Anzahl der Parameter nicht zu groß werden lassen und weil ich demonstrieren wollte, wie man nachträglich Werte von Instanzen einer Klassen ändert, habe ich self.dx und self.dy auf Null gesetzt – sie werden später geändert.

Die update()-Funktion behandelt nun nicht mehr nur den rechten Rand des Bildschirms, sondern auch den linken. Denn die Sprites sollen auch in beide Richtungen (von rechts nach links wie auch von links nach rechts) über den Bildschirm wuseln können.

In der Hauptroutine main() habe ich die einzelnen Sprites initialisiert und sie einer SpriteGroup, die ich allSprites genannt habe, zugeteilt.

    # background = pygame.Surface(screen.get_size())
    # background.fill((0, 80, 125))
    background = pygame.image.load("images/background.png").convert()
    screen.blit(background, (0, 0))

    planet    = Spaceship("images/planet.png", 500, 500)
    planet.dx = 1
    rocket    = Spaceship("images/rocketship.png", 300, 300)
    rocket.dx = 10
    octopussy = Spaceship("images/octopus2.png", 400, 400)
    octopussy.dx = -5
    beetle    = Spaceship("images/beetleship.png", 200, 200)
    beetle.dx = 3
    allSprites = pygame.sprite.Group(planet, rocket, octopussy, beetle)

Dort seht Ihr auch, wie ich das dx jeweils individuell für die einzelnen Sprites gesetzt habe. Dazu habe ich noch ein Bild als Hintergrund geladen, wenn Ihr das nich möchtet, kommentiert die Zeile einfach aus und nehmt stattdessen die beiden darüber stehenden, auskommentierten Zeilen, die den gewohnten blauen Hintergrund zeichnen.

Das ist eigentlich schon alles. Da die ganze Sprite-Mechanik in der update()-Methode der Basisklasse stattfindet, die von der SpriteGroup für alle aufgerufen wird, ist das gesamte Skript mal wieder von erfrischender Kürze (hier ist es für Euer Interesse und damit Ihr es nachprogrammieren könnt, vollständig wiedergegeben):

#!python
# coding=utf-8

# PyGame: SpaceCute

import pygame, random
from pygame.locals import *

pygame.init()

screen = pygame.display.set_mode((800, 600))

class Spaceship(pygame.sprite.Sprite):
    
    def __init__(self, pic, posx, posy):
        pygame.sprite.Sprite.__init__(self)
        self.pic = pic
        self.posx = posx
        self.posy = posy
        self.image = pygame.image.load(pic).convert_alpha()
        self.rect = self.image.get_rect()
        self.rect.centerx = posx
        self.rect.centery = posy
        self.dx = 0
        self.dy = 0
        
    def update(self):
        self.rect.centerx += self.dx
        if self.rect.left > screen.get_width():
            self.rect.right = 0
            self.rect.centery = random.randrange(50, screen.get_height()-85)
        elif self.rect.right < 0:
            self.rect.left = screen.get_width()
            self.rect.centery = random.randrange(50, screen.get_height()-85)

def main():
    
    pygame.display.set_caption("SpaceCute")
    
    # background = pygame.Surface(screen.get_size())
    # background.fill((0, 80, 125))
    background = pygame.image.load("images/background.png").convert()
    screen.blit(background, (0, 0))

    planet    = Spaceship("images/planet.png", 500, 500)
    planet.dx = 1
    rocket    = Spaceship("images/rocketship.png", 300, 300)
    rocket.dx = 10
    octopussy = Spaceship("images/octopus2.png", 400, 400)
    octopussy.dx = -5
    beetle    = Spaceship("images/beetleship.png", 200, 200)
    beetle.dx = 3
    allSprites = pygame.sprite.Group(planet, rocket, octopussy, beetle)
    
    clock = pygame.time.Clock()
    keepGoing = True

    while keepGoing:
        # Max Framerate 30 fps
        clock.tick(30)
    
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                keepGoing = False
        
        allSprites.clear(screen, background)
        allSprites.update()
        allSprites.draw(screen)
        
        pygame.display.flip()

if __name__ == "__main__":
    main()

Falls Ihr das Skriptchen nachprogrammieren wollt, hier für Euch auch noch einmal die von mir verwendeten Bildchen:

image image image image

Caveat

Wenn Ihr das Skript laufen lasst, werdet Ihr feststellen, daß es keine wirkliche Ordnung gibt, in welcher Reihenfolge die Sprites der SpriteGroup nach einem Neustart gezeichnet werden. Mal ist der Planet vor der Rakete, mal fliegt die Rakete hinter dem Planeten vorbei usw. Es gibt in PyGame auch Funktionen, die die z-Order der Sprites berücksichtigen, doch die benötigen mehr Ressourcen und da die Reihenfolge für das Beispiel unerheblich ist, habe ich es erst einmal dabei belassen.

Als nächstes möchte ich auf Basis dieses Beispielskriptes (und der darin verwendeten Sprites) ein Minispiel programmieren und Euch vorstellen. Dafür werde ich vermutlich mehrere Blogbeiträge benötigen. Still digging!

Die bisherigen PyGame-Tutorials im Schockwellenreiter

Wird (hoffentlich) fortgesetzt …


(Kommentieren)  Getting Started With PyGame (4): SpaceCute – 20160526 bitte flattrn

image image



Über …

Der Schockwellenreiter ist seit dem 24. April 2000 das Weblog digitale Kritzelheft von Jörg Kantel (Neuköllner, EDV-Leiter, 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


Werbung


image  image  image
image  image  image