lehrkraefte:snr:informatik:glf22:python:snake:ballgame-fehlerhaftes-programm

Ball game program

ball-game-zu-verbessern.py
import pygame
from pygame.locals import *
from random import *
 
# Spielgeschwindigkeit bzw. genauer Frequenz der Spielzyklen am Anfang.
FRAMES_PER_SECOND_AM_ANFANG = 40
 
# Das Spielfeld besteht aus kleinen rechteckigen Boxen mit Koordinaten
# 0 bis MAXX (jeweils einschliesslich) in x-Richtung und
# 0 bis MAXY (jeweils einschliesslich) in y-Richtung.
# Achtung: y-Achse zeigt nach unten (wie Zeilennummern)
MAXX = 30
MAXY = 20
 
# Festlegung von Breite und Höhe einer Box in Pixel. 
# Meist sind Breite und Höhe gleich, was quadratische Boxen liefert.
SEITENLAENGE_BOX = 25
 
# Radius des Balles am Anfang.
RADIUS_BALL_AM_ANFANG = 0.7
 
# Anzahl Leben am Anfang.
LEBEN_AM_ANFANG = 10
 
# Einige von den obigen Werten abhängige Konstanten.
ANZAHL_BOXEN_X = MAXX + 1
ANZAHL_BOXEN_Y = MAXY + 1
 
FENSTER_BREITE = ANZAHL_BOXEN_X * SEITENLAENGE_BOX
FENSTER_HOEHE = ANZAHL_BOXEN_Y * SEITENLAENGE_BOX
PLATZ_FUER_TEXT = 3 * SEITENLAENGE_BOX 
 
# Farben per Rot-, Grün- und Blauwert
# (jeweils auf Skala von 0 bis 255).
# Wer will, kann hier zusätzliche eigene Farben festlegen.
#             rot  grün  blau
ROT     =    (255,    0,    0)
GRUEN   =    (  0,  255,    0)
BLAU    =    (  0,    0,  255)
GELB    =    (255,  255,    0)
MAGENTA =    (255,    0,  255)
CYAN    =    (  0,  255,  255)
WEISS   =    (255,  255,  255)
SCHWARZ =    (  0,    0,    0)
HELLGRAU =   (80,  80,  80)
DUNKELGRAU = (160,  160,  160)
HINTERGRUND_FARBE = SCHWARZ
# HINTERGRUND_FARBE = HELLGRAU
 
#
# Definition der Klasse Punkt. Bitte einfach akzeptieren.
#
class Punkt:
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def __str__(self):
        return f'({self.x}, {self.y})'
 
    def __repr__(self):
        return f'({self.x}, {self.y})'
 
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
 
    def __add__(self, other):
        return Punkt(self.x + other.x, self.y + other.y)
 
    def __sub__(self, other):
        return Punkt(self.x - other.x, self.y - other.y)
 
    def laenge(self):
        return (self.x * self.x + self.y * self.y) ** 0.5
 
# 
# Ende der Definition der Klasse Punkt.
#
 
#
# Einige Funktionsdefinitionen
#
 
def zeichne_box(p, farbe):
    rechteck = pygame.Rect(p.x * SEITENLAENGE_BOX + 1, p.y * SEITENLAENGE_BOX + 1, SEITENLAENGE_BOX - 1, SEITENLAENGE_BOX - 1)
    pygame.draw.rect(leinwand, farbe, rechteck)
 
def zeichne_kreis(p, r, farbe):    
    pygame.draw.circle(leinwand, farbe, ((p.x + 0.0) * SEITENLAENGE_BOX + 1, (p.y + 0.0) * SEITENLAENGE_BOX + 1), r * SEITENLAENGE_BOX, width=0)
 
def zeichne_gitter():
    for x in range(ANZAHL_BOXEN_X + 1):
        pygame.draw.line(leinwand, HELLGRAU, (x * SEITENLAENGE_BOX, 0), (x * SEITENLAENGE_BOX, FENSTER_HOEHE))
    for y in range(ANZAHL_BOXEN_Y + 1):
        pygame.draw.line(leinwand, HELLGRAU, (0, y * SEITENLAENGE_BOX), (FENSTER_BREITE, y * SEITENLAENGE_BOX))
 
