[2.7][PyGame] Grundlagen für PyGame.

Benutzeravatar
Vaixell
Schleifen-Versteher
Beiträge: 16
Registriert: Di Apr 23, 2013 7:42 pm
Wohnort: Ostbevern
Kontaktdaten:

[2.7][PyGame] Grundlagen für PyGame.

Beitragvon Vaixell » Mi Mai 08, 2013 7:54 pm

Moin und willkommen zu meinem knackigen PyGame-Grundlagen-Gedöns. Hiermit möchte ich euch die ersten Schritte in der Programmierung mit PyGame zeigen. Source lässt sich einfach downloaden, sowie die anderen Teile wie Sound, Grafiken usw.. Ich möchte an der Stelle darauf hinweisen, dass Pythonkenntnisse von Nöten sind.

Inhaltsverzeichnis:
- 1. Was ist PyGame?
- 2. Wo bekomme ich PyGame her?
- 3. Das Grundgerüst eines PyGame-Programms.
- 4. Ein einfaches Fenster.
- 5. Grafiken und Musik.
- 6. Objekte mit Draw() ins Fenster zaubern.
- 7. Externe Schriftarten verwenden.
- 8. Einfache Animation.
- 9. Transparente Farben mit dem Alphakanal.

1. Was ist PyGame?
PyGame ist ein Set von Modulen für die Programmiersprache Python. Es gibt unter Anderem die Funktionalität der SDL-Bibliothek, was die Programmierung von vollausgestatteten Spielen und Multimediaanwendungen erlaubt. PyGame läuft genau wie Python selbst auf beinahe jedem Betriebssystem, ohne Änderungen am Code vornehmen zu müssen. Zudem wurde es mehrere Millionen Male heruntergeladen und zich Python-Spiele benötigen PyGame.

2. Wo bekomme ich PyGame her?
Von der offiziellen Website. Einfach die richtige Version raussuchen, runterladen und in die Pythoninstallation instalieren. Achtung: Bei einem 32er-System muss die 32er-Version her und bei einem 64er-System die 64er-Version! Ansonsten wird es in der Konsole Fehler regnen.

3. Das Grundgerüst eines PyGame-Programms.
Kommen wir mal zum schönen Teil, der Programmierung. Um PyGame erst verwenden zu können, müssen wir einige Zeilen Code schreiben, sprich, PyGame importieren und initialisieren. Das schaffen wir mit folgendem Code:

[code=Python file=example.pyw]# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *

pygame.init()[/code]
Somit hätten wir das Grundgerüst. Anmerkung: Der Grund, warum ich in der Shebangzeile das Coding auf UTF-8 setze, ist der, dass dadurch problemlos Umlaute verwendet werden können. Und das dürfte bei deutschsprachigen Programmen ungemein hilfreich sein.

4. Ein einfaches Fenster.
Das Grundgerüst allein bringt uns nichts. Das auszuführen, würde keine Reaktion seitens Python hevorrufen, da alle Befehle durchlaufen werden, ohne dass irgendwas erzeugt wird. Machen wir doch einfach mal ein Fenster! Und auch hier gibt es eine kleine Erinnerung: In Python ist die Einhaltung der Einrückung wichtiger als alles andere! Ein Leerzeichen zu viel oder zu wenig lässt das gesamte Programm abschmieren! So, jetzt aber genug damit, machen wir uns endlich ans Fenster.

[code=Python file=window.pyw]# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *

pygame.init()

# Wir legen die Farbe Schwarz fest.
BLACK = (0, 0, 0)

# Wir legen Größe, Titel und Inhalt des Fensters fest.
screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Ein kleines Fenster.")
screen.fill(BLACK)

# Der Main-Loop. In Python ist alles standardmäßig auf True gestellt.
while True:
for event in pygame.event.get():
# Was passiert, wenn das Programm beendet wird?
if event.type == QUIT:
pygame.quit()
# Was passiert, wenn Escape gedrückt wird?
if event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
# Wenn eine Änderung am Fenster vorgenommen wurde, wird diese jetzt sichtbar.
pygame.display.update()[/code]
Das sollte dann ungefähr so aussehen:
Bild

Ist aber irgendwie langweilig, oder..? Machen wir es doch mal interessant!

5. Grafiken und Musik.
Bis jetzt können wir nur langeweile, nutzlose Dinger hinklatschen, die nur den Rechner sinnlos belasten. Wie wäre es, wenn wir das Fenster mit einem tollen Titelbild schmücken oder Musik im Hintergrund laufen lassen? -- Download.

