Python Crash Course Game showing not showing images correctly - python

I've been trying to solve this issue where all images are just completely messed up and don't show properly.
It doesn't pop up any error so it is hard to traceback the cause for this: Here is a more detailed image of the issue
The code is as follows:
main code (alien_invasion.py):
import sys
import game_functions as gf
import pygame
from settings import Settings
from ship import Ship
from pygame.sprite import Group
from alien import Alien
from game_stats import GameStats
from button import Button
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")
play_button = Button(ai_settings, screen, "Play")
stats = GameStats(ai_settings)
alien = Alien(ai_settings, screen)
screen.fill(ai_settings.bg_color)
# Make a ship.
ship = Ship(ai_settings, screen)
aliens = Group()
bullets = Group()
# Background color
bg_color = (230, 230, 230)
gf.create_fleet(ai_settings, screen, aliens, ship)
while True:
gf.check_events(ai_settings, screen, ship, bullets, stats, play_button)
if stats.game_active:
ship.update(ai_settings)
gf.update_aliens(ai_settings, aliens, ship, stats, screen, bullets)
gf.update_bullets(bullets, aliens, ai_settings, screen, ship)
gf.update_screen(ai_settings, bullets, screen, ship, aliens, stats, play_button)
if not stats.game_active:
play_button.draw_button()
screen.fill(ai_settings.bg_color)
ship.blitme(screen)
pygame.display.flip()
run_game()
Alien code (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
self.image = pygame.image.load(r'C:\Users\user\Desktop\alien invasion\alien.bmp')
#Load the alien image and set its rect attribute
self.rect = self.image.get_rect()
#Start each new alienn near the top left of the screen
self.rect.x = self.rect.width
self.rect.y = self.rect.height
#Store the alien's exact position
self.x = float(self.rect.x)
def blitme(self):
#Draw the alien at its current location
self.screen.blit(self.image, self.rect)
def update(self):
self.x += (self.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction)
self.rect.x = self.x
def check_edges(self):
screen_rect = self.screen.get_rect()
if self.rect.right >= screen_rect.right:
return True
elif self.rect.left <= 0:
return True
Bullet code (bullet.py):
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
def __init__(self, ai_settings, screen, ship):
super().__init__()
self.screen = screen
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height)
self.rect.centerx = ship.rect.centerx
self.rect.top = ship.rect.top
self.y = float(self.rect.y)
self.color = ai_settings.bullet_color
self.ship_speed_factor = ai_settings.bullet_speed_factor
def update(self):
self.y -= self.ship_speed_factor
self.rect.y = self.y
def draw_bullet(self):
pygame.draw.rect(self.screen, self.color, self.rect)
Button code (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, 250, 0)
self.text_color = (255, 255, 255)
self.font = pygame.font.SysFont(None, 48)
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):
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 function code (game_functions.py):
import sys
import pygame
from bullet import Bullet
from alien import Alien
from time import sleep
def check_events(ai_settings, screen, ship, bullets, stats, play_button):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
check_play_button(stats, play_button, mouse_x, mouse_y)
elif event.type == pygame.KEYDOWN:
check_keydown_events(event,ship, ai_settings, screen, bullets)
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship)
def update_screen(ai_settings, bullets, screen, ship, aliens, stats, play_button):
for bullet in bullets.sprites():
bullet.draw_bullet()
aliens.draw(screen)
ship.blitme(screen)
pygame.display.flip()
def check_keydown_events(event, ship, ai_settings, screen, bullets):
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings, screen, ship, bullets)
elif event.key == pygame.K_q:
sys.exit()
def fire_bullet(ai_settings, screen, ship, bullets):
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
def check_keyup_events(event, ship):
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
def update_bullets(bullets, aliens, ai_settings, screen, ship):
bullets.update()
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
if len(aliens) == 0:
bullets.empty()
create_fleet(ai_settings, screen, aliens, ship)
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
def create_fleet(ai_settings, screen, aliens, ship):
alien = Alien(ai_settings, screen)
alien_width = alien.rect.width
number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)
number_rows = get_number_rows(ai_settings, ship.rect.height, alien.rect.height)
for row_number in range(number_rows):
for alien_number in range(number_aliens_x):
create_alien(ai_settings, screen, aliens, alien_number, row_number)
def get_number_aliens_x(ai_settings, alien_width):
available_space_x = ai_settings.screen_width - 2 * alien_width
number_aliens_x = int(available_space_x / (2 * alien_width))
return number_aliens_x
def create_alien(ai_settings, screen, aliens, alien_number, row_number):
alien = Alien(ai_settings, screen)
alien_width = alien.rect.width
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
aliens.add(alien)
def get_number_rows(ai_settings, ship_height, alien_height):
available_space_y = (ai_settings.screen_height - (3 * alien_height) - (ship_height))
number_rows = int(available_space_y / (2 * alien_height))
return number_rows
def update_aliens(ai_settings, aliens, ship, stats, screen, bullets):
check_fleet_edges(ai_settings, aliens)
aliens.update()
if pygame.sprite.spritecollideany(ship, aliens):
ship_hit(ai_settings, stats, screen, ship, aliens, bullets)
check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets)
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):
for alien in aliens.sprites():
alien.rect.y += ai_settings.fleet_drop_speed
ai_settings.fleet_direction *= -1
def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):
if stats.ships_left > 0:
stats.ships_left -= 1
aliens.empty()
bullets.empty()
create_fleet(ai_settings, screen, aliens, ship)
ship.center_ship
sleep(0.5)
else:
stats.game_active = False
def check_aliens_bottom(ai_settings, stats, screen, ship, aliens, bullets):
screen_rect = screen.get_rect()
for alien in aliens.sprites():
if alien.rect.bottom >= screen_rect.bottom:
ship_hit(ai_settings, stats, screen, ship, aliens, bullets)
break
def check_play_button(stats, play_button, mouse_x, mouse_y):
if play_button.rect.collidepoint(mouse_x, mouse_y):
stats.game_active = True
Game stats (game_stats.py):
class GameStats():
def __init__(self, ai_settings):
self.ai_settings = ai_settings
self.reset_stats()
self.game_active = True
def reset_stats(self):
self.ships_left = self.ai_settings.ship_limit
Settings code (settings.py):
class Settings():
def __init__(self):
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)
self.ship_speed_factor = 10
self.ship_limit = 3
self.bullet_speed_factor = 3
self.bullet_width = 3
self.bullet_height = 12
self.bullet_color = (60, 60, 60)
self.bullets_allowed = 3
self.alien_speed_factor = 1
self.fleet_drop_speed = 10
self.fleet_x_margin = 70
self.fleet_y_margin = 70
self.fleet_direction = -1
Ship code (ship.py):
import pygame
from pygame.sprite import Sprite
class Ship(Sprite):
def __init__(self, ai_settings, screen):
super(Ship, self).__init__()
self.screen = screen
self.ai_settings = ai_settings
self.image = pygame.image.load(r'C:\Users\user\Desktop\alien invasion\ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
self.moving_right = False
self.moving_left = False
self.center = float(self.rect.centerx)
self.center += self.ai_settings.ship_speed_factor
def update(self, ai_settings):
self.ai_settings = ai_settings
if self.moving_right and self.rect.right < self.screen_rect.right:
self.rect.centerx += 1
self.center += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor
self.rect.centerx -= 1
def blitme(self, screen):
self.screen.blit(self.image, self.rect)
def center_ship(self):
self.center = self.screen_rect.centerx
Any help would really appreciate it!

Simple change needed. Clear the screen before drawing the aliens.
while True:
screen.fill(ai_settings.bg_color) # <<<<<<< clear screen first
gf.check_events(ai_settings, screen, ship, bullets, stats, play_button)
if stats.game_active:
ship.update(ai_settings)
gf.update_aliens(ai_settings, aliens, ship, stats, screen, bullets)
gf.update_bullets(bullets, aliens, ai_settings, screen, ship)
gf.update_screen(ai_settings, bullets, screen, ship, aliens, stats, play_button)
if not stats.game_active:
play_button.draw_button()

Related

AttributeError: 'pygame.Surface' object has no attribute 'bullet_width'

please help me solve the error.
I have already double-checked everything and nothing works, the same traceback
Here is the full Traceback:
File "E:\Python\Alien_Invasion\alien_invasion.py", line 29, in <module>
run_game()
File "E:\Python\Alien_Invasion\alien_invasion.py", line 23, in run_game
gf.check_events(ai_settings, ship, screen, bullets)
File "E:\Python\Alien_Invasion\game_functions.py", line 29, in check_events
check_keydown_events(event, ship, ai_settings, screen, bullets)
File "E:\Python\Alien_Invasion\game_functions.py", line 13, in check_keydown_events
new_bullet = Bullet(ai_settings, screen, ship)
File "E:\Python\Alien_Invasion\bullet.py", line 12, in __init__
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height)
AttributeError: 'pygame.Surface' object has no attribute 'bullet_width'
Here is the code for the "bullet.py" file that has the problem:
class Bullet(Sprite):
def __init__(self, ai_settings, ship, screen):
#Создаєм обєкт пулі
super(Bullet, self).__init__()
self.screen = screen
#Создаем пулю в позиции (0,0)
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height)
self.rect.centerx = ship.rect.centerx
self.rect.top = ship.rect.top
#Позиция пуле задана дробным числом
self.y = float(self.rect.y)
self.color = ai_settings.bullet_color
self.speed_factor = ai_settings.bullet_speed_factor
def update(self):
#Перемещает пулю по y
self.y -= self.speed_factor
#Обновлює позицію пулі в float
self.rect.y = self.y
def draw_bullet(self):
#Выводит пули на экран
pygame.draw.rect(self.screen, self.color, self.rect)
This is a class setting with instantiate Bullet object
class Settings():
def __init__(self):
self.screen_width = 1200
self.screen_hight = 800
self.bg_color = (20,228,255)
self.ship_speed_factor = 1
#Параметры пуль
self.bullet_speed_factor = 1
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = 253,251,255
This is the main module in which the while loop happens.
import sys
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
from pygame.sprite import Group
def run_game():
#Ініціалізує pygame, setting і створює екран
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width,
ai_settings.screen_hight))
pygame.display.set_caption("Alien Invasion")
#Создаєм корабль
ship = Ship(screen, ai_settings)
#Створюєм группу для хранения пуль
bullets = Group()
#Запуск основного циклу гри
while True:
gf.check_events(ai_settings, ship, screen, bullets)
ship.update()
ship.blitme()
bullets.update()
gf.update_screen(ai_settings, screen, ship, bullets)
run_game()
This is a module with a functional game program
import sys
import pygame
from bullet import Bullet
def check_keydown_events(event, ship, screen, ai_settings, bullets):
#Нажатие клавиш
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
#Создание новой пули и занесение её в группу bullets
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
def check_keyup_events(event, ship):
#Отпуск клавиш
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
def check_events(ship, ai_settings, screen, bullets):
#Обработка нажатия клавиш и мышки
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event, ship, ai_settings, screen, bullets)
def update_screen(ai_settings, screen, ship, bullets):
#Обновляет экран, и последнюю картинку
for bullet in bullets.sprites():
bullet.draw_bullet()
screen.fill(ai_settings.bg_color)
ship.blitme()
#Отображает последний экран
pygame.display.flip()
The signature of is check_keydown_events
def check_keydown_events(event, ship, screen, ai_settings, bullets):
When calling the function in check_events you accidentally swapped the ship and ai_settings arguments
check_keydown_events(event, ship, ai_settings, screen, bullets)
The correct call is:
check_keydown_events(event, screen, ship, ai_settings, bullets)

