Pygame image moving without proper input - python

I recently started tinkering a bit with pygame and I made this little piece of code (following a tutorial):
import pygame
pygame.init()
display_width = 1920
display_height = 1080
black = (0,0,0)
white = (255,255,255)
red = (255,0,0)
gameDisplay = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Galvadon's Adventure")
clock = pygame.time.Clock()
galvadon = pygame.image.load("galvadonModelVersion1.0.png")
def galvadonIsHere(x,y):
gameDisplay.blit(galvadon,(x,y))
x = (display_width * 0.30)
y = (display_height * 0.2)
y_change = 0
crashed = False
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
y_change = 5
elif event.key == pygame.K_UP:
y_change = -5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
y += y_change
gameDisplay.fill(white)
galvadonIsHere(x,y)
print(event)
pygame.display.update()
clock.tick(30)
pygame.quit()
quit()
and to an extent this code works, the problem is that after I move the image using the up and down arrows, the image starts to respond to any mouse movement by just gliding in the direction it last moved towards. I probably missed something out, but I just can't seem to find what it is. I looked at various websites looking for the answer but I couldn't find anyone asking a similar question, hence why I make this topic.

There are couple of things that you can do better here. But lets start with fixing the issue.
'Bug' is that after you press keys, y_change is set and never reset for next engine loop. This should help you:
...
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
y_change = 5
elif event.key == pygame.K_UP:
y_change = -5
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
y += y_change
gameDisplay.fill(white)
galvadonIsHere(x, y)
print(event)
pygame.display.update()
clock.tick(30)
y_change = 0
...
Pay close attention at the last line in my snippet. Here you reset y_change so in next engine loop, whatever happens or doesn't, it wont affect position of your image.
Refactor and improve
First, you can agree that checking if event type is KEY_DOWN and nesting checks if it is particular key button is pain to read and work with. Not to mention you check if event type is KEYUP even though you know that is KEYDOWN here:
if event.type == pygame.KEYDOWN:
...
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP or event.key == pygame.K_DOWN:
y_change = 0
So, what I do is define helper function, that can be usual one or lambda. Now, many would argue that lambda functions are affecting readability but here it can certainly help you with these checks.
Example:
key_pressed = lambda event, key: event.type == pygame.KEYDOWN and event.key == key
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
break
elif key_pressed(event, pygame.K_DOWN):
y_change = 5
elif key_pressed(event, pygame.K_UP):
y_change = -5
else:
y_change = 0
y += y_change
gameDisplay.fill(white)
galvadonIsHere(x, y)
print(event)
pygame.display.update()
clock.tick(30)
y_change = 0
One more thing, pay attention at condition that there was pygame.QUIT event. break exits the for loop and then while loop ends too. This way you do not process any queued events, nor you update and blit image.

Your problem is in the while loop. The if statement for keyup is in the if statement for keydown, so it is preventing it from working. The following solves your problem:
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_DOWN:
y_change = 5
elif event.key == pygame.K_UP:
y_change = -5
else:
y_change = 0
Hope this helps.

Related

Keystrokes not registering in Python/Pygame?

I am new to Python and especially new to Pygame. Been working on a basic space invader type game to attempt to learn more about Pygame, but I cannot figure out the code for moving the user ship. Have looked up some tutorials on it, and I THINK my code looks good, but I might be looking over something. I am in Python version 3.8 and Pygame version 1.9.6.
'''
This script is creating a space invader type game with the Pygame module.
Tutorial following YT video from freecodecamp.org
(https://www.youtube.com/watch?v=FfWpgLFMI7w&ab_channel=freeCodeCamp.org)
'''
import sys
import pygame
# Initializing Pygame
# (ALWAYS REQUIRED)
pygame.init()
# Screen Dimensions
width = 800
height = 600
screen = pygame.display.set_mode((width, height))
# Other Game Settings
framerate = pygame.time.Clock()
framerate.tick(60)
# Setting Title and Images
pygame.display.set_caption('Space Invaders')
icon = pygame.image.load('spaceship.png')
pygame.display.set_icon(icon)
player_ship = pygame.image.load('space-invaders.png')
def player(x,y):
'''
Draws the player's ship on the screen at (x,y) coordinates.
'''
screen.blit(player_ship,(x, y))
# Game Function
def game():
'''
Actual code for the game itself.
'''
# Sets the starting position for the player's ship
playerX = 368 # Middle of Screen (on x-axis)
playerY = 506 # 30px off bottom of the screen (y-axis)
x_change = 0
# Game Loop
game_exit = False
while not game_exit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True
elif event.type == pygame.KEYDOWN:
if event.type == pygame.K_ESCAPE:
game_exit = True
elif event.type == pygame.K_d:
x_change = 5
elif event.type == pygame.K_a:
x_change = -5
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d or event.key == pygame.K_a:
x_change = 0
playerX += x_change
print(x_change) # Using this to see if the script is recognizing the user keystrokes
# Setting Screen RGB
screen.fill((0,0,0))
player(playerX, playerY)
# Screen Update
# (ALWAYS REQUIRED)
pygame.display.update()
game()
pygame.quit()
sys.exit()
Thanks for your help!
The issue is you're checking for an event.type of pygame.K_d, etc.
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True
elif event.type == pygame.KEYDOWN:
if event.type == pygame.K_ESCAPE: # <-- HERE
game_exit = True
elif event.type == pygame.K_d: # <-- HERE
x_change = 5
elif event.type == pygame.K_a: # <-- AND HERE
x_change = -5
The event.type cannot be equal to both pygame.KEYDOWN and pygame.K_d at the same time!. If you check the documentation on event, notice that the key-code is sent in event.key, so it's a simple fix.
KEYDOWN key, mod, unicode, scancode
KEYUP key, mod
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_exit = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE: # <-- FIX HERE
game_exit = True
elif event.key == pygame.K_d: # <-- FIX HERE
x_change = 5
elif event.key == pygame.K_a: # <-- AND FIX HERE
x_change = -5

Pygame moving object /image repeat itself [duplicate]

This question already has answers here:
Pygame how to fix 'trailing pixels'?
(4 answers)
Closed 5 years ago.
I'am building a simple game using pygame ,the function of this game is to control an image and make it move up/down left/right but i got this problem, the image repeats itself when moving down or aside
import pygame
pygame.init()
display_width = 1080
display_height = 1080
screen = pygame.display.set_mode((display_width,display_height))
Clock = pygame.time.Clock()
pygame.display.set_caption('DEMO')
black=(0,0,0)
white=(255,255,255)
red=(255,0,0)
green=(0,255,0)
blue=(0,0,255)
screen.fill(white)
face=pygame.image.load('H:\\brain.jpg')
def brain(x,y):
screen.blit(face,(x,y))
x1 =(display_width*0.5)
y1 =(display_height*0.5)
x_change =0
y_change =0
gameExit = False
while not gameExit:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
elif event.key == pygame.K_DOWN:
y_change = 5
elif event.key == pygame.K_UP:
y_change = -5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
if event.type == pygame.KEYUP:
if event.key == pygame.K_DOWN or event.key == pygame.K_UP:
y_change = 0
x1 += x_change
y1 += y_change
print(event)
brain(x1,y1)
pygame.display.update()
Clock.tick(100)
pygame.quit()
quit()
You have to blit your background at every iteration of the while-loop:
while True:
for event in pygame.event.get():
#get keyboard input
screen.fill((255, 255, 255)) #or, you can draw a background image
x1 += x_change
y1 += y_change
print(event)
brain(x1,y1)
pygame.display.update()
You need to blank out the old image, as well as drawing the new one. What you see is the residue: the portion of the previous images that wasn't covered by the white (background color) of the new image.
One easy way to handle this is to expand your drawn image to include a white border at least as large as the size of the motion.

keys do not move the object in the game written in python

Update: manish kumar gave me the solution for the problem. I had to write event.key instead of event.type in a certain part of the code.
check it out at it below:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
I am trying to make a simple game by using Pygame.
Simply I have written code to move a car to the left and right.
Everything works well except that the keys do not move the car.
here is the code:
import pygame
from pygame.locals import *
pygame.init()
black = (0,0,0)
white = (255,255,255)
GD1 = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Racing!")
clock = pygame.time.Clock()
carimg = pygame.image.load("C:/Users/Abdulaziz/Downloads/my_app___car_sprite_5_by_nicolaspok-d65xysp.png")
def car(x,y):
GD1.blit(carimg,(x,y))
x = (800 * 0.45)
y = (600 * 0.7)
x_change = 0
crashed = False
while not crashed:
for event in pygame.event.get():
if event.type == pygame.QUIT:
crashed = True
if event.type == pygame.KEYDOWN:
if event.type == pygame.K_LEFT:
x_change = -5
elif event.type == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
GD1.fill(white)
car(x,y)
pygame.display.flip()
clock.tick(60)
pygame.quit()
quit()
the problem is probably in this part of the code:
if event.type == pygame.KEYDOWN:
if event.type == pygame.K_LEFT:
x_change = -5
elif event.type == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
Again, the car appears but do not move.
you have to use event.key instead of event.type.
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
I think the problem lies here:
for event in pygame.event.get():
# modifications to x_change
x += x_change
If the call to pygame.event.get() returns two events, a KEYDOWN and a KEYUP, then x_change will be set to 5 or -5, but then it will be set back to 0.
You should update x at each iteration:
for event in pygame.event.get():
# modifications to x_change
x += x_change

Player movement stops when direction reverses in Pygame

I am messing around with pygame and I am eventually working towards a pong clone. I implemented player movement with the arrow keys and when ever I switch from going up to immediately going down, my player freezes and won't move again until I press that direction key again. Here is my code:
import sys, pygame
pygame.init()
display_width = 640
display_height = 480
display = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Test Game")
black = (0,0,0)
white = (255,255,255)
clock = pygame.time.Clock()
running = True
class Player:
def __init__(self,x,y,hspd,vspd,color,screen):
self.x = x
self.y = y
self.hspd = hspd
self.vspd = vspd
self.color = color
self.screen = screen
def draw(self):
pygame.draw.rect(self.screen,self.color,(self.x,self.y,32,32))
def move(self):
self.x += self.hspd
self.y += self.vspd
player = Player(0,0,0,0,black,display)
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
player.hspd = 0
if event.key == pygame.K_LEFT:
player.hspd = 0
if event.key == pygame.K_UP:
player.vspd = 0
if event.key == pygame.K_DOWN:
player.vspd = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player.hspd = 4
if event.key == pygame.K_LEFT:
player.hspd = -4
if event.key == pygame.K_UP:
player.vspd = -4
if event.key == pygame.K_DOWN:
player.vspd = 4
#Clear the screen
display.fill(white)
#Move objects
player.move()
#Draw objects
player.draw()
#Update the screen
pygame.display.flip()
print "I made it!"
pygame.quit()
sys.exit()
I suggest you work with key.get_pressed() to check for the current set of pressed keys.
In your scenario - when you press down and release up (in that order) - the speed is set to 0, so you need to inspect the keys pressed not just by the current event.
Here is a working version of the relevant part:
def current_speed():
# uses the fact that true = 1 and false = 0
currently_pressed = pygame.key.get_pressed()
hdir = currently_pressed[pygame.K_RIGHT] - currently_pressed[pygame.K_LEFT]
vdir = currently_pressed[pygame.K_DOWN] - currently_pressed[pygame.K_UP]
return hdir * 4, vdir * 4
while running:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
player.hspd, player.vspd = current_speed()
#Clear the screen
display.fill(white)
#Move objects
player.move()
#Draw objects
player.draw()
#Update the screen
pygame.display.flip()
To expand on LPK's answer, your key down (for event.key == pygame.K_DOWN) is likely being processed before your key up (from event.key == pygame.K_UP) is processed. So while both are down (and you can confirm this), you may experience movement, until you release the up key.
your problem is here:
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT:
player.hspd = 0
if event.key == pygame.K_LEFT:
player.hspd = 0
if event.key == pygame.K_UP:
player.vspd = 0
if event.key == pygame.K_DOWN:
player.vspd = 0
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
player.hspd = 4
if event.key == pygame.K_LEFT:
player.hspd = -4
if event.key == pygame.K_UP:
player.vspd = -4
if event.key == pygame.K_DOWN:
player.vspd = 4
I am guessing that your key event down is still consumed when u switch the keys immediately, meaning no other key down event is getting triggered as long as the first event didn't fire its key up event yet.
EDIT: maybe its better to check if the player is moving and if so just reverse speed . Then you would only need to check the down event.
Otherwise your event will be consumed and not checked properly.
For your method you would need to store the occurred key events since the last frame and check that list.

Window boundaries in pygame

Basically I am trying to add some boundaries to a small game I am making, I have a sprite which can only move left to right and I am trying to prevent it from it from moving off the game window, if the sprite reaches the edge they can go no further and can then go in the opposite direction.
My current code:
tankSprite = pygame.image.load('Sprites/Tank.png') #fixed apostrophe
tankSprite_width = 28
def tank(x,y):
gameWindow.blit(tankSprite, (x,y))
def game_loop():
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change = 0
gameExit = False
gameMove = True
while not gameExit and gameMove == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = False
if event.type ==pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
if event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFTor event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
gameWindow.fill(white)
tank(x,y)
if x > display_width - tankSprite_width or x < 0:
gameMove = False
elif x < display_width - tankSprite_width or x > 0:
gameMove = True
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()
quit()
My current code partially works, when the sprite reaches the edge the solution closes itself rather than letting me go back. If I remove:
pygame.quit()
quit()
Then the sprite just stops and I can't move it back. In a project I did a while back I used something like:
if event.key == pygame.K_LEFT and sprite.x < 590:
sprite.x += 5
The above code worked well from what I can remember but I can't seem to figure it out for my project now, can anyone help me out please?
I wish to make it so that the sprite can't go past the screen border, when the player reaches the border they either stay or go back in the opposite direction. Thanks
p.s. Sorry about the dodgy formatting
Just split your if-statement and check the condition for each direction separately:
tankSprite = pygame.image.load('Sprites/Tank.png')
tankSprite_width = 28
def tank(x,y):
gameWindow.blit(tankSprite, (x,y))
def game_loop():
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change = 0
gameExit = False
gameMove = True
while not gameExit and gameMove == True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameExit = False
if event.type ==pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x_change = -5
if event.key == pygame.K_RIGHT:
x_change = 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFTor event.key == pygame.K_RIGHT:
x_change = 0
#valid move, add x_change
if((x+x_change)> 0 and (x+x_change)<(display_width - tankSprite_width):
x += x_change
gameWindow.fill(white)
tank(x,y)
#deleted stuff here
pygame.display.update()
clock.tick(60)
game_loop()
pygame.quit()
quit()
With this method, you don't need to even use the gameMove variable anymore.
You could also get rid of the x_change variable entirely by simply applying the changes directly to x instead.
Also, I think you may have meant gameExit = True under the if statement if event.type == pygame.QUIT:, as it makes sense to exit when event pygame.QUIT is triggered.

Categories

Resources