[code=Python file=extended_window.pyw]# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *

pygame.init()

BLACK = (0, 0, 0)

# Wir legen die Titelgrafik und ein Icon fest.
TITLEPIC = pygame.image.load("data/title.png")
ICON = pygame.image.load("data/icon.png")

screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Ein besseres Fenster!")
# Und ein Icon kommt auch dazu.
pygame.display.set_icon(ICON)
screen.fill(BLACK)
# Eine Grafik wird am Nullpunkt angesetzt.
screen.blit(TITLEPIC, (0, 0))

# Musik wird eingesetzt.
pygame.mixer.music.load("data/music.mp3")
# -1 steht für eine Endlosschleife und 0.0 steht für den Startpunkt der Musik.
pygame.mixer.music.play(-1, 0.0)
pygame.mixer.music.set_volume(0.1)

while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
if event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
pygame.display.update()[/code]
Unser Ergebnis ist dieses musikabspielende Fenster:
Bild

6. Objekte mit Draw() ins Fenster zaubern.
Hintergrundbilder sind ja schön und gut. Sie können das gesamte oder auch nur Teile des Fensters füllen, je nach dem, welche Größe die Grafik hat und wo sie plaziert wird. Doch wenn man kleine Objekte, wie Kreise oder Polygone haben möchte, ist es unsinnig, diese über Grafiken ins Fenster zu bringen. Dafür nutzen wir die Draw()-Funktion von PyGame.

[code=Python file=draw.pyw]# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *

pygame.init()

BLACK = (0, 0, 0)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
FUCHSIA = (255, 0, 255)
YELLOW = (255, 255, 0)

screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Draw-Spielchen")
screen.fill(YELLOW)
# Nun kommt der etwas schwierigere Teil, das Zeichnen. Vorab eine kurze Erklärung: Zuerst sagen wir Python, welches Surface-Objekt angesteuert werden soll (screen). Als nächstes legen wir die Farbe fest, in unserem Falle blau. Mit den folgenden Tupeln legen wir fest, wo sich die Ecken unseres Poygons befinden.
pygame.draw.polygon(screen, BLUE, ((140, 0), (280, 110), (240, 280), (70, 280), (0, 100)))
# Zeichnen wir mal ein einfaches X. Wir legen wieder Surface, Farbe sowie Start- und Endpunkt fest. Natürlich wird die optionale Linienbreite in Pixeln auch nicht fehlen. Wird diese weggelassen, wird die Linie ein Pixel breit.
pygame.draw.line(screen, RED, (300, 300), (500, 500), 4)
pygame.draw.line(screen, RED, (500, 300), (300, 500), 4)
# So weit, so gut. Rumkugeln tun rumkugeln, deswegen zeichnen wi mal einen Kreis. Surface, Farbe, Position, Durchmesser und dreckige Füllung. (Bei 0 wird alles sauber ausgefüllt.)
pygame.draw.circle(screen, BLACK, (500, 200), 25, 10)
# Vorletztes Objekt: eine Ellipse. Wie immer Surface und Position, danach Länge und Breite sowie Pixelbreite.
pygame.draw.ellipse(screen, GREEN, (500, 100, 40, 80), 7)
# Zum Schluss gibt es ein einfaches Rechteck, welches wir vertikal zeichnen. Surface, Farbe, Position, Ausrichtung.
pygame.draw.rect(screen, FUCHSIA, (200, 300, 20, 50))

while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
if event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
pygame.display.update()[/code]
Und dies ist unser stechend gutes Ergebnis!
Bild

7. Externe Schriftarten verwenden.
Es wird Zeit, dass ich mal zeige, wie man externe Schriftarten verwendet. Dies ist in wenigen Schritten gemacht, man braucht nur drei neue Objekte. -- Download.

[code=Python file=font.pyw]# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *

pygame.init()

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Externe Schrift.")
screen.fill(BLACK)
# Neues Font-Objekt. Angegeben werden Pfad zur Datei und die Schriftgröße.
fontObject = pygame.font.Font("extfont.ttf", 85)
# Neues Text-Surface-Objekt. Dieses Mal geben wir den gewünschten Test ein, beantworten die Frage, ob wir Anti-Aliasing verwenden möchten und geben die Schriftfarbe ein. Man kann auch einen vierten Wert übergeben, und zwar den Hintergrund. Standardmäßig ist dieser Wert auf None gestellt, es wird also kein Hintergrund angezeigt.
textSurfaceObject = fontObject.render("Hallo Welt!", True, WHITE)
# Neues Text-Rect-Objekt. Wir lassen uns einfach nur den Bereich des Text-Surface-Objekts übergeben.
textRectObject = textSurfaceObject.get_rect()
# Nun geben wie die Position der Schrift an.
textRectObject.center = (300, 300)
# Zu guter Letzt lassen wir uns die Schrift anzeigen.
screen.blit(textSurfaceObject, textRectObject)

