【问题标题】:Pong paddles have some weird bug preventing from letting a player score [duplicate]乒乓球拍有一些奇怪的错误阻止玩家得分[重复]
【发布时间】:2020-07-26 14:32:56
【问题描述】:

我做了一个乒乓球游戏。现在的问题是,当我移动桨时,球并没有越过它,而是在一些看不见的墙上反弹。这是我的代码,你自己运行它,你可以看到问题(你必须稍微移动一下桨)

# Pong

# Importing libraries
import pygame
import random
import time

# Initializing PyGame
pygame.init()

# Creating a font
font = pygame.font.SysFont(None, 30)

# Set the height and width of the screen
window_width = 700
window_height = 500
size = [window_width, window_height]
game_win = pygame.display.set_mode(size)


# Creating a messaging system
def message(sentence, x, y):
    sentence = font.render(sentence, True, white)
    game_win.blit(sentence, [x, y])


# Creating a color
white = (225, 225, 225)
black = (0, 0, 0)

# Setting up ball
ball_size = 25


class Ball:
    """
    Class to keep track of a ball's location and vector.
    """

    def __init__(self):
        self.x = 0
        self.y = 0
        self.change_x = 0
        self.change_y = 0


def make_ball():
    ball = Ball()
    # Starting position of the ball.
    # Take into account the ball size so we don't spawn on the edge.
    ball.x = 350
    ball.y = 250

    # Speed and direction of rectangle
    ball.change_x = 5
    ball.change_y = 5

    return ball


def main():
    # Scores
    left_score = 0
    right_score = 0

    pygame.init()

    pygame.display.set_caption("Ping Pong")

    # Loop until the user clicks the close button.
    done = False

    # Used to manage how fast the screen updates
    clock = pygame.time.Clock()

    ball_list = []

    ball = make_ball()
    ball_list.append(ball)

    # Right paddle coordinates
    y = 200
    y_change = 0
    x = 50
    # Left paddle coordinates
    y1 = 200
    y1_change = 0
    x1 = 650

    while not done:
        # --- Event Processing
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_w:
                    y_change = -5

                elif event.key == pygame.K_s:
                    y_change = 5

                elif event.key == pygame.K_UP:
                    y1_change = -5

                elif event.key == pygame.K_DOWN:
                    y1_change = 5

            elif event.type == pygame.KEYUP:
                y_change = 0
                y1_change = 0

        y += y_change
        y1 += y1_change

        if y > window_height - 100:
            y -= 5
        if y < 50:
            y += 5
        if y1 > window_height - 100:
            y1 -= 5
        if y1 < 50:
            y1 += 5

        message("Left player score: " + str(left_score), 10, 10)
        message("Right player score: " + str(right_score), 490, 10)

        # Drawing a left paddle
        pygame.draw.rect(game_win, white, [x, y, 25, 100])
        # Drawing a right paddle
        pygame.draw.rect(game_win, white, [x1, y1, 25, 100])

        # Updating screen to changes take place
        pygame.display.update()

        # Logic
        for ball in ball_list:
            # Move the ball's center
            ball.x += ball.change_x
            ball.y += ball.change_y

            # Bounce the ball if needed
            if ball.y > 50 - ball_size or ball.y < ball_size:
                ball.change_y *= -1
            if ball.x > window_width - ball_size:
                ball.change_x *= -1
                left_score += 1
            if ball.x < ball_size:
                ball.change_x *= -1
                right_score += 1
            # Here is the part where it all becomes weird and buggy
            if ball.x-ball_size <= x <= ball.x + ball_size:
                ball.change_x *= -1
            if ball.x-ball_size <= x1 <= ball.x + ball_size:
                ball.change_x *= -1
            if ball.y-ball_size <= y <= ball.y + ball_size:
                ball.change_x *= -1
            if ball.y-ball_size <= y1 <= ball.y + ball_size:
                ball.change_x *= -1

            if right_score == 10:
                message('RIGHT PLAYER HAS WON!!', 300, 200)
                time.sleep(10)
                done = True
            elif left_score == 10:
                message("LEFT PLAYER HAS WON!!", 300, 200)
                time.sleep(10)
                done = True

        # Drawing
        # Set the screen background
        game_win.fill(black)

        # Draw the balls
        for ball in ball_list:
            pygame.draw.circle(game_win, white, [ball.x, ball.y], ball_size)

        # Wrap-up
        # Limit to 60 frames per second
        clock.tick(60)

        # Go ahead and update the screen with what we've drawn.
        pygame.display.flip()

    # Close everything down
    pygame.quit()


if __name__ == "__main__":
    main()

当我把桨移开时,球仍然可以从一些看不见的墙上反弹。其他一切都很好,只是我放# Bounce if needed的部分。

