Reputation: 1
I am currently learning python from the book 'Python Crash Course'.
In the book I am currently on a project called Alien Invasion. I am running into a problem in the game after I tried to add the ability for the ship to gain speed the longer you press the button. It says that the settings() does not have the attribute 'blit' (when it calls the blitme function to draw the ship in the game).
My code is split into multiple modules which I have included below.
All modules are .py.
alieninvasionbase:
import sys
import pygame
from settings import *
from ship import *
from gamef import *
def start_game():
pygame.init()
ai_settings = settings()
screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
pygame.display.set_caption("Space Wars")
ship = Ship(ai_settings, screen)
while True:
ship.update()
check_events(ship)
us(ai_settings,screen,ship)
start_game()
game.py:
import sys
import ship
import pygame
def check_events(ship):
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
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 us(self,ai_settings,screen,ship):
self.screen.fill(ai_settings.bg_color)
self.ship.blitme()
self.pygame.display.flip()
check_events(ship)
ship.py:
import pygame
import sys
class Ship():
def __init__(self,screen,ai_settings):
self.screen = screen
self.ai_settings = ai_settings
self.image = pygame.image.load('images/spaceship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = self.image.get_rect()
self.screen_rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
self.moving_right = False
self.moving_left = False
def update(self):
if self.moving_right == True:
self.rect.centerx += 1
if self.moving_left == True:
self.rect.centerx += -1
def blitme(self):
self.screen.blit(self.image,self.rect)
settings.py:
import pygame
import sys
import ship
class settings():
def __init__(self):
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (0,0,0)
Upvotes: 0
Views: 126
Reputation: 29608
The us
method in game.py is not an instance method since it's not part of a class, so it does not need the self
parameter. See What is the purpose of the word 'self', in Python?.
def us(self,ai_settings,screen,ship):
self.screen.fill(ai_settings.bg_color)
self.ship.blitme()
self.pygame.display.flip()
Remove self
and just use the 3 parameters directly.
def us(ai_settings,screen,ship):
screen.fill(ai_settings.bg_color)
ship.blitme()
pygame.display.flip()
I think it would be better to make check_events
and us
instance methods of Ship
, since you pass ship
as a parameter anyway, and also all Ship
instances already has a copy of screen
and ai_settings
.
Another problem I see is that you mixed-up the arguments to Ship
. The class __init__
methods accept screen
and ai_settings
, in that specific order:
def __init__(self,screen,ai_settings): # <--- look at the input order
self.screen = screen
self.ai_settings = ai_settings
But you instantiate a ship like this:
ship = Ship(ai_settings, screen) # <--- the order here is incorrect
Notice the order is incorrect. So in __init__
, the 1st argument ai_settings
gets assigned to self.screen
and the 2nd argument screen
gets assigned to self.ai_settings
. The order is important for positional arguments of a function, Python does not check the variable name.
That will lead to the error you mentioned here:
def blitme(self):
self.screen.blit(self.image,self.rect)
Because, in effect, self.screen
is actually the settings
instance ai_settings
. You can check that by printing-out type(self.screen)
. It is the same as:
ai_settings = settings() # instantiated in `start_game`
ai_settings.blit(...) # inside `Ship#blitme`
and the settings
class does not have the blit
attribute.
Upvotes: 1