Reputation: 93
I am trying to make a streetfighter style like game with circles and rectangles(too lazy to draw the art). However, when I play try to play a punching sound, it sounds like it was distorted. Same goes for the KO sound effect I play when a player dies.
here are the sounds
https://audio.nathanli1818.repl.co/
heres the code:
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()
on python 3.8.8
Upvotes: 0
Views: 1263
Reputation: 388
Your problem is coming from the fact that the sound is being played multiple times on top of itself. This happens because every frame, you check if pygame.K_e
is held, and then play the sound if it is. However, when you press a key, it's likely that you'll be holding the key for more than a single frame, so this leads to the sound being played multiple times on top of itself in quick succession.
One way to rectify the problem would be to play the sound using a pygame.mixer.Channel
, which only allows one sound to be playing at any time:
# 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)
That said, this probably isn't actually what you want - rather, you should probably instead be checking for a 'key release' event instead of just checking whether the E key is held in your fighter_*
functions. This will put sufficient time between calls to attack
to prevent the distortion you're hearing from occurring.
Upvotes: 1