13 KiB
Tipps & Hinweise
Titelbild und Logo einfügen
-
Ein Logo macht das Spiel persönlicher! Die Funktion zum Laden eines Logos ist im Code vorbereitet, aber aktuell deaktiviert.
-
Die Kids können später ein eigenes Logo als
images/logo.pngerstellen und die folgende Zeile inwater-game.pyaktivieren:# logo_img = pygame.image.load("images/logo.png") # pygame.display.set_icon(logo_img) -
Tipp: Das Logo sollte quadratisch und als PNG gespeichert sein.
-
So kann jeder sein eigenes Spiel-Icon gestalten!
Titelbildschirm, Gewinn- und Verlustbildschirm
- Implementiere einen Titelbildschirm und zeige bei Spielende einen Gewinn- oder Verlustbildschirm (siehe Codebeispiel unten).
Beispiel für Titelbildschirm und Gewinn/Verlust:
# Titelbildschirm anzeigen
show_title_screen(WIN)
# ...
if win_condition:
show_win_screen(WIN)
elif lose_condition:
show_lose_screen(WIN)
So kannst du Gewinn- und Verlustbildschirme umsetzen:
- Schreibe eine Funktion, die den Bildschirm einfärbt und einen Text anzeigt:
def show_win_screen(win):
win.fill((40, 180, 80))
font = pygame.font.SysFont(None, 72)
text = font.render("Gewonnen!", True, (255, 255, 255))
win.blit(text, (win.get_width() // 2 - text.get_width() // 2, win.get_height() // 2 - text.get_height() // 2))
pygame.display.update()
pygame.time.wait(2500)
def show_lose_screen(win):
win.fill((180, 40, 40))
font = pygame.font.SysFont(None, 72)
text = font.render("Verloren!", True, (255, 255, 255))
win.blit(text, (win.get_width() // 2 - text.get_width() // 2, win.get_height() // 2 - text.get_height() // 2))
pygame.display.update()
pygame.time.wait(2500)
- Rufe die jeweilige Funktion auf, wenn die Gewinn- oder Verlustbedingung erfüllt ist:
if win_condition:
show_win_screen(WIN)
elif lose_condition:
show_lose_screen(WIN)
- Die Bedingungen kannst du selbst festlegen, z.B. alle Gegner besiegt = Gewinn, Spieler tot = Verlust.
- Nach dem Bildschirm kannst du das Spiel beenden oder neu starten.
Trinkbrunnen-Pixelpositionen ins Spiel laden und anzeigen
- Die Datei
trinkbrunnen_pixel_positions.npyenthält alle Trinkbrunnen-Positionen als Pixelkoordinaten. - So lädst du die Positionen und zeichnest die Trinkbrunnen im Spiel:
Schritt 1: Importiere numpy und lade die Datei
import numpy as np
trinkbrunnen_positions = np.load('trinkbrunnen_pixel_positions.npy')
Schritt 2: Zeichne die Trinkbrunnen in der Spielschleife
for px, py in trinkbrunnen_positions:
pygame.draw.circle(WIN, (0, 180, 255), (px - ox, py - oy), 10)
oxundoysind die Offsets für das Kamerascrolling (falls verwendet).- Die Farbe
(0, 180, 255)ist ein helles Blau, der Radius10kann angepasst werden.
Schritt 3: Interaktion mit Trinkbrunnen
- Um z.B. Munition aufzufüllen, prüfe ob der Spieler einen Trinkbrunnen berührt:
player_rect = pygame.Rect(player.x, player.y, PLAYER_SIZE, PLAYER_SIZE)
for px, py in trinkbrunnen_positions:
brunnen_rect = pygame.Rect(px, py, 20, 20) # Größe anpassen
if player_rect.colliderect(brunnen_rect):
player.ammo = MAX_AMMO
- So werden die Trinkbrunnen sichtbar und interaktiv im Spiel!
Die Karte größer machen (Abstandsfaktor)
- Wenn du möchtest, dass die Karte größer wirkt und die Abstände zwischen den Trinkbrunnen (und anderen Objekten) wachsen, kannst du einen "Abstandsfaktor" einführen.
- Damit werden alle Positionen und die Kartengröße mit einem Faktor multipliziert, sodass die Karte gestreckt wird und die Wege länger werden.
So geht's:
Wo und wie den Abstandsfaktor einbauen?
- Definiere den Abstandsfaktor ganz oben in deiner Hauptdatei (z.B.
water-game.py):
DIST_FACTOR = 2.0 # Beispielwert, kann angepasst werden
- Wende den Faktor direkt nach dem Laden der Daten an:
- Nachdem du die Trinkbrunnen-Positionen und ggf. die Spieler-/Gegner-Positionen geladen hast, multipliziere sie mit dem Abstandsfaktor:
# Nach dem Laden der Trinkbrunnen-Positionen
trinkbrunnen_positions = np.load('trinkbrunnen_pixel_positions.npy')
trinkbrunnen_positions = [(int(px * DIST_FACTOR), int(py * DIST_FACTOR)) for px, py in trinkbrunnen_positions]
# Spieler und Gegner ebenfalls anpassen (direkt nach deren Initialisierung):
player.x *= DIST_FACTOR
player.y *= DIST_FACTOR
for enemy in enemies:
enemy.x *= DIST_FACTOR
enemy.y *= DIST_FACTOR
- Beim Rendern der Karte:
- Skaliere die Karte beim Anzeigen:
scaled_map = pygame.transform.smoothscale(map_surface, (int(MAP_W * DIST_FACTOR), int(MAP_H * DIST_FACTOR)))
WIN.blit(scaled_map, (0, 0))
Tipp:
- Der Abstandsfaktor sollte immer am Anfang und nur einmal auf die Positionen angewendet werden, damit alle Objekte synchron gestreckt werden.
- Passe ggf. auch die Spielfeldgröße (
WIDTH,HEIGHT) an, wenn die Karte sehr groß wird.
Schnelles Skalieren der Karte nach dem Laden
- Statt alle Positionen und Objekte zu multiplizieren, kannst du die Karte direkt nach dem Laden einmalig skalieren und die Originalkoordinaten beibehalten.
- Das ist viel schneller und spart Rechenzeit!
So geht's:
- Karte nach dem Laden skalieren:
DIST_FACTOR = 2.0 # Beispielwert
# Nach dem Laden der Karte (z.B. map_surface):
scaled_map = pygame.transform.smoothscale(map_surface, (int(MAP_W * DIST_FACTOR), int(MAP_H * DIST_FACTOR)))
- Beim Rendern die Karte und alle Objekte mit dem Faktor verschieben:
WIN.blit(scaled_map, (0, 0))
for px, py in trinkbrunnen_positions:
pygame.draw.circle(WIN, (0, 180, 255), (int(px * DIST_FACTOR), int(py * DIST_FACTOR)), 10)
# Spieler, Gegner usw. ebenfalls mit DIST_FACTOR multiplizieren, aber nur beim Zeichnen!
- Die Positionsdaten bleiben im Speicher unverändert, nur die Darstellung wird gestreckt.
- Das ist besonders bei großen Karten und vielen Objekten viel performanter.
- Du kannst den Abstandsfaktor jederzeit ändern, ohne die Originaldaten zu verlieren.
.exe erstellen (Windows)
Kurzanleitung auf Deutsch:
-
Installiere PyInstaller:
pip install pyinstaller -
Konvertiere dein Logo zu einer
.ico-Datei (z.B. mit favicon.io). -
Erstelle die .exe:
pyinstaller --onefile --windowed --icon=images/logo.ico water-game.py -
Die ausführbare Datei findest du im
dist-Ordner.
Mac: App als ausführbare Datei erstellen
Kurzanleitung auf Deutsch:
-
Installiere PyInstaller:
pip install pyinstaller -
Erstelle die Mac-App:
pyinstaller --onefile --windowed --icon=images/logo.png water-game.py- Das Icon kann als PNG verwendet werden.
- Die App wird im
dist-Ordner als ausführbare Datei erscheinen.
-
(Optional) Um eine echte Mac-App zu erzeugen, nutze das Flag
--nameund--osx-bundle-identifier:pyinstaller --onefile --windowed --icon=images/logo.png --name=WasserGame --osx-bundle-identifier=com.deinname.wassergame water-game.py
Hinweis:
- Die App kann per Doppelklick gestartet werden.
- Für die Verteilung an andere Macs kann eine Code-Signierung und Notarisierung nötig sein (siehe Apple Doku).
Tipp: Intro-Video vor Spielstart abspielen
- Du kannst ein Video (z.B. MP4) als Intro vor dem eigentlichen Spiel abspielen.
- Nutze dazu z.B. die Bibliothek
pygame-vlcoderopencv-pythonzum Abspielen von Videos im Pygame-Fenster.
Beispiel mit pygame-vlc:
import vlc
import pygame
def play_intro_video(win, video_path):
instance = vlc.Instance()
player = instance.media_player_new()
media = instance.media_new(video_path)
player.set_media(media)
player.set_xwindow(win.get_window_id()) # Für Linux, für Windows/Mac ggf. anpassen
player.play()
# Warte bis das Video fertig ist oder eine Taste gedrückt wird
playing = True
while playing:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN or event.type == pygame.QUIT:
player.stop()
playing = False
pygame.time.wait(100)
- Das Video kann z.B. als
intro.mp4im Projektordner liegen. - Nach dem Intro kannst du wie gewohnt den Titelbildschirm anzeigen.
- Für Windows/Mac kann die Fenster-ID Methode abweichen, siehe Doku von pygame-vlc.
Munition für den Spieler und Anzeige als Counter
- So fügst du dem Spieler eine Munition-Variable hinzu und zeigst sie als Counter im Spiel an:
1. Munition im Player anlegen:
- Ergänze die Player-Klasse um ein Attribut, z.B.:
class Player:
def __init__(self, x, y, image):
self.x = x
self.y = y
self.image = image
self.ammo = 10 # Startwert für Munition
# ...
2. Munition beim Schießen verringern:
if player.ammo > 0:
bottles.append(TapWater(player.x, player.y, player.dir))
player.ammo -= 1
else:
print("Keine Munition!")
3. Munition beim Berühren eines Trinkbrunnens auffüllen:
MAX_AMMO = 10
# ...
if player_rect.colliderect(brunnen_rect):
player.ammo = MAX_AMMO
Tipp: Nur 1 Munition pro Trinkbrunnen-Besuch auffüllen
- Wenn der Spieler bei jedem Kontakt mit einem Trinkbrunnen nur 1 Munition bekommen soll, ändere die Auffüll-Logik so:
if player_rect.colliderect(brunnen_rect):
if player.ammo < MAX_AMMO:
player.ammo += 1
- So muss der Spieler mehrere Brunnen aufsuchen, um volle Munition zu bekommen.
- Optional: Damit der Spieler nicht mehrfach pro Frame Munition bekommt, kannst du merken, ob er gerade einen Brunnen berührt hat und erst wieder auffüllen, wenn er den Brunnen verlässt und erneut berührt.
4. Munition als Counter im HUD anzeigen:
- Im Haupt-Draw-Loop nach dem Zeichnen der Spielfläche:
font = pygame.font.SysFont(None, 32)
ammo_text = font.render(f"Wasser: {player.ammo}", True, (0, 0, 255))
WIN.blit(ammo_text, (20, 20))
- So sieht der Spieler immer, wie viel Munition noch übrig ist!
Tipp: Trinkbrunnen als "benutzt" markieren und blockieren
- Um zu verhindern, dass ein Brunnen mehrfach benutzt wird, kannst du für jeden Brunnen speichern, ob er schon verwendet wurde.
- Nutze dazu z.B. eine Liste oder ein Dictionary:
# Nach dem Laden der Positionen:
used_brunnen = [False] * len(trinkbrunnen_positions)
# Beim Auffüllen:
for i, (px, py) in enumerate(trinkbrunnen_positions):
brunnen_rect = pygame.Rect(px, py, 20, 20)
if player_rect.colliderect(brunnen_rect) and not used_brunnen[i]:
player.ammo += 1
used_brunnen[i] = True # Brunnen blockieren
- So kann jeder Brunnen nur einmal pro Spiel verwendet werden.
- Optional: Zeige blockierte Brunnen anders an (z.B. grau oder mit Symbol).
Tipp: Trinkbrunnen für 10 Sekunden blockieren
- Statt einen Brunnen dauerhaft zu blockieren, kannst du ihn für eine bestimmte Zeit (z.B. 10 Sekunden) sperren.
- Nutze dazu eine Liste mit Zeitstempeln:
import time
# Nach dem Laden der Positionen:
blocked_until = [0] * len(trinkbrunnen_positions)
# Beim Auffüllen:
now = time.time()
for i, (px, py) in enumerate(trinkbrunnen_positions):
brunnen_rect = pygame.Rect(px, py, 20, 20)
if player_rect.colliderect(brunnen_rect) and now > blocked_until[i]:
player.ammo += 1
blocked_until[i] = now + 10 # 10 Sekunden blockieren
- Beim Zeichnen kannst du blockierte Brunnen anders anzeigen:
for i, (px, py) in enumerate(trinkbrunnen_positions):
color = (0, 180, 255) if time.time() > blocked_until[i] else (120, 120, 120)
pygame.draw.circle(WIN, color, (px, py), 10)
- So wird jeder Brunnen nach Benutzung für 10 Sekunden gesperrt und dann wieder nutzbar!
Tipp: Karte drehen und spiegeln (Rotation/Flip)
- Manchmal ist die Karte nach dem Laden verdreht oder gespiegelt. Mit einer Einstellung kannst du das einfach korrigieren!
So geht's:
- Füge Flags für Rotation und Flip hinzu, z.B. ganz oben in deiner Hauptdatei:
MAP_ROTATE_DEGREES = 90 # z.B. 90, 180, 270
MAP_FLIP_X = False # True = horizontal spiegeln
MAP_FLIP_Y = False # True = vertikal spiegeln
- Wende die Transformationen direkt nach dem Laden der Karte an:
# Nach dem Laden von map_surface:
if MAP_ROTATE_DEGREES:
map_surface = pygame.transform.rotate(map_surface, MAP_ROTATE_DEGREES)
if MAP_FLIP_X or MAP_FLIP_Y:
map_surface = pygame.transform.flip(map_surface, MAP_FLIP_X, MAP_FLIP_Y)
- Die Trinkbrunnen-Positionen müssen ggf. ebenfalls angepasst werden, wenn die Karte rotiert oder gespiegelt wird.
- Teste verschiedene Einstellungen, bis die Karte richtig angezeigt wird!