while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
if event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
pygame.display.update()[/code]
Nun haben wir ein schönes kleines Fenster, das die Welt begrüßt.
Bild

8. Einfache Animation.
Kommen wir zu Animationen. Wir werden einfach mal eine Grafik durchs Fenster laufen lassen. Dazu werden wir zum ersten Mal eine Clock nutzen und die FPS steuern. Download.

[code=Python file=animation.pyw]# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *

pygame.init()

WHITE = (255, 255, 255)
# Wir legen die maximalen FPS und die Clock fest.
FPS = 30
fpsClock = pygame.time.Clock()
# Pfad zur Grafik, die durchs Fenster laufen wird.
img = pygame.image.load("cat.png")
# Die Position der Grafik am Anfang.
imgX = 10
imgY = 10
# Richtung, die die Grafik "geht".
direction = "right"

screen = pygame.display.set_mode((600, 600), 0, 32)
pygame.display.set_caption("Einfache Animation")

# Der neue Main Loop. Hier wird sich alles abspielen.
while True:
# Die Füllung des Fensters wird nun in den Main Loop geworfen. Andernfalls gibt es eine eher unschöne Animation, da die Grafik immer wieder alle fünf Pixel neu geladen wird. Wie das aussieht, sieht man unten.
screen.fill(WHITE)
# Wir haben anfangs die Richtung 'Rechts' angegeben. Also wird dieser Block ausgeführt.
if direction == "right":
# imgX = imgX + 5
imgX += 5
# Wenn imgX 280 erreicht hat, wird die Richtung gewechselt.
if imgX == 280:
direction = "down"
elif direction == "down":
imgY += 5
if imgY == 220:
direction = "left"
elif direction == "left":
imgX -= 5
if imgX == 10:
direction = "up"
elif direction == "up":
imgY -= 5
if imgY == 10:
# Und das Spielchen geht von vorne los.
direction = "right"
# Da die Grafik immer an einer anderen Stelle plaziert werden muss, kommt dies nach den if/elif-Abfragen.
screen.blit(img, (imgX, imgY))

for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
if event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
pygame.display.update()
# Ohne diese Zeile würde die Animation ohne FPS-Begrenzung laufen.
fpsClock.tick(FPS)[/code]
Und hier das Ergebis. Die letzten beiden Bilder zeigen, was passiert, wenn die Zeile "screen.fill(WHITE)" nicht im Main Loop wäre.
Bild Bild Bild Bild

9. Transparente Farben mit dem Alphakanal.
Etwas spät, aber mich juckt es schon die ganze Zeit, das hier noch mit reinzubringen. Ich zeige mal schnell, wie man den Alphakanal verwendet, um transparente Farben ins Bild zu werfen.

[code=Python file=alpha.pyw]# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *

pygame.init()

WHITE = (255, 255, 255)
BLUE = (0, 0, 225)
RED = (255, 0, 0)
# Wir fügen dem Tupel einen vierten Wert hinzu, den Alphakanal. Ist dieser 0, so ist die Farbe unsichtbar. Ist der Wert 255, so gibt es keine Transparenz. Also ist es besser (0, 0, 255), anstatt (0, 0, 255, 255) zu schreiben, da der Alphakanal demnach unnötig wäre.
A_BLUE = (0, 0, 225, 128)
A_RED = (255, 0, 0, 128)

screen = pygame.display.set_mode((600, 600))
pygame.display.set_caption("Spielerei mit dem Alphakanal")

screen.fill(WHITE)

# Um den Alphakanal überhaupt nutzen zu können, müssen wir ein geeignetes Surface-Objekt erstellen und dieses dann am Ende in unser Hauptobjekt zu kopieren.
alphasurface = screen.convert_alpha()

pygame.draw.circle(alphasurface, BLUE, (130, 200), 120, 0)
pygame.draw.circle(alphasurface, RED, (130, 400), 120, 0)
# Alles was den Alphakanal verwendet, muss auf das dafür vorhergesehende Objekt (alphasurface).
pygame.draw.circle(alphasurface, A_BLUE, (420, 200), 120, 0)
# Nach jeder transparenter Aktion muss das Alpha-Objekt kopiert werden.
screen.blit(alphasurface, (0, 0))
pygame.draw.circle(alphasurface, A_RED, (420, 400), 120, 0)
screen.blit(alphasurface, (0, 0))