AttributeError: 'Ship' object has no attribute 'bullet_width'

I am a learner of the Python Crash Course and now I am working on the alien invasion program. I just finished the chapter about adding bullets to my spaceship and when I press the space button, python threw "AttributeError: 'Ship' object has no attribute 'bullet_width'". I had tried to debug it and run it step by step but I couldn't find the mistake I've made. Can anybody help me to deal with it? Here are my codes:
alien_invasion(main code):
import sys
import pygame
from pygame.sprite import Group
from settings import Settings
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")
# 创建一艘飞船
ship = Ship(ai_settings, screen)
# 创建一个用于存储子弹的编组
bullets = Group()
bg_color = (230, 230, 230)
# 开始游戏的主循环
while True:
gf.check_events(ship, ai_settings, ship, bullets)
ship.update()
bullets.update()
gf.update_screen(ai_settings, screen, ship, 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
# 在(0, 0)处创建一个表示子弹的矩形,再设置正确的位置
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width,
ai_settings.bullet_height)
self.rect.centerx = ship.rect.centerx
self.rect.top = ship.rect.top
#存储用小数表示的子弹位置
self.y = float(self.rect.y)
self.color = ai_settings.bullet_color
self.speed_factor = ai_settings.bullet_speed_factor
def update(self):
"""向上移动子弹"""
# 更新表示子弹位置的小数值
self.y -= self.speed_factor
# 更新表示子弹的rect的位置
self.rect.y = self.y
def draw_bullet(self):
"""在屏幕上绘制子弹"""
pygame.draw.rect(self.screen, self.color, self.rect)
game_function.py:
import sys
import pygame
from bullet import Bullet
def check_keydown_events(event, ai_settings, screen, ship, bullets):
"""响应按键"""
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
#创建一颗子弹,并将其加入到编组bullet中
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
def check_keyup_events(event, ship):
"""响应松开"""
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
def check_events(ai_settings, screen, ship, 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)
def update_screen(ai_settings, screen, ship, bullets):
"""更新屏幕上的图像,并切换到新屏幕"""
# 每次循环时都重绘屏幕
screen.fill(ai_settings.bg_color)
# 在飞船和外星人后面重绘所有子弹
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
#让最近绘制的屏幕可见
pygame.display.flip()
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/ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
# 将每艘新飞船放在屏幕底部中央
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
# 在飞船的属性center中存储最小数值
self.center = float(self.rect.centerx)
#移动标志
self.moving_right = False
self.moving_left = False
self.moving_up = False
self.moving_down = False
def update(self):
"""根据移动标志调整飞船的位置"""
# 更新飞船的center值,而不是rect
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor
#根据self.center更新rect对象
self.rect.centerx = self.center
def blitme(self):
"""在指定位置绘制飞船"""
self.screen.blit(self.image, self.rect)
settings.py:
class Settings():
"""存储《外星人入侵》的所有设置的类"""
def __init__(self):
"""初始化游戏的设置"""
#屏幕设置
self.screen_width = 1300
self.screen_height = 680
self.bg_color = (230, 230, 230)
#飞船的设置
self.ship_speed_factor = 1.5
#子弹设置
self.bullet_speed_factor = 1.5
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = 60, 60, 60
Thanks a lot, man!
See the signature of the check_events function:
def check_events(ai_settings, screen, ship, bullets):
However, when you call check_events, the ship is passed twice, but the screen is missing:
gf.check_events(ship, ai_settings, ship, bullets)
gf.check_events(ai_settings, screen, ship, bullets)

