'Python Crash Course, Alien Invasion - a ship doesn't move after reaching the screen's right corner
I'm working on the Alien Invasion from "Python Crash Course" by Erick Matthes. I've bogged down on trying to make a ship move across a screen. Most of time, the ship moves as expected. However, after reaching the very right corner of the screen, the ship ceases to react to pressed keys. Pressing a left arrow key on keyboard doesn't move the ship leftwards at all. What's wrong with my code?
alien_invasion.py
"""The main module of the Alien Invasion"""
import sys
import pygame
from settings import Settings
from ship import Ship
class AlienInvasion():
"""A class storing and managing all game's functionality."""
def __init__(self):
"""Initialize essential settings."""
self.settings = Settings()
self.screen = pygame.display.set_mode((0,0), pygame.FULLSCREEN)
self.settings.window_width = self.screen.get_rect().width
self.settings.window_height = self.screen.get_rect().height
pygame.display.set_caption(self.settings.game_title)
self.ship = Ship(self)
self._run_game()
def _end_game(self):
"""Close the game's window."""
pygame.quit()
sys.exit()
def _check_events(self):
"""Check events and react to them."""
for event in pygame.event.get():
if event.type == pygame.QUIT:
self._end_game()
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):
"""Detect pressed keys and react accordingly."""
if event.key == pygame.K_q:
self._end_game()
if event.key == pygame.K_RIGHT:
self.ship.moving_right = True
if event.key == pygame.K_LEFT:
self.ship.moving_left = True
def _check_keyup_events(self, event):
"""Detect released keys and react accordingly."""
if event.key == pygame.K_RIGHT:
self.ship_moving_right = False
if event.key == pygame.K_LEFT:
self.ship.moving_left = False
def _update_screen(self):
"""Draw the most recent surface on the screen."""
self.screen.fill(self.settings.background_colour)
self.ship.update()
self.ship.blitme()
pygame.display.flip()
def _run_game(self):
"""Start a new game"""
while True:
#Main loop
self._check_events()
self._update_screen()
ai = AlienInvasion()
ship.py
"""A module containing a Ship class"""
import pygame
class Ship():
"""A simple attempt to represent a ship."""
def __init__(self, ai):
"""Initialize a ship's settings."""
self.ai = ai
self.screen = self.ai.screen
self.image = pygame.image.load('ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = self.screen.get_rect()
self.rect.midbottom = self.screen_rect.midbottom
#Motions' attributes
self.moving_right = False
self.moving_left = False
self.x = float(self.rect.x)
self.speed = self.ai.settings.ship_speed
def blitme(self):
"""Draw a ship on the screen."""
self.screen.blit(self.image, self.rect)
def update(self):
"""Update a ship's position on the screen."""
if self.moving_right and self.rect.right < self.screen_rect.right:
self.x += self.speed
if self.moving_left and self.rect.left > 0:
self.x -= self.speed
self.rect.x = self.x
settings.py
"""Module containing a Settings class"""
class Settings():
"""A module managing all game's essential settings."""
def __init__(self):
"""Initialize settings."""
self.background_colour = (230, 230, 230)
self.game_title = 'Alien Invasion'
self.window_width = 1200
self.window_height = 600
self.window_size = (self.window_width, self.window_height)
#Ship's settings
self.ship_speed = 1.5
Solution 1:[1]
The ship won't move left, which means it's probably stuck moving right. That points to an issue in releasing the movement to the right, which happens in _check_keydown_events():
def _check_keyup_events(self, event):
"""Detect released keys and react accordingly."""
if event.key == pygame.K_RIGHT:
self.ship_moving_right = False
if event.key == pygame.K_LEFT:
self.ship.moving_left = False
Here's the problematic line:
self.ship_moving_right = False
This should be self.ship.moving_right, not self.ship_moving_right. The correct version finds the ship attribute of the game, and sets the ship's moving_right attribute to False. The incorrect version creates a new game attribute ship_moving_right, and sets it to False; it never changes the value of self.ship.moving_right. So, the ship tries to move right for the rest of the game. This is a great example of how one character can produce no Python errors, but has a significant impact on the overall behavior of the game.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | japhyr |
