物体碰撞时播放声音
Play sound when objects collide
我试图在对象 ball
与 angryball
碰撞时播放 ouch
声音,但声音并不总是播放。当两个对象位于相同的 x 或 y 坐标上时,它会在第一次碰撞时开始,但此后它无法正确播放以应对未来的碰撞。
也许这是我如何设法处理他们的坐标以检查碰撞的错误?
import pygame
import os
import random
size = width, height = 750, 422
screen = pygame.display.set_mode(size)
img_path = os.path.join(os.getcwd())
background_image = pygame.image.load('background.jpg').convert()
bg_image_rect = background_image.get_rect()
pygame.mixer.pre_init(44100, 16, 2, 4096)
pygame.display.set_caption("BallGame")
class Ball(object):
def __init__(self):
self.image = pygame.image.load("ball.png")
self.image_rect = self.image.get_rect()
self.image_rect.x
self.image_rect.y
self.facing = 'LEFT'
def handle_keys(self):
key = pygame.key.get_pressed()
dist = 5
if key[pygame.K_DOWN] and self.image_rect.y < 321:
self.facing = 'DOWN'
self.image_rect.y += dist
elif key[pygame.K_UP] and self.image_rect.y > 0:
self.facing = 'UP'
self.image_rect.y -= dist
if key[pygame.K_RIGHT] and self.image_rect.x < 649:
self.facing = 'RIGHT'
self.image_rect.x += dist
elif key[pygame.K_LEFT] and self.image_rect.x > 0:
self.facing = 'LEFT'
self.image_rect.x -= dist
def draw(self, surface):
if self.facing == "RIGHT":
surface.blit(pygame.transform.flip(self.image, True, False),(self.image_rect.x,self.image_rect.y))
elif self.facing == "DOWN":
surface.blit(pygame.image.load("ball_down.png"),(self.image_rect.x,self.image_rect.y))
if self.facing == "UP":
surface.blit(pygame.image.load("ball_up.png"),(self.image_rect.x,self.image_rect.y))
elif self.facing == "LEFT":
surface.blit(self.image,(self.image_rect.x,self.image_rect.y))
mob_images = [pygame.image.load("image1.png").convert_alpha(),pygame.image.load("image2.png").convert_alpha(),pygame.image.load("image3.png").convert_alpha(),pygame.image.load("image4.png").convert_alpha(),pygame.image.load("image5.png").convert_alpha()]
class Angryball(pygame.sprite.Sprite):
def __init__(self, mob_images, pos_x, pos_y):
super(Angryball, self).__init__()
self.mob_images = mob_images
self.image = random.choice(self.mob_images)
self.rect = self.image.get_rect(x=pos_x, y=pos_y)
self.facing = 'LEFT'
def update(self, screen):
if self.rect.x <= 0:
self.rect.right = screen.get_rect().width
self.rect.top = random.randint(0, screen.get_rect().height)
self.image = random.choice(self.mob_images)
else:
self.rect.move_ip(-5, 0)
pygame.init()
screen = pygame.display.set_mode((750, 422))
ball = Ball()
angryball = Angryball(mob_images , 700, random.randrange(400))
sprites = pygame.sprite.Group()
sprites.add(angryball)
clock = pygame.time.Clock()
pygame.mixer.music.load("bg_music.mp3")
pygame.mixer.music.play(-1, 0.0)
ouch = pygame.mixer.Sound("border_sound.wav")
running = True
while running:
esc_key = pygame.key.get_pressed()
for event in pygame.event.get():
if esc_key[pygame.K_ESCAPE]:
pygame.display.quit()
pygame.quit()
running = False
if ball.image_rect.x == angryball.rect.x:
ouch.play()
if ball.image_rect.y == angryball.rect.y:
ouch.play()
ball.handle_keys()
screen.blit(background_image, bg_image_rect)
screen.blit(background_image, bg_image_rect.move(bg_image_rect.width, 0))
bg_image_rect.move_ip(-2, 0)
if bg_image_rect.right <= 0:
bg_image_rect.x = 0
sprites.update(screen)
sprites.draw(screen)
ball.draw(screen)
pygame.display.update()
clock.tick(60)
按照建议,我用
替换了碰撞检测
if ball.image_rect.colliderect(angryball.rect):
成功了
您还可以检查特定点的碰撞,例如:
ball.rect.collidepoint(angryball.rect.x, angryball.rect.y)
它的作用是测试一个点是否确实在精灵的矩形内。我发现它很好用,简单明了,易于使用和理解。
您需要替换这些行,
if ball.image_rect.x == angryball.rect.x:
ouch.play()
if ball.image_rect.y == angryball.rect.y:
ouch.play()
用这个(检查两个矩形是否碰撞):
if ball.image_rect.colliderect(angryball.rect):
ouch.play()
现在的问题是,声音会在两个物体碰撞的每一帧播放,因此会变得非常响亮(最多同时在 8 个声道中播放)。此外,如果所有通道都被占用,如果多个物体在短时间内发生碰撞,声音播放可能会被跳过。
为了防止这种情况,您可以给 Angryball
一个 collided
属性(布尔值)并在第一次碰撞后将其设置为 True
。然后在一段时间后或在重置位置的同时将其重置为False
。
if ball.image_rect.colliderect(angryball.rect) and not angryball.collided:
angryball.collided = True
ouch.play()
我试图在对象 ball
与 angryball
碰撞时播放 ouch
声音,但声音并不总是播放。当两个对象位于相同的 x 或 y 坐标上时,它会在第一次碰撞时开始,但此后它无法正确播放以应对未来的碰撞。
也许这是我如何设法处理他们的坐标以检查碰撞的错误?
import pygame
import os
import random
size = width, height = 750, 422
screen = pygame.display.set_mode(size)
img_path = os.path.join(os.getcwd())
background_image = pygame.image.load('background.jpg').convert()
bg_image_rect = background_image.get_rect()
pygame.mixer.pre_init(44100, 16, 2, 4096)
pygame.display.set_caption("BallGame")
class Ball(object):
def __init__(self):
self.image = pygame.image.load("ball.png")
self.image_rect = self.image.get_rect()
self.image_rect.x
self.image_rect.y
self.facing = 'LEFT'
def handle_keys(self):
key = pygame.key.get_pressed()
dist = 5
if key[pygame.K_DOWN] and self.image_rect.y < 321:
self.facing = 'DOWN'
self.image_rect.y += dist
elif key[pygame.K_UP] and self.image_rect.y > 0:
self.facing = 'UP'
self.image_rect.y -= dist
if key[pygame.K_RIGHT] and self.image_rect.x < 649:
self.facing = 'RIGHT'
self.image_rect.x += dist
elif key[pygame.K_LEFT] and self.image_rect.x > 0:
self.facing = 'LEFT'
self.image_rect.x -= dist
def draw(self, surface):
if self.facing == "RIGHT":
surface.blit(pygame.transform.flip(self.image, True, False),(self.image_rect.x,self.image_rect.y))
elif self.facing == "DOWN":
surface.blit(pygame.image.load("ball_down.png"),(self.image_rect.x,self.image_rect.y))
if self.facing == "UP":
surface.blit(pygame.image.load("ball_up.png"),(self.image_rect.x,self.image_rect.y))
elif self.facing == "LEFT":
surface.blit(self.image,(self.image_rect.x,self.image_rect.y))
mob_images = [pygame.image.load("image1.png").convert_alpha(),pygame.image.load("image2.png").convert_alpha(),pygame.image.load("image3.png").convert_alpha(),pygame.image.load("image4.png").convert_alpha(),pygame.image.load("image5.png").convert_alpha()]
class Angryball(pygame.sprite.Sprite):
def __init__(self, mob_images, pos_x, pos_y):
super(Angryball, self).__init__()
self.mob_images = mob_images
self.image = random.choice(self.mob_images)
self.rect = self.image.get_rect(x=pos_x, y=pos_y)
self.facing = 'LEFT'
def update(self, screen):
if self.rect.x <= 0:
self.rect.right = screen.get_rect().width
self.rect.top = random.randint(0, screen.get_rect().height)
self.image = random.choice(self.mob_images)
else:
self.rect.move_ip(-5, 0)
pygame.init()
screen = pygame.display.set_mode((750, 422))
ball = Ball()
angryball = Angryball(mob_images , 700, random.randrange(400))
sprites = pygame.sprite.Group()
sprites.add(angryball)
clock = pygame.time.Clock()
pygame.mixer.music.load("bg_music.mp3")
pygame.mixer.music.play(-1, 0.0)
ouch = pygame.mixer.Sound("border_sound.wav")
running = True
while running:
esc_key = pygame.key.get_pressed()
for event in pygame.event.get():
if esc_key[pygame.K_ESCAPE]:
pygame.display.quit()
pygame.quit()
running = False
if ball.image_rect.x == angryball.rect.x:
ouch.play()
if ball.image_rect.y == angryball.rect.y:
ouch.play()
ball.handle_keys()
screen.blit(background_image, bg_image_rect)
screen.blit(background_image, bg_image_rect.move(bg_image_rect.width, 0))
bg_image_rect.move_ip(-2, 0)
if bg_image_rect.right <= 0:
bg_image_rect.x = 0
sprites.update(screen)
sprites.draw(screen)
ball.draw(screen)
pygame.display.update()
clock.tick(60)
按照建议,我用
替换了碰撞检测if ball.image_rect.colliderect(angryball.rect):
成功了
您还可以检查特定点的碰撞,例如:
ball.rect.collidepoint(angryball.rect.x, angryball.rect.y)
它的作用是测试一个点是否确实在精灵的矩形内。我发现它很好用,简单明了,易于使用和理解。
您需要替换这些行,
if ball.image_rect.x == angryball.rect.x:
ouch.play()
if ball.image_rect.y == angryball.rect.y:
ouch.play()
用这个(检查两个矩形是否碰撞):
if ball.image_rect.colliderect(angryball.rect):
ouch.play()
现在的问题是,声音会在两个物体碰撞的每一帧播放,因此会变得非常响亮(最多同时在 8 个声道中播放)。此外,如果所有通道都被占用,如果多个物体在短时间内发生碰撞,声音播放可能会被跳过。
为了防止这种情况,您可以给 Angryball
一个 collided
属性(布尔值)并在第一次碰撞后将其设置为 True
。然后在一段时间后或在重置位置的同时将其重置为False
。
if ball.image_rect.colliderect(angryball.rect) and not angryball.collided:
angryball.collided = True
ouch.play()