Pygame spritecollide 给我可迭代的错误

问题描述 投票:0回答:1

我正在使用 pygame 创建一个 Brick Breaker 游戏。除了碰撞之外,我已经让其他一切都正常工作了。我尝试使用 collide_rect 但它不起作用,但它没有给我错误消息。我尝试使用 spritecollide,但它给了我错误消息 Ball object is not iterable。我的目标是检测方块,将其移除,并提高分数。抱歉,我的代码有点乱。 这是我的代码(碰撞检测位于底部附近):

import pygame
import paddle
import ball
import block
import time
import random
import math
screenW, screenH = 1280, 720

backroundColor = [0,0,0]

offset = 30
PaddleW = 200
PaddleH = 25
PaddleX = screenW / 2 - PaddleW / 2
PaddleY = screenH - PaddleH - offset

n = 10
blockW = screenW / n #128 per block
blockH = blockW /4 + 10
pygame.init()
pygame.display.set_caption("Brick Breaker")
Display = pygame.display.set_mode((screenW, screenH))
Display.fill(backroundColor)

player = paddle.Paddle(PaddleX, PaddleY, PaddleW, PaddleH)

ballSize = 12
ballX = PaddleX
ballY = PaddleY-20
ballSpeed = -4
ballMoveY = ballSpeed
ballMoveX = ballSpeed
balls = pygame.sprite.Group()
balls = ball.Ball(ballX, ballY, ballSize)
#ballDraw = ball.Ball.draw(Display)

lives = 3
score = 0
shiftX = 0
shiftY = 0

#blocks init
'''blocks = pygame.sprite.Group()
blocks = []'''

#block1 = pygame.sprite.Group()
block1 = block.Block(10,60,blockW,blockH)

counter = 0
def displayText(text, color, posX, posY, size):
    str(text)
    font = pygame.font.SysFont('impact', size)
    textWrite = font.render(text, True, color)
    Display.blit(textWrite, (posX, posY))
def waitForKey():
    wait = True
    while wait:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                    pygame.quit()
            keys = pygame.key.get_pressed()
            if keys[pygame.K_SPACE]:
                wait = False


'''m=3
for y in range (4): #Spawn blocks
    for i in range (0, int(screenW), int(blockW)):
        blocks.append(block.Block(i+2, blockH*(y+2), blockW-4, blockH-4))'''
block1.draw(Display)
#blocks.draw = (14,14,14,14)

FPSClock = pygame.time.Clock()
FPS = 144

GameOver = False
Display.fill([130,140,230])
displayText('Brick Breaker', [200,230,100], 450,100, 80)
displayText('Use the mouse to move the paddle and bounce the ball. Try to break the bricks and not die.', [220,10,10], 120, 300,30)
displayText('Press space to begin', [0,0,0],520,510, 30)
pygame.display.flip()
waitForKey()
while not GameOver:
    counter += 1/FPS
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            if GameOver == False:
                GameOver = True
    mouseX = pygame.mouse.get_pos()[0]
    Display.fill(backroundColor)
    player.draw(Display)
    player.move(mouseX)

    balls.move(ballX, ballY) #pygame.draw.circle(Display, [0, 120, 120], [int(ballX), int(ballY)], ballSize)
    balls.draw(Display)

    '''
    for x in range(len(blocks)):
        blocks[x].draw(Display)
    '''
    #Draw blocks
    block1.draw(Display)

    if ballX <= 0:
        ballMoveX = -ballSpeed
        pygame.mixer.music.load("GungaGinga.mp3")
        pygame.mixer.music.play(1)
        #shiftX = random.randint(-2,2)
        #shiftY = -shiftX
    elif ballX >= screenW:
        ballMoveX = ballSpeed
        pygame.mixer.music.load("GungaGinga.mp3")
        pygame.mixer.music.play(1)
        #shiftX = random.randint(-2, 2)
        #shiftY = -shiftX
    if ballY <= 0:
        ballMoveY = -ballSpeed
        pygame.mixer.music.load("GungaGinga.mp3")
        pygame.mixer.music.play(1)
        #shiftY = random.randint(-2, 2)
        #shiftX = -shiftY
    elif ballY >= screenH:

        pygame.mixer.music.load("OOF.mp3")
        pygame.mixer.music.play(1)
        ballMoveY = ballSpeed
        lives -= 1
        ballX = PaddleX
        ballY = PaddleY - 20
        balls.move(ballX, ballY)
        #shiftX = 0
        #shiftY = 0
        time.sleep(1)

    if ballY <= PaddleY + PaddleW and ballY +ballSize >= PaddleY:
        if (ballX >= mouseX or ballX <= mouseX) and (ballX + ballSize <= mouseX + PaddleW/2 and ballX + ballSize >= mouseX - PaddleW/2): # or ballX + ballSize >= mouseX - PaddleW/2
            ballMoveY = -ballMoveY#ballSpeed
            pygame.mixer.music.load("GungaGinga.mp3")
            pygame.mixer.music.play(1)
            pygame.mixer.music.load("OOF.mp3")
            pygame.mixer.music.play(1)
    ballX += ballMoveX
    ballX = ballX +shiftX
    ballY += ballMoveY
    ballY = ballY + shiftY

    displayText('Lives: %s'%lives, [90,190,90], 20, 10, 40)
    displayText('Time: %.1f' %counter, [20,190,90], 1100, 10, 40)
    displayText('Score: %s' % score, [90, 190, 90], 570, 10, 40)
    if counter == 5:
        ballSpeed -= 1

