Peksio
Peksio

Reputation: 585

Python and Pygame Value is updating but update is not taken into account by code?

I wanted to ask you for your help. I am following tutorial about creating alien game but I modified it a little bit and I cannot get it to work properly. I have value for alien_speed in settings pyfile. I am modifying it in method increase_speed and I am printing it (and it is actually growing like I want it to). But aliens have still the same speed. I don't understand why it is not working. Can maybe someone point me in right direction ?

settings.py:

import pygame

resolution_width = 1280
resolution_height = 720

class Settings:
    """A class to store all settings for Space Impact."""

    def __init__(self):
        """Initialize the game's static settings."""
        # Screen settings
        # This line is needed to avoid error: No video mode has been set
        self.screen = pygame.display.set_mode((0, 0))
        self.screen_width = resolution_width
        self.screen_height = resolution_height
        self.bg_image = pygame.image.load("images/background_1.png").convert()

        # Bullet settings
        self.bullet_speed = self.screen_width*0.01
        self.bullet_width = self.screen_width*0.02
        self.bullet_height = self.screen_height*0.02
        self.bullet_color = (0, 0, 0)

        # How quickly the game speeds up
        self.speedup_scale = 999
        # Ship Settings
        self.ships_limit = 3



        self.initialize_dynamic_settings()

    def initialize_dynamic_settings(self):
        self.alien_speed = self.screen_width*0.003

    def increase_speed(self):
        """Increase speed settings."""
        self.alien_speed *= self.speedup_scale
        print(self.alien_speed)

alien.py:

import pygame
from pygame.sprite import Sprite
from settings import Settings
import random


class Alien(Sprite):
    """A class to represent a single alien."""

    def __init__(self, space_impact):
        """Initialize alien and set it's starting position."""
        super().__init__()
        self.screen = space_impact.screen
        self.settings = Settings()

        # Load the alien image and set it's rect attribute.
        self.index = 0
        self.timer = 0
        self.image = []
        self.image.append(pygame.image.load('images/alien_1.png'))
        self.image.append(pygame.image.load('images/alien_2.png'))
        self.image = self.image[self.index]
        self.image = pygame.transform.scale(self.image, (80 * int(self.settings.screen_width * 0.0019),
                                            40 * int(self.settings.screen_width*0.0019)))

        self.rect = self.image.get_rect()

        random_height = random.uniform(0.01, 0.85)
        random_width = random.uniform(1.1, 2)
        self.rect.x = int(self.settings.screen_width * random_width)
        self.rect.y = int(self.settings.screen_height * random_height)

        # Store the alien's exact horizontal position.
        self.x = float(self.rect.x)

    def update(self):
        """Move the alien to left side."""
        self.x -= self.settings.alien_speed
        self.rect.x = self.x

        if self.timer >= 0 and self.timer <= 25:
            self.timer += 1
            self.index = 0

        elif self.timer >= 26 and self.timer < 50:
            self.timer += 1
            self.index = 1
        else:
            self.timer = 0

        if self.index == 0:
            self.image = pygame.image.load("images/alien_1.png")
        if self.index == 1:
            self.image = pygame.image.load("images/alien_2.png")

        self.image = pygame.transform.scale(self.image, (80 * int(self.settings.screen_width * 0.0019),
                                            40 * int(self.settings.screen_width * 0.0019)))

Edit: Of course in my main file I am calling function self.settings.increase_speed()


Edit2:

import pygame

resolution_width = 1280
resolution_height = 720

class Settings:
    """A class to store all settings for Space Impact."""

    screen_width = resolution_width
    alien_speed = screen_width * 0.003
    speedup_scale = 3
    alien_speed *= speedup_scale

    def __init__(self):
        """Initialize the game's static settings."""
        # Screen settings
        # This line is needed to avoid error: No video mode has been set
        self.screen = pygame.display.set_mode((0, 0))
        self.screen_width = resolution_width
        self.screen_height = resolution_height
        self.bg_image = pygame.image.load("images/background_1.png").convert()

        # Bullet settings
        self.bullet_speed = self.screen_width*0.01
        self.bullet_width = self.screen_width*0.02
        self.bullet_height = self.screen_height*0.02
        self.bullet_color = (0, 0, 0)

        # How quickly the game speeds up
        self.speedup_scale = 3
        # Ship Settings
        self.ships_limit = 3




    def increase_speed(self):
        """Increase speed settings."""
        global alien_speed
        global speedup_scale
        alien_speed *= speedup_scale
        print(self.alien_speed)

Edit3:

I managed to fix it thanks to your comments. Thank you :)

Upvotes: 1

Views: 187

Answers (1)

Rabbid76
Rabbid76

Reputation: 210890

Settings seems to contain global settings, but each Alien creates its own instance of Settings:

class Alien(Sprite):
   """A class to represent a single alien."""

   def __init__(self, space_impact):
       # [...]

       self.settings = Settings()

That means that each Alien has its own Settings and thus alien_speed.

Either you've to update the settings in each instance of Alien, that means you've to call increase_speed() for each Alien separately.

Or just pass a singleton instance of Settings to Aliens. That makes it sufficient to update the singleton instance:

class Alien(Sprite):
    """A class to represent a single alien."""

    def __init__(self, space_impact, settings):
        """Initialize alien and set it's starting position."""
        super().__init__()
        self.screen = space_impact.screen
        self.settings = settings
        # [...]

In "main":

alien = Alien(space_impact, self.settings)

Another option would be to turn the attributes of the class Settings to class attributes. Instance attribute are unique to each instance, but class attributes are shared by all instances.

Upvotes: 3

Related Questions