Bob Tan
Bob Tan

Reputation: 103

python crash course 13-1 only one row of sprites appear

I am currently doing an exercise in python crash course where I have multiple rows of stars and I am making all of them move downwards towards the bottom of the screen. When I change the settings to make the stars move to the side instead, everything works. However, when I try to make them move downwards, only one row of stars appear at the very top of the screen and then they move down(as opposed to the whole screen being populated with aliens that move down). Not sure what is causing the issue, and would greatly appreciate any help and assistance. Thank you all!

stars_game.py

from star import Star
from random import randint

class StarGame:

    def __init__(self):
        pygame.init()
        self.settings = Settings()
        self.screen = pygame.display.set_mode(
            (0,0), pygame.FULLSCREEN)
        self.settings.screen_width = self.screen.get_rect().width 
        self.settings.screen_height = self.screen.get_rect().height
        pygame.display.set_caption("Star Game")

        self.stars = pygame.sprite.Group()

        self._create_fleet()



    def run_game(self):
        while True:
            self._check_events()
            self._update_stars()
            self._update_screen()

            
    def _create_fleet(self):
        star = Star(self)
        star_width, star_height = star.rect.size
        #star_width += 20
        #star_height += 20
        available_space_x = self.settings.screen_width - (2 * star_width) 
        number_stars_x = available_space_x // (2 * star_width)

        available_space_y = (self.settings.screen_height - 2 * star_height)
        number_rows = available_space_y // (2 * star_height)
        for row_number in range(number_rows):
            for star_number in range(number_stars_x):
                    self._create_star(star_number, row_number)
            
    def _create_star(self, star_number, row_number):
        star = Star(self)
        star_width, star_height = star.rect.size
        star.x = star_width + 2 * star_width * star_number
        star.rect.x = star.x
        star.rect.y = star.rect.height + 2 * star.rect.height * row_number
        self.stars.add(star)

    def _update_stars(self):
        """Update the positions of all stars in the fleet."""
        self.stars.update()

    def _check_events(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_q:
                    sys.exit()

    def _update_screen(self):
        self.screen.fill(self.settings.bg_color)
        self.stars.draw(self.screen)
        pygame.display.flip()

if __name__ == '__main__':
    sg = StarGame()
    sg.run_game()

settings.py

class Settings:
    """A class to store all settings for Alien Invasion."""

    def __init__(self):
        """Initialise the game's settings."""
        #Screen settings
        self.screen_width = 1200
        self.screen_height = 800
        self.bg_color = (230, 230, 230)

        self.star_speed = 1.0

star.py

import pygame
from pygame.sprite import Sprite 

class Star(Sprite):

    def __init__(self, sg_game):
        super().__init__()
        self.screen = sg_game.screen
        self.settings = sg_game.settings

        self.image = pygame.image.load('images/alien.bmp')
        self.rect = self.image.get_rect()
        self.rect.x = self.rect.width
        self.rect.y = self.rect.height
        self.x = float(self.rect.x)
        self.y = float(self.rect.y)

    def update(self):
        self.y += self.settings.star_speed
        self.rect.y = self.y

Upvotes: 1

Views: 158

Answers (1)

Rabbid76
Rabbid76

Reputation: 210880

You have to initialize star.y attribute instead of star.rect.y in the _create_star method:

class StarGame:
    # [...]

    def _create_star(self, star_number, row_number):
        star = Star(self)
        star_width, star_height = star.rect.size
        star.x = star_width + 2 * star_width * star_number
        star.y = star.rect.height + 2 * star.rect.height * row_number
        self.stars.add(star)

However, synchronize the position stored in the rect attribute in update, via the x and y attribute:

class Star(Sprite):
    # [...]

    def update(self):
        self.y += self.settings.star_speed
        self.rect.topleft = round(self.x), round(self.y)

Upvotes: 2

Related Questions