Seite 1 von 1

Ball hat ein statisches movement

Verfasst: Donnerstag 30. Dezember 2021, 13:19
von Lengeta
Hey Leute,
Ich versuche gerade ein Pong ähnliches spiel zu programmieren und bin dabei auf das Problem gestoßen, dass der Ball exakt den selben weg nimmt und so das spiel natürlich extrem langweilig ist.
Ich hab auch kein gutes Pong tutorial gefunden, wo der Ball eine realistische Logik hat.
Habt ihr irgendeine idee, wie ich den Ball besser schreiben kann?

Code: Alles auswählen

import pygame
import random
import time

# colors
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)
white = (255, 255, 255)
black = (0, 0, 0)
light_gray = (200, 200, 200)
dark_gray = (50, 50, 50)
blood = (102, 0, 0)
colors = [red, green, black, blue, white, light_gray]

# constants
FPS = 60

class Game():
    def __init__(self):
        # general settings
        pygame.init()
        clock = pygame.time.Clock()
        self.player_speed = 0
        self.ball_speed_x = 4 * random.choice((1, -1))
        self.ball_speed_y = 4
        self.score = 0
        self.game_over = False

        # window settings
        self.width = 400
        self.height = 800
        self.screen = pygame.display.set_mode((self.width, self.height))
        pygame.display.set_caption("bounce em all")

        # game rectangles
        self.player = pygame.Rect(self.width / 2 - 20, 760, 40, 10)
        self.ball = pygame.Rect(self.width / 2, 50, 10, 10)
        self.left_border = pygame.Rect(0, 0, 10, self.height)
        self.right_border = pygame.Rect(self.width - 10, 0, 10, self.height)
        self.upper_border = pygame.Rect(0, 0, self.width, 10)

        # game loop
        running = True
        while running:
            # input handling
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_RIGHT:
                        self.player_speed += 7
                    if event.key == pygame.K_LEFT:
                        self.player_speed -= 7

                if event.type == pygame.KEYUP:
                    if event.key == pygame.K_RIGHT:
                        self.player_speed -= 7
                    if event.key == pygame.K_LEFT:
                        self.player_speed += 7

            # commands
            self.player_movement()
            self.ball_movement()

            # visuals
            self.screen.fill(white)
            pygame.draw.rect(self.screen, red, self.player)
            pygame.draw.rect(self.screen, dark_gray, self.left_border)
            pygame.draw.rect(self.screen, dark_gray, self.right_border)
            pygame.draw.rect(self.screen, dark_gray, self.upper_border)
            pygame.draw.ellipse(self.screen, blue, self.ball)

            # update and time
            self.print_score()
            if self.game_over == True:
                self.print_game_over()
            pygame.display.flip()
            clock.tick(FPS)

    # functions
    def player_movement(self):
        self.player.x += self.player_speed
        if self.player.left <= 10:
            self.player.left = 10
        if self.player.right >= self.width - 10:
            self.player.right = self.width - 10

    def ball_movement(self):
        self.ball.x += self.ball_speed_x
        self.ball.y += self.ball_speed_y

        # ball borders
        if self.ball.colliderect(self.player):
            self.ball_speed_y *= -1
            self.score += 1
        elif self.ball.colliderect(self.upper_border):
            self.ball_speed_y *= -1
        elif self.ball.colliderect(self.right_border):
            self.ball_speed_x *= -1
        elif self.ball.colliderect(self.left_border):
            self.ball_speed_x *= -1
        elif self.ball.y >= self.height:
            self.game_over = True
        # if ball left do ... of right ... and so on and so forth

    def print_game_over(self):
        go_font = pygame.font.Font("Youmurdererbb-pwoK.otf", 70)
        go_text = go_font.render("Game Over", False, blood)
        self.screen.blit(go_text, (80, 330))

    def print_score(self):
        score_font = pygame.font.Font("freesansbold.ttf", 17)
        score_text = score_font.render("Score: " + str(self.score), True, black)
        self.screen.blit(score_text, (14, 14))


