Need Help in Python Variable updation (Pygame module) - python

I am trying to increase my speed variable in my pygame code. But as i run this piece of code the speed remain 0.1 (if i press UP key) and 0 (else case). I am unable to debug this. Any help in this would be greatly appreciated.
import pygame
speed = 0
screen = pygame.display.set_mode((400,400),0,32)
pygame.display.update()
clock = pygame.time.Clock()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
if speed < 8 :
speed+=0.1
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
if speed > 0 :
speed+= -0.1
pygame.display.update()
print(speed)
clock.tick(60)
pygame.quit()
quit()

You are confusing the event KEYUP with the UP key. The event KEYUP occurs when a key (any key) is released. The event KEYDOWN occurs when any key is pressed down.
In you code, this means that when the UP key is pressed down, the speed is set to 0.1, and when the UP key is release, the speed is set to 0.0.
If you want the speed to keep increasing, and decreasing when a key is released, you should use a timer, like so:
import pygame
speed = 0
screen = pygame.display.set_mode((400,400),0,32)
pygame.display.update()
clock = pygame.time.Clock()
pygame.time.set_timer(pygame.USEREVENT+1, 20)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
break
if event.type == pygame.USEREVENT+1:
if pygame.key.get_pressed()[pygame.K_UP]:
if speed < 8 :
speed+=0.1
else:
if speed > 0.1:
speed+= -0.1
else:
speed = 0.0
pygame.display.update()
print(speed)
clock.tick(60)
pygame.quit()
quit()
Adjust the delay in the set_timer to suit your taste. Also, note the addition to reset the speed to zero. Float operations are not completely exact, so repeated adding and substracting can lead to a 'zero' that is negative.

The way I've seen this done is:
keys_pressed = pygame.key.get_pressed()
if keys_pressed[pygame.K_UP]:
if speed < 8:
speed += 0.1
if keys_pressed[pygame.K_DOWN]:
if speed > 0:
speed += -0.1

Related

Why isn't 'type' attribute working with event object in Python [duplicate]

This question already has answers here:
How to get keyboard input in pygame?
(11 answers)
How can I make a sprite move when key is held down
(6 answers)
Closed 1 year ago.
I am a newbie to pygame so when I type the below code in, it shows that there is no such thing as a 'type' attribute for the event object. Can you please tell me what's the error.
# Importing libraries and other stuff
import pygame
from pygame.locals import *
# defining the funtion for drawing the block
def draw_block():
surface.fill((232,127,7))
surface.blit(block,(block_x,block_y))
pygame.display.flip()
if __name__ == "__main__":
pygame.init()
surface = pygame.display.set_mode((500,500))
surface.fill((232,127,7))
block = pygame.image.load("block_better_3.jpg").convert()
block_x = 100
block_y = 100
surface.blit(block,(block_x,block_y))
pygame.display.flip()
# Making the window run until user input
running = True
while running:
for event in pygame.event.get():
if event.type == K_ESCAPE:
running = False
elif event.type == QUIT:
running = False
elif event.key == K_UP:
block_y -= 10
elif event.key == K_DOWN:
block_y += 10
elif event.key == K_LEFT:
block_x -= 10
elif event.key == K_RIGHT:
block_x +=10
If you want to know when a key is pressed, you need to verify that the event type (event.type) is KEYDOWN and the key attribute of the event object (event.key) is the specific key (K_ESCAPE, K_UP, ...):
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
elif event.key == K_UP:
block_y -= 10
elif event.key == K_DOWN:
block_y += 10
elif event.key == K_LEFT:
block_x -= 10
elif event.key == K_RIGHT:
block_x += 10
See also pygame.event module and pygame.key module.
The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action or a step-by-step movement.
If you want to achieve a continuously movement, you have to use pygame.key.get_pressed(). pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement:
running = True
while running:
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
keys = pygame.key.get_pressed()
if keys[K_UP]:
block_y -= 1
if keys[K_DOWN]:
block_y += 1
if keys[K_LEFT]:
block_x -= 1
if keys[K_RIGHT]:
block_x += 1
Further more you need to redraw the scene in every frame:
# Importing libraries and other stuff
import pygame
from pygame.locals import *
# defining the funtion for drawing the block
def draw_block():
surface.fill((232, 127, 7))
surface.blit(block,(block_x, block_y))
pygame.display.flip()
if __name__ == "__main__":
pygame.init()
surface = pygame.display.set_mode((500,500))
clock = pygame.time.Clock()
block = pygame.image.load("block_better_3.jpg").convert()
block_x = 100
block_y = 100
# application loop
running = True
while running:
# limit the frames per second
clock.tick(100)
# handle the events
for event in pygame.event.get():
if event.type == QUIT:
running = False
elif event.type == KEYDOWN:
if event.key == K_ESCAPE:
running = False
# update the game states and positions of objects
keys = pygame.key.get_pressed()
block_x += (keys[K_RIGHT] - keys[K_LEFT]) * 2
block_y += (keys[K_DOWN] - keys[K_UP]) * 2
# clear the display; draw the scene; update the display
draw_block()
pygame.quit()
The typical PyGame application loop has to:
handle the events by calling either pygame.event.pump() or pygame.event.get().
update the game states and positions of objects dependent on the input events and time (respectively frames)
clear the entire display or draw the background
draw the entire scene (blit all the objects)
update the display by calling either pygame.display.update() or pygame.display.flip()
limit the frames per second to limit CPU usage with pygame.time.Clock.tick

Why does my pygame window freeze and crash?

Whenever I try to run my program it freezes up and crashes. I'm not a master pygame coder, but I'm almost sure its something to do with my main loop. It's supposed to allow the user to move left and right using arrow keys. I've tried adding a clock and changing the size of the screen but that didn't work. Here is the code:
import pygame
import sys
import random
import time
pygame.init()
screen = pygame.display.set_mode((500,500))
events = pygame.event.get()
clock = pygame.time.Clock()
x = 50
y = 50
game_over = False
while not game_over:
for event in events:
if event.type != pygame.QUIT:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
x += 5
elif event.key == pygame.K_LEFT:
x -= 5
else:
sys.exit()
screen.fill((0,0,0))
pygame.draw.rect(screen, (255,255,255), (x,y,50,50))
clock.tick(30)
pygame.display.update()
The code needs to process the event queue continuously, otherwise your operating environment will consider your window to be non-responsive (locked up). Your code is almost there, except it only fetches the new events once, but this needs to be done every iteration of the main loop.
import pygame
import sys
pygame.init()
screen = pygame.display.set_mode((500,500))
clock = pygame.time.Clock()
x = 50
y = 50
game_over = False
while not game_over:
events = pygame.event.get() # <<-- HERE handle every time
for event in events:
if event.type != pygame.QUIT:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
x += 5
elif event.key == pygame.K_LEFT:
x -= 5
else:
sys.exit()
screen.fill((0,0,0))
pygame.draw.rect(screen, (255,255,255), (x,y,50,50))
clock.tick(30)
pygame.display.update()
You cant do foe event in events, as when you call pygame.events.get(), you are updating them, you are updating them once and looping over them every frame, you need to use for event in pygame.event.get(): so you are calling the function every frame and updating the events every frame
unless you were trying to do this?
events = pygame.event.get
...
for event in events():
which does the same as above

pygame - Unpress key on event.key

I am having a problem with pyGame (complete newbie here). I practice with event.key and would like to unpress / cut off key that is pressed continuously. I have tried to google it and checked this site, but that led to no promising results. Whole thing takes place in
if event.key == pygame.K_UP and isJumping == False:
(full lines 49 - 55)
## HOW TO UNPRESS K_UP IN CASE IT WAS PRESSED AND NOT RELEASED?
if event.key == pygame.K_UP and isJumping == False:
yChange -= 10
isJumping = True
elif event.key == pygame.K_UP and isJumping == True:
print("X")
This works just fine if up arrow is pressed once, but keeps on executing yChange in a loop in case it was not released - that of course is not desired at all. Could you help me with this please?
import pygame
pygame.init() # Initialize pyGame module
# Set screen dimensions
screenW = 800
screenH = 600
# Set color
AQUA = (155, 255, 255)
# Set FPS
FPS = 60
fpsClock = pygame.time.Clock()
# Set character
mainChar = pygame.image.load('p1_front.png')
mainCharX = screenH / 2 # char X position
mainCharY = screenW / 2 # char Y position
isJumping = False
xChange = 0
yChange = 0
MOVSPEED = 1
# Set backgrounds
mainBg = pygame.image.load('bg_castle.png')
mainBg = pygame.transform.scale(mainBg, (screenW, screenH))
# Set the window, param in a tuple is width / height
DISPLAYSURF = pygame.display.set_mode((screenW, screenH))
# Set window name (game title)
pygame.display.set_caption("Newbie training")
while True: # Main loop of the game
#set BG
DISPLAYSURF.blit(mainBg, (0,0))
# Events loop below
for event in pygame.event.get():
if event.type == pygame.QUIT: # Quit window when [x] is pressed
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_RIGHT:
xChange += MOVSPEED
elif event.key == pygame.K_LEFT:
xChange -= MOVSPEED
## HOW TO UNPRESS K_UP IN CASE IT WAS PRESSED AND NOT RELEASED?
if event.key == pygame.K_UP and isJumping == False:
yChange -= 10
isJumping = True
elif event.key == pygame.K_UP and isJumping == True:
print("X")
if event.type == pygame.KEYUP:
if event.key == pygame.K_RIGHT or event.key == pygame.K_LEFT:
xChange = 0
if event.key == pygame.K_UP:
yChange = 0
#print(event)
mainCharX += xChange
mainCharY += yChange
DISPLAYSURF.blit(mainChar, (mainCharX, mainCharY)) # Load character
pygame.display.update() #update window
fpsClock.tick(FPS) # FPS goes always after update
If you only want the player to be able to jump 10 'units' per up press then stop in place, you could simply set yChange to 0 each frame after you add it to mainCharY.
However, if you're looking for a more robust jumping system (button is pressed, player moves up for a few frames, then stops and falls back down) more is required.
To give you an idea: what if you had some logic at the end of each frame that checks if mainCharY > 0 (player is not on ground) and, if so, subtracts some number from yChange (as if gravity were pulling them down)?
In the above case, your code should avoid the repeating up press problem. It might be easier to just test (mainCharY > 0) instead of using an isJumping variable.
It seems you're misunderstanding how the event queue and event loop work. When you press a key, a single pygame.KEYDOWN event gets added to the event queue. Calling pygame.event.get empties the event queue and puts all events into a list over which you iterate with the for loop: for event in pygame.event.get():. That means pygame doesn't know that you're still holding the key, it will only see that you've pressed UP once. It will also notice that you release the key and add a pygame.KEYUP event to the queue.
In your case you're decreasing the yChange variable to -10 when you press the UP key. In the while loop mainCharY will then be decremented by -10 each frame and the character will move upwards. As soon as you release the key, the yChange is reset to 0 and the player character stops.
if event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
yChange = 0
To implement jumping in your game, you should add a GRAVITY constant which you add to your y-velocity each frame to accelerate downwards. When the character touches the ground, set the y-velocity to 0 and a variable (on_ground or something similar) to True, so that you know that the player can jump. When the player presses the jump key, you can set the y-velocity to a negative value and the sprite will start to move upwards until the GRAVITY pulls him down again. Here's a complete example.
I don't think it's likely at all that pygame could miss a key event.
I think the problem is that you're not setting isJumping to false anywhere, which stops the changing of yChange forever after the first press. If I'm interpreting this correctly, the following code should work:
if event.type == pygame.KEYDOWN:
... # Your other code
if event.key == pygame.K_UP and not isJumping: # "== False" is not necessary
yChange -= 10
isJumping = True
if event.type == pygame.KEYUP:
... # Your other code
if event.key == pygame.K_UP and isJumping:
yChange = 0
isJumping = False # <-- This is the addition to the code
One thing to keep in mind is that this jumping system won't look very natural. Look to #SamHolloway's answer for more clarification on this.

Event Coding Keyboard Input