def schreibe(x, y, text, groesse):
    schrift = pygame.font.SysFont('freemono', round(groesse * SEITENLAENGE_BOX))
    formatierter_text = schrift.render(text, True, WEISS, SCHWARZ)
    rechteck = formatierter_text.get_rect()
    rechteck.center = (round((x + 0.5) * SEITENLAENGE_BOX), round((y + 0.5) * SEITENLAENGE_BOX))
    leinwand.blit(formatierter_text, rechteck)
 
# Nicht verwendet, aber man könnte damit statt der farbigen Boxen Bilder anzeigen.
def zeige_bild(bild, p):
    rechteck = pygame.Rect(p.x * SEITENLAENGE_BOX + 1, p.y * SEITENLAENGE_BOX + 1, SEITENLAENGE_BOX - 1, SEITENLAENGE_BOX - 1)
    leinwand.blit(bild, rechteck)
 
def abstand(p, q):
    return (p-q).laenge()
#
# Ende des Abschnitts mit den Funktionsdefinitionen.
#
 
#
# Hier geht das eigentliche Programm los.
#
 
# Initialisierung des Spielfelds
pygame.init()
uhr = pygame.time.Clock()
leinwand = pygame.display.set_mode((FENSTER_BREITE + 1, FENSTER_HOEHE + 1 + PLATZ_FUER_TEXT))
pygame.display.set_caption('My favorite game')
 
