0
\$\begingroup\$

I'm making a game in Pygame running in Python 3.10 and the lastest version of pygame, and I can't get to display a volume control for the background music . The music is played correctly, but there is no volume control

import pygame
import random

# Initialize Pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Genesis Breaker: Legioss Shmup")
clock = pygame.time.Clock()

# Colors
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

# MUSICA 

pygame.mixer.init()
music_list = ["Space Life.mp3", "The Future is coming.mp3", "Danger Sector.mp3"]
current_music = random.choice(music_list)
pygame.mixer.music.load(current_music)
pygame.mixer.music.set_volume(0.5)  # 50% volume
pygame.mixer.music.play(-1)  # Loop indefinitely

music_volume = 0.5  # Initial volume (50%)
volume_display_timer = 0  # Timer for volume display

pygame.mixer.music.set_volume(music_volume)

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False

if event.type == pygame.KEYDOWN:
    if event.key == pygame.K_f:
        bullets.extend(legioss.shoot())
    elif event.key == pygame.K_PLUS or event.key == pygame.K_EQUALS:  # + or = key
        music_volume = min(music_volume + 0.1, 1.0)
        pygame.mixer.music.set_volume(music_volume)
        volume_display_timer = pygame.time.get_ticks()
    elif event.key == pygame.K_MINUS:  # - key
        music_volume = max(music_volume - 0.1, 0.0)
        pygame.mixer.music.set_volume(music_volume)
        volume_display_timer = pygame.time.get_ticks()

    elif event.key == pygame.K_PAGEUP:  # Page Up
        music_volume = min(music_volume + 0.1, 1.0)
        pygame.mixer.music.set_volume(music_volume)
        volume_display_timer = pygame.time.get_ticks()
    elif event.key == pygame.K_PAGEDOWN:  # Page Down
        music_volume = max(music_volume - 0.1, 0.0)
        pygame.mixer.music.set_volume(music_volume)
        volume_display_timer = pygame.time.get_ticks()

font = pygame.font.SysFont('arial', 24)

volume_bg = pygame.Surface((120, 60), pygame.SRCALPHA)
volume_bg.fill((0, 0, 0, 100))
screen.blit(volume_bg, (5, 165))
pygame.draw.rect(screen, (255, 0, 0), (10, 200, 100, 20), 1)
pygame.draw.rect(screen, WHITE, (10, 200, 100, 20), 2)
pygame.draw.rect(screen, (0, 255, 0), (12, 202, 96 * music_volume, 16))
volume_instruction = font.render("Usa PgUp/PgDn para ajustar volumen", True, WHITE)
screen.blit(volume_instruction, (10, 220))
if pygame.time.get_ticks() - volume_display_timer < 2000:
    volume_text = font.render(f"Volumen: {int(music_volume * 100)}%", True, WHITE)
    screen.blit(volume_text, (10, 170))

##################### FIN MUSICA ##########################################################

legioss_fighter = pygame.image.load("legioss_fighter.png")
legioss_fighter = pygame.transform.scale(legioss_fighter, (80, 100))

legioss_diver = pygame.Surface((64, 64))
legioss_diver.fill((100, 255, 100))  # Green for Diver
legioss_soldier = pygame.Surface((64, 64))
legioss_soldier.fill((255, 100, 100))  # Red for Soldier
tread_bomber = pygame.Surface((128, 64))
tread_bomber.fill((200, 200, 200))  # Gray for Bulldog

invid_frames = [
    pygame.transform.scale(pygame.image.load("invid1.png").convert_alpha(), (72, 72)),
    pygame.transform.scale(pygame.image.load("invid2.png").convert_alpha(), (72, 72)),
    pygame.transform.scale(pygame.image.load("invid3.png").convert_alpha(), (72, 72))
]

    
background_img = pygame.image.load("starfield.png")
background_img = pygame.transform.scale(background_img, (800, 1200))

napalm_img = pygame.Surface((32, 32))
napalm_img.fill((255, 150, 0))  # Orange for napalm

