How to determine if a key is pressed in python using pygame - python

Is there a really simple way of knowing if the key SPACE is currently DOWN. I'm making a basic snake game and I don't know to use pygame and I can't find it anywhere.
I imagine it like something along these lines:
if K_SPACE = DOWN:
turtle.turn(90)
thank you for any help

In your game loop:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_SPACE:
turtle.turn(90)

Related

How Do I Play An Audio Whenever I Click On a Specific Key On The Keyboard?

So, my idea is to create a program (using the "Keyboard" module) that, while I am pressing on a key ("Enter", in this case), a sound is played (only once), as soon as I stop pressing that key, another sound would be played (only once).
In other words, NASA uses a communications system in which, when a "call" starts, a "beeeep" is played, when the "call" is ended (like an "Over") a "beeeeep" is played again.
This was my first attempt:
import keyboard
import pygame
def BeepOn():
pygame.mixer.init()
pygame.mixer.music.load("Mic On.mp3")
pygame.mixer.music.play(loops=0)
pygame.mixer.music.set_volume(0.50)
def BeepOff():
pygame.mixer.init()
pygame.mixer.music.load("Mic Off.mp3")
pygame.mixer.music.play(loops=0)
pygame.mixer.music.set_volume(0.50)
while True:
if keyboard.on_press_key('Enter'):
BeepOn()
if keyboard.on_release_key('Enter'):
BeepOff()
if keyboard.is_pressed('End'):
exit()
Attention:
I would like you to just have to click on one key instead of two.
I hope I explained it well!
I look forward to an answer (however stupid it may be).
Regards,
Diogo Matos
Here:
import pygame
#Condition for while loop
running = True
def BeepOn():
pygame.mixer.init()
pygame.mixer.music.load("Mic On.mp3")
pygame.mixer.music.play(loops=0)
pygame.mixer.music.set_volume(0.50)
def BeepOff():
pygame.mixer.init()
pygame.mixer.music.load("Mic Off.mp3")
pygame.mixer.music.play(loops=0)
pygame.mixer.music.set_volume(0.50)
while running:
for event in pygame.event.get():
#Tests for quit
if event.type == pygame.QUIT:
running = False
#Tests if enter is pressed
if event.type = pygame.KEYDOWN:
if Event.key == pygame.K_RETURN:
BeepOn()
#Tests if enter is released
if event.type = pygame.KEYUP:
if Event.key == pygame.K_RETURN:
BeepOff()
pygame.quit()
I hope this helps, I'm not familiar with the keyboard module, so I just did it all from pygame. (:
If this helps please let me know...

Keydown function not working

I have just downloaded pygame 1.9.2 for python 3.3 and the keydown function is not working. The IDLE shell keeps telling me the same error:
NameError: name 'KEYDOWN' is not defined
How do I solve this problem? I am kinda new to programming so could you please explain this to me.
NOTE: Sorry for deleting my previous answer but Stack Overflow just randomly posted my answer before I was done.
Well, there could be several things wrong. You could be using pygame.key.keydown(), which is wrong, and you should be using pygame.key.get_pressed().
But what I suspect is wrong with your code is that you're not using pygame.KEYDOWN properly.
If you're trying to do something while a key is being held down, use pygame.key.get_pressed(), and do something like this:
key = pygame.key.get_pressed()
if key[pygame.K_WHATEVER_KEY_YOU_WANT]:
# do code
and just repeat that for every key you want to check.
If you're just trying to check if a key is being pressed, use pygame.KEYDOWN with an if statement, then check if the key you want is being pressed in a nested if statement under the first if statement. Like so:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_WHATEVER_KEY_YOU_WANT:
#do code
I'm assuming you have an event variable your using to iterate over pygame.event.get() function that 'gets' events. If not then here is the code above in a game/window loop:
running = True # variable to control while loop
while running: # while the variable running is equal to true
for event in pygame.event.get(): # use the variable 'event' to iterate over user events
if event.type == pygame.QUIT: # test if the user is trying to close the window
running = False # break the loop if the user is trying to close the window
pygame.quit() # de-initialize pygame module
quit() # quit() the IDE shell
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_WHATEVER_KEY_YOU_WANT:
#do code
This is basically how you use pygame.KEYDOWN. It's probably not the only way however. I recommend (since you're new to programming) to read the pygame docs on their official website for more info about checking key input in pygame. And read some of the answers to this question.

