2

I'm new to Python and currently in the process of creating a game using the Python Crash Course. My project involves developing an invasion game where I control a spaceship. However, I'm facing difficulties in effectively managing the spaceship's direction.

AlienGame.py

import sys
import pygame
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("TemplAReeb's First Game")
    ship = Ship(ai_settings, screen)
    bg_color = (230, 230, 230)

    while True:
        gf.check_events(ship)
        ship.update()
        gf.update_screen(ai_settings, screen, ship)
        screen.fill(bg_color)
        ship.blitme()
        pygame.display.flip()
        for event in pygame.event.get():
            if event.type==pygame.QUIT:
                sys.exit()
        screen.fill(bg_color)
        ship.blitme()
        pygame.display.flip()
run_game()

game_functions.py

import sys
import pygame
def check_keydown_events(event, ship):
    if event.key == pygame.K_RIGHT:
        ship.moving_right = True
    elif event.key == pygame.K_LEFT:
        ship.moving_left = True

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):
    for event in pygame.event.get():
        if event.type==pygame.QUIT:
            sys.exit()

        elif event.type==pygame.KEYDOWN:
            check_keydown_events(event, ship)

        elif event.type==pygame.KEYUP:
            check_keyup_events(event, ship)

def update_screen(ai_settings, screen, ship):
    bg_color = (230, 230, 230)
    screen.fill(bg_color)
    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('D:/Python/Pycharm Projects/GameAlien/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
        self.center = float(self.rect.centerx)
        self.moving_right=False
        self.moving_left=False

    def update(self):
        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.rect.centerx = self.center
    def blitme(self):
        self.screen.blit(self.image, self.rect)

When I press the left arrow key, the ship should shift towards the left, and correspondingly, when I press the right arrow key, it should move right. Unfortunately, the ship's movement behavior is currently erratic; it either shifts unpredictably or initiates movement in one direction without responding to further input, essentially becoming stuck.

taylorSeries
  • 505
  • 2
  • 6
  • 18
Temp Estcrowd
  • 73
  • 1
  • 5

1 Answers1

2

The issue is that you've multiple calls to pygame.event.get() in the main loop. Note, pygame.event.get() gets all the messages and remove them from the queue, so randomly either the 1st or the 2nd call gets the event and the other call gets nothing at all.

Get the events once in the main loop and pass them to the function check_events:

def check_events(ship, events):

    for event in events:
        if event.type==pygame.QUIT:
            sys.exit()

        elif event.type==pygame.KEYDOWN:
            check_keydown_events(event, ship)

        elif event.type==pygame.KEYUP:
            check_keyup_events(event, ship)
while True:

    # the one and only call to `pygame.event.get()`
    # get the pending events and clear the event  queue
    events = pygame.event.get()

    for event in events:
        if event.type==pygame.QUIT:
            sys.exit()

    check_events(ship, events)

    # [...]

But note, the code can be simplified by using pygame.key.get_pressed():

def check_events(ship):

    keys = pygame.key.get_pressed()
    ship.moving_right = keys[pygame.K_RIGHT]
    ship.moving_left  = keys[pygame.K_LEFT]

The states which are returned by pygame.key.get_pressed() are evaluated when the events are handled by either pygame.event.get() or pygame.event.poll()

Rabbid76
  • 202,892
  • 27
  • 131
  • 174