# Classes
class Legioss:
    def __init__(self):
        self.collision_timer = 0
        self.modes = [legioss_fighter, legioss_diver, legioss_soldier]
        self.mode = 0
        self.image = self.modes[self.mode]
        #self.rect = self.image.get_rect(topleft=(400, 500))
        self.rect = self.image.get_rect(topleft=(400, 400))
        self.speed = 6
        self.shoot_delay = 0
        self.tread_active = False
        self.tread_timer = 0
        self.energy = 100
        self.energy_timer = pygame.time.get_ticks()

    def move(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT] and self.rect.x > 0:
            self.rect.x -= self.speed
        if keys[pygame.K_RIGHT] and self.rect.x < 800 - self.rect.width:
            self.rect.x += self.speed
        if keys[pygame.K_UP] and self.rect.y > 0:  # Changed from 300 to 0
            self.rect.y -= self.speed
        if keys[pygame.K_DOWN] and self.rect.y < 600 - self.rect.height:
            self.rect.y += self.speed
        if keys[pygame.K_SPACE] and pygame.time.get_ticks() - self.shoot_delay > 500 and self.energy >= 20:
            self.mode = (self.mode + 1) % 3
            self.image = self.modes[self.mode]
            self.rect = self.image.get_rect(center=self.rect.center)
            self.shoot_delay = pygame.time.get_ticks()
            self.energy -= 20
        if keys[pygame.K_t] and not self.tread_active and pygame.time.get_ticks() - self.tread_timer > 15000 and self.energy >= 50:
            self.tread_active = True
            self.tread_timer = pygame.time.get_ticks()
            self.energy -= 50
##        if pygame.time.get_ticks() - self.energy_timer > 1000:
##            self.energy = min(self.energy + 5, 100)
##            self.energy_timer = pygame.time.get_ticks()

    def shoot(self):
        if self.mode == 2:
            return [Bullet(self.rect.centerx - 10, self.rect.top), Bullet(self.rect.centerx + 10, self.rect.top)]
        return [Bullet(self.rect.centerx, self.rect.top)]

    def draw(self, surface):
        surface.blit(self.image, self.rect)
        if self.tread_active:
            tread_rect = tread_bomber.get_rect(center=(self.rect.centerx, self.rect.centery + 30))
            surface.blit(tread_bomber, tread_rect)
            if pygame.time.get_ticks() - self.tread_timer > 5000:
                self.tread_active = False
                return Napalm(self.rect.centerx, self.rect.top)
        return None

class Enemy:
    def __init__(self):
        self.frames = invid_frames
        self.frame_index = 0
        self.image = self.frames[self.frame_index]
        self.rect = self.image.get_rect(topleft=(random.randint(0, 800 - 30), -50))
        self.speed = 3
        self.move_timer = pygame.time.get_ticks()
        self.direction = random.choice([-1, 1])
        self.frame_timer = pygame.time.get_ticks()

    def move(self):
        self.rect.y += self.speed
        if pygame.time.get_ticks() - self.move_timer > 1000:
            self.rect.x += self.direction * 2
            if self.rect.x < 0:
                self.rect.x = 0
                self.direction = 1
            elif self.rect.x > 800 - self.rect.width:
                self.rect.x = 800 - self.rect.width
                self.direction = -1
            self.move_timer = pygame.time.get_ticks()
        if pygame.time.get_ticks() - self.frame_timer > 200:
            self.frame_index = (self.frame_index + 1) % len(self.frames)
            self.image = self.frames[self.frame_index]
            self.frame_timer = pygame.time.get_ticks()
        if self.rect.y > 600:
            self.rect.y = -50
            self.rect.x = random.randint(0, 800 - 30)

    def draw(self, surface):
        surface.blit(self.image, self.rect)

class Bullet:
    def __init__(self, x, y):
        self.rect = pygame.Rect(x - 2, y, 5, 10)
        self.speed = -15

    def move(self):
        self.rect.y += self.speed
        if self.rect.y < 0:
            return False
        return True

    def draw(self, surface):
        pygame.draw.rect(surface, (255, 0, 0), self.rect)

class Napalm:
    def __init__(self, x, y):
        self.image = napalm_img
        self.rect = self.image.get_rect(center=(x, y))
        self.speed = -10
        self.damage = 5

    def move(self):
        self.rect.y += self.speed
        if self.rect.y < 0:
            return False
        return True

    def draw(self, surface):
        surface.blit(self.image, self.rect)

game_over = False

# Game setup
legioss = Legioss()
enemies = [Enemy() for _ in range(5)]
bullets = []
napalms = []
bg_y = 0
bg_speed = 3
score = 0
font = pygame.font.Font(None, 36)