#Collision Test
    #if pygame.sprite.spritecollideany(balls, blocks):
        #blocks.kill(blocks)
    #hitBlock = pygame.sprite.collide_mask(blocks, player)
    '''    def hit(self):
        hit_block = pygame.sprite.groupcollide(blocks, self.balls, False, True)
        if hit_block:
            return True
        else:
            return False'''
    #is_a_collision = pygame.sprite.collide_mask(blocks, balls)
    '''
    if self.hit():
        print("collision")
        score += 10
        blocks.kill(blocks)
        '''
    #collision
    #hit_block = pygame.sprite.spritecollide(balls, block1, False, True)
    #hit_block()
    #pygame.Surface.get_rect(block1)
    #Current colliderect not working
    if pygame.sprite.collide_rect(block1, balls):
        score += 10
        #block1.kill()
        print("collision")

    #Spritecollide not working -  gives error message

    if pygame.sprite.spritecollide(block1, balls,False):
        #block1.kill()
        score += 10



    pygame.display.flip()
    pygame.display.update()
    FPSClock.tick(FPS)
    if (lives <= 0):
        #You died
        Display.fill([130, 140, 230])
        displayText('You Lost', [200, 230, 100], 500, 100, 80)
        displayText('Thanks for trying',[250, 10, 10], 540, 300, 35)
        displayText('Press space to exit', [0, 0, 0], 540, 510, 30)
        pygame.display.flip()
        waitForKey()
        GameOver = True
    #balls.hit()
    '''
    if balls.collide():
        print("collide")
        score += 10
        '''
pygame.quit()

这是我的课程示例:

import pygame

class Block(pygame.sprite.Sprite):
    def __init__(self, posx, posy, width, height):
        pygame.sprite.Sprite.__init__(self)
        super().__init__()
        #self.rect = self.image.get_rect()
        self.rect = pygame.Rect(posx, posy, width, height)
        self.posx = posx
        self.posy = posy
        self.height = height
        self.width = width
    def draw (self, Display):
        pygame.draw.rect(Display, [6,130,183], [self.posx, self.posy, self.width, self.height])

我正在使用 PyCharm 请让我知道该怎么做。 谢谢

python pygame collision
1个回答
1
投票

问题在于条件

if (ballX >= mouseX or ballX <= mouseX) and (ballX + ballSize <= mouseX + PaddleW/2 and ballX + ballSize >= mouseX - PaddleW/2):

第一个条件 (

(ballX >= mouseX or ballX <= mouseX)
) 的结果始终是
True
,而第二个条件则搞砸了。

如果您的范围为

x1
x1+w1
,第二个范围为
x2
x2+w2
,则这两个范围重叠,如果

x1 <= x2+w and x2 <= x1+w1 

所以碰撞测试必须是:

if ballY <= PaddleY + PaddleH and PaddleY <= ballY + ballSize:
    if ballX <= mouseX + PaddleW/2 and mouseX - PaddleW/2 <= ballX + ballSize:
        ballMoveY = -ballMoveY
        score += 10

无论如何,我建议使用

pygame.Rect
对象和方法
.colliderect()
。例如:

ball_rect   = pygame.Rect(ballX, ballY, ballSize, ballSize)
paddle_rect = pygame.Rect(mouseX-PaddleW/2, PaddleY, PaddleW, PaddleH)
if ball_rect.colliderect(paddle_rect):
    ballMoveY = -ballMoveY
    score += 10

由于您的对象是

Sprites
,我建议保持
.rect
属性为最新。例如:

class Ball(pygame.sprite.Sprite):
    # [...]

    def move(self, x, y):
        self.rect.topleft = (x, y)
        self.posx, self.posy = self.rect.topleft
class Paddle(pygame.sprite.Sprite):
    # [...]

    def move(self, x):
        self.rect.centerx = x
        self.posx = self.rect.left

现在您可以使用对象的

.rect
属性进行碰撞测试:

if ball.rect.colliderect(player.rect):
    ballMoveY = -ballMoveY
    score += 10

由于这两个对象都是精灵,因此建议使用

pygame.sprite.collide_rect()

if pygame.sprite.collide_rect(ball, player):
    ballMoveY = -ballMoveY
    score += 10

注意,

Sprite
对象与
Group
或事件2
Group
的碰撞可以分别通过
pygame.sprite.spritecollide()
找到
pygame.sprite.groupcollide()
。例如:

blocks = pygame.sprite.Group()
blocks.add(block.Block(10,block1Y,blockW, blockH, blockColor))
if pygame.sprite.spritecollide(ball, blocks, False):
    ballMoveY = -ballMoveY
    score += 10
for block in blocks:
    block.draw(Display)
© www.soinside.com 2019 - 2024. All rights reserved.