while True:
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
if event.type == KEYDOWN and event.key == K_ESCAPE:
pygame.quit()
pygame.display.update()[/code]
Unser Ergebnis (Bild Zwei zeigt was passiert, wenn man alphasurface nicht nach jeder Aktion blitted):
Bild Bild
Anmerkung: Das neue Alpha Surface-Objekt ist zwingend notwendig. Würde man screen einfach nur konvertieren und seine Sachen drauf werfen, so würde es keine Transparenz geben.

Beste Grüße
--Vaixell.
Zuletzt geändert von Vaixell am So Aug 18, 2013 6:21 am, insgesamt 4-mal geändert.

Benutzeravatar
XDClaner
Globaler Moderator
Beiträge: 40
Registriert: Di Apr 23, 2013 9:19 pm

Re: [2.7][PyGame] Grundlagen für PyGame.

Beitragvon XDClaner » Mi Mai 08, 2013 8:21 pm

Dein Tutorial ist sehr interessant geschrieben und reizt mich tatsächlich, mich auch mal ein wenig detaillierter mit Python auseinanderzusetzen. Bisher hat mich immer abgeschreckt, dass ich es hauptsächlich als interpretierbare Skriptsprache kenne. Offensichtlich scheint sie aber durchaus für Spieleprogrammierung geeignet ( also schnell genug) zu sein.

Allerdings hätte ich noch eine wichtige Frage:
Wie gut lässt sich OpenGL in Python benutzen?

Benutzeravatar
Vaixell
Schleifen-Versteher
Beiträge: 16
Registriert: Di Apr 23, 2013 7:42 pm
Wohnort: Ostbevern
Kontaktdaten:

Re: [2.7][PyGame] Grundlagen für PyGame.

Beitragvon Vaixell » Mi Mai 08, 2013 8:53 pm

XDClaner hat geschrieben:Dein Tutorial ist sehr interessant geschrieben und reizt mich tatsächlich, mich auch mal ein wenig detaillierter mit Python auseinanderzusetzen. Bisher hat mich immer abgeschreckt, dass ich es hauptsächlich als interpretierbare Skriptsprache kenne. Offensichtlich scheint sie aber durchaus für Spieleprogrammierung geeignet ( also schnell genug) zu sein.

Im Vergleich zu C und Java ist Python natürlich eine lahme Krücke. Man sollte wirklich schon darauf achten, dass man sauber schreibt, wenn man was Größeres damit machen will. Das merkt man aber auch. Bestes Beispiel sind zwei Programme aus Gummworld 2. Während Supermap mit ca. 1.400 FPS läuft, hinkt Parallax mit ca. 70 FPS hinterher (Notebookwerte). Dabei ist Supermap viel größer.

XDCl|e|aner hat geschrieben:Allerdings hätte ich noch eine wichtige Frage:
Wie gut lässt sich OpenGL in Python benutzen?

Für Python kann man PyOpenGL verwenden. Wie weit das zu gebrauchen ist, kann ich aber nicht sagen, weil ich damit nie was gemacht habe. Aber dafür gibt es auch recht interessante Beispiele. Weiß zwar nicht mehr, wo genau ich die gefunden hatte, aber bei der Suche nach PyOpenGL Examples, findet man sowieso das Beste. Bild

EDIT: Verwendung von Draw() und externen Schriftarten sind jetzt auch drinne.

Benutzeravatar
Vaixell
Schleifen-Versteher
Beiträge: 16
Registriert: Di Apr 23, 2013 7:42 pm
Wohnort: Ostbevern
Kontaktdaten:

Re: [2.7][PyGame] Grundlagen für PyGame.

Beitragvon Vaixell » Fr Mai 10, 2013 10:39 am

Sou, Animation ist fertig. An Grundlagen, denke ich, reicht das, oder?
Zuletzt geändert von Vaixell am So Dez 07, 2014 10:11 am, insgesamt 2-mal geändert.

Benutzeravatar
XDClaner
Globaler Moderator
Beiträge: 40
Registriert: Di Apr 23, 2013 9:19 pm

Re: [2.7][PyGame] Grundlagen für PyGame.

Beitragvon XDClaner » Fr Mai 10, 2013 6:56 pm

Das sieht doch schon ganz manierlich aus :)
Sobald ich ein bisschen Zeit finde, lese ich mir das ganze noch mal durch und probiere das nachzuvollziehen...


Zurück zu „Python“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast