This question already has an answer here:
Faster version of 'pygame.event.get()'. Why are events being missed and why are the events delayed?
(1 answer)
Closed 2 years ago.
I am working on the Alien Invasion game from Python Crash Course.pdf
import sys
import pygame
def check_events(ship):
"""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, ship)
elif event.type == pygame.KEYUP:
check_keyup_events(event, ship)
def check_keydown_events(event, ship):
"""respond to keypresses."""
if event.key == pygame.K_d:
ship.moving_right = True
if event.key == pygame.K_a:
ship.moving_left = True
def check_keyup_events(event, ship):
"""respond to key releases."""
if event.key == pygame.K_d:
ship.moving_right = False
if event.key == pygame.K_a:
ship.moving_left = False
# Move the ship to the right.
#ship.rect.centerx += 1
def update_screen(ai_settings, screen, ship):
"""update images on screen and flip to the new screen"""
#redraw the screen during each pass through the loop.
screen.fill(ai_settings.bg_color)
ship.blitme()
#make the most recently drawn screen visible.
pygame.display.flip()
#alien invasion
import sys
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
def run_game():
#intialize 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 a Ship
ship = Ship(ai_settings, screen)
#set the background color
#bg_color = (52, 86, 139)
# start the main loop for the game
while True:
gf.check_events(ship)
ship.update()
gf.update_screen(ai_settings, screen, ship)
#watch for keyboard and mouse events.
#redraw the screen during each pass through the loop.
screen.fill(ai_settings.bg_color)
ship.blitme()
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
#make the most recently drawn screen visible
pygame.display.flip()
run_game()
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 ships center
self.center = float(self.rect.centerx)
#Movement flags
self.moving_right = False
self.moving_left = False
def update(self):
"""update the ships position based on the movement flag"""
# Update the ships 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
if self.moving_right:
self.rect.centerx += 1
if self.moving_left:
self.rect.centerx -= 1
def blitme(self):
"""Draw the ship at its current location."""
# pygame.draw.rect(self, (255,0,0), (100, 100), 36)
self.screen.blit(self.image, self.rect)
class Settings():
"""A class to store all settings for Alien Invasion"""
def __init__(self):
"""intialize the games settings."""
# Screen settings
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (52, 86, 139)
#ship settings
self.ship_speed_factor = 1.5
This is the code from my game_functions class
When I press 'D', 85% of the time nothing happens. Sometimes it non stop slides to the left or right, either or. Same thing when pressing "A".
Why is this happening? What am I doing wrong in this code? This code is fairly basic I just want it to move left or right.
Their is no code that turns self.moving_right and self.moving_left to
false to stop them from moving.
I would use something like this:
if event.type == pygame.KEYUP :
if event.key == pygame.K_RIGHT:
self.moving_right = False
elif event.key == pygame.K_ESCAPE :
self.moving_left = False
Here's the documantation:
https://www.pygame.org/docs/ref/key.html
Related
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
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.
I learned about the events settings through a very helpful user here on stackoverflow already. I think I understand how that function works. I currently spawn 1 enemy on the right side of the screen that moves towards the left. I am attempting to spawn them at certain time intervals.
However, I don't know where I am supposed to put the code in for the event. I've tried adding it into def _create_fleet(self): and def __init__(self): and def __init__(self, placeholder): under the "Alien.py" separate file, but none of them seem to work. Could someone please show me where the correct area to do so is?
I am trying to add this:
FIRE_EVENT = pygame.USEREVENT + 1 # This is just a integer.
pygame.time.set_timer(FIRE_EVENT, 1000) # 1000 milliseconds is 1 seconds.
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == FIRE_EVENT: # Will appear once every second.
***whatever the right place to add will be put in here***
and the full code is here:
import sys
import pygame
from ship import Ship
from bullets import Bullet
from alien import Alien
from time import time, sleep
class Sideways:
"""Overall class to manage game assets"""
def __init__(self):
"""Initialize the game and create game resources"""
pygame.init()
self.screen = pygame.display.set_mode((1200, 600))
self.screen_rect = self.screen.get_rect()
pygame.display.set_caption("Pew Pew")
self.bg_color = (204, 255, 255)
self.ship = Ship(self)
self.moving_up = False
self.moving_down = False
self.moving_left = False
self.moving_right = False
self.bullets = pygame.sprite.Group()
self.aliens = pygame.sprite.Group()
self._create_fleet()
def _create_fleet(self):
""""Create a fleet of aliens"""
alien = Alien(self)
self.aliens.add(alien)
def _update_aliens(self):
self.aliens.update()
def run_game(self):
while True:
self._ship_movement_andfiring()
self.ship.blitme()
self._update_screen()
self._update_bullets()
self._update_aliens()
def _update_bullets(self):
self.bullets.update()
for bullet in self.bullets.sprites():
bullet.draw_bullet()
for bullet in self.bullets.copy():
if bullet.rect.right > self.screen_rect.width:
self.bullets.remove(bullet)
collisions = pygame.sprite.groupcollide(self.bullets, self.aliens, True, True)
def _update_screen(self):
pygame.display.flip()
self.screen.fill(self.bg_color)
self.aliens.draw(self.screen)
def _ship_movement_andfiring(self):
if self.moving_up == True:
self.ship.rect.y -= 1
if self.moving_down == True:
self.ship.rect.y += 1
if self.moving_right == True:
self.ship.rect.x += 1
if self.moving_left == True:
self.ship.rect.x -= 1
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
self.moving_up = True
elif event.key == pygame.K_DOWN:
self.moving_down = True
elif event.key == pygame.K_RIGHT:
self.moving_right = True
elif event.key == pygame.K_LEFT:
self.moving_left = True
elif event.key == pygame.K_SPACE:
self._fire_bullet()
elif event.key == pygame.K_ESCAPE:
sys.exit()
elif event.type == pygame.KEYUP:
if event.key != pygame.K_SPACE:
self.moving_up = False
self.moving_down = False
self.moving_left = False
self.moving_right = False
if self.ship.rect.midleft <= self.ship.screen_rect.midleft:
self.moving_left = False
if self.ship.rect.bottom > self.ship.screen_rect.bottom:
self.moving_down = False
if self.ship.rect.midright >= self.ship.screen_rect.midright:
self.moving_right = False
if self.ship.rect.top <= 0:
self.moving_up = False
def _fire_bullet(self):
new_bullet = Bullet(self)
self.bullets.add(new_bullet)
if __name__ == '__main__':
pewpew = Sideways()
pewpew.run_game()
with a separate "alien.py" file to create the aliens here:
import pygame
from pygame.sprite import Sprite
from random import randint
class Alien(Sprite):
"""A class to represent a single alien in the fleet."""
def __init__(self, placeholder):
"""Initialize the alien and set its starting position"""
super().__init__()
self.screen = placeholder.screen
self.screen_rect = self.screen.get_rect()
#load the alien image and set its rect attribute
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
#Start each new alien randomly on right side of screen
random_number = randint(0, self.screen_rect.height-self.rect.height)
self.rect.x = self.screen_rect.width - self.rect.width
self.rect.y = random_number
#Store the alien's horizontal position
self.x = float(self.rect.x)
def update(self):
"""Move alien to the left"""
self.x -= 0.1
self.rect.x = self.x
Create the timer event in the constructor of the your class Sideways:
class Sideways:
def __init__(self):
# [...]
self.bullets = pygame.sprite.Group()
# self._create_fleet() <--- DELETE
# create timer event
self.FIRE_EVENT = pygame.USEREVENT + 1 # This is just a integer.
pygame.time.set_timer(self.FIRE_EVENT, 1000) # 1000 milliseconds is 1 seconds.
Handle the event tin the event loop and create a new enemy when the event occurs:
class Sideways:
# [...]
def _ship_movement_andfiring(self):
# [...]
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == self.FIRE_EVENT:
self._create_fleet()
# [...]
There's no error in the code. I've fixed lots of errors before but it doesn't pop up any error. I've also checked the game_functions to see if it had something do to with that, but everything seems to be perfectly fine.
The error is that when I click the spacebar to shoot the bullets, the ship starts slowing down.
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
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(ai_settings, screen)
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)
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(screen)
pygame.display.flip()
run_game()
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)
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(screen)
pygame.display.flip()
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.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, 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)
Any help I would really appreciate it thank you!
The update_screen function looks suspicious here - redrawing the ship and flipping the display for every bullet is probably not what was intended. Moving those lines outside the loop should help:
def update_screen(ai_settings, bullets, screen, ship):
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme(screen)
pygame.display.flip()
I'm practicing python in python crash course and I am doing the first project which is alien invasion.
I'm still in the beginning of it in the part where you start to move the ship left to right and on keydown and keyup for the right key it works fine. For the left key it just keeps moving left and will not stop moving. I have written exactly what the books as said to write and i have looked on here and on google to see if anyone one else has had this error as well but can't seem to find anything that can help me.
alien_invasion.py
import pygame
from settings import Settings
from ship import Ship
import game_functions as gf
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")
# Make a ship
ship = Ship(screen)
# Start the main loop for the game.
while True:
gf.check_events(ship)
ship.update()
gf.update_screen(ai_settings, screen, ship)
run_game()
game_functions.py
import sys
import pygame
def check_events(ship):
"""Respond to keypresses and mouse events"""
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 update_screen(ai_settings, screen, ship):
"""Update images on the screen and flip to the new screen."""
# Redraw the screen during each pass through the loop.
screen.fill(ai_settings.bg_color)
ship.blitme()
# make the most recently drawn screen visible.
pygame.display.flip()
ship.py
import pygame
class Ship():
def __init__(self, screen):
"""Initialize the ship and set its starting position."""
self.screen = screen
# Load the ship image and get its rect.
self.image = pygame.image.load('img/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
# Movement flags
self.moving_right = False
self.moving_left = False
def update(self):
"""Update the ships's position based on the movement flag"""
if self.moving_right:
self.rect.centerx += 1
if self.moving_left:
self.rect.centerx -= 1
def blitme(self):
"""Draw the ship at its current location"""
self.screen.blit(self.image, self.rect)
in check_events
ship.moving_left = False
ship.moving_left == False would be a check for true or false.
Just do it that way:
elif event.type == pygame.KEYUP:
self.ship.moving_right = False
self.ship.moving_left = False
Unfortunately, it's not the first error in the book :(
I am using a book called Python Crash Course by Eric Matthes. A part of the book deals with python code projects and I started coding for an Alien Invasion Game. I attached the code written so far for the game to work but whenever I run the code, the spaceship does not move regardless of whether I press my keyboard's right or left key. I have ran the code several times but my editor doesn't indicate that there are errors. Is there something I need to fix in my code? I would greatly appreciate it if someone knows how to fix this.
Alien_invasion.py code:
import sys
import pygame
from settings import Settings
from ship import Ship
class AlienInvasion:
"""Overall class to manage game assets and behavior."""
def __init__(self):
"""Initialize the game, and create game resources."""
pygame.init()
self.settings = Settings()
self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))
pygame.display.set_caption("Alien Invasion")
self.ship = Ship(self)
# Set the background color.
self.bg_color = (230, 230, 230)
def run_game(self):
"""Start the main loop for the game."""
while True:
self._check_events()
self.ship.update()
self._update_screen()
# Redraw the screen during each pass through the loop.
def _check_events(self):
"""Respond to keypresses and mouse events."""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
self.ship.moving_right = True
elif event.key == pygame.K_LEFT:
self.ship.moving_left = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
self.ship.moving_right = False
elif event.key == pygame.K_LEFT:
self.ship.moving_left = False
# Move the ship to the right.
self.ship.rect.x += 1
def _update_screen(self):
"""Update images on the screen, and flip to the new screen."""
self.screen.fill(self.settings.bg_color)
self.ship.blitme()
pygame.display.flip()
if __name__ == '__main__':
# Make a game instance, and run the game.
ai = AlienInvasion()
ai.run_game()
Ship.py code:
import pygame
class Ship:
"""A class to manage the ship."""
def __init__(self, ai_game):
"""Initialize the ship and set its starting position."""
self.screen = ai_game.screen
self.screen_rect = ai_game.screen.get_rect()
# Load the ship image and get its rect.
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
# Movement flags
self.moving_right = False
self.moving_left = False
def update(self):
"""Update the ship's position based on the movement flag."""
if self.moving_right:
self.rect.x += 1
if self.moving_left:
self.rect.x -= 1
# Start each new ship at the bottom center of the screen.
self.rect.midbottom = self.screen_rect.midbottom
def blitme(self):
"""Draw the ship at its current location."""
self.screen.blit(self.image, self.rect)
Settings.py code:
class Settings:
"""A class to store all settings for Alien Invasion."""
def __init__(self):
"""Initialize the game's settings."""
# Screen settings
self.screen_width = 1200
self.screen_height = 800
self.bg_color = (230, 230, 230)
I got the code working, it was a typo error.
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
if **event.key** == pygame.K_RIGHT:
self.ship.moving_right = True
elif **event.key** == pygame.K_LEFT:
self.ship.moving_left = True
elif event.type == pygame.KEYUP:
if **event.key** == pygame.K_RIGHT:
self.ship.moving_right = False
elif **event.key** == pygame.K_LEFT:
self.ship.moving_left = False
Earlier I coded event.type instead of event.key
The code is working now, will continue working on the project.