예제 #1
0
    def __init__(self):

        self.setting = Settings()

        pygame.init()
        #initializes background setting of pygame
        self.screen = pygame.display.set_mode(
            (self.setting.width, self.setting.height),
            pygame.RESIZABLE)  #creates the game window
        pygame.display.set_caption('Space Invader')

        self.game_stats = Game_Stats(self)

        self.ship = Ship(self)

        #container class to manage multiple object (bullet) of pygame.Sprite type
        self.bullets = pygame.sprite.Group()

        #container class instance to manage multiple object (bullet) of pygame.Sprite type
        self.aliens = pygame.sprite.Group()
        self._create_alien_fleet()

        #create a button instance
        self.button = Button(self, 'Play')

        #instance of Score_Board() class
        self.scoreboard = Score_Board(self)
예제 #2
0
    def __init__(self):
        # super().__init__()
        # Initialize game and create a screen object
        pygame.init()
        self.settings = Settings()

        # Check current working dir
        print(os.getcwd())

        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
        # 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("Alien Invasion")

        # Create an instance to store game statistics.
        # and create a score board
        self.stats = Game_Stats(self)
        self.score_board = Score_Board(self)

        self.ship = Ship(self)

        self.bullets = pygame.sprite.Group()

        self.aliens = pygame.sprite.Group()

        self._create_fleet()

        # Make the Play button.
        self.play_button = Button(self, "Don Sam, let's play!")
예제 #3
0
def run_game():
    ai_settings = Settings()
    pygame.init()
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))
    ship = Ship(screen, ai_settings)
    """groups of aliens"""
    aliens = Group()
    """creating fleet of aliens"""
    gf.create_fleet(ai_settings, screen, ship, aliens)
    """groups of bullets"""
    bullets = Group()

    pygame.display.set_caption("GAMES OF ALIEN")
    # Create an instance to store game statistics.
    stats = Game_Stats(ai_settings)

    play_button = Button(ai_settings, screen, stats, ship, bullets, gf)

    sb = Score_Board(ai_settings, screen, stats)

    # RUNNING MAIN LOOP
    while True:
        # RUNNING EVENT LOOP FOR CONTROL GAME USING KEYBOARD
        gf.check_event(ai_settings, screen, ship, sb, bullets, stats,
                       play_button, aliens)
        if stats.game_active:
            ship.update()
            gf.update_bullets(aliens, bullets, ai_settings, screen, ship,
                              stats, sb)
            gf.update_aliens(ai_settings, stats, screen, ship, sb, aliens,
                             bullets)
        gf.update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets,
                         play_button)
예제 #4
0
def run_game():

    pygame.init()
    game_settings = Settings()
    screen = pygame.display.set_mode(
        (game_settings.screen_width, game_settings.screen_height))
    pygame.display.set_caption("Alien Invasion")
    ship = Ship(screen, game_settings)

    bullets = Group()

    aliens = Group()
    gf.create_fleet(aliens, screen, game_settings, ship)

    stats = Game_Stats(game_settings)

    play_button = Button(screen, "PLAY")
    sb = Scoreboard(game_settings, screen, stats)

    while True:

        gf.check_events(ship, bullets, screen, game_settings, stats,
                        play_button, aliens, sb)
        if stats.game_active:
            ship.update()
            bullets.update()
            gf.update_bullets(bullets, aliens, screen, game_settings, ship,
                              stats, sb)
            gf.update_alien(aliens, ship, bullets, game_settings, stats,
                            screen, sb)
            gf.check_fleet_edges(game_settings, aliens)

        gf.update_screen(game_settings, ship, screen, bullets, aliens, stats,
                         play_button, sb)
def run_game():
    """the game main function
    """

    pygame.init()
    pygame.display.set_caption("ALIEN INVASION")

    # > vars declaration goes here

    ai_settings = Settings()
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))

    bullets = Group()
    aliens = Group()

    ship = Ship(screen, ai_settings)
    stats = Game_Stats(ai_settings)
    play_button = Button(screen, "PLAY")
    sb = Scoreboard(screen, ai_settings, stats)

    while True:

        check_events(ship, ai_settings, bullets, screen, stats, play_button,
                     aliens, sb)

        if stats.game_active:

            create_fleet(screen, ai_settings, aliens, ship)
            update_bullets(bullets, aliens, screen, ai_settings, ship, stats,
                           sb)
            update_aliens(aliens, ai_settings, ship, stats, bullets, sb)

        update_screen(screen, ai_settings, ship, bullets, aliens, stats,
                      play_button, sb)
def run_game():
    #Initializes game, creates screen obj, bullet group, aliens
    pygame.init()
    settings = Settings()
    screen = pygame.display.set_mode((settings.screen_l, settings.screen_w))
    pygame.display.set_caption('Trump Invasion')
    bullets = Group()
    aliens = Group()

    #Makes a ship
    ship = Ship(settings, screen)

    #Create game stats instance
    stats = Game_Stats(settings)

    #Creates fleet
    gfnc.create_fleet(settings, screen, aliens, ship)

    #Play button
    button = Button(settings, screen, "Play")

    #Scoreboard
    score = Scoreboard(screen, settings, stats)

    #Starts main loops
    while True:

        #Keyboard and mouse events
        gfnc.check_events(settings, screen, ship, bullets, stats, button,
                          aliens, score)

        if stats.game_status:
            ship.update()

            #Removes bullets off screen
            gfnc.update_bullets(bullets, aliens, settings, screen, ship, stats,
                                score)

            #Moves aliens
            gfnc.update_aliens(settings, aliens, ship, stats, screen, bullets)

        #Updates the screen
        gfnc.update_screen(settings, screen, ship, bullets, aliens, button,
                           stats, score)
def run_game():

	#Initialize PyGame ,Settings and screen Object
	pygame.init()
	ai_settings = Settings()
	screen = pygame.display.set_mode(
	(ai_settings.screen_width
	,ai_settings.screen_height))
	pygame.display.set_caption("Alien Invasion")
	
	#make the ship , group of bullets and a group of aliens
	ship = Ship(ai_settings,screen)
	bullets = Group()
	aliens = Group()

	#make instance of Game_Stats class
	stats = Game_Stats(ai_settings)
						
	
	#make instance of scoreboard
	sb = Scoreboard(ai_settings,screen,stats)
		
	#make the play button
	play_button = Button(ai_settings,screen,"Play")
	
	#create the fleet of aliens
	gf.create_fleet(ai_settings,screen,ship,aliens)
	
	music_theme = pygame.mixer.music.load('Sounds/ambience.wav')
	pygame.mixer.music.play(-1)
	
	#Start The Main loop for the game
	while True:	
		gf.check_events(ai_settings,screen,sb,aliens,stats,play_button,ship,bullets)
		if stats.game_active:
			ship.update_ship()
			gf.update_bullet(ai_settings,screen,stats,sb,ship,bullets,aliens)
			gf.update_aliens(ai_settings,stats,sb,screen,ship,aliens,bullets)
		gf.update_screen(ai_settings,screen,stats,ship,aliens,bullets,play_button,sb)
예제 #8
0
def run_game():
    #
    pygame.init()
    ai_settings = Settings()

    #screen = pygame.display.set_mode((1200, 800))
    screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
    pygame.display.set_caption("Alien Invasion")

    #
    play_button = Button(ai_settings, screen, "Play")

    #
    stats = Game_Stats(ai_settings)
    sb = Scoreboard(ai_settings, screen, stats)

    #
    ship = Ship(ai_settings, screen)
    bullets = Group()
    #alien = Alien(ai_settings, screen)
    aliens = Group()

    #
    gf.creat_fleet(ai_settings, screen, ship, aliens)

    while True:
        gf.check_events(ai_settings, screen, stats, sb, play_button, ship, 
            aliens, bullets)
        if stats.game_active:
            ship.update()
            gf.update_bullets(ai_settings, screen, stats, sb, ship, 
                aliens, bullets)
            gf.update_aliens(ai_settings, screen, stats, sb, ship, 
                aliens, bullets)
        
        gf.update_screen(ai_settings, screen, stats, sb, ship, aliens, 
            bullets, play_button)
예제 #9
0
def run_game():
    #初始化游戏并创建一个屏幕对象
    pygame.init()
    ai_settings = Settings()
    screen = pygame.display.set_mode(
        (ai_settings.screen_width, ai_settings.screen_height))
    pygame.display.set_caption('Alien Invasion')

    #创建一个飞船
    ship = Ship(screen, ai_settings)
    #创建一个游戏统计信息的实例
    stats = Game_Stats(ai_settings)

    #外星人编组
    aliens = Group()
    #子弹编组
    bullets = Group()
    #创建外星人群
    gf.create_fleet(ai_settings, screen, ship, aliens)
    #创建Play按钮
    play_button = Button(screen, "play")
    #开始游戏的主循环
    while True:

        #监听键盘和鼠标事件
        gf.check_event(ship, ai_settings, screen, bullets, stats, play_button,
                       aliens, ai_settings)
        if stats.game_active:
            #更新飞船位置
            ship.update()
            #更新子弹位置并删除消失的子弹
            gf.update_bullets(bullets, aliens)
            #移动外星人
            gf.update_aliens(stats, ai_settings, bullets, aliens, ship, screen)
        #更新屏幕上的图像,并切换到新屏幕
        gf.update_screen(ai_settings, screen, ship, bullets, aliens, stats,
                         play_button)
def run():
    # Initialization
    pygame.init()
    settings = Settings()
    state = Game_State()
    screen = pygame.display.set_mode(
        (settings.screen_width, settings.screen_height))
    pygame.display.set_caption("Super Mario Bros")
    bg_color = settings.bg_color
    stats = Game_Stats(screen, settings)

    clock = pygame.time.Clock()

    mario = Mario(screen, settings, stats)

    pygame.mixer.music.load("Sounds/overworld.mp3")
    pygame.mixer.music.play(-1)

    # Groups
    map_group = Group()
    block_group = Group()
    floor_group = Group()
    pipe_group = Group()
    enemy_group = Group()
    powerup_group = Group()
    fireball_group = Group()
    dead_group = Group()

    map.generate_map(screen, settings, map_group, floor_group, pipe_group,
                     block_group, enemy_group)
    f = Flag(screen, settings, 198 * settings.block_width,
             13 * settings.block_height)
    f.add(map_group)

    pipesprites = pipe_group.sprites()

    timer = 0
    death_counter = 0

    # Game Loop
    while state.running:
        settings.reset_holders()
        clock.tick(settings.fps)

        # handle mario death
        if mario.is_dead and death_counter <= 240:
            # draw black screen
            if death_counter == 60:
                screen.fill(settings.bg_color)
                stats.lives -= 1
                if stats.lives < 0:
                    stats.init_base_values()
                    #display game over
                    game_over_label = Text(None, settings.TEXT_SIZE,
                                           "Game Over", settings.WHITE, 0, 0)
                    game_over_label.rect.center = (settings.screen_width / 2,
                                                   settings.screen_height / 2)
                    game_over_label.draw(screen)
                else:
                    # display level
                    lvl_str = "World " + str(stats.world) + "-" + str(
                        stats.level_num)
                    level_label = Text(None, settings.TEXT_SIZE, lvl_str,
                                       settings.WHITE, 0, 0)
                    level_label.rect.center = (settings.screen_width / 2,
                                               settings.screen_height / 2)
                    level_label.draw(screen)
                pygame.display.flip()
            death_counter += 1
            print(death_counter)
        elif mario.is_dead and death_counter > 240:
            # reset
            death_counter = 0
            mario.kill()
            mario = Mario(screen, settings, stats)
            map_group = Group()
            block_group = Group()
            floor_group = Group()
            pipe_group = Group()
            enemy_group = Group()
            powerup_group = Group()
            fireball_group = Group()
            dead_group = Group()
            pygame.mixer.music.play(-1)
            map.generate_map(screen, settings, map_group, floor_group,
                             pipe_group, block_group, enemy_group)
            f = Flag(screen, settings, 198 * settings.block_width,
                     13 * settings.block_height)
            f.add(map_group)
            stats.new_level()

        # victory -> change level -> use death_counter to reset
        if mario.has_won and death_counter <= 300:
            # draw black screen
            if death_counter == 100:
                stats.level_num += 1
                screen.fill(settings.bg_color)
                # display level
                lvl_str = "World " + str(stats.world) + "-" + str(
                    stats.level_num)
                level_label = Text(None, settings.TEXT_SIZE, lvl_str,
                                   settings.WHITE, 0, 0)
                level_label.rect.center = (settings.screen_width / 2,
                                           settings.screen_height / 2)
                level_label.draw(screen)
                coming_soon = Text(None, settings.TEXT_SIZE, "Coming Soon",
                                   settings.WHITE, 0, 0)
                coming_soon.rect.center = (settings.screen_width / 2,
                                           (settings.screen_height / 2) +
                                           settings.SPACER)
                coming_soon.draw(screen)
                pygame.display.flip()
            death_counter += 1
            print(death_counter)
        elif mario.has_won and death_counter > 300:
            # reset game
            death_counter = 0
            mario.kill()
            mario = Mario(screen, settings, stats)
            map_group = Group()
            block_group = Group()
            floor_group = Group()
            pipe_group = Group()
            enemy_group = Group()
            powerup_group = Group()
            fireball_group = Group()
            dead_group = Group()
            pygame.mixer.music.load("Sounds/overworld.mp3")
            pygame.mixer.music.play(-1)
            map.generate_map(screen, settings, map_group, floor_group,
                             pipe_group, block_group, enemy_group)
            f = Flag(screen, settings, 198 * settings.block_width,
                     13 * settings.block_height)
            f.add(map_group)
            stats.new_level()

        # Game Play
        gf.check_events(state, mario, screen, settings, fireball_group,
                        map_group)
        # Update here
        if not mario.is_dead and not mario.has_won:
            if timer < settings.fps:
                timer += 1
            else:
                timer = 0
                stats.decrement_time()

            gf.update(screen, settings, mario, map_group, floor_group,
                      pipe_group, block_group, enemy_group, powerup_group,
                      fireball_group, dead_group, f)

            if stats.did_time_runout():
                mario.dead()
            if stats.time == 100:
                pygame.mixer.Sound('Sounds/time_warning.wav').play()

            # update game values
            stats.add_score(settings.score_holder)
            stats.add_coin(settings.coin_holder)
            if settings.one_up:
                stats.lives += 1
                settings.one_up = False
            # Display here
            stats.update()
            gf.update_screen(screen, settings, stats, mario, map_group,
                             floor_group, pipe_group, block_group, enemy_group,
                             powerup_group, fireball_group, dead_group, f)
        # stats.draw()

    pygame.quit()
    sys.exit()
예제 #11
0
    os.path.join(ui_settings.images_path, 'explosion.png')).convert_alpha()

# Spawn new mob.


def newMob():
    m = Mob(ui_settings)
    all_sprites.add(m)
    mobs.add(m)


# play background music.
ui_settings.play_music()

# Create instance of the game and statistics.
stats = Game_Stats(ui_settings, screen)
debris = Debris(ui_settings, screen)

# Game loop
game_over = True
running = True
while running:
    if game_over:
        screen.blit(background, background_rect)
        stats.welcome_screen()
        stats.reset_stats()
        game_over = False
        all_sprites = Group()
        player = Player(ui_settings)
        mobs = Group()
        bullets = Group()
예제 #12
0
class Space_Invader:
    '''class to manage game resources and assets'''
    def __init__(self):

        self.setting = Settings()

        pygame.init()
        #initializes background setting of pygame
        self.screen = pygame.display.set_mode(
            (self.setting.width, self.setting.height),
            pygame.RESIZABLE)  #creates the game window
        pygame.display.set_caption('Space Invader')

        self.game_stats = Game_Stats(self)

        self.ship = Ship(self)

        #container class to manage multiple object (bullet) of pygame.Sprite type
        self.bullets = pygame.sprite.Group()

        #container class instance to manage multiple object (bullet) of pygame.Sprite type
        self.aliens = pygame.sprite.Group()
        self._create_alien_fleet()

        #create a button instance
        self.button = Button(self, 'Play')

        #instance of Score_Board() class
        self.scoreboard = Score_Board(self)

    def run_game(self):

        while True:
            self._check_event()

            if self.game_stats.game_active:

                for alien in self.aliens.sprites():
                    alien.move_alien()

                self.ship.move_ship()
                #calls move_bullet method for each sprite object
                for bullet in self.bullets.sprites():
                    bullet.move_bullet()

                #remove bullets that went beyond the game window
                self._remove_bullets()

                #when all of the fleet is destroyed we redraw the fleet
                if not self.aliens:  #empty group evaluates False
                    self.setting.level_up()
                    self._create_alien_fleet()
            # else:
            # 	print("GAME OVER!!!")

            self._update_screen()
            #debug statement
            #print(f'width :{self.setting.width}  , height :{self.setting.height}')

    def _create_alien_fleet(self):
        #create a dummy alien ship to manage spacing on screen
        alien = Alien(self)

        alien_width = alien.alien_rect.width
        alien_height = alien.alien_rect.height

        #calculate no. of aliens that can be drawn in a row on game window
        available_space = self.setting.width - 2 * alien_width
        no_of_alien = available_space // (2 * alien_width)

        #calculate no. of rows of aliens that can be drawn
        available_space = self.setting.height - 3 * alien_height - self.ship.image_rect.height
        no_of_row = available_space // (2 * alien_height)
        #print("no. of rows "+str(no_of_row)) #debug statement

        #creating Alien object and adding them to pygame.sprite.Group()
        for row_no in range(no_of_row):
            for alien_number in range(no_of_alien):
                self._create_alien(row_no, alien_number)

    def _create_alien(self, row_no, alien_number):
        alien = Alien(self)
        alien_width = alien.alien_rect.width
        alien_height = alien.alien_rect.height
        alien.y = alien_height + 2 * alien_height * row_no
        alien.x = alien_width + 2 * alien_number * alien_width
        alien.alien_rect.y = alien.y
        alien.alien_rect.x = alien.x
        self.aliens.add(alien)

    def _check_event(self):

        #an event loop to recognise user action
        for event in pygame.event.get():
            #print(f'event : {event}')     #just a debug statement
            # identifying the event if game's close window button is pressed
            if (event.type == pygame.QUIT):
                sys.exit()

            elif (event.type == pygame.KEYDOWN):
                self._keydown_event_check(
                    event)  #identify if some key is pressed

            elif (event.type == pygame.KEYUP):
                self._keyup_event_check(
                    event)  #identify if some key is released

            elif (event.type == pygame.VIDEORESIZE):
                self.setting.width = event.w
                self.setting.height = event.h
                self.screen = pygame.display.set_mode(
                    (self.setting.width, self.setting.height),
                    pygame.RESIZABLE)

            elif (event.type == pygame.MOUSEBUTTONDOWN):
                mouse_pos = pygame.mouse.get_pos(
                )  # returns tuple with mouse x,y coordinate
                self._check_play_button(
                    mouse_pos)  #checks if play button is pressed

    def _update_screen(self):

        #gives background color to game window by redrawing screen on every loop
        self.screen.fill(self.setting.bg_color)

        #draws ship on screen
        self.ship.draw_ship()

        #draw alien ships
        for alien in self.aliens.sprites():
            alien.draw_alien()

        #detecting collision between ship and alien
        if pygame.sprite.spritecollideany(
                self.ship,
                self.aliens):  #returns alien that collided else None
            self._ship_hit()

        #draws bullet on screen
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()

        #removing bullet and aliens that had collided
        '''any bullet that collides with an alien becomes 
		a key in the collisions dictionary. The value associated 
		with each bullet is a list of aliens it has collided with'''
        collision = pygame.sprite.groupcollide(self.bullets, self.aliens, True,
                                               True)

        if collision:
            for alien in collision.values():
                self.game_stats.current_score += (
                    self.setting.alien_hit_point * len(alien))

        #updating high score
        if self.game_stats.current_score > self.scoreboard.high_score:
            Score_Board.update_high_score(
                self.game_stats.current_score
            )  #update_high_score() is defined in game_stats.py

        #number lifes user have indicated by ship image on top right corner
        self.life_indicator()

        #prints score
        self.scoreboard.draw_score(self.game_stats.current_score)

        #display button initially or when self.game_stats.game_active = False
        if self.game_stats.game_active == False:
            self.button.draw_button()

        #drawing the screen with updated game element states
        pygame.display.flip()

        #detecting if any ship reached bottom
        self.alien_reaches_bottom()

    def _keydown_event_check(self, event):
        if (event.key == pygame.K_RIGHT):
            self.ship.move_right = True

        elif (event.key == pygame.K_LEFT):
            self.ship.move_left = True

        elif (event.key == pygame.K_UP):
            self.ship.move_up = True

        elif (event.key == pygame.K_DOWN):
            self.ship.move_down = True

        elif (event.key == pygame.K_q):
            sys.exit()

        elif (
            (event.key == pygame.K_SPACE) and (self.game_stats.game_active)
        ):  #rest of KEYDOWN events remain inactive because in run_game loop neither alien nor ship is repositioned until game_status_active become true
            self._fire_new_bullet()

    def _keyup_event_check(self, event):
        if (event.key == pygame.K_RIGHT):
            self.ship.move_right = False

        elif (event.key == pygame.K_LEFT):
            self.ship.move_left = False

        elif (event.key == pygame.K_UP):
            self.ship.move_up = False

        elif (event.key == pygame.K_DOWN):
            self.ship.move_down = False

    def _check_play_button(self, mouse_pos):
        button_clicked = self.button.button_rect.collidepoint(mouse_pos)
        if (button_clicked and not self.game_stats.game_active):
            self.game_stats.reset_stats()
            self.game_stats.game_active = True

    def _fire_new_bullet(self):
        if (len(self.bullets) <= self.setting.no_allowed_bullets):
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)

    def _remove_bullets(self):
        #we cannot remove element and iterate simultaneously hence we are working on copy
        for bullet in self.bullets.copy():
            if bullet.bullet_rect.top <= 0:
                #print('--removing bullet---')#debug
                self.bullets.remove(bullet)
        #debug line
        #print(f"bullet -{len(self.bullets)}")

    def alien_reaches_bottom(self):
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            alien_rect = alien.alien_rect
            if (alien_rect.bottom >= screen_rect.bottom):
                #this is same as though ship is hit by alien
                self._ship_hit()

    def _ship_hit(self):
        #pause game for 1 sec
        sleep(1)

        #decrement no. of ships left
        self.game_stats.no_of_ship_left -= 1

        #clear game window
        self.aliens.empty()
        self.bullets.empty()

        #redraw fleet and reposition ship
        self._create_alien_fleet()
        self.ship.reposition_ship(self)

        #if no. of ship left = 0 then gameover
        if self.game_stats.no_of_ship_left == 0:
            self.game_stats.game_active = False
            print("GAME OVER!!!")

    def life_indicator(self):
        '''displays no. of before game over at top right corner'''
        for count in range(self.game_stats.no_of_ship_left):
            #print('count = '+str(count))#debug line
            image = pygame.image.load('./images/ship_indicator.bmp')
            image_rect = image.get_rect()
            screen_rect = self.screen.get_rect()
            image_rect.top = screen_rect.top
            image_rect.right = screen_rect.right - count * image_rect.width
            self.screen.blit(image, image_rect)
예제 #13
0
class Alien_Invasion:
    """Overall class to manage game assets and behavior."""
    def __init__(self):
        # super().__init__()
        # Initialize game and create a screen object
        pygame.init()
        self.settings = Settings()

        # Check current working dir
        print(os.getcwd())

        self.screen = pygame.display.set_mode(
            (self.settings.screen_width, self.settings.screen_height))
        # 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("Alien Invasion")

        # Create an instance to store game statistics.
        # and create a score board
        self.stats = Game_Stats(self)
        self.score_board = Score_Board(self)

        self.ship = Ship(self)

        self.bullets = pygame.sprite.Group()

        self.aliens = pygame.sprite.Group()

        self._create_fleet()

        # Make the Play button.
        self.play_button = Button(self, "Don Sam, let's play!")

    def run_game(self):
        """Start the main loop for the game."""
        while True:
            self._check_events()
            if self.stats.game_active:
                self.ship.update()
                self._update_bullets()
                self._update_aliens()

            self._update_screen()

    # helper method, not meant to be call through class instance
    def _check_events(self):
        # Response for keyboard and mouse events
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                self._check_keydown_events(event)
            elif event.type == pygame.KEYUP:
                self._check_keyup_events(event)
            elif event.type == pygame.MOUSEBUTTONDOWN:
                mouse_pos = pygame.mouse.get_pos()
                self._check_play_button(mouse_pos)

    def _check_play_button(self, mouse_pos):
        """Start a new game when the player clicks Play."""
        button_clicked = self.play_button.rect.collidepoint(mouse_pos)
        if button_clicked and not self.stats.game_active:
            # Reset the game settings.
            self.settings.initialize_dynamic_settings()

            # Reset the game statistics.
            self.stats.reset_stats()
            self.stats.game_active = True
            self.score_board.prep_score()
            self.score_board.prep_level()
            self.score_board.prep_ships()

            # Get rid of any remaining aliens and bullets.
            self.aliens.empty()
            self.bullets.empty()

            # Create a new fleet and center the ship.
            self._create_fleet()
            self.ship.center_ship()

            # Hide the mouse cursor
            pygame.mouse.set_visible(False)

    def _check_keydown_events(self, event):
        """Respond to keypresses."""
        if event.key == pygame.K_RIGHT:
            # Move the ship to the right
            self.ship.moving_right = True
        elif event.key == pygame.K_LEFT:
            # Move the ship to the left
            self.ship.moving_left = True
        elif event.key == pygame.K_q:
            sys.exit()
        elif event.key == pygame.K_SPACE:
            self._fire_bullet()

    def _check_keyup_events(self, event):
        """Respond to key releases."""
        if event.key == pygame.K_RIGHT:
            self.ship.moving_right = False
        if event.key == pygame.K_LEFT:
            self.ship.moving_left = False

    def _fire_bullet(self):
        """Create a new bullet and add it to the bullets group."""
        if (len(self.bullets) < self.settings.bullets_allowed):
            new_bullet = Bullet(self)
            self.bullets.add(new_bullet)

    def _update_bullets(self):
        """Update position of bullets and get rid of old bullets."""
        # Update bullet position
        self.bullets.update()
        # Get rid of bullets that have disappeared.
        for bullet in self.bullets.copy():
            if (bullet.rect.bottom <= 0):
                self.bullets.remove(bullet)

        self._check_bullet_alien_collison()

    def _check_bullet_alien_collison(self):
        """Respond to bullet-alien collisions."""
        if not self.aliens:
            # Destroy existing bullets and create new fleet.
            self.bullets.empty()
            self._create_fleet()
            self.settings.increase_speed()

            # Increase level
            self.stats.level += 1
            self.score_board.prep_level()

        # Check for any bullets that have hit aliens.
        # If so, get rid of the bullet and the alien.
        collision = pygame.sprite.groupcollide(self.bullets, self.aliens,
                                               False, True)

        if collision:
            for aliens in collision.values():
                self.stats.score += self.settings.alien_points * len(aliens)

            self.score_board.prep_score()
            self.score_board.check_high_score()

    def _update_aliens(self):
        """
        Check if the fleet is at an edge,
        then update the positions of all aliens in the fleet.
        """
        self._check_fleet_edges()
        self.aliens.update()

        # Look for alien-ship collisions.
        if pygame.sprite.spritecollideany(self.ship, self.aliens):
            self._ship_hit()

        # Look for aliens hitting the bottom of the screen.
        self._check_aliens_bottom()

    def _create_alien(self, alien_number, row_number):
        # Create an alien and place it in the fleet.
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        alien.x = alien_width + 2 * alien_width * alien_number
        alien.rect.x = alien.x
        alien.rect.y = alien.rect.height + 2 * alien.rect.height * row_number
        self.aliens.add(alien)

    def _create_fleet(self):
        """Create the fleet of aliens."""
        # Make an alien
        alien = Alien(self)
        alien_width, alien_height = alien.rect.size
        available_space_x = self.settings.screen_width - (2 * alien_width)
        number_aliens_x = available_space_x // (2 * alien_width)
        # Determine the number of rows of aliens that fit on the screen.
        ship_height = self.ship.rect.height
        available_space_y = (self.settings.screen_height - (3 * alien_height) -
                             ship_height)
        number_rows = available_space_y // (2 * alien_height)

        # Create full fleet of alien
        for row_number in range(number_rows):
            for alien_number in range(number_aliens_x):
                self._create_alien(alien_number, row_number)

    def _check_fleet_edges(self):
        """Respond appropriately if any aliens have reached an edge."""
        for alien in self.aliens.sprites():
            if alien.check_edges():
                self._change_fleet_direction()
                break

    def _change_fleet_direction(self):
        """Drop the entire fleet and change the fleet's direction."""
        for alien in self.aliens.sprites():
            alien.rect.y += self.settings.fleet_drop_speed
        self.settings.fleet_direction *= -1

    def _update_screen(self):
        # Redraw the screen during each pass through the loop.
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()
        for bullet in self.bullets.sprites():
            bullet.draw_bullet()
        self.aliens.draw(self.screen)

        # Draw the score information.
        self.score_board.prep_ships()
        self.score_board.show_score()

        # Draw the play button if the game is inactive.
        if not self.stats.game_active:
            self.play_button.draw_button()

        # Make the most recently drawn screen visible
        pygame.display.flip()

    def _ship_hit(self):
        """Respond to the ship being hit by an alien."""
        if self.stats.ships_left > 0:
            # Decrement ships_left.
            self.stats.ships_left -= 1

            # Get rid of any remaining aliens and bullets.
            self.aliens.empty()
            self.bullets.empty()

            # Create a new fleet and center the ship.
            self._create_fleet()
            self.ship.center_ship()
            self.stats.reset_stats()

            # Decrement ships_left, and update scoreboard.
            # self.stats.ships_left -= 1
            self.score_board.prep_ships()
            self.score_board.prep_score()
            self.score_board.prep_level()

            # Pause
            sleep(0.5)
        else:
            self.stats.game_active = False
            pygame.mouse.set_visible(True)

    def _check_aliens_bottom(self):
        """Check if any aliens have reached the bottom of the screen."""
        screen_rect = self.screen.get_rect()
        for alien in self.aliens.sprites():
            if alien.rect.bottom >= screen_rect.bottom:
                # Treat this the same as if the ship got hit.
                self._ship_hit()
                break