Python Crash Course Alien Invasion | AttributeError: 'Bullet' object has no attribute 'speed_factor'

I am doing Python Crash Course Alien invasion and when I test this code, an error pops out saying that "Bullet" has no object "speed_factor"
I've been trying for so long to find out why, checked multiple times the code and even compared it to other codes, but it all seems fine.
The game code (alien_invasion.py):
import sys
import game_functions as gf
import pygame
from settings import Settings
from ship import Ship
from pygame.sprite import Group
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")
screen.fill(ai_settings.bg_color)
# Make a ship.
ship = Ship(screen, ai_settings)
bullets = Group()
# Background color
bg_color = (230, 230, 230)
while True:
gf.check_events(ai_settings, screen, ship, bullets)
gf.update_screen(ai_settings, bullets, screen, ship)
gf.check_events(ship, screen, ship, bullets)
ship.update(ai_settings)
bullets.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
screen.fill(ai_settings.bg_color)
ship.blitme()
pygame.display.flip()
run_game()
Settings code (settings.py):
class Settings():
def __init__(self):
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)
self.ship_speed_factor = 2
self.bullet_speed_factor = 1
self.bullet_width = 3
self.bullet_height = 12
self.bullet_color = (60, 60, 60)
self.bullet_limit = 5
Ship code (ship.py):
import pygame
from pygame.sprite import Sprite
class Ship(Sprite):
def __init__(self, screen, ai_settings):
self.screen = screen
self.ai_settings = ai_settings
self.image = pygame.image.load(r'C:\Users\user\Desktop\alien invasion\ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
self.moving_right = False
self.moving_left = False
self.center = float(self.rect.centerx)
self.center += self.ai_settings.ship_speed_factor
def update(self, ai_settings):
self.ai_settings = ai_settings
if self.moving_right and self.rect.right < self.screen_rect.right:
self.rect.centerx += 1
self.center += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor
self.rect.centerx -= 1
def blitme(self):
self.screen.blit(self.image, self.rect)
Bullet code (bullet.py):
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
def __init__(self, ai_settings, screen, ship):
super().__init__()
self.screen = screen
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height)
self.rect.centerx = ship.rect.centerx
self.rect.top = ship.rect.top
self.y = float(self.rect.y)
self.color = ai_settings.bullet_color
self.ship_speed_factor = ai_settings.bullet_speed_factor
def update(self):
self.y -= self.speed_factor
self.rect.y = self.y
def draw_bullet(self):
pygame.draw.rect(self.screen, self.color, self.rect)
game_functions.py:
import pygame
from bullet import Bullet
def check_keydown_events(event, ship, ai_settings, screen, bullets):
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
def check_keyup_events(event, ship):
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
def check_events(ai_settings, screen, ship, bullets):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown_events(event,ship, ai_settings, screen, bullets)
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
def update_screen(ai_settings, bullets, screen, ship):
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
Error log:
File "C:\Users\user\Desktop\alien invasion\bullet.py", line 17, in update
self.y -= self.speed_factor
AttributeError: 'Bullet' object has no attribute 'speed_factor'
I would really appreciate any kind of help as this is driving me crazy.
In the __init__ of your Bullet class, you're setting self.ship_speed_factor but in its update method you're trying to do self.y -= self.speed_factor.
I guess you're just using a wrong field name, in which case you should do either of:
replace self.y -= self.speed_factor with self.y -= self.ship_speed_factor in update
replace self.ship_speed_factor = ... with self.speed_factor = ... in __init__

pygame.Surface object has no attribute 'prep_ships'

Been trying to figure out what's wrong but I can't seem to find the answer.
Here is the game_functions where the error is located:
import sys
from time import sleep
import pygame
from bullet import Bullet
from alien import Alien
def check_keydown_events(event, ai_settings, screen, ship, bullets):
"""Respond to keypresses."""
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings, screen, ship, bullets)
elif event.key == pygame.K_q:
sys.exit()
def fire_bullet(ai_settings, screen, ship, bullets):
"""Fire a bullet if limit not reached yet."""
# Create a new bullet and add it to the bullets group.
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
def check_keyup_events(event, ai_settings, ship):
"""Respond to key releases."""
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
def check_events(ai_settings, screen, stats, sb, play_button, ship,
aliens, bullets):
"""Respond to keypresses and mouse events."""
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, ai_settings, ship)
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
check_play_button(ai_settings, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y)
def check_play_button(ai_settings, screen, stats, sb, play_button, ship, aliens, bullets, mouse_x, mouse_y):
"""Start a new game when the player clicks Play."""
button_clicked = play_button.rect.collidepoint(mouse_x, mouse_y)
if button_clicked and not stats.game_active:
# Reset the game settings.
ai_settings.initialize_dynamic_settings()
# Hide the mouse cursor.
pygame.mouse.set_visible(False)
# Reset the game statistics.
stats.reset_stats()
stats.game_active = True
# Reset the scoreboard images.
sb.prep_score()
sb.prep_high_score()
sb.prep_level()
sb.prep_ships()
# Empty the list of aliens and bullets.
aliens.empty()
bullets.empty()
# Create a new fleet and center the ship.
create_fleet(ai_settings, screen, ship, aliens)
ship.center_ship()
def update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets, play_button):
"""Update images on the screenand flip to the new screen."""
# Redraw the screen during each pass through the loop.
screen.fill(ai_settings.bg_color)
# Redraw all bullets behind ship and aliens.
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
aliens.draw(screen)
# Draw the score information.
sb.show_score()
# Draw the play button if the game is inactive.
if not stats.game_active:
play_button.draw_button()
# Make the most recently drawn screen visible.
pygame.display.flip()
def update_bullets(ai_settings, screen, stats, sb, ship, aliens, bullets):
"""Update position of bullets and get rid of old bullets."""
# Update bullet positions.
bullets.update()
# Get rid of bullets that have dissapeared.
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
check_bullet_alien_collisions(ai_settings, screen, stats, sb, ship, aliens, bullets)
def check_bullet_alien_collisions(ai_settings, screen,stats, sb, ship, aliens, bullets):
"""Respond to bullet-alien collisions."""
# Remove any bullets and aliens that have collided
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
if collisions:
for aliens in collisions.values():
stats.score += ai_settings.alien_points * len(aliens)
sb.prep_score()
check_high_score(stats, sb)
if len(aliens) == 0:
# If the entire fleet is destroyed, start a new level.
bullets.empty()
ai_settings.increase_speed()
# Increase level.
stats.level += 1
sb.prep_level()
create_fleet(ai_settings, screen, ship, aliens)
def get_number_aliens_x(ai_settings, alien_width):
"""Determine the number of aliens that fit in a row."""
available_space_x = ai_settings.screen_width - 2 * alien_width
number_aliens_x = int(available_space_x / (2 * alien_width))
return number_aliens_x
def get_number_rows(ai_settings, ship_height, alien_height):
"""Determine the number of rows of aliens that fit on the screen."""
available_space_y = (ai_settings.screen_height -
(3 * alien_height) - ship_height)
number_rows = int(available_space_y / (2 * alien_height))
return number_rows
def create_alien(ai_settings, screen, aliens, alien_number, row_number):
"""Create an alien and place it in the row."""
alien = Alien(ai_settings, screen)
alien_width = alien.rect.width
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
aliens.add(alien)
def create_fleet(ai_settings, screen, ship, aliens):
"""Create a full fleet of aliens."""
# Create an alien and find the number of aliens in a row.
alien = Alien(ai_settings, screen)
number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)
number_rows = get_number_rows(ai_settings, ship.rect.height,
alien.rect.height)
# Create the fleet of aliens.
for row_number in range(number_rows):
for alien_number in range(number_aliens_x):
create_alien(ai_settings, screen, aliens, alien_number,
row_number)
def check_fleet_edges(ai_settings, aliens):
"""Respond appropriately if any aliens have reached an edge."""
for alien in aliens.sprites():
if alien.check_edges():
change_fleet_direction(ai_settings, aliens)
break
def change_fleet_direction(ai_settings, aliens):
"""Drop the entire fleet and change the fleet's direction."""
for alien in aliens.sprites():
alien.rect.y += ai_settings.fleet_drop_speed
ai_settings.fleet_direction *= -1
def update_aliens(ai_settings, stats, screen, sb, ship, aliens, bullets):
"""
Check if the fleet is at an edge,
and then update the positions of all aliens in the fleet.
"""
check_fleet_edges(ai_settings, aliens)
aliens.update()
# Look for alien-ship collisions.
if pygame.sprite.spritecollideany(ship, aliens):
ship_hit(ai_settings, stats, sb, screen, ship, aliens, bullets)
# Look for aliens hitting the bottom of the screen.
check_aliens_bottom(ai_settings, stats, screen, sb, ship, aliens, bullets)
def ship_hit(ai_settings, stats, screen, sb, ship, aliens, bullets):
"""Respond to the ship being hit by an alien."""
if stats.ships_left > 0:
# Decrement ships_left.
stats.ships_left -= 1
# Update scoreboard.
# HERE IS THE ERROR.
sb.prep_ships()
# Empty the list of aliens and bullets.
aliens.empty()
bullets.empty()
# Create a new fleet and center the ship.
create_fleet(ai_settings, screen, ship, aliens)
ship.center_ship()
# Pause.
sleep(0.5)
else:
stats.game_active = False
pygame.mouse.set_visible(True)
def check_aliens_bottom(ai_settings, stats, screen, sb, ship, aliens, bullets):
"""Check if any aliens have reached the bottom of the screen."""
screen_rect = screen.get_rect()
for alien in aliens.sprites():
if alien.rect.bottom >= screen_rect.bottom:
# Treat the same as if the ship got hit.
ship_hit(ai_settings, stats, screen, sb, ship, aliens, bullets)
break
def check_high_score(stats, sb):
"""Check to see if there's a new high score."""
if stats.score > stats.high_score:
stats.high_score = stats.score
sb.prep_high_score()
Here is scoreboard.py:
class Scoreboard():
"""A class to report scoring information."""
def __init__(self, ai_settings, screen, stats):
"""Initialize scorekeeping attributes."""
self.screen = screen
self.screen_rect = screen.get_rect()
self.ai_settings = ai_settings
self.stats = stats
# Font settings for scoring information.
self.text_color = (30, 30, 30)
self.font = pygame.font.SysFont(None, 48)
# Prepare the initial score images.
self.prep_score()
self.prep_high_score()
self.prep_level()
self.prep_ships()
def prep_score(self):
"""Turn the score into a rendered image."""
rounded_score = int(round(self.stats.score, -1))
score_str = "{:,}".format(rounded_score)
score_str = str(self.stats.score)
self.score_image = self.font.render(score_str, True, self.text_color, self.ai_settings.bg_color)
# Display the score at the top right of the screen.
self.score_rect = self.score_image.get_rect()
self.score_rect.right = self.screen_rect.right - 20
self.score_rect.top = 20
def prep_high_score(self):
"""Turn the high score into a rendered image."""
high_score = int(round(self.stats.high_score, -1))
high_score_str = "{:,}".format(high_score)
self.high_score_image = self.font.render(high_score_str, True, self.text_color, self.ai_settings.bg_color)
# Center the high score at the top of the screen.
self.high_score_rect = self.high_score_image.get_rect()
self.high_score_rect.centerx = self.screen_rect.centerx
self.high_score_rect.top = self.score_rect.top
def prep_level(self):
"""Turn the level into a rendered image."""
self.level_image = self.font.render(str(self.stats.level), True, self.text_color, self.ai_settings.bg_color)
# Position the level below the score.
self.level_rect = self.level_image.get_rect()
self.level_rect.right = self.score_rect.right
self.level_rect.top = self.score_rect.bottom + 10
def prep_ships(self):
"""Show how many ships are left."""
self.ships = Group()
for ship_number in range(self.stats.ships_left):
ship = Ship(self.ai_settings, self.screen)
ship.rect.x = 10 + ship_number * ship.rect.width
ship.rect.y = 10
self.ships.add(ship)
def show_score(self):
"""Draw scores and ships to the screen."""
self.screen.blit(self.score_image, self.score_rect)
self.screen.blit(self.high_score_image, self.high_score_rect)
self.screen.blit(self.level_image, self.level_rect)
# Draw ships.
self.ships.draw(self.screen)
here is ship.py:
import pygame
from pygame.sprite import Sprite
class Ship(Sprite):
def __init__(self, ai_settings, screen):
"""Initialize the ship and set its starting position."""
super(Ship, self).__init__()
self.screen = screen
self.ai_settings = ai_settings
# Load the ship image and get its rect.
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
# Start each new ship at the bottom center of the screen.
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
# Store a decimal value for the ship's center.
self.center = float(self.rect.centerx)
# Movement flags
self.moving_right = False
self.moving_left = False
def update(self):
"""Update the ship's position based on movement flags."""
# Update the ship's center value, not the rect.
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor
# Update rect object from self.center.
self.rect.centerx = self.center
def blitme(self):
"""Draw the ship at its current location."""
self.screen.blit(self.image, self.rect)
def center_ship(self):
"""Center the ship on the screen."""
self.center = self.screen_rect.centerx
And here is alien_invasion.py, the code that i run:
import pygame
from pygame.sprite import Group
from settings import Settings
from game_stats import GameStats
from scoreboard import Scoreboard
from button import Button
from ship import Ship
import game_functions as gf
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 Play button.
play_button = Button(ai_settings, screen, "Play")
# Create an instance to store game statistics and create a scoreboard.
stats = GameStats(ai_settings)
sb = Scoreboard(ai_settings, screen, stats)
# Make a ship, a group of bullets, and a group of aliens.
ship = Ship(ai_settings, screen)
bullets = Group()
aliens = Group()
# Create the fleet of aliens.
gf.create_fleet(ai_settings, screen, ship, aliens)
# Start the main loop for the game.
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, stats, screen, sb, ship, aliens, bullets)
gf.update_screen(ai_settings, screen, stats, sb, ship, aliens, bullets, play_button)
run_game()
This is the error that i keep getting:
game_functions.py, line 182 in ship_hit
sb.prep_ships()
AttribueError: 'pygame.Surface' objecthas no attribute 'prep_ships'
I really can't figure out what's wrong. Not even the rubber duck can help me this time. So some help would be appreciated.
The issue is the line ship_hit(ai_settings, stats, sb, screen, ship, aliens, bullets) in the function update_aliens. In this line the arguments stats and sb are swapped. It has to be:
ship_hit(ai_settings, stats, sb, screen, ship, aliens, bullets)
ship_hit(ai_settings, stats, screen, sb, ship, aliens, bullets)

