'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