game = Game()

Re: Ball hat ein statisches movement

Verfasst: Donnerstag 30. Dezember 2021, 13:53
von rogerb
@Lengeta,

Hiermit

Code: Alles auswählen

self.ball_speed_x = 4 * random.choice((1, -1))
gibt es nur zwei mögliche Fälle: -4 und 4

Bei

Code: Alles auswählen

self.ball_speed_x = random.randint(-4, 4)
bekommst du wenigsten *alle* Werte zwischen -4 und 4.

Außerdem könnte man die Position von Spieler und Ball bei der Kollision vergleichen und die horizontale Geschwindigkeit des Ball vergrößern, wenn der Ball nicht zentral auf den Schläger auftrifft.

Code: Alles auswählen

# ball borders
if self.ball.colliderect(self.player):
    if abs(self.ball.centerx - self.player.centerx) > 5: # horizontale Verschibung zwischen Ball und Player mehr als 5 Pixel
        self.ball_speed_x *= 2   # Dann horizontale Geschwindigkeit des Balls verdoppeln
    self.ball_speed_y *= -1
    self.score += 1
  
Übrigens, die while-Schleife sollte nicht in der __init__ sondern in einer eigenen Methode angelegt sein.

Re: Ball hat ein statisches movement

Verfasst: Donnerstag 30. Dezember 2021, 16:09
von Lengeta
@rogerb:
Danke das mit der while schleife merk ich mir, aber warum sollte die nicht in die _init_ Methode?
DAs problem mit

Code: Alles auswählen

self.ball_speed_x = random.randint(-4, 4)
ist das die Geschwindigkeit sich dadurch auch ändert und der ball bewegt sich trotzdem noch vorhersagbar nur, hat er jetzt ein paar variationen.
In einem durchlauf hat er leider trotzdem noch das selbe Bewegungsmuster

Re: Ball hat ein statisches movement

Verfasst: Donnerstag 30. Dezember 2021, 16:45
von __deets__
Dann musst du eben bei jedem Abprallvorgang wieder eine neue Geschwindigkeit zufällig bestimmen. Etwas realistischer ist im Zweifel nur eine kleine Änderung, damit die Grundrichtung erhalten bleibt.

Re: Ball hat ein statisches movement

Verfasst: Donnerstag 30. Dezember 2021, 16:58
von rogerb
Danke das mit der while schleife merk ich mir, aber warum sollte die nicht in die _init_ Methode?
Die init-Methode wird automatisch aufgerufen wenn aus der Klasse ein Objekt erzeugt wird. Dabei dient die init-Methode dazu Instanz-Attribute zu initialisieren.
game = Game()

"game" ist das Objekt welches aus dem Bauplan der Klasse "Game" erstellt wurde. Das "game" Objekt wird erst erstellt nachdem die init-Methode abgearbeitet wurde. Da du dort eine Endlosschleife hast, passiert das aber erst wenn der Benutzer das Programm schließt.
In diesem Fall hat das keine Nachteile. In den meisten anderen Fällen für die man Klassen verwendet, aber schon. Daher sollte man das von Anfang an sauber programmieren.

Die while-Schleife könnte man in einer "run" Methode unterbringen und dann so verwenden:

Code: Alles auswählen

game = Game()
game.run()
In einem durchlauf hat er leider trotzdem noch das selbe Bewegungsmuster
Dafür hatte ich ja vorgeschlagen, beim seitlichen Treffen des Schlägers die horizontale Geschwindigkeit zu erhöhen.
Eine gewissen Berechenbarkeit ist ja auch gewünscht, sonst wird es ein reines Zufallsspiel.

Um es noch spannender zu machen kann man nach einer gewissen Zeit einen zweiten Ball ins Spiel bringen. Oder man kann auch weitere Hindernisse ins Spielfeld bauen an denen der Ball abprallt.
Die können dann wie beim klassischen Breakout zerstört werden, oder sie könnten durch den Impuls des Balls einfach verschoben werden.