[英]distorted audio when playing a sound with pygame
我正在尝试用圆形和矩形制作街头霸王风格的游戏(懒得画艺术)。 但是,当我尝试播放出拳的声音时,听起来像是失真了。 我在玩家死亡时播放的 KO 音效也是如此。
这是声音
https://audio.nathanli1818.repl.co/
继承人的代码:
import pygame
pygame.init()
colors = {
"white": (255, 255, 255),
"black": (0, 0, 0),
"blue": (71, 52, 237),
"green": (53, 189, 71),
"brown": (79, 21, 21),
"red": (184, 39, 39),
"purple": (145, 27, 209)
}
class Fighter:
def __init__(self, win, x, y, win_width, win_height, color, healthx, healthy):
self.win = win
self.gravity = 0
self.win_width = win_width
self.win_height = win_height
self.color = color
self.health = 100
self.healthx = healthx
self.healthy = healthy
self.dir_ = "right"
self.x = x
self.y = y
self.base = pygame.Rect(0, 0, 70, 100)
self.base.centerx = self.x
self.base.centery = self.y
self.attack_ = pygame.Rect(0, 0, 20, 20)
self.healthbar = pygame.Rect(0, 0, self.health * 3, 20)
self.healthbar.center = (self.healthx, self.healthy)
self.background = pygame.Rect(0, 0, 300, 20)
self.background.center = self.healthbar.center
self.punch = pygame.mixer.Sound("sounds/attack.wav")
self.punch.set_volume(0.3)
self.KO = pygame.mixer.Sound("sounds/KO.mp3")
self.KO.set_volume(0.3)
def render(self):
pygame.draw.ellipse(self.win, self.color, self.base)
self.x = self.base.centerx
self.y = self.base.centery
def move(self, x, y):
self.base.centerx = x
self.base.centery = y
def fall(self):
self.base.y += self.gravity
self.gravity += 1
if self.base.bottom >= self.win_height - 50:
self.gravity = 0
self.base.bottom = self.win_height - 50
def draw_healthbar(self):
if self.health <= 0:
flag = 0
if not flag:
self.KO.play()
flag += 1
self.health = 100
self.healthbar.width = self.health * 3
pygame.draw.rect(self.win, colors["red"], self.background)
pygame.draw.rect(self.win, colors["green"], self.healthbar)
def attack(self, type_):
if type_ == "punch":
flag = 0
if self.dir_ == "right":
if not flag:
self.punch.play()
flag += 1
self.attack_.center = (self.base.topright[0] + 35, self.base.centery - 10)
pygame.draw.rect(self.win, self.color, self.attack_)
elif self.dir_ == "left":
if not flag:
self.punch.play()
flag += 1
self.attack_.center = (self.base.topleft[0] - 35, self.base.centery - 10)
pygame.draw.rect(self.win, self.color, self.attack_)
class Background:
def __init__(self, win, win_width, win_height):
self.win = win
self.win_width = win_width
self.win_height = win_height
self.sky = (self.win_width, self.win_height - 100)
self.ground = (self.win_width, 100)
self.platform = (220, 30)
self.platformTop = (220, 5)
self.platformBottom = (220, 5)
self.sky_base = pygame.Rect(0, 0, *self.sky)
self.ground_base = pygame.Rect(0, 0, *self.ground)
self.ground_base.bottom = self.win_height
self.platform_base = pygame.Rect(0, 0, *self.platform)
self.platform_base.center = (self.win_width / 2, self.win_height / 2 + 15)
self.platform_top = pygame.Rect(0, 0, *self.platformTop)
self.platform_top.center = (self.platform_base.centerx, self.platform_base.top + self.platformBottom[1])
self.platform_bottom = pygame.Rect(0, 0, *self.platformBottom)
self.platform_bottom.center = (self.platform_base.centerx, self.platform_base.bottom - self.platformBottom[1])
def load(self):
pygame.draw.rect(self.win, colors["blue"], self.sky_base)
pygame.draw.rect(self.win, colors["green"], self.ground_base)
pygame.draw.rect(self.win, colors["brown"], self.platform_base)
class Game:
def __init__(self):
self.width = 900
self.height = 500
self.running = True
self.attackFlag1 = 0
self.attackFlag2 = 0
self.fps = 60
self.win = pygame.display.set_mode((self.width, self.height))
self.clock = pygame.time.Clock()
self.fighter = Fighter(self.win, 200, 450, self.width, self.height, colors["red"], 200, 50)
self.fighter2 = Fighter(self.win, 700, 450, self.width, self.height, colors["purple"], 700, 50)
self.background = Background(self.win, self.width, self.height)
pygame.display.set_caption("street fighter")
def fighter_1(self, keys):
if keys[pygame.K_a]:
if self.fighter.base.left <= 0:
self.fighter.x += 10
self.fighter.dir_ = "left"
x = self.fighter.x
self.fighter.move(x - 10, self.fighter.y)
if keys[pygame.K_d]:
if self.fighter.base.right >= self.width:
self.fighter.x -= 10
self.fighter.dir_ = "right"
x = self.fighter.x
self.fighter.move(x + 10, self.fighter.y)
if keys[pygame.K_w] and self.fighter.base.bottom == 450:
self.fighter.gravity = -20
if keys[pygame.K_s] and self.fighter.base.bottom != 450:
self.fighter.gravity += 10
if self.background.platform_top.colliderect(self.fighter.base):
if keys[pygame.K_w]:
self.fighter.gravity = -20
else:
self.fighter.gravity = 0
self.fighter.base.bottom = self.background.platform_top.bottom
if self.background.platform_bottom.colliderect(self.fighter.base):
self.fighter.gravity += 5
if keys[pygame.K_e]:
self.fighter.attack("punch")
if self.fighter.base.colliderect(self.fighter2.attack_):
if self.attackFlag2 == 0:
self.fighter.health -= 5
self.attackFlag2 += 1
def fighter_2(self, keys):
if keys[pygame.K_LEFT]:
if self.fighter2.base.left <= 0:
self.fighter2.x += 10
self.fighter2.dir_ = "left"
x = self.fighter2.x
self.fighter2.move(x - 10, self.fighter2.y)
if keys[pygame.K_RIGHT]:
if self.fighter2.base.right >= self.width:
self.fighter2.x -= 10
self.fighter2.dir_ = "right"
x = self.fighter2.x
self.fighter2.move(x + 10, self.fighter2.y)
if keys[pygame.K_UP] and self.fighter2.base.bottom == 450:
self.fighter2.gravity = -20
if keys[pygame.K_DOWN] and self.fighter2.base.bottom != 450:
self.fighter2.gravity += 10
if self.background.platform_top.colliderect(self.fighter2.base):
if keys[pygame.K_UP]:
self.fighter2.gravity = -20
else:
self.fighter2.gravity = 0
self.fighter2.base.bottom = self.background.platform_top.bottom
if self.background.platform_bottom.colliderect(self.fighter2.base):
self.fighter2.gravity += 5
if self.fighter2.base.colliderect(self.fighter.attack_):
if self.attackFlag1 == 0:
self.fighter2.health -= 50
self.attackFlag1 += 1
if keys[pygame.K_RSHIFT]:
self.fighter2.attack("punch")
def run(self):
while self.running:
self.clock.tick(self.fps)
self.background.load()
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
if event.type == pygame.KEYUP:
if event.key == pygame.K_e:
self.fighter.attack_.y = 1000
self.attackFlag1 = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_RSHIFT:
self.fighter2.attack_.y = 1000
self.attackFlag2 = 0
keys = pygame.key.get_pressed()
self.fighter_1(keys)
self.fighter.fall()
self.fighter.draw_healthbar()
self.fighter.render()
self.fighter_2(keys)
self.fighter2.fall()
self.fighter2.draw_healthbar()
self.fighter2.render()
pygame.display.update()
pygame.quit()
if __name__ == '__main__':
Game().run()
在 python 3.8.8
您的问题来自声音在其自身之上多次播放的事实。 发生这种情况是因为每一帧,您检查pygame.K_e
是否被保持,如果是则播放声音。 但是,当您按下一个键时,您可能会按住该键超过一帧,因此这会导致声音在其自身之上快速连续播放多次。
解决问题的一种方法是使用pygame.mixer.Channel
播放声音,它只允许在任何时候播放一种声音:
# Get a reference to a pygame channel
self.channel = pygame.mixer.Channel(0)
# Load punch sound effect
self.punch = pygame.mixer.Sound("sounds/attack.wav")
# ...
# Play using channel
self.channel.play(self.punch)
也就是说,这实际上可能不是您想要的 - 相反,您可能应该检查“键释放”事件,而不是仅检查 E 键是否保留在您的fighter_*
函数中。 这将在呼叫attack
之间留出足够的时间,以防止您听到的失真发生。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.