# Initialisierung der Daten des Spielers, insbesondere Startposition
spieler = Punkt(MAXX // 2, MAXY // 2)
farbe_spieler = GRUEN
 
# Initialisieren der Daten des Balls
radius_ball = RADIUS_BALL_AM_ANFANG
ball = Punkt(radius_ball, randrange(MAXY // 4, 3 * MAXY // 4))
bewegungsrichtung_ball = Punkt(0.1 + 0.4 * random(), randrange(-1, 2, 2) * 0.1 + 0.4 * random())
farbe_ball = MAGENTA
 
frames_per_second = FRAMES_PER_SECOND_AM_ANFANG
spiel_aktiv = True
leben = LEBEN_AM_ANFANG
 
# Hier startet die sogenannte "game loop".
while spiel_aktiv:
    leinwand.fill(HINTERGRUND_FARBE)
    zeichne_gitter()
    zeichne_kreis(ball, radius_ball, farbe_ball)
    # zeichne_box(ball, farbe_ball)
    zeichne_box(spieler, farbe_spieler)
    schreibe(MAXX // 4, MAXY + 1, f'Lives: {leben}', 0.7)
    schreibe(3 * MAXX // 4, MAXY + 1, f'Update frequenqy: {frames_per_second}', 0.7)
    schreibe(MAXX // 4, MAXY + 2, f'Player position: {spieler}', 0.7)
    schreibe(3 * MAXX // 4, MAXY + 2, f'Ball position: ({ball.x:.1f}, {ball.y:.1f})',0.7)
    schreibe(MAXX // 4, MAXY + 3, f'Enter key moves player to center', 0.7)
    schreibe(3 * MAXX // 4, MAXY + 3, f'Ball direction: ({bewegungsrichtung_ball.x:.1f}, {bewegungsrichtung_ball.y:.1f})',0.7)
    pygame.display.update()
    uhr.tick(frames_per_second)
 
    if leben >= 20 or leben <= 0:
        spiel_aktiv = False
        ende = 'gewonnen oder verloren'
 
    if abstand(spieler, ball) < radius_ball + 0.9:
        leben = leben + 1
        radius_ball = max(0.3, 0.9 * radius_ball)
        # Spieler bekommt neue Position.
        spieler.x = 2 * MAXX // 3
        spieler.y = randrange(MAXY + 1)
 
        # Ball bekommt neue Position und Richtung.
        ball = Punkt(radius_ball, randrange(MAXY // 4, 3 * MAXY // 4))
        bewegungsrichtung_ball = Punkt(0.1 + 0.4 * random(), randrange(-1, 2, 2) * 0.1 + 0.4 * random())
 
 
    # Spielerposition bei Tastendruck verändern. 
    # 
    # Teilaufgabe 1: Passe die folgenden 21 Zeilen so an,
    # dass die Pfeiltasten das grüne Quadrat wie gewünscht steuern.
    #
    for ereignis in pygame.event.get():
        if ereignis.type == KEYDOWN:
            if ereignis.key == K_LEFT:
                print("Pfeiltaste ... gedrückt.")
                spieler.y = spieler.y + 1
                if spieler.y >= MAXY:
                    spieler.y = 1
            elif ereignis.key == K_RIGHT:
                print("Pfeiltaste ... gedrückt.")
                spieler.x = spieler.x - 1
                if spieler.x < 0:
                    spieler.x = 3
            elif ereignis.key == K_UP:
                print("Pfeiltaste hoch gedrückt.")
                spieler.x = spieler.x + 2
            elif ereignis.key == K_DOWN:
                print("Pfeiltaste runter gedrückt.")
                spieler.y = spieler.y - 1
                if spieler.y < 0:
                    spieler.y = spieler.x
                    spieler.x = 0
            elif ereignis.key == K_ESCAPE:
                print("Escape-Taste gedrückt.")
                spiel_aktiv = False
                ende = 'Abbruch'
            elif ereignis.key == K_RETURN:
                print("Enter/Return-Taste gedrückt.")
                spieler.x = MAXX // 2
                spieler.y = MAXY // 2
            elif ereignis.key == K_q:
                print("Taste 'q' gedrückt.")
                spiel_aktiv = False
                ende = 'Abbruch'
        elif ereignis.type == QUIT:
            print("Button zum Schliessen des Pygame-Fensters angeklickt.")
            spiel_aktiv = False
            ende = 'Abbruch'
 
    # Position des Balls verändern.
    ball = ball + bewegungsrichtung_ball
    #
    # Teilaufgabe 2: Passe die folgenden 10 Zeilen so an,
    # dass der Ball rechts, oben und unten normal reflektiert wird.
    #
    if ball.y - radius_ball < 0:
        bewegungsrichtung_ball.y = - bewegungsrichtung_ball.y
        bewegungsrichtung_ball.x = - bewegungsrichtung_ball.y
    if ball.y + radius_ball > MAXY + 1:
        bewegungsrichtung_ball.y = - 0.1
        bewegungsrichtung_ball.x = 0.4
    if ball.x + radius_ball > MAXX + 1:
        bewegungsrichtung_ball.x = - bewegungsrichtung_ball.x
        # Die folgende Zeile nicht verändern.
        leben = leben - 2
 
    # Ab hier nichts mehr verändern!
    if ball.x - radius_ball < 0:
        bewegungsrichtung_ball.x = 0.1 + 0.4 * random()
        if bewegungsrichtung_ball.y > 0:
            bewegungsrichtung_ball.y = 0.1 + 0.4 * random()
        else:
            bewegungsrichtung_ball.y = -(0.1 + 0.4 * random())
 
if ende == 'gewonnen oder verloren':
    if leben >= 20:
        schreibe(MAXX // 2, MAXY // 2, 'Congratulations!', 2)
    else:
        schreibe(MAXX // 2, MAXY // 2, 'GAME OVER', 2)
    schreibe(MAXX // 2, MAXY // 2 + 3, 'press any key', 1)
    pygame.display.update()
    pygame.time.delay(500)
    pygame.event.clear()
    pygame.event.wait()
pygame.quit()
exit()
  • lehrkraefte/snr/informatik/glf22/python/snake/ballgame-fehlerhaftes-programm.txt
  • Last modified: 2023/01/26 23:45
  • by Olaf Schnürer