Score_Bug in Pygame

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
unknown_user_123
User
Beiträge: 27
Registriert: Dienstag 14. April 2020, 09:32

Wenn ich das Programm starte und den Ball mit einer der Seiten von meinem Rechteck Berühre, dann bleibt er dort kleben.
Ich hab sicherheitshalber mal die High score Funktion auskommentiert, damit ihr keine Probleme mit der Datei habt.
Ich hoffe, dass ihr mein Problem lösen könnt!
Der Fehler liegt glaube ich im Bereich um Zeile 70


Code: Alles auswählen

import pygame
import sys

pygame.init()
clock = pygame.time.Clock()

# Definieren von Screen
db = 600
dh = 600
screen = pygame.display.set_mode((db, dh))
pygame.display.set_caption("Pong the Game")

# Definieren von Spieler
x = 300
y = 500
breite = 100
hohe = 25
speed = 7

# Definieren von Ball
xball = 300
yball = 100
ball_speed = 5

score = 0


def restart():
    global xball, yball, score
    xball = 300
    yball = 100
    score = 0
dark_white = (200, 200, 200)




myFont = pygame.font.SysFont("Comic Sans MS", 30)
#Highscore auslesen
def get_high():
    """with open("highscore") as file:
        for line in file:
            return line"""
    return "10"


# Hauptschleife

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
    gedrueckt = pygame.key.get_pressed()
    if gedrueckt[pygame.K_RIGHT]:
        x += speed
    if gedrueckt[pygame.K_LEFT]:
        x -= speed
    if x < 0:
        x = 0
    if x > db - breite:
        x = db - breite

    yball += ball_speed
    screen.fill((0, 0, 34))
    player = pygame.draw.rect(screen, (255, 255, 255), (x, y, breite, hohe))
    ball = pygame.draw.circle(screen, (255, 255, 255), (xball, yball,), 17)
    if ball.colliderect(player):
        ball_speed *= -1
        score += 1 # todo Fehler Beheben: Wenn man den Ball von der Seite aus Berührt, dann bleibt er am Ball kleben
        if score > int(get_high()):
            """with open ("highscore", "w") as file:
                file.write(str(score))"""
            pass




    if ball.top <= 0:
        ball_speed *= -1


    if ball.bottom >= dh:
        restart()
    score_show = myFont.render("Score: " + str(score), 1, dark_white)
    highest_score = myFont.render("Highscore: " + get_high(),  1, dark_white)
    screen.blit(score_show, (db/2, dh/6))
    screen.blit(highest_score, (db / 2, dh / 3))

    pygame.display.update()
    clock.tick(60)
Benutzeravatar
__blackjack__
User
Beiträge: 14002
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@unknown_user_123: Du hast da nichts auskommentiert, Du hast unsinnigerweise den ersten Teil einer Funktion zum Docstring gemacht und an anderer Stelle Code zu einer literalen Zeichenkette die dort keinen Sinn macht. Literale Zeichenketten sind keine Kommentare! Kommentare fangen mit einem ``#``-Zeichen an.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

``global`` hat in einem sauberen Programm nichts zu suchen.

Namen werden klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). `my` ist in 99,9% der Fälle eine völlig sinnfreie Vorsilbe, weil die keinerlei sinnvolle Information enthält. Namen sollten auch keine kryptischen Abkürzungen enthalten, oder gar nur aus ihnen bestehen. Was soll das `d` in `db` und `dh` überhaupt bedeuten? Man sollte auch nach einem konsistenten Muster benennen. Also zum Beispiel statt:

Code: Alles auswählen

    # Definieren von Spieler
    x = 300
    y = 500
    breite = 100
    hoehe = 25
    speed = 7

    # Definieren von Ball
    xball = 300
    yball = 100
    ball_speed = 5
sollte das besser so aussehen, dann kann man sich auch die Kommentare sparen, weil das bereits aus dem Code ersichtlich wird:

Code: Alles auswählen

    player_x = 300
    player_y = 500
    player_breite = 100
    player_hoehe = 25
    player_speed = 7

    ball_x = 300
    ball_y = 100
    ball_speed = 5
    ball_radius = 17
Da sieht man auch ganz gut, dass man hier zu viele Einzelnamen hat, die man zu Objekten zusammenfassen sollte.

Eine ``for``-Schleife die gleich als erstes ein ``return`` enthält ist keine sinnvolle Schleife. Wenn in der Datei sowieso nur eine Zeile steht, dann liess die Datei einfach komplett aus und gut ist. Zudem gehört das Umwandeln in eine ganze Zahl *in* diese Funktion, denn ein Hiscore ist semantische eine Zahl und keine Zeichenkette.

Erster zaghafter Zwischenstand:

Code: Alles auswählen

#!/usr/bin/env python3
import sys

import pygame

DARK_WHITE = (200, 200, 200)
SCREEN_WIDTH = 600
SCREEN_HEIGHT = 600


def load_highscore():
    # with open("highscore") as file:
    #     return int(file.read())
    return "10"


def main():
    pygame.init()
    clock = pygame.time.Clock()
    screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
    pygame.display.set_caption("Pong the Game")
    font = pygame.font.SysFont("Comic Sans MS", 30)

    player_x = 300
    player_y = 500
    player_breite = 100
    player_hoehe = 25
    player_speed = 7

    ball_x = 300
    ball_y = 100
    ball_speed = 5
    ball_radius = 17

    score = 0

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
        gedrueckt = pygame.key.get_pressed()
        if gedrueckt[pygame.K_RIGHT]:
            player_x += player_speed
        if gedrueckt[pygame.K_LEFT]:
            player_x -= player_speed
        if player_x < 0:
            player_x = 0
        if player_x > SCREEN_WIDTH - player_breite:
            player_x = SCREEN_WIDTH - player_breite

        ball_y += ball_speed
        screen.fill((0, 0, 34))
        player_rect = pygame.draw.rect(
            screen,
            (255, 255, 255),
            (player_x, player_y, player_breite, player_hoehe),
        )
        ball_rect = pygame.draw.circle(
            screen, (255, 255, 255), (ball_x, ball_y), ball_radius
        )
        if ball_rect.colliderect(player_rect):
            ball_speed *= -1
            #
            # FIXME Wenn man den Ball von der Seite aus berührt, dann bleibt er
            # am Schläger kleben
            #
            score += 1
            if score > load_highscore():
                # with open("highscore", "w") as file:
                #     file.write(f"{score}\n")
                pass

        if ball_rect.top <= 0:
            ball_speed *= -1

        if ball_rect.bottom >= SCREEN_HEIGHT:
            ball_x = 300
            ball_y = 100
            score = 0

        score_show = font.render(f"Score: {score}", 1, DARK_WHITE)
        highest_score = font.render(
            f"Highscore: {load_highscore()}", 1, DARK_WHITE
        )
        screen.blit(score_show, (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 6))
        screen.blit(highest_score, (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 3))

        pygame.display.update()
        clock.tick(60)


if __name__ == "__main__":
    main()
Das Problem mit dem Ball ist halt, dass die 5 Pixel nicht ausreichen um beim nächsten Schritt aus dem Schläger wieder heraus zu kommen und der deswegen in jede weiteren Schritt immer die Richtung wechselt weil er in jedem Schritt mit dem Schläger kollidiert. Was sollte denn stattdessen passieren? *Das* musst Du dann im Code an der entsprechenden Stelle auch sagen.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Antworten