【问题讨论】:

    标签: python pygame collision-detection


    【解决方案1】:

    我建议计算球和桨的边界矩形,并使用pygame.Rect 和colliderect() 来检测球和桨之间的碰撞。
    另见Sometimes the ball doesn't bounce off the paddle in pong game。

    例如:

    def main():
        # [...]
    
        while not done:
            # [...]
    
            # Logic
            for ball in ball_list:
                # [...]
    
                ball_rect = pygame.Rect(ball.x-ball_size, ball.y-ball_size, ball_size*2, ball_size*2)
                
                left_paddle_rect = pygame.Rect(x, y, 25, 75)
                if ball.change_x < 0 and ball_rect.colliderect(left_paddle_rect):
                    ball.change_x = abs(ball.change_x)
                
                right_paddle_rect = pygame.Rect(x1, y1, 25, 75)
                if ball.change_x > 0 and ball_rect.colliderect(right_paddle_rect):
                    ball.change_x = -abs(ball.change_x)
    

    此外,窗口的高度是 500 而不是 50_

    if ball.y &gt; 50 - ball_size or ball.y &lt; ball_size:

    if ball.y > 500 - ball_size or ball.y < ball_size:
    

    我建议分别删除对pygame.display.flip() 的多个调用pygame.display.update()。在主应用程序循环结束时只更新一次显示。查看完整示例:

    # Importing libraries
    import pygame
    import random
    import time
    
    # Initializing PyGame
    pygame.init()
    
    # Creating a font
    font = pygame.font.SysFont(None, 30)
    
    # Set the height and width of the screen
    window_width = 700
    window_height = 500
    size = [window_width, window_height]
    game_win = pygame.display.set_mode(size)
    
    
    # Creating a messaging system
    def message(sentence, x, y):
        sentence = font.render(sentence, True, white)
        game_win.blit(sentence, [x, y])
    
    
    # Creating a color
    white = (225, 225, 225)
    black = (0, 0, 0)
    
    # Setting up ball
    ball_size = 25
    
    
    class Ball:
        """
        Class to keep track of a ball's location and vector.
        """
    
        def __init__(self):
            self.x = 0
            self.y = 0
            self.change_x = 0
            self.change_y = 0
    
    
    def make_ball():
        ball = Ball()
        # Starting position of the ball.
        # Take into account the ball size so we don't spawn on the edge.
        ball.x = 350
        ball.y = 250
    
        # Speed and direction of rectangle
        ball.change_x = 5
        ball.change_y = 5
    
        return ball
    
    
    def main():
        # Scores
        left_score = 0
        right_score = 0
    
        pygame.init()
    
        pygame.display.set_caption("Ping Pong")
    
        # Loop until the user clicks the close button.
        done = False
    
        # Used to manage how fast the screen updates
        clock = pygame.time.Clock()
    
        ball_list = []
    
        ball = make_ball()
        ball_list.append(ball)
    
        # Right paddle coordinates
        y = 200
        y_change = 0
        x = 50
        # Left paddle coordinates
        y1 = 200
        y1_change = 0
        x1 = 650
    
        while not done:
            # --- Event Processing
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    done = True
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_w:
                        y_change = -5
    
                    elif event.key == pygame.K_s:
                        y_change = 5
    
                    elif event.key == pygame.K_UP:
                        y1_change = -5
    
                    elif event.key == pygame.K_DOWN:
                        y1_change = 5
    
                elif event.type == pygame.KEYUP:
                    y_change = 0
                    y1_change = 0
    
            y += y_change
            y1 += y1_change
    
            if y > window_height - 100:
                y -= 5
            if y < 50:
                y += 5
            if y1 > window_height - 100:
                y1 -= 5
            if y1 < 50:
                y1 += 5
    
            message("Left player score: " + str(left_score), 10, 10)
            message("Right player score: " + str(right_score), 490, 10)
    
    
            # Logic
            for ball in ball_list:
                # Move the ball's center
                ball.x += ball.change_x
                ball.y += ball.change_y
    
                # Bounce the ball if needed
                if ball.y > 500 - ball_size or ball.y < ball_size:
                    ball.change_y *= -1
                if ball.x > window_width - ball_size:
                    ball.change_x *= -1
                    left_score += 1
                if ball.x < ball_size:
                    ball.change_x *= -1
                    right_score += 1
                
                # Here is the part where it all becomes weird and buggy
                ball_rect = pygame.Rect(ball.x-ball_size, ball.y-ball_size, ball_size*2, ball_size*2)
                
                left_paddle_rect = pygame.Rect(x, y, 25, 75)
                if ball.change_x < 0 and ball_rect.colliderect(left_paddle_rect):
                    ball.change_x = abs(ball.change_x)
                
                right_paddle_rect = pygame.Rect(x1, y1, 25, 75)
                if ball.change_x > 0 and ball_rect.colliderect(right_paddle_rect):
                    ball.change_x = -abs(ball.change_x)
    
                if right_score == 10:
                    message('RIGHT PLAYER HAS WON!!', 300, 200)
                    time.sleep(10)
                    done = True
                elif left_score == 10:
                    message("LEFT PLAYER HAS WON!!", 300, 200)
                    time.sleep(10)
                    done = True
    
            # Drawing
            # Set the screen background
            game_win.fill(black)
    
            # Drawing a left paddle
            pygame.draw.rect(game_win, white, [x, y, 25, 100])
            # Drawing a right paddle
            pygame.draw.rect(game_win, white, [x1, y1, 25, 100])
    
            # Draw the balls
            for ball in ball_list:
                pygame.draw.circle(game_win, white, [ball.x, ball.y], ball_size)
    
            # Go ahead and update the screen with what we've drawn.
            pygame.display.flip()
    
            # Wrap-up
            # Limit to 60 frames per second
            clock.tick(60)
    
        # Close everything down
        pygame.quit()
    
    
    if __name__ == "__main__":
        main()
    

    【讨论】:

    • 谢谢,这很有帮助。
    猜你喜欢
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 2020-06-13
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多