# Main loop
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.KEYDOWN and event.key == pygame.K_f:
            bullets.extend(legioss.shoot())

    # Update
    if not game_over:
        bg_y = (bg_y + bg_speed) % 1200
        legioss.move()
        napalm = legioss.draw(screen)
        if napalm:
            napalms.append(napalm)
        for enemy in enemies:
            enemy.move()
        bullets = [bullet for bullet in bullets if bullet.move()]
        napalms = [napalm for napalm in napalms if napalm.move()]
        for bullet in bullets[:]:
            for enemy in enemies[:]:
                if bullet.rect.colliderect(enemy.rect):
                    bullets.remove(bullet)
                    enemies.remove(enemy)
                    enemies.append(Enemy())
                    score += 10
                    break
        for napalm in napalms[:]:
            for enemy in enemies[:]:
                if napalm.rect.colliderect(enemy.rect):
                    enemies.remove(enemy)
                    enemies.append(Enemy())
                    score += 50
                    break

        if pygame.time.get_ticks() - legioss.collision_timer > 500:
            for enemy in enemies:
                if enemy.rect.colliderect(legioss.rect):
                    legioss.energy = max(0, legioss.energy - 10)
                    legioss.collision_timer = pygame.time.get_ticks()
                break

        if legioss.energy <= 0:
            game_over = True
            pygame.mixer.music.stop()

    if game_over:

        game_over_bg = pygame.Surface((600, 200), pygame.SRCALPHA)
        game_over_bg.fill((0, 0, 0, 220))  # Más opaco y grande
        screen.blit(game_over_bg, (100, 75))  # Centrado horizontalmente
        game_over_font = pygame.font.SysFont('consolas', 64)
        game_over_text = game_over_font.render("Game Over", True, WHITE)
        screen.blit(game_over_text, (250, 125))  # Centrado en el rectángulo

        pygame.display.update()

    #bg_y = (bg_y + bg_speed) % 1200
    screen.blit(background_img, (0, bg_y - 1200))
    screen.blit(background_img, (0, bg_y))
    fade = pygame.Surface((800, 20), pygame.SRCALPHA)
    for y in range(20):
        alpha = int(50 * (y / 20))  # Max alpha 50
        pygame.draw.line(fade, (0, 0, 0, alpha), (0, y), (800, y))
    screen.blit(fade, (0, 0))
    flipped_fade = pygame.transform.flip(fade, False, True)
    screen.blit(flipped_fade, (0, 580))
    # Draw
    for enemy in enemies:
        enemy.draw(screen)
    for bullet in bullets:
        bullet.draw(screen)
    for napalm in napalms:
        napalm.draw(screen)
    legioss.draw(screen)
    score_text = font.render(f"Score: {score}", True, WHITE)
    energy_text = font.render(f"Energy: {legioss.energy}", True, WHITE)
    screen.blit(score_text, (10, 10))
    screen.blit(energy_text, (10, 50))

    pygame.display.flip()
    clock.tick(60)

pygame.quit()
\$\endgroup\$
5
  • \$\begingroup\$ By "Display volume control", are you asking it to display the volume control in the application itself, or as part of, for example, the Windows 10 Volume Mixer volume controls for all applications that output sound? \$\endgroup\$ Commented May 29 at 22:58
  • 1
    \$\begingroup\$ @AlexanderThe1st I didnt understand the second part of your question after the "or". I want a volume control in the game, so the user can turn down the volumen of the game \$\endgroup\$ Commented May 29 at 23:43
  • \$\begingroup\$ That clears things up - I was hoping to clarify if the issue was the volume control not appearing the game like a sound setting in the game itself, or if it was a matter of it not being able to be controlled at the application level like the Volume Mixer allows in Windows (i.e. the OS-level sound control system, but not just for the whole OS, but for individual applications as well.). \$\endgroup\$ Commented May 29 at 23:48
  • \$\begingroup\$ Out of curiosity - have you tried moving around the #Musica after the napalm_img steps and before the #Classes definition steps? My immediate guess is that it is being drawn, but then is being drawn on top of, but unsure if that is something you have looked into earlier or not. \$\endgroup\$ Commented May 30 at 0:00
  • 1
    \$\begingroup\$ I'm voting to close because this question is cross posted here on Stack Overflow. Cross posting (posting the same question across multiple Stack Exchange sites) is not allowed. Please select the community that is best suited to your question. If you want multiple points of view from different communities, you need to edit your question in a way that reflects that. (note: previously commented, but neglected to vote to close) \$\endgroup\$ Commented Jun 1 at 22:10

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.