I am coding with python on my raspberry pi. Python isn't my best language so bear with me.
I need a simple code that responds to key strokes on my keyboard. I'd doing this so I can set the Pulse Width Modulation, but I don't need that code, I already have it. My main concern is I am struggling to understand the pygame functionality required for my task.
I would like to be able to type a key, such as "up arrow" ↑ and have the program output "up pressed" for every millisecond the up arrow is pressed.
The pseudo-code would look like:
double x = 1
while x == 1:
if input.key == K_UP:
print("Up Arrow Pressed")
if input.key == K_q
x = 2
wait 1ms
pygame.quit()
Again I have no clue what to import or call due to not knowing the syntax.
Here's some code that will check if the ↑ key is pressed:
import pygame
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode([320,240])
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
keys = pygame.key.get_pressed()
if keys[pygame.K_UP]:
print("Up Arrow Pressed")
elif keys[pygame.K_q]:
done = True
clock.tick(1000)
pygame.quit()
Note that clock.tick(1000) will limit the code to one-thousand frames per second, so won't exactly equate to your desired 1 millisecond delay. On my PC I only see a frame rate of around six-hundred.
Perhaps you should be looking at the key down and key up events and toggle your output then?
import pygame
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode([320,240])
done = False
output = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
output = True
elif event.type == pygame.KEYUP:
if event.key == pygame.K_UP:
output = False
elif event.key == pygame.K_q:
done = True
pygame.display.set_caption(f"Output Status {output}")
clock.tick(60)
pygame.quit()
If you run this, you'll see the title of the window change whilst the ↑ key is pressed.

Move left or right to fast causes img to stick

I am making a spaceship invaders game in python 3 with pygame. I am currently having troubles with the spaceship sticking making me double tap a left or right arrow key for it to take effect. Here is my code:
import pygame
pygame.init()
display_width = 800
display_height = 600
black = (0, 0, 0)
white = (255, 255, 255)
#Window Size
gameDisplay = pygame.display.set_mode((display_width, display_height))
#Title Of Window
pygame.display.set_caption('A Bit Racey')
#FPS
clock = pygame.time.Clock()
spaceshipImg = pygame.image.load('SpaceShipSmall.png')
def spaceship(x,y):
gameDisplay.blit(spaceshipImg, (x,y))
x = (display_width * 0.45)
y = (display_height * 0.8)
x_change = 0
crashed = False
while not crashed:
# this will listen for any event every fps
for event in pygame.event.get():
if event.type == pygame.QUIT:
#change later
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
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
x += x_change
gameDisplay.fill(white)
spaceship(x,y)
pygame.display.update()
clock.tick(60)
pygame.quit()
quit()
Every time a pygame.KEYUP event is detected for the left or right arrow key you reset x_change. Even when you hold down e.g. your right arrow key a single left arrow key press stops the movement of your spaceship.
To solve this problem you could use the pygame.key.get_pressed() method to get the state of all keyboard buttons. This function returns a sequence of boolean values indexed by pygames key constant values representing the state of every key on the keyboard.
Because you don´t need to call pygame.key.get_pressed() every time an event happens, the updated main loop should look like this:
while not crashed:
# this will listen for any event every fps
for event in pygame.event.get():
if event.type == pygame.QUIT:
#change later
crashed = True
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
#get the state of all keyboard buttons
pressedKeys = pygame.key.get_pressed()
#change position if pygame.K_LEFT or pygame.K_RIGHT is pressed
if pressedKeys[pygame.K_LEFT]:
x += -5
elif pressedKeys[pygame.K_RIGHT]:
x += 5
gameDisplay.fill(white)
spaceship(x,y)
pygame.display.update()
clock.tick(60)
Notice that a pygame.K_LEFT event has a higher priority than a pygame.K_RIGHT event. You could change this behavior by using two separate if blocks. Many thanks to #sloth for pointing this out!:
#change position if either pygame.K_LEFT or pygame.K_RIGHT is pressed
if pressedKeys[pygame.K_LEFT]:
x += -5
if pressedKeys[pygame.K_RIGHT]:
x += 5
I hope this helps you :)
add the following statement before x += x_change:
print (event.type, event.key, x)
this will print the event data and x position to the console.
try your script again, try holding down the left key for 3 seconds, then release, and repeat for the right key. See if you see multiple keydown events while holding down the keys. I think you should only see one keyup event upon release.

Categories

Resources