Nested if-statements, clean code, and being Pythonic, with controller/keyboard input

First the background: I use Python and PyGame. I've experimented with writing my own input/controller module, that allows users to remap controls in any way they like. This necessarily requires that my code be written to handle different types of input (for example, keyboard keys, controller buttons, and controller axes/hats/etc.)
For example, if the button "Right" is mapped to an arrow key, the code to handle GetPush("Right") or GetRelease("Right") would be somewhat different than if it were mapped to a control stick being pushed along a certain axis. To help take care of this, I made a helper function __GetButtonType() which -- as the name replies -- returns what type of button it is. For the code shown here, buttons are referred to as strings. The first letter of the string denotes the button type, and the rest denotes the button. For example k97 refers to the keyboard key with a value of 97. (the A key.)
Now for the issue at hand. My code does what I want it to do. But as I began cleaning it up, I came across one part that bothered me. I have the following segment of code which handles presses from the keyboard. (The DoSomething() functions replace entirely unrelated code, that I assume does not matter for the question at hand.)
for n in TheController.ControlMap:
if __GetButtonType(n)=="key":
if event.type == KEYUP:
if event.key == int(n[1:]): DoSomething()
if event.type == KEYDOWN:
if event.key == int(n[1:]): DoSomethingElse()
Something about this just looks a little off to me. It may be that the if event.key == int(n[1:]) condition is repeated. That seems wasteful. However, if event.key is not KEYUP or KEYDOWN, then the event will not have a key attribute (that is how pyGame works, that isn't of my design.) This means that the condition if (event.type == KEYDOWN and event.key == int(n[1:]) will throw an error whenever the event.type is something else.
However, I thought about it a bit, and realized that I CAN shorten the code by one line by structuring it in the following way:
for n in TheController.ControlMap:
if event.type == KEYUP:
if __GetButtonType(n)=="key" and event.key == int(n[1:]): DoSomething()
if event.type == KEYDOWN:
if __GetButtonType(n)=="key" and event.key == int(n[1:]): DoSomethingElse()
Both code snippets work. Both do the same thing. The first one looks a bit easier to read, but not by a whole lot. The second one uses fewer lines. My question is this:
Which style is "better"? Does one perform faster than the other one would by a non-negligible amount? Or is one just considered "poor practice?" Maybe they both are, in fact. I am still relatively new to programming.
Thank you,
Chris
Both of your statements have one same feature which would make people cringe. Equivalent if statements are repeated twice. This is no good because it clatters your code and is absolutely unnecessary:
if event.type in [KEYUP, KEYDOWN] and __GetButtonType(n)=="key" and event.key == int(n[1:]):
if event.type == KEYUP:
DoSomething()
elif event.type == KEYDOWN:
DoSomethingElse()
Here the first condition makes sure that you don't get an error on event.key.
Also use elif because the options are mutually exclusive. Simple else will also suffice, but I'd leave elif for the purpose of readability. Also you can hide this into DoSomething(event.type).
Another option which could look ugly or pretty depending on who you ask is collapse it all into a flat if-else:
if event.type in [KEYUP, KEYDOWN] and __GetButtonType(n)=="key" and event.key == int(n[1:]):
(DoSomething if event.type == KEYUP else DoSomethingElse)()
But that's getting a bit weird... Still, it works.
Performance-wise, there is absolutely nothing to worry about here. Optimization is a whole other topic and the first thing to optimize would be program design / algorithm rather than local low-importance commands.
on the lines of what 'sashkello' mentioned, I generally have the below block of code common in my pygame programs.
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN and event.key == pygame.K_LEFT :
do_something()
elif event.type == pygame.KEYDOWN and event.key == pygame.K_RIGHT:
do_something_else()

How to delay pygame.key.get_pressed()?

I haven't been able to find a straightforward answer.
key.set_repeat() works for KEYDOWN events, but not for key.get_pressed():
import sys, pygame
from pygame.locals import *
pygame.init()
Clock = pygame.time.Clock()
pygame.display.set_mode((200, 100))
pygame.key.set_repeat(1, 500)
while True:
if pygame.key.get_pressed()[K_UP]:
print('up!')
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_DOWN:
print('down!')
Clock.tick(30)
Even the slightest tap on UP explodes into at least a few up!s, only down!s are delayed. I want to use key.get_pressed() since it conveniently handles multiple inputs. Do I have to work around it with some sorta tick counter? Alternatively, is there a way to handle multiple KEYDOWN events?
Just don't mess around with key.set_repeat() if you don't have to.
Simply use key.get_pressed() to check for keys that are pressed and where keeping that key pressed down has a meaning to you, e.g. something like move left while K_LEFT is pressed.
Use event.get() / KEYDOWN when you're interessed in a single key press, e.g. something like pressing K_P pauses the game.
If you mess around with key.set_repeat(), e.g. set the delay to low, you won't be able to recognize a single key stroke, since every key stroke will create multiple KEYDOWN events.
To handle multiple KEYDOWN events, just check for the relevant events. Every key stroke will generate a KEYDOWN event, so you can simple check e.g.:
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_DOWN:
print('down!')
elif event.key == K_UP:
print('up!')
That will of course print up!/down! multiple times if the user keeps pressing the keys.
The golden rule is: If you're interessted in the KEYDOWN and the KEYUP event of a single key, better use key.get_pressed() instead.
Even the slightest tap on UP explodes into at least a few up!s, only down!s are delayed
That's because the event system and key.get_pressed() are totally different. If you get pressing K_UP over multiple frames, for each frame 'up!' is printed because the key is pressed down in every frame. key.get_pressed() simple returns which keys are pressed at the moment you call this function. In other words: you can't "delay" it.

Why is this tiny pygame program freezing and doing nothing?

This program infinite loops. Does nothing. Won't take input or print anything. Ideas?
import pygame
pygame.init()
running = 1
while(running):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
print "hi"
running = 0
The problem with your script is solely that there's no window that could capture the events.
You have to create and initialize a window with pygame.display.set_mode first.
import pygame
pygame.init()
# create a window that will capture the events
pygame.display.set_mode((200, 200))
running = 1
while(running):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
print "hi"
running = 0
Try the following:
import pygame, sys
pygame.init()
pygame.mixer.init(22050, -16, 2, 3072)
pygame.mixer.music.load("Kundara_Lake-of-Dust-320.mp3")
pygame.mixer.music.play(1, 0.0)
running = 1
while(running):
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
pygame.mixer.music.stop()
pygame.quit()
running = 0
From http://www.pygame.org/docs/ref/pygame.html
pygame.quit
Uninitialize all pygame modules that have previously been initialized. When the Python interpreter shuts down, this method is called regardless, so your program should not need it, except when it wants to terminate its pygame resources and continue. It is safe to call this function more than once: repeated calls have no effect.
Note, that pygame.quit will not exit your program. Consider letting your program end in the same way a normal python program will end.
You are looping infinitely calling pygame.quit() due to while(1).
You need to update the screen. Try it with
screen = pygame.display.set_mode((640,360),0,32)
and in the loop, write
pygame.dispay.flip()
to close the window completely, you can use
sys.exit()
just be sure to include sys in your imports
pygame does not recognize the term 'input' or 'print'. It would be a lot simpler if it did!! Instead, to get text onto the screen, you must use 'drawText('message',font,surface,(xpos,ypos) putting your own text in 'message', your own surface name in 'surface' and the x and y co-ordinates in 'xpos' and 'ypos'.

Categories