This question already has answers here:
How can I make a sprite move when key is held down
(6 answers)
How to get keyboard input in pygame?
(11 answers)
Closed 8 months ago.
I have the following code for an application I am developing in pygame. When I click the down key or any key for that matter, "here" is not being printed. The code is as follows:
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
print("here")
if event.key == pygame.K_DOWN:
player_speed += 7
if event.key == pygame.K_UP:
player_speed -= 7
if event.type == pygame.KEYUP:
print("here")
if event.key == pygame.K_DOWN:
player_speed -= 7
if event.key == pygame.K_UP:
player_speed += 7
Where is the error here (it is not a syntax one as the code runs fine - it is just indented weirdly on this post)? Is there another requisite prior to taking in keyboard input.
It's not clear what the error is without more of your code, preferably a Minimal, Reproducible Example.
Here's what such an example could look like:
import pygame
import random
screen = pygame.display.set_mode((480, 320))
pygame.init()
player_speed = 0
run = True
clock = pygame.time.Clock()
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
elif event.type == pygame.KEYDOWN:
print(f"Key {pygame.key.name(event.key)} pressed")
if event.key == pygame.K_DOWN:
player_speed += 7
elif event.key == pygame.K_UP:
player_speed -= 7
elif event.type == pygame.KEYUP:
print(f"Key {pygame.key.name(event.key)} released")
if event.key == pygame.K_DOWN:
player_speed -= 7
if event.key == pygame.K_UP:
player_speed += 7
screen.fill(pygame.Color("grey"))
pygame.display.update()
pygame.display.set_caption(f"Player Speed {player_speed}")
clock.tick(60) # limit to 60 FPS
pygame.quit()
This produces the following:
I've expanded your debug print statements to provide more context and added an update to the title bar to display the current value of the player_speed variable.
Related
I'm currently trying to build a game through vscode using pygame lib.
My code to move character around with keyboard arrow keys won't apply to my module.
My module won't close even though I click exit button or esc.
Any thoughts why its not working?
import pygame
import os
pygame.init()
screen_width = 480
screen_height = 640
screen = pygame.display.set_mode((screen_width,screen_height))
pygame.display.set_caption("June's Game")
background = pygame.image.load("D:/Python/pygame_basic/background.png")
character = pygame.image.load("D:/Python/pygame_basic/character.png")
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_position = (screen_width / 2) - (character_width / 2)
character_y_position = screen_height - character_height
to_x = 0
to_y = 0
running = True #게임이 진행중인가
while running:
for event in pygame.event.get():
if event == pygame.QUIT:
running = False
if event == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
to_x -= 5
elif event.key == pygame.K_RIGHT:
to_x += 5
elif event.key == pygame.K_UP:
to_y -= 5
elif event.key == pygame.K_DOWN:
to_y += 5
if event == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
to_x = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
to_y = 0
character_x_position += to_x
character_y_position += to_y
#screen.fill((0,0,255))
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
pygame.quit()
i coudln't get it to work
event is an object. You have to get the type of the event, e.g.:
if event == pygame.KEYDOWN
if event.type == pygame.KEYDOWN:
You have to limit the frames per second to limit CPU usage with pygame.time.Clock.tick and to control the speed of the game. Otherwise, the player moves much too fast and immediately disappears from the screen. The method tick() of a pygame.time.Clock object, delays the game in that way, that every iteration of the loop consumes the same period of time.
clock = pygame.time.Clock()
running = True
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
to_x -= 5
elif event.key == pygame.K_RIGHT:
to_x += 5
elif event.key == pygame.K_UP:
to_y -= 5
elif event.key == pygame.K_DOWN:
to_y += 5
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
to_x = 0
elif event.key == pygame.K_UP or event.key == pygame.K_DOWN:
to_y = 0
character_x_position += to_x
character_y_position += to_y
#screen.fill((0,0,255))
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
However, there is a better method to move an object when a key is held down (See How can I make a sprite move when key is held down):
to_x = 0
to_y = 0
speed = 5
clock = pygame.time.Clock()
running = True
while running:
clock.tick(100)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
keys = pygame.key.get_pressed()
to_x = (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
to_y = (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed
character_x_position += to_x
character_y_position += to_y
screen.blit(background, (0,0))
screen.blit(character, (character_x_position,character_y_position))
pygame.display.update()
This question already has answers here:
How can I move the ball instead of leaving a trail all over the screen in pygame?
(1 answer)
How can I make a sprite move when key is held down
(6 answers)
Closed 4 months ago.
So i programmed a block which should move in pygame
But when i press any of the movement buttons it doesnt move the block it just duplicates it and moves it and the old square doesnt do anything
Yeah im probably really retarded and the answer is really obviousä
here is the script:
import pygame
from sys import exit
pygame.init()
width=800
height=800
screen = pygame.display.set_mode((width,height))
posy=500
posx=500
clock = pygame.time.Clock()
pygame.display.set_caption("Block")
while True:
for event in pygame.event.get():
pygame.draw.rect(screen, "red", pygame.Rect(posy, posx, 60, 60))
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
posx=posx-10
elif event.key == pygame.K_s:
posx=posx+10
elif event.key == pygame.K_a:
posy=posy-10
elif event.key == pygame.K_d:
posy=posy+10
if event.key == pygame.K_ESCAPE:
pygame.event.post(pygame.event.Event(exit()))
pygame.display.update()
clock.tick(60)
It looks like you're creating a new object every time, so you need to adjust your code like this:
rect = pygame.Rect(posy, posx, 60, 60)
for event in pygame.event.get():
pygame.draw.rect(screen, "red", rect)
if event.type == pygame.QUIT:
pygame.quit()
exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
rect.move_ip(0, -10)
elif event.key == pygame.K_s:
rect.move_ip(0, 10)
elif event.key == pygame.K_a:
rect.move_ip(-10, 0)
elif event.key == pygame.K_d:
rect.move_ip(10, 0)
import pygame
#Imports all modules
import time
pygame.init()
exitp = False
x = 240
y = 240
#Controls
def controls():
for event in pygame.event.get():
if event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
y -= 10
if event.type == pygame.KEYDOWN and event.key == pygame.K_DOWN:
y += 10
if event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT:
x -= 10
if event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
x += 10
while not exitp:
controls()
bg = pygame.display.set_mode((500,500))
color = (128,255,0)
pygame.draw.rect(bg, color, pygame.Rect(x,y,50,50))
pygame.display.flip()
I think the error was due to the function, but IDK because of a pygame import error.
Please help me make the controls thing into a loop.
I am trying to get user keyboard input using pygame. However, the problem is that after I run my code on IDLE, the keyboard input is never read by the program, and whatever I type is shown on the shell. Same issue if I run my code on PyCharm. Any idea? Below is my code:
pygame.init()
screen = pygame.display.set_mode((800, 600))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == KEYDOWN and event.key == pygame.K_w:
print("Yup!")
pygame.display.flip()
I'm having the exact same issue, also on a Mac using Pycharm and python 3.6. I'm printing the events and only MouseMotion events are recorded, rather than KeyDown.
Edit: apparently it's a known issue: Window does not get focus on OS X with Python 3
This is my code, and it also should work:
while not crashed:
for event in pygame.event.get():
print(event)
if event.type == pygame.QUIT:
crashed = True
# get current list
pressed = pygame.key.get_pressed()
if pressed[pygame.K_UP]:
print("UP")
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_1:
print('this DOES work! :)')
elif event.key == pygame.K_LEFT:
x_change = -5
elif event.key == pygame.K_RIGHT:
x_change = 5
elif pressed[pygame.K_UP]:
print("UP")
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
x_change = 0
pygame.display.flip()
x += x_change
gameDisplay.fill(black)
ship(x, y)
pygame.display.update()
clock.tick(60)
This code works perfectly for me
import pygame
pygame.init()
windowSize = width,height = 800,600
screen = pygame.display.set_mode(windowSize)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
quit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
print("Yup!")
pygame.display.flip()
I'm making a simple top-down game with moving and collision between player and walls, using pygame.
I made my code so that when keys[pygame.K_LSHIFT] is True during the pygame.key.get_pressed at the state of the keyboard when it's called, block_speed changes to 5 instead of 3. So it works and when I hold SHIFT and move with WASD keys at the same time my speed becomes 5.
Now, the problem is when I let go of SHIFT while still moving, my speed doesn't change back to 3 but stays at 5. But if I stop moving, then move, block_speed changes back to 3 as expected. It seems as if any change to block_speed only happens when I stop moving then move again.
I'm guessing it only receives the new value of block_speed after the current copy of block_speed is done being used.
How do I change block_speed with SHIFT while this variable is being used by the program?
def run(self):
pygame.init()
pygame.display.set_caption("Platformer v1")
block_speed = 3
sprite_list = pygame.sprite.Group()
wall_list = pygame.sprite.Group()
left_wall = Wall(0,0,10,resolution[1])
wall_list.add(left_wall)
sprite_list.add(left_wall)
top_wall = Wall(10,0,resolution[0]-10,10)
wall_list.add(top_wall)
sprite_list.add(top_wall)
test_wall = Wall(10,150,200,10)
wall_list.add(test_wall)
sprite_list.add(test_wall)
player = Player(50,50)
player.walls = wall_list
sprite_list.add(player)
while True:
self.screen.fill(black)
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if keys[pygame.K_LSHIFT]:
block_speed = 5
else:
block_speed = 3
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
player.change_x += block_speed
elif event.key == pygame.K_a:
player.change_x += -block_speed
elif event.key == pygame.K_w:
player.change_y += -block_speed
elif event.key == pygame.K_s:
player.change_y += block_speed
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d or event.key == pygame.K_a:
player.change_x = 0
elif event.key == pygame.K_w or event.key == pygame.K_s:
player.change_y = 0
sprite_list.update()
sprite_list.draw(self.screen)
pygame.display.update()
self.clock.tick(FPS)
Your issue is that when you add block speed to player.change_x/change_y, it performs that calculation at that time. Changing the variable afterwards won't make a difference.
A simple solution for your case is to simply make the change to block_speed happen before you use it. If you do this, block_speed has the value you want when it comes to changing the other variables, giving you the result you want.
Edit: I realise there is another issue - that is, you only change the movement speed if the key is newly pressed (the event is fired), so changing block speed still won't change the speed unless a direction key is pressed. The solution is to do your calculation every time, regardless.
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if keys[pygame.K_LSHIFT]:
block_speed = 5
else:
block_speed = 3
if keys[pygame.K_d]:
player.change_x += block_speed
if keys[pygame.K_a]:
player.change_x += -block_speed
if keys[pygame.K_w]:
player.change_y += -block_speed
if keys[pygame.K_s]:
player.change_y += block_speed
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d or event.key == pygame.K_a:
player.change_x = 0
elif event.key == pygame.K_w or event.key == pygame.K_s:
player.change_y = 0
An alternative would be to store the direction when a key is pressed, then multiply this up by the speed at the time you do the movement each frame:
keys = pygame.key.get_pressed()
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if keys[pygame.K_LSHIFT]:
player.block_speed = 5
else:
player.block_speed = 3
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
player.change_x += 1
elif event.key == pygame.K_a:
player.change_x -= 1
elif event.key == pygame.K_w:
player.change_y -= 1
elif event.key == pygame.K_s:
player.change_y += 1
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d or event.key == pygame.K_a:
player.change_x = 0
elif event.key == pygame.K_w or event.key == pygame.K_s:
player.change_y = 0
And then in your position code, do self.rect.x += self.change_x * self.block_speed instead. This is probably a preferable solution.
I've had the same issue and tried using the code from the suggested answer but found it did not work for me. My sprite still moved at the base speed until a key was lifted.
Looking at this thread, I tried moving the get_pressed() key detection outside of the event loop, which fixed things.
keys = pygame.key.get_pressed()
if keys[pygame.K_LSHIFT]:
player.block_speed = 5
else:
player.block_speed = 3
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_d:
player.change_x += 1
#etc.
elif event.type == pygame.KEYUP:
if event.key == pygame.K_d or event.key == pygame.K_a:
player.change_x = 0
#etc.
As in the above answer, in your position code have self.rect.x += self.change_x * self.block_speed.
This allowed me to get a speed boost effect when a certain key was held down and revert back to the base speed when it was not.
import pygame
running = True
while running:
for event in pygame.event.get():
#K_UP mean releasing the key
if event.type == pygame.K_UP:
if event.key == pygame.K_LSHIFT:
block_speed = 3