简体   繁体   中英

Pygame collisions happening 19 at a time - Python 3.x

I just started learning pygame today and am running into some issues with collision. When the ship hits the asteroid most time it will not do anything, but something 19 collisions and a lot of sound effects happen all at once.

from pygame import *
import random as rand
from colors import *
import os
pygame.mixer.pre_init(44100, 16, 2, 4096) #frequency, size, channels, buffersize
pygame.init() #turn all of pygame on.
fps = 60
window_size = window_width, window_height = 800, 600


pygame.mixer.music.load('music.wav')
pygame.mixer.music.play(-1)
explode = pygame.mixer.Sound("explode.wav")


class Player(pygame.sprite.Sprite):
    #sprite for player
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load("plane.png")
        self.rect = self.image.get_rect()
        self.setprop()
        self.xspeed = 0

    def setprop( self ):
        self.rect = self.image.get_rect()
        self.orgin_x = self.rect.centerx
        self.orgin_y = self.rect.centery

    def set_position(self, x, y):
        self.rect.x = x - self.orgin_x
        self.rect.y = y - self.orgin_y

    def update(self):
        self.xspeed = 0
        keystate = pygame.key.get_pressed()
        if keystate[pygame.K_LEFT]:
            self.xspeed = -8
        if keystate[pygame.K_RIGHT]:
            self.xspeed = 8
        self.rect.x += self.xspeed

        if self.rect.right > window_width:
            self.rect.right = window_width

        if self.rect.left < 0:
            self.rect.left = 0

class Mob(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image  = pygame.image.load("boulder.png")
        #self.image.fill(red)
        self.rect   = self.image.get_rect()
        self.rect.x = rand.randrange(window_width - self.rect.width)
        self.rect.y = rand.randrange( -100, -40 )
        self.speed  = rand.randrange(6, 8)
        self.sound = pygame.mixer.Sound("swoosh.wav")

    def play_sound(self):
        self.sound.play()

    def update(self):
        self.rect.y += self.speed
        if self.rect.top > window_height + 10:
            self.rect.x = rand.randrange(window_width - self.rect.width)
            self.rect.y = rand.randrange( -100, -40 )
            self.speed  = rand.randrange(6, 8)




sprites = pygame.sprite.Group()
mobs = pygame.sprite.Group()
player = Player()
sprites.add(player)
for i in range(12):
    m = Mob()
    mobs.add(m)



player.set_position( window_width/2, window_height/2 +215 )       

pygame.init()
pygame.mixer.init()
window = pygame.display.set_mode( window_size, pygame.RESIZABLE )
pygame.display.set_caption('Dodge the Boulders!')
clock = pygame.time.Clock()
explode = pygame.mixer.Sound("explode.wav")


running = True

while ( running ):

    for event in pygame.event.get():
        if( event.type == pygame.QUIT ):
            running = False

    if ( pygame.sprite.collide_rect(m, player) ):
            explode.play()
            print('collide')





    clock.tick( fps )

    window.fill(black)
    sprites.update()
    sprites.draw(window)
    mobs.update()
    mobs.draw(window)
    pygame.display.update()


pygame.display.quit()
pygame.quit()

Here is the part I'm using for collision (in my game loop)

if ( pygame.sprite.collide_rect(m, player) ):
    explode.play()
    print('collide')

I've use this method of collision in other files and it seemed to have worked, I'm not sure what the issue is here. The only thing I could think of is that I'm not updating it somewhere but I couldn't find anything. I don't want anything else to happen other than playing a sound (and print collision)

Your game loop sees a collision -> plays the sound . The loop is fast .

Understand the problem?

You can try making a global variable and set it to True when collision happened to avoid multiple sounds.

Example:

crash = False // at global scope

if (pygame.sprite.collide_rect(m, player) and not crash):
    explode.play()
    print('collide')
    crash = True

Just make sure to reset it to False when needed if your game continues after crash.

Figured it out a bit ago but decided to post here.

so this

hits = pygame.sprite.spritecollide(player, mobs, False)
if hits:    
    running = False

will take a sprite first, and then a group. (boolean is dokill). It basically can only test in this way.

This however can test group against group:

hits = pygame.sprite.groupcollide(mobs, bullets, True, True)
if hits:
    pygame.mixer.Sound.play(zap)

You could just use spritecollide and kill the collided mob. Then play the sound and add a new mob for every collided mob.

# A list of mobs that have collided with the player.
# Set dokill to True to remove the collided sprites.
collided_mobs = pygame.sprite.spritecollide(player, mobs, True)
# Do something for every collided mob.
for mob_sprite in collided_mobs:
    sound.play()
    mobs.add(Mob())  # Add a new mob to replace the collided.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM