Занимаюсь по учебнику Эрик Матиз. Изучаем Python упражнение 14-2. Не могу найти ошибку почему игра запускается в активном состоянии
Интересует как запустить игру в не активном состоянии. Уже сто раз код пересмотрел и не смог найти ошибку, пожалуйста помогите!!!
alien_invasion.py
import pygame
from pygame.sprite import Group
from settings import Settings
from game_stats import GameStats
from button import Button
from ship import Ship
import game_functions as gf
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")
# Создание кнопки Play.
play_button = Button(ai_settings, screen, "Play")
# Создание экземпляра GameStats
stats = GameStats(ai_settings)
# Создание корабля, группы пуль и группы пришельцев.
ship = Ship(ai_settings, screen)
bullets = Group()
aliens = Group()
gf.create_alien(ai_settings, screen, aliens)
while True:
gf.check_events(ai_settings, screen, stats, play_button, ship,
aliens, bullets)
ship.update()
gf.update_bullets(ai_settings, screen, stats, aliens, bullets)
gf.update_aliens(ai_settings, aliens)
gf.update_screen(ai_settings, screen, stats, play_button, ship,
aliens, bullets)
run_game()
bullet.py
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
def __init__(self, ai_settings, screen, ship):
super(Bullet, self).__init__()
self.screen = screen
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,
ai_settings.bullet_height)
self.rect.centery = ship.rect.centery
self.rect.right = ship.rect.right
self.x = float(self.rect.x)
self.color = ai_settings.bullet_color
self.speed_factor = ai_settings.bullet_speed_factor
def update(self):
self.x += self.speed_factor
self.rect.x = self.x
def draw_bullet(self):
pygame.draw.rect(self.screen, self.color, self.rect)
game_functions.py
import sys
import pygame
from alien import Alien
from bullet import Bullet
def check_keydown_events(event, ai_settings, screen, ship, bullets):
"""Реагируйте на нажатия клавиш."""
if event.key == pygame.K_UP:
ship.moving_up = True
elif event.key == pygame.K_DOWN:
ship.moving_down = True
elif event.key == pygame.K_SPACE:
# Создание новой пули и включение ее в группу bullets.
fire_bullet(ai_settings, screen, ship, bullets)
elif event.key == pygame.K_q:
sys.exit()
def check_keyup_events(event, ship):
"""Реагирует на отпускание клавиш."""
if event.key == pygame.K_UP:
ship.moving_up = False
elif event.key == pygame.K_DOWN:
ship.moving_down = False
def check_events(ai_settings, screen, stats, play_button, ship, aliens,
bullets):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event,ai_settings, screen, ship, bullets)
elif event.type == pygame.KEYUP:
check_keyup_events(event,ship)
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
check_play_button(ai_settings, screen, stats, play_button,
ship, aliens, bullets, mouse_x, mouse_y)
def check_play_button(ai_settings, screen, stats, play_button, ship,
aliens, bullets, mouse_x, mouse_y):
"""Запускает новую игру при нажатии кнопки Play."""
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
if button_clicked and not stats.game_active:
# Сброс игровых настроек.
ai_settings.initialize_dynamic_settings()
# Указатель мыши скрывается.
pygame.mouse.set_visible(False)
# Начало игры
stats.game_active = True
# Очистка списков пришельцев и пуль.
aliens.empty()
bullets.empty()
# Создание нового флота и размещение корабля в центре.
create_alien(ai_settings, screen, aliens)
ship.center_ship()
ai_settings.bullets_allowed = 3
def fire_bullet(ai_settings, screen, ship, bullets):
"""Выпускает пулю, если максимум еще не достигнут."""
# Создание новой пули и включение ее в группу bullets.
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
def update_screen(ai_settings, screen, stats, play_button, ship, aliens,
bullets):
# При каждом проходе цикла перерисовывается экран.
screen.fill(ai_settings.bg_color)
# Все пули выводятся позади изображений корабля и пришельцев.
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
aliens.draw(screen)
# Кнопка Play отображается в том случае, если игра неактивна.
if not stats.game_active:
play_button.draw_button()
# Отображение последнего прорисованного экрана.
pygame.display.flip()
def update_bullets(ai_settings, screen, stats, aliens, bullets):
"""Обновляет позиции пуль и уничтожает старые пули."""
# Обновление позиций пуль.
bullets.update()
screen_rect = screen.get_rect()
# Уничтожение исчезнувших пуль.
for bullet in bullets.copy():
if bullet.rect.right >= screen_rect.right:
bullets.remove(bullet)
ai_settings.bullets_allowed -= 1
if ai_settings.bullets_allowed == 0:
# Если все пули заканчиваются, игра звершается.
stats.game_active = False
pygame.mouse.set_visible(True)
check_bullet_alien_collisions(ai_settings, screen, aliens, bullets)
def check_bullet_alien_collisions(ai_settings, screen, aliens, bullets):
"""Обработка коллизий пуль с пришельцами."""
# Удаление пуль и пришельцев, участвующих в коллизиях.
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
if collisions:
create_alien(ai_settings, screen, aliens)
def check_fleet_edges(ai_settings, aliens):
"""Реагирует на достижение пришельцем края экрана."""
for alien in aliens.sprites():
if alien.check_edges():
change_fleet_direction(ai_settings, aliens)
break
def change_fleet_direction(ai_settings, aliens):
"""Опускает весь флот и меняет направление флота."""
ai_settings.fleet_direction *= -1
def update_aliens(ai_settings, aliens):
"""Проверяет, достиг ли флот края экрана,
после чего обновляет позиции всех пришельцев во флоте."""
check_fleet_edges(ai_settings, aliens)
aliens.update()
def create_alien(ai_settings, screen, aliens):
"""Создает пришельца и размещает его в ряду."""
alien = Alien(ai_settings, screen)
aliens.add(alien)
ship.py
import pygame
class Ship():
def __init__(self,ai_settings, screen):
"""Инициализирует корабль и задает его начальную позицию."""
self.screen = screen
self.ai_settings = ai_settings
# Загрузка изображения корабля и получение прямоугольника.
self.image = pygame.image.load('images/maverick_ship.gif')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
# Каждый новый корабль появляется у левого края экрана.
self.rect.centery = self.screen_rect.centery
self.rect.left = self.screen_rect.left
# Сохранение вещественной координаты центра корабля.
self.center = float(self.rect.centery)
# Флаги перемещения
self.moving_up = False
self.moving_down = False
def center_ship(self):
"""Размещает корабль в центре нижней стороны."""
self.center = self.screen_rect.centery
def update(self):
"""Обновляет позицию корабля с учетом флагов."""
# Обновляется атрибут center, не rect.
if self.moving_up and self.rect.top > self.screen_rect.top:
self.center -= self.ai_settings.ship_speed_factor
if self.moving_down and self.rect.bottom < self.screen_rect.bottom:
self.center += self.ai_settings.ship_speed_factor
# Обновление атрибута rect на основании self.center.
self.rect.centery = self.center
def blitme(self):
self.screen.blit(self.image,self.rect)
alien.py
import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
"""Класс, представляющий одного пришельца."""
def __init__(self, ai_settings, screen):
"""Инициализирует пришельца и задает его начальную позицию."""
super(Alien, self).__init__()
self.screen = screen
self.ai_settings = ai_settings
# Загрузка изображения пришельца и назначение атрибута rect.
self.image = pygame.image.load('images/alien.jpg')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
self.rect.centery = self.screen_rect.centery
self.rect.right = self.screen_rect.right
self.center = float(self.rect.centery)
def check_edges(self):
"""Возвращает True, если пришелец находится у края экрана."""
screen_rect = self.screen.get_rect()
if self.rect.bottom >= screen_rect.bottom:
return True
elif self.rect.top <= 0:
return True
def update(self):
"""Перемещает пришельца вправо."""
self.center += (self.ai_settings.alien_speed_factor *
self.ai_settings.fleet_direction)
self.rect.centery = self.center
def blitme(self):
"""Выводит пришельца в текущем положении.."""
self.screen.blit(self.image, self.rect)
button.py
import pygame.font
class Button():
def __init__(self, ai_settings, screen, msg):
"""Инициализирует атрибуты кнопки."""
self.screen = screen
self.screen_rect = screen.get_rect()
# Назначение размеров и свойств кнопок.
self.width, self.height = 200, 50
self.button_color = (0, 255, 0)
self.text_color = (255, 255, 255)
self.font = pygame.font.SysFont(None, 48)
# Построение объекта rect кнопки и выравнивание по центру экрана.
self.rect = pygame.Rect(0, 0, self.width, self.height)
self.rect.center = self.screen_rect.center
# Сообщение кнопки создается только один раз.
self.prep_msg(msg)
def prep_msg(self, msg):
"""Преобразует msg в прямоугольник и выравнивает текст по центру."""
self.msg_image = self.font.render(msg, True, self.text_color,
self.button_color)
self.msg_image_rect = self.msg_image.get_rect()
self.msg_image_rect.center = self.rect.center
def draw_button(self):
# Отображение пустой кнопки и вывод сообщения.
self.screen.fill(self.button_color, self.rect)
self.screen.blit(self.msg_image, self.msg_image_rect)
game.stats.py
class GameStats():
"""Отслеживание статистики для игры Alien Invasion."""
def __init__(self, ai_settings):
"""Инициализирует статистику."""
self.ai_settings = ai_settings
# Игра запускается в неактивном состоянии.
self.game_active = False
settings.py
class Settings():
def __init__(self):
"""Инициализирует статические настройки игры."""
# Параметры экрана
self.screen_width = 800
self.screen_height = 600
self.bg_color = (0, 0, 0)
# Параметры пули
self.bullet_width = 15
self.bullet_height = 3
self.bullet_color = (60, 60, 60)
self.bullets_allowed = 3
# настройки пришельцев
self.fleet_drop_speed = 0.2
self.initialize_dynamic_settings()
def initialize_dynamic_settings(self):
"""Инициализирует настройки, изменяющиеся в ходе игры."""
self.ship_speed_factor = 1.5
self.bullet_speed_factor = 1
self.alien_speed_factor = 0.1
# fleet_direction = 1 обозначает движение вправо; а -1 - влево.
self.fleet_direction = 1