简体   繁体   English

Pygame碰撞一次发生19次 - Python 3.x.

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

I just started learning pygame today and am running into some issues with collision. 我今天刚刚开始学习pygame,并遇到了一些碰撞问题。 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. 当船撞到小行星大部分时间它都不会做任何事情,但是同时发生了19次碰撞和很多声音效果。

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. 您可以尝试制作全局变量,并在发生碰撞时将其设置为True以避免多个声音。

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. 如果游戏在崩溃后继续游戏,请确保在需要时将其重置为False

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). (布尔是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. 你可以使用spritecollide并杀死相撞的暴徒。 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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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