AttributeError: не видит существующий атрибут
Пишу учебный проект на pygame. По кнгие Э.Метиз "Изучаем Python".
Столкнулся с такой ошибкой: AttributeError: 'pygame.Surface' object has no attribute 'ship_speed'
Хотя атрибут определён в файле с настройками, не могу понять в чём проблема.
game.py
import pygame
from settings import Settings
from ship import Ship
from bullet import Bullet
class AlienInvasion():
"""A class for managing resources and game behavior"""
def __init__(self):
"""Inizialization game and create games resources"""
pygame.init()
self.settings = Settings()
self.screen = pygame.display.set_mode(
(self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("Alien Invasion")
self.ship = Ship(self.screen)
self.bullets = pygame.sprite.Group()
def run_game(self):
"""Launch main cycle game"""
while True:
self._check_events()
self.ship.update()
self.bullets.update()
self._update_screen()
def _check_events(self):
"""keyboard and mouse"""
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)
def _check_keydown_events(self, event):
"""reacts to keydown"""
if event.key == pygame.K_RIGHT:
self.ship.moving_right = True
elif event.key == pygame.K_LEFT:
self.ship.moving_left = True
elif event.key == pygame.K_F10:
sys.exit()
elif event.key == pygame.K_SPACE:
self._fire_bullet()
def _check_keyup_events(self, event):
"""reacts to keyup."""
if event.key == pygame.K_RIGHT:
self.ship.moving_right = False
elif event.key == pygame.K_LEFT:
self.ship.moving_left = False
def _fire_bullet(self):
"""Create new bullet and including it in the bullets group."""
new_bullet = Bullet(self)
self.bullets.add(new_bullet)
def _update_screen(self):
"""Refresh the screen and display a new screen."""
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
pygame.display.flip()
if __name__ == '__main__':
# Create exemple and launch game.
ai = AlienInvasion()
ai.run_game()
ship.py
import pygame
class Ship():
"""Class for control ship"""
def __init__(self, ai_game):
"""initialization ship and sets its initial position."""
self.screen = ai_game
self.settings = ai_game
self.screen_rect = ai_game.get_rect()
# Load image ship.
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
# Each new ship appears at the bottom of the screen.
self.rect.midbottom = self.screen_rect.midbottom
# Saving the real coordinate of the center of the ship.
self.x = float(self.rect.x)
# Move flag
self.moving_right = False
self.moving_left = False
def update(self):
"""Updates the ship's position with the flag."""
# Updatees atribut x, not rect.
if self.moving_right and self.rect.right < self.screen_rect.right:
self.x += self.settings.ship_speed
if self.moving_left and self.rect.left > 0:
self.x -= self.settings.ship_speed
# Update atribut rect based on self.x.
self.rect.x = self.x
def blitme(self):
"""Draw ship in current position."""
self.screen.blit(self.image, self.rect)
settings.py
class Settings():
"""A class for save all settings game Alien Invasion"""
def __init__(self):
"""Inicialization settings game"""
# Display settings
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)
# Ship settings
self.ship_speed = 1.5
# Bullet settings
self.bullet_speed = 1
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = (60, 60, 60)
Полный текст отчёта об ошибке:
pygame 1.9.6
Hello from the pygame community. https://www.pygame.org/contribute.html
Traceback (most recent call last):
File "C:\Users\Gradysnik\Desktop\python_work\alien_invasion\game.py", line 79, in <module>
ai.run_game()
File "C:\Users\Gradysnik\Desktop\python_work\alien_invasion\game.py", line 27, in run_game
self.ship.update()
File "C:\Users\Gradysnik\Desktop\python_work\alien_invasion\ship.py", line 29, in update
self.x += self.settings.ship_speed
AttributeError: 'pygame.Surface' object has no attribute 'ship_speed'
[Finished in 2.2s with exit code 1]
Ответы (1 шт):
В классе Ship я вижу такую строчку:
self.settings = ai_game
Смотрим, что такое ai_game, оно приходит отсюда:
def __init__(self, ai_game):
Смотрим создание экземпляра класса Ship в классе AlienInvasion:
self.screen = pygame.display.set_mode(
(self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("Alien Invasion")
self.ship = Ship(self.screen)
Ну то есть в settings у вас вовсе не Settings, а то, на что ошибка ругается - pygame.Surface и там нет поля ship_speed.
Видимо, класс Ship всё же должен начинаться так:
import pygame
from settings import Settings # <- добавить import
class Ship():
"""Class for control ship"""
def __init__(self, ai_game):
"""initialization ship and sets its initial position."""
self.screen = ai_game
self.settings = Settings() # <- тут была ошибка
Зачем вы собственно назвали эту переменную ai_game, а не screen - это тоже вопрос.