【问题标题】:How to Make the Ball Bounce only if it Hits the Paddle in Python, Pygame (Breakout Recreation)如何在 Python 中仅在球击中球拍时使球反弹,Pygame(突破娱乐)
【发布时间】:2013-03-29 15:14:44
【问题描述】:

谁能帮我解决这个问题?我无法制作一种简单的方法来检测球是否击中桨然后通过更改 rect_change_y 变量将其反弹。这是有效的代码,但球在击中游戏底部时不会与桨交互或死亡。

import pygame

black = ( 0, 0, 0)
white = ( 255, 255, 255)
green = ( 0, 255, 0)
red = ( 255, 0, 0)

rect_x = 10
rect_y = 250

pad_x = 350
pad_y = 480

ball = 3

rect_change_x = 1
rect_change_y = 1

pad_x_c = 0

pygame.init()

size=[700,500]
screen=pygame.display.set_mode(size)

pygame.mouse.set_visible(0)

pygame.display.set_caption("Breakout Recreation WIP")

done=False

clock=pygame.time.Clock()
# -------- Main Program Loop -----------
while ball != 0:
    # ALL EVENT PROCESSING SHOULD GO BELOW THIS COMMENT
    for event in pygame.event.get(): # User did something
        if event.type == pygame.QUIT: # If user clicked close
            done=True # Flag that we are done so we exit this loop
        keys = pygame.key.get_pressed()  #checking pressed keys
        if keys[pygame.K_LEFT]:
            pad_x_c -= 2
        elif keys[pygame.K_RIGHT]:
            pad_x_c += 2  
        else :
            pad_x_c = 0
    # ALL EVENT PROCESSING SHOULD GO ABOVE THIS COMMENT
    # ALL GAME LOGIC SHOULD GO BELOW THIS COMMENT
    # ALL GAME LOGIC SHOULD GO ABOVE THIS COMMENT
    # ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT
    # First, clear the screen to white. Don't put other drawing commands
    # above this, or they will be erased with this command.
    screen.fill(black)
    # Draw the rectangle
    pygame.draw.rect(screen,white,[rect_x,rect_y,15,15])
    pygame.draw.rect(screen,white,[pad_x,pad_y,50,10])
    # Move the rectangle starting point
    rect_x += rect_change_x
    rect_y += rect_change_y
    pad_x += pad_x_c
    # Bounce the ball if needed
    if rect_y > 480 or rect_y < 10:
        rect_change_y = rect_change_y * -1
    if rect_x > 680 or rect_x < 5:
        rect_change_x = rect_change_x * -1    
    if pad_x <= 5 :
        pad_x_c = 0
    if pad_x >= 645 :
        pad_x_c = 0
    # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT

    pygame.display.flip()

    clock.tick(100)

pygame.quit ()

然后这里的代码应该可以工作(对我来说)但没有。

import pygame

black = ( 0, 0, 0)
white = ( 255, 255, 255)
green = ( 0, 255, 0)
red = ( 255, 0, 0)

rect_x = 10
rect_y = 250

pad_x = 350
pad_y = 480

ball = 3

rect_change_x = 1
rect_change_y = 1

pad_x_c = 0

pygame.init()

size=[700,500]
screen=pygame.display.set_mode(size)

pygame.mouse.set_visible(0)

pygame.display.set_caption("Breakout Recreation WIP")

done=False

clock=pygame.time.Clock()
# -------- Main Program Loop -----------
while ball != 0:
    # ALL EVENT PROCESSING SHOULD GO BELOW THIS COMMENT
    for event in pygame.event.get(): # User did something
        if event.type == pygame.QUIT: # If user clicked close
            done=True # Flag that we are done so we exit this loop
        keys = pygame.key.get_pressed()  #checking pressed keys
        if keys[pygame.K_LEFT]:
            pad_x_c -= 2
        elif keys[pygame.K_RIGHT]:
            pad_x_c += 2  
        else :
            pad_x_c = 0
    # ALL EVENT PROCESSING SHOULD GO ABOVE THIS COMMENT
    # ALL GAME LOGIC SHOULD GO BELOW THIS COMMENT
    # ALL GAME LOGIC SHOULD GO ABOVE THIS COMMENT
    # ALL CODE TO DRAW SHOULD GO BELOW THIS COMMENT
    # First, clear the screen to white. Don't put other drawing commands
    # above this, or they will be erased with this command.
    screen.fill(black)
    # Draw the rectangle
    pygame.draw.rect(screen,white,[rect_x,rect_y,15,15])
    pygame.draw.rect(screen,white,[pad_x,pad_y,50,10])
    # Move the rectangle starting point
    rect_x += rect_change_x
    rect_y += rect_change_y
    pad_x += pad_x_c
    # Bounce the ball if needed
    if rect_y == pad_y:
        if rect_x == pad_x:
            rect_change_y = rect_change_y * -1
    if rect_y > 490:
        ball -= 1
        rect_y = 250
        rect_x = 10
        rect_change_x = 1
        rect_change_y = 1
    if rect_y < 10:
        rect_change_y = rect_change_y * -1
    if rect_x > 680 or rect_x < 5:
        rect_change_x = rect_change_x * -1       
    if pad_x <= 5 :
        pad_x_c = 0
    if pad_x >= 645 :
        pad_x_c = 0
    # ALL CODE TO DRAW SHOULD GO ABOVE THIS COMMENT

    pygame.display.flip()

    clock.tick(100)

pygame.quit ()

最后,关于如何制作积木并对它们做同样的事情,除了摧毁它们而不是球之外,有什么建议吗?

谢谢大家!

【问题讨论】:

    标签: python python-3.x pygame breakout


    【解决方案1】:

    您可以使用Rect 类来表示球和桨,还可以利用该类提供的方法:

    • Rect.move_ip 将矩形移动到位:

      myrect = pygame.Rect(0, 0, 10, 10)
      myrect.move_ip(100, 50)
      

      myrect 左上角位于 (100, 50) 并保持相同的宽度和高度。

    • Rect.clamp_ip 确保矩形都在屏幕内。

      myrect = pygame.Rect(100, 0, 10, 10)
      bounds = pygame.Rect(0, 0, 50, 50)
      myrect.clamp_ip(bounds)
      

      myrect 左上角位于 (40, 0),其右下角位于 (10, 50),在 bounds 矩形内。

    • Rect.colliderect 检查球和桨是否碰撞。

      myrect = pygame.Rect(0, 0, 10, 10)
      another = pygame.Rect(5, 5, 10, 10)
      print(myrect.colliderect(another)) # 1
      

      由于myrectanother重叠,当你调用colliderect时返回1,表示两个矩形有碰撞。


    我真的很喜欢 Pygame,所以我不介意根据这些建议重写你的程序。希望对您有所帮助:

    import pygame
    
    # Constants
    WIDTH = 700
    HEIGHT = 500
    SCREEN_AREA = pygame.Rect(0, 0, WIDTH, HEIGHT)
    BLACK = (0, 0, 0)
    WHITE = (255, 255, 255)
    
    # Initialization
    pygame.init()
    screen = pygame.display.set_mode([WIDTH, HEIGHT])
    pygame.mouse.set_visible(0)
    pygame.display.set_caption("Breakout Recreation WIP")
    clock = pygame.time.Clock()
    
    # Variables
    paddle = pygame.Rect(350, 480, 50, 10)
    ball = pygame.Rect(10, 250, 15, 15)
    paddle_movement_x = 0
    ball_direction = (1, 1)
    balls = 3
    done = False
    
    while not done and balls > 0:
    
        # Process events
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
            keys = pygame.key.get_pressed()
            if keys[pygame.K_LEFT]:
                paddle_movement_x = -2
            elif keys[pygame.K_RIGHT]:
                paddle_movement_x = 2
            else:
                paddle_movement_x = 0
    
        # Move paddle
        paddle.move_ip(paddle_movement_x, 0)
        paddle.clamp_ip(SCREEN_AREA)
    
        # Move ball
        ball.move_ip(*ball_direction)
        if ball.right > WIDTH or ball.left < 0:
            ball_direction = -ball_direction[0], ball_direction[1]
        elif ball.top < 0 or ball.bottom > HEIGHT or paddle.colliderect(ball):
            ball_direction = ball_direction[0], -ball_direction[1]
        ball.clamp_ip(SCREEN_AREA)
    
        # Redraw screen
        screen.fill(BLACK)
        pygame.draw.rect(screen, WHITE, paddle)
        pygame.draw.rect(screen, WHITE, ball)
        pygame.display.flip()
        clock.tick(100)
    
    pygame.quit()
    

    【讨论】:

    • 谢谢!你能解释一下新命令是如何工作的吗,我从来没有使用过它们。我喜欢你保留大部分内容的方式,但我不知道 move_ip 或夹具是如何工作的......谢谢!另外,现在有没有一种简单的方法可以检测球是否击中了桨下方的底部?
    • @PythonInProgress 我添加了一些代码示例来说明每种方法,并且我还修复了弹跳球运动的方向(有一个小错误)。
    • 感谢罗达斯!最有帮助:P!
    猜你喜欢
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多