AttributeError 'pygame.Surface' object has no attribute 'rect'

Here is a game from the book "Python Crash Course (author: Eric Matthes)"
I do exactly what the book told. But I found these problems, and why?
File "D:\pythoncode\l_one\venv\lib\site-packages\pygame\sprite.py", line 1586, in spritecollideany
spritecollide = sprite.rect.colliderect
AttributeError: 'pygame.Surface' object has no attribute 'rect'
Here are my codes: https://github.com/yushu-liu/Learn_Python/tree/master/Alien_Invasion
And part of my codes as follows(aline_invasion.py):
import sys
from settings import Settings
from ship import Ship
from pygame.sprite import Group
import game_functions as gf
from alien import Alien
from game_stats import GameStats
import pygame
def run_game():
# Initialize game and create a 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")
# Set the background Color
bg_color = (230,230,230)
# Make a ship, a group of bullets, and a group of aliens.
ship = Ship(ai_settings, screen)
bullets = Group()
aliens = Group()
# Create the fleet of aliens
gf.create_fleet(ai_settings,screen,ship,aliens)
# Create an instance to store game statistics.
stats = GameStats(ai_settings)
# Start the main loop for the game
while True:
# Watch for keyboard and mouse events
gf.check_events(ai_settings,screen,ship,bullets)
if stats.game_active:
ship.update()
# Make the most recently drawn screen visible
gf.update_bullets(ai_settings,screen,ship,aliens,bullets)
gf.update_aliens(ai_settings,stats,ship,screen,aliens,bullets)
gf.update_screen(ai_settings,screen,ship,aliens,bullets)
run_game()
And another part of my codes as follows(game_function.py):
import sys
import pygame
from bullet import Bullet
from alien import Alien
from time import sleep
def check_keydown_events(event,ai_settings,screen,ship,bullets):
'''Respond to keypresses'''
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings,screen,ship,bullets)
elif event.key == pygame.K_q:
sys.exit()
def check_keyup_events(event,ship):
'''Respond to key releases.'''
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
def check_events(ai_settings, screen, ship, bullets):
'''Respond to keypresses and mouse events'''
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)
def fire_bullet(ai_settings,screen,ship,bullets):
'''Fire a bullet if limit not reached yet.'''
# Create a new bullet and add it to the bullets group
if len(bullets) < ai_settings.bullets_allowed:
new_bullet = Bullet(ai_settings,screen,ship)
bullets.add(new_bullet)
def update_screen(ai_settings,screen,ship,aliens, bullets):
'''Update images screen during each pass through the loop'''
# Redraw the screen during each pass through the loop
screen.fill(ai_settings.bg_color)
# Redraw all bullets behind ship and aliens.
for bullet in bullets.sprites():
bullet.draw_bullet()
# Redraw the ship and the alien
ship.blitme()
# When calling draw, Pygame automatically draws each element in the group
# at the position defined by its rect
aliens.draw(screen)
# Make the most recently drawn screen visible
pygame.display.flip()
def update_bullets(ai_settings, screen, ship, aliens,bullets):
'''Update position of bullets and get rid of old bullets.'''
# Update the latest positions of bullets
bullets.update()
# Get rid of bullets that have disappeared.
for bullet in bullets.copy():
if bullet.rect.bottom <= 0:
bullets.remove(bullet)
check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets)
def check_bullet_alien_collisions(ai_settings,screen,ship,aliens,bullets):
'''Respond to bullet-alien collisions.'''
# Remove any bullets and aliens that have collided
collisions = pygame.sprite.groupcollide(bullets, aliens, True, True)
if len(aliens) == 0:
# If the entire fleet is destroyed, start a new level
bullets.empty()
create_fleet(ai_settings, screen, ship, aliens)
def get_number_aliens_x(ai_settings,alien_width):
'''Determine the number of aliens that fit in a row.'''
availabe_space_x = ai_settings.screen_width - 2 * alien_width
number_aliens_x = int(availabe_space_x/(2 * alien_width))
return number_aliens_x
def get_number_rows(ai_settings, ship_height, alien_height):
'''Determine the number of rows of aliens that fit on the screen,'''
available_space_y = (ai_settings.screen_height - (3 * alien_height) - ship_height)
number_rows = int(available_space_y / (2 * alien_height))
return number_rows
def create_alien(ai_settings,screen,aliens,alien_number,row_number):
'''Create an alien an place it in the row'''
alien = Alien(ai_settings,screen)
alien_width = alien.rect.width
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
aliens.add(alien)
def create_fleet(ai_settings, screen, ship, aliens):
'''Create a full fleet of aliens.'''
# Create an alien and find the number of aliens in a row.
alien = Alien(ai_settings, screen)
number_aliens_x = get_number_aliens_x(ai_settings, alien.rect.width)
number_rows = get_number_rows(ai_settings, ship.rect.height, alien.rect.height)
# Create the fleet of aliens
for row_number in range(number_rows):
for alien_number in range(number_aliens_x):
create_alien(ai_settings, screen, aliens, alien_number,row_number)
def check_fleet_edges(ai_settings, aliens):
'''Respond appropirately if any aliens have reached and edge'''
for alien in aliens.sprites():
if alien.check_edges():
change_fleet_direction(ai_settings, aliens)
break
def change_fleet_direction(ai_settings,aliens):
'''Drop the entire fleet and change the fleet's direction.'''
for alien in aliens.sprites():
alien.rect.y += ai_settings.fleet_drop_speed
ai_settings.fleet_direction *= -1
def ship_hit(ai_settings, stats, screen, ship, aliens, bullets):
'''Respond to ship being hit by alien.'''
if stats.ships_left > 0:
# Decrement ship_left
stats.ships_left -= 1
# Update scoreboard.
aliens.empty()
bullets.empty()
# Create a new fleet and center the ship.
create_fleet(ai_settings, screen, ship, aliens)
ship.center_ship()
# Pause
sleep(0.5)
else:
stats.game_active = False
pygame.mouse.set_visible(True)
def check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets):
'''Check if any aliens have reached the bottom of the screen'''
screen_rect = screen.get_rect()
for alien in aliens.sprites():
if alien.rect.bottom >= screen_rect.bottom:
# Treat this the same as if the ship get hit
ship_hit(ai_settings,stats,screen,ship,aliens,bullets)
break
def update_aliens(ai_settings,stats,screen,ship,aliens,bullets):
'''
Check if the fleet is at an edge, and then update the positions of all
aliens in the fleet.
'''
check_fleet_edges(ai_settings,aliens)
aliens.update()
# Look for alien-ship collisions.
# Look for aliens hitting the bottom of the screen.
if pygame.sprite.spritecollideany(ship,aliens):
ship_hit(ai_settings,stats, screen, ship,aliens, bullets)
# Look for aliens hitting the bottom of the screen.
check_aliens_bottom(ai_settings,stats,screen,ship,aliens,bullets)
alien.py as follow:
import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
'''A class to represent a single alien in the fleet'''
def __init__(self,ai_settings,screen):
'''Initialize the alien an set its starting position.'''
super(Alien,self).__init__()
self.screen = screen
self.ai_settings = ai_settings
# Load the alien image an sets its rect attribute.
self.image = pygame.image.load('images/alien.bmp')
self.rect = self.image.get_rect()
# Start each new alien near the top left of the screen.
self.rect.x = self.rect.width
self.rect.y = self.rect.height
# Store the alien's exact position.
self.x = float(self.rect.x)
def blitme(self):
'''Draw the alien at its current location.'''
self.screen.blit(self.image,self.rect)
def check_edges(self):
'''Return True if alien is at edge of screen.'''
screen_rect = self.screen.get_rect() # 注意get_rect
if self.rect.right >= screen_rect.right:
return True
elif self.rect.left <= 0:
return True
def update(self):
'''Move the alien right.'''
self.x += (self.ai_settings.alien_speed_factor * self.ai_settings.fleet_direction)
self.rect.x = self.x
ship.py as fllow:
import pygame
class Ship():
def __init__(self,ai_settings,screen):
'''Initialize the ship and set its starting position'''
self.screen = screen
self.ai_settings = ai_settings
# Load the ship image and get its rect.
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
# Start each new ship at the bottom center of the screen.
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
# Store a decimal value for the ship's center.
self.center = float(self.rect.centerx)
# Movement flags
self.moving_right = False
self.moving_left = False
def center_ship(self):
'''Make sure the ship in the center of screen.'''
self.center = self.screen_rect.centerx
def update(self):
'''Update the ship's position based on the movement flags.'''
# Update the ship's center value,not the rect
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center += self.ai_settings.ship_speed_factor
if self.moving_left and self.rect.left > 0:
self.center -= self.ai_settings.ship_speed_factor
# Update rect object from self.center.
self.rect.centerx = self.center
def blitme(self):
'''Draw the ship at its current location.'''
self.screen.blit(self.image,self.rect)
game_stats.py as follow:
class GameStats():
'''Track statistics for Alien Invasion'''
def __init__(self,ai_settings):
'''Start Alien Invasion in an active state'''
self.ai_settings = ai_settings
self.reset_stats()
# Start Alien Invasion in an active state
self.game_active = True
def reset_stats(self):
'''Initialize statistics than can change during the game'''
self.ships_left = self.ai_settings.ship_limit
You have two issues.
Your first one is located at line #42 of your aline_invasion.py file:
gf.update_aliens(ai_settings,stats,ship,screen,aliens,bullets)
should be:
gf.update_aliens(ai_settings, stats, screen, ship, aliens, bullets)
If you look at the method declaration for update_aliens in the game_functions.py file you can see that your order was incorrect, which is important. You want to pass things into a method in the order they belong.
Your second issue is located at line #171 of game_functions.py
if pygame.sprite.spritecollideany(aliens, ship):
should be:
if pygame.sprite.spritecollideany(ship, aliens):
Per this post, and this documentation the method you are calling accepts a sprite first, then a group. You were passing the group in first, and then the sprite. Again, the order is important.

Categories

Resources