Reputation: 19
I'm working on a basic shooter game in Pygame (I'm following a tutorial.) I decided to add background music to keep things nice. Code (quite long!):
import pygame
from pygame import image as sprite
pygame.init()
dow = pygame.display.set_mode((1000, 700))
pygame.display.set_caption("PY.Touhou")
clock = pygame.time.Clock()
rightSprites = [sprite.load('ness-right1.png'),
pygame.image.load('ness-right2.png'),
pygame.image.load('ness-right3.png'),
pygame.image.load('ness-right4.png'),
pygame.image.load('ness-right5.png'),
pygame.image.load('ness-right6.png'),
pygame.image.load('ness-right7.png'),
pygame.image.load('ness-right8.png')
]
leftSprites = [
sprite.load('ness-left1.png'),
sprite.load('ness-left2.png'),
sprite.load('ness-left3.png'),
sprite.load('ness-left4.png'),
sprite.load('ness-left5.png'),
sprite.load('ness-left6.png'),
sprite.load('ness-left7.png'),
sprite.load('ness-left8.png')
]
scene = pygame.image.load('bg.png')
idle = pygame.image.load('ness-idle.png')
class Player(object):
def __init__(self, x_pos, y_pos, w, h):
self.x_pos = x_pos
self.y_pos = y_pos
self.w = w
self.h = h
self.velocity = 15
self.JUMPbool = False
self.atleft = False
self.atright = False
self.steps = 0
self.jumpheight = 12
self.hitbox = (self.x_pos + 50, self.y_pos, 73, 227)
self.still = True
def move(self):
if self.steps + 1 >= 24:
self.steps = 0
if not self.still:
if self.atleft:
dow.blit(leftSprites[self.steps // 4], (self.x_pos, self.y_pos))
self.steps += 1
elif self.atright:
dow.blit(rightSprites[self.steps // 4], (self.x_pos, self.y_pos))
self.steps += 1
else:
if self.atright:
dow.blit(rightSprites[1], (self.x_pos, self.y_pos))
else:
dow.blit(leftSprites[1], (self.x_pos, self.y_pos))
self.hitbox = (self.x_pos + 50, self.y_pos, 73, 227)
# pygame.draw.rect(dow, (0, 0, 255), self.hitbox, 2)
class IceBullet(object):
def __init__(self, x_pos, y_pos, radius, color, direction):
self.x_pos = x_pos
self.y_pos = y_pos
self.radius = radius
self.color = color
self.direction = direction
self.velocity = 8 * direction
def summon(self):
pygame.draw.circle(dow, self.color, (self.x_pos, self.y_pos), self.radius)
class EnemyCirno(object):
erightSprites = [sprite.load('e-right%s.png' % pic) for pic in range(1, 9)]
eleftSprites = [sprite.load('e-left%s.png' % pic) for pic in range(1, 9)]
def __init__(self, x_pos, y_pos, w, h, ending):
self.x_pos = x_pos
self.y_pos = y_pos
self.w = w
self.h = h
self.ending = ending
self.path = [self.x_pos, self.ending]
self.hitbox = (self.x_pos + 50, self.y_pos, 73, 227)
self.steps = 0
self.health = 20
self.isAlive = True
self.velocity = 4
def summon(self):
self.move()
if self.isAlive:
if self.steps + 1 >= 24:
self.steps = 0
if self.velocity > 0:
dow.blit(self.erightSprites[self.steps // 4], (self.x_pos, self.y_pos))
self.steps += 1
else:
dow.blit(self.eleftSprites[self.steps // 4], (self.x_pos, self.y_pos))
self.steps += 1
pygame.draw.rect(dow, (255, 10, 0), (100, 110, 400, 20))
pygame.draw.rect(dow, (5, 255, 10), (100, 110, 200 - (20 * (10 - self.health)), 20))
enemy_health = italicStyle.render('Enemy Health', 1, (255, 0, 0))
dow.blit(enemy_health, (100, 150))
self.hitbox = (self.x_pos + 50, self.y_pos, 73, 227)
# pygame.draw.rect(dow, (0, 0, 0), self.hitbox, 2)
def move(self):
if self.velocity > 0:
if self.x_pos + self.velocity < self.path[1]:
self.x_pos += self.velocity
else:
self.velocity = self.velocity * -1
self.steps = 0
else:
if self.x_pos - self.velocity > self.path[0]:
self.x_pos += self.velocity
else:
self.velocity = self.velocity * -1
self.steps = 0
def hit(self):
if self.health > 1:
self.health -= 0.50
hit = pygame.mixer.Sound('hit.wav')
hit.play()
else:
self.isAlive = False
dead = pygame.mixer.Sound('death_sound.wav')
dead.play()
# Main starting loop.
letterStyle = pygame.font.SysFont('Bookman Old Style', 50)
italicStyle = pygame.font.SysFont('Bookman Old Style', 30, False, True)
cirno = Player(300, 470, 160, 233)
score = 0
evilCirno = EnemyCirno(50, 470, 160, 233, 800)
maxShots = 0
bullets = []
running = True
while running is True:
clock.tick(24)
pygame.time.delay(10)
music = pygame.mixer.music.load('main_theme.wav') # And here is where the bug begins!
pygame.mixer.music.play()
for events in pygame.event.get():
if events.type == pygame.QUIT:
running = False
key = pygame.key.get_pressed()
def update_screen():
dow.blit(scene, (0, 0))
textdisplay = letterStyle.render('Score: ' + str(score), 1, (0, 255, 255))
won = italicStyle.render("Enemy defeated!", 1, (10, 255, 19))
dow.blit(textdisplay, (50, 30))
if not evilCirno.isAlive:
dow.blit(won, (100, 150))
cirno.move()
evilCirno.summon()
for shot in bullets:
shot.summon()
pygame.display.update()
if maxShots > 0:
maxShots += 1
if maxShots > 5:
maxShots = 0
for shot in bullets:
if evilCirno.isAlive:
if shot.y_pos - shot.radius < evilCirno.hitbox[1] + evilCirno.hitbox[3] and shot.y_pos + shot.radius > \
evilCirno.hitbox[1]:
if shot.x_pos + shot.radius > evilCirno.hitbox[0] and shot.x_pos - shot.radius < evilCirno.hitbox[0] + \
evilCirno.hitbox[2]:
evilCirno.hit()
score += 50
bullets.pop(bullets.index(shot))
if 1000 > shot.x_pos > 0:
shot.x_pos += shot.velocity
else:
bullets.pop(bullets.index(shot))
if key[pygame.K_z] and maxShots == 0:
shoot = pygame.mixer.Sound('bullet.wav')
shoot.play()
if cirno.atleft:
facing = -1
else:
facing = 1
if len(bullets) < 5:
bullets.append(
IceBullet(round(cirno.x_pos + cirno.w // 2), round(cirno.y_pos + cirno.h // 1.2), 20, (0, 0, 255),
facing))
maxShots = 1
if key[pygame.K_LEFT] and cirno.x_pos > cirno.velocity: # Will stop ASAP when reached
cirno.x_pos -= cirno.velocity
cirno.atleft = True
cirno.atright = False
cirno.still = False
elif key[
pygame.K_RIGHT] and cirno.x_pos < 1000 - cirno.velocity - cirno.w: # If it goes past this, it will stop ASAP, as well
cirno.x_pos += cirno.velocity
cirno.atright = True
cirno.atleft = False
cirno.still = False
else:
cirno.steps = 0
cirno.still = True
if not cirno.JUMPbool:
if key[pygame.K_UP]:
cirno.JUMPbool = True
cirno.steps = 0
else:
if cirno.jumpheight >= -12: # What to do if pygame.K_SPACE is pressed down.
cirno.y_pos -= (cirno.jumpheight * abs(cirno.jumpheight)) * 0.5
cirno.jumpheight -= 1
else:
cirno.jumpheight = 12
cirno.JUMPbool = False
update_screen()
pygame.quit()
So far, the music actually does play, as well as the sounds. Though the problem is that it just loops the beginning part of the music over and over (which is only the first few seconds), so what you get is just something that sounds like a broken MP3 player. (for reference the music is 1:45. Even weirder is that I've seen people use it with no issues.) Is there any way to fix this bug? Thanks for your help :)
Upvotes: 1
Views: 422
Reputation: 14906
Do you see the bug here?
while running is True:
[...]
music = pygame.mixer.music.load('main_theme.wav')
pygame.mixer.music.play()
It's re-loading and re-playing replaying the music inside your code main loop. That is every single updated frame of game-play,
Load and play music outside your main loop:
music = pygame.mixer.music.load('main_theme.wav')
pygame.mixer.music.play()
while running is True:
[...]
Your code can then call the mixer.get_busy()
function too see if the music has stopped, and do something about it.
You probably also want to investigate PyGame Sound mixer channels, so your sound effects mix in with the background music properly.
Upvotes: 1