Relative newbie to Python here. My program at this point is waiting for the user to press enter so it can get back to the main loop. Is something wrong with the following code? (Ignore the print statements, I am using them for debugging.)
def checkReturnKeyPress():
print ('check return key function started')
while True: # loop until user presses return key
print ('check return key 2nd loop')
for event in pygame.event.get(): # event handling loop
print ('keydown for loop')
if event.type == KEYDOWN:
print ('keydown')
if event.key == K_RETURN:
print ('return')
return
Sorry again for how messy this is, I'll clean it up once it's working. I have a feeling the part that's wrong is the "for event in pygame" part, if that helps.
You need a break in there somewhere. I'm guessing the K_RETURN is where you are looking for the return key to be pressed. If so you should add a break after the print('return') so that you will break out of your infinite loop.
Related
I am thirteen years old, and I am learning to code. I think that I am doing quite well, however, I have hit a massive roadblock.
I am trying to program some sort of advanced Etch a sketch game, and with the general coding, I can do it.
like:
if the player says 'forward' + number:
go forward by that number.
that all works and it can draw shapes and everything, and rub out and change color even.
But what I am trying to do, is make my program respond to going forward when the button 'w' 'a' 's' or 'd' buttons are pressed, then without clicking enter, have it immediately have a turtle move by 40 pixels up, down, left or right.
I am using a platform called Trinket.io and so far it is proving very useful to code on. but whenever I find a website that says, 'this should work!' it doesn't. or it is only a snippet of code, or whatever the problem is, the program won't respond when I click w a s or d.
On Trinket.io, when you open up a pygame trinket it gives you two example games that both work on w a s d movement. I have tried to take some code form that, and modify it so it will print some text 'you clicked a' or 'you clicked w'. This hasn't worked either.
By the way, all of this testing has been done on a completely different trinket so various bits of code in the Etch a sketch prodject can't be the problem.
from time import *
import pygame
pygame.init()
UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'
while True: # main game loop
for event in pygame.event.get(): # event handling loop
if event.type == K_DOWN:
print('key down')
elif event.key == K_UP:
print('key up')
this piece of code is as close as I think I have gotten so far to my goal as it produces no error messages, it just doesn't work or do anything.
Try putting your event handling loop in a different thread so it can run with your game:
from time import *
import pygame
import _thread
pygame.init()
UP = 'up'
DOWN = 'down'
LEFT = 'left'
RIGHT = 'right'
def controller():
while True: # main game loop
for event in pygame.event.get(): # event handling loop
if event.type == K_DOWN:
print('key down')
elif event.key == K_UP:
print('key up')
_thread.start_new_thread(controller)
Your controller should be running parallel with your game, This means that the rest of your game will also have to be put into it's own thread
.
See this for more info on threading: https://www.tutorialspoint.com/python3/python_multithreading.htm
I'm trying to make an input box.
So we can type something in it.
The first problem I get was when we try to keep a key held for a while, it is repeated only once.
Now this was resolved with the help of the answers done on this link : Pygame key hold down?
However, the problem encountered now, is that when we try to press a key only once, sometimes it is repeated more than once (twice or more commonly).
The pseudo-code looks like this:
for event in pygame.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
self.quit_screen = True
# events related to the input box
if event.type == pygame.MOUSEBUTTONDOWN:
#Things related to it
#Disactivate the typing on the input box if KEYUP activated
if event.type == pygame.KEYUP:
self.typing = False
self.backspace_pressed = False
if event.type == pygame.KEYDOWN:
print("KEYDOWN\n")
if self.user_input_box.input_box_active:
# If we press 'enter', we save
if event.key == pygame.K_RETURN:
#save the text in some variables
# If we press the key '\b' (backspace), we delete a caracter
elif event.key == pygame.K_BACKSPACE:
self.backspace_pressed = True
else: #Get the current letter
self.typing = True
self.cur_letter = event.unicode
if self.typing: #Adding the letter saved in cur_letter to the current text(user_entry)
self.user_input.user_entry += self.cur_letter
if self.backspace_pressed:
self.user_input.user_entry = self.user_input.user_entry[:-1]
You could make a delay to differentiate between pressing once and holding down. You can define some variables like this:
self.press_timer = 0
self.already_pressed = False
and then, in the key code you can continue to add on this number until it reaches a certain threshold. So...
if event.type == pygame.KEYDOWN:
self.press_timer += 1
if press_timer < 50 and not self.already_pressed:
# Typing code
self.already_pressed = True
elif press_timer > 50 and self.already_pressed:
# Same code, but without setting already_pressed to True
Then, in the pygame.KEYUP code...
if event.type == pygame.KEYUP:
self.typing = False
self.backspace_pressed = False
self.press_timer = 0
self.already_pressed = False
This should allow the leeway to press one key, and then after holding it for a set amount of time, allow the letters to be added endlessly.
If you want to get key repeats what you are doing is not really the right way to go about it. It is preferable to have the system send you multiple events when it has sensed that a key has been held down. You can get the system to send you repeated KEYDOWN events for a held down key by setting this before you start the event checking loop:
pygame.key.set_repeat(delay, interval)
You can see more here in the docs
It is turned off by default so you have to enable it.
With respect your current code and why it is repeating when you do nor want it to, you are running the lines:
if self.typing: #Adding the letter saved in cur_letter to the current text(user_entry)
self.user_input.user_entry += self.cur_letter
every pass through the event loop, which means that anything event will cause you to execute it. There may events that come through that you may not be expecting. Some like mouse movement events but also other behind the scenes ones you may not realize can occur. You can see what those events are by adding this line at the top of your loop for debugging:
print(f"event: {pygame.event.event_name(event.type)}")
So I have this code that looks after the user inputs for a pac-man style game.
def receiving_inputs(self):
while True:
events = pg.event.get()
for event in events:
if event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
self.move = 'n'
elif event.key == pg.K_RIGHT:
self.move = 'e'
elif event.key == pg.K_DOWN:
self.move = 's'
elif event.key == pg.K_LEFT:
self.move = 'w'
time.sleep(1/60)
threading.Thread(target=self.receiving_inputs).start()
When I press any keys on my keyboard I do not get any events, however, moving the mouse around will return an event using this code.
The annoying thing is that this exact code works perfectly when not in a thread. i.e when in the program's main loop.
Just fyi I want to use a thread here to minimize the number of times pygame doesn't register a key press (which I'm assuming is due to other things in the mainloop).
Thanks in advance.
You don't get any events at all, because you have to get the events in the main thread.
See the documentation of pygame.event:
[...] The event subsystem should be called from the main thread.
It is only possible to post events from other thread, but the event queue has to be handled in the main thread.
How do you reset a while True loop. For example this is my code:
x=True
while x==True:
print ("Random Text")
randomtext= input()
if randomtext == "yes":
print ("hi")
x=False
elif randomtext == "no":
print("This is supposed to reset the loop")
#resets loop and prints Random Text again
print ("hi")
if x==True:
print ("placeholder text")
input()
I want it to reset the loop if "randomtext" is equal to yes. I want to reset it it in the middle of the loop. This is a very simple question but this is getting in my programming. Thank you.
I'm assuming that by resetting the loop you mean jumping code until reaching the start of the loop again. This is done with the "continue" keyword.
if randomtext == "yes":
continue
If you actually meant breaking out of the loop, you should instead use the "break" keyword.
So I have this code that looks after the user inputs for a pac-man style game.
def receiving_inputs(self):
while True:
events = pg.event.get()
for event in events:
if event.type == pg.KEYDOWN:
if event.key == pg.K_UP:
self.move = 'n'
elif event.key == pg.K_RIGHT:
self.move = 'e'
elif event.key == pg.K_DOWN:
self.move = 's'
elif event.key == pg.K_LEFT:
self.move = 'w'
time.sleep(1/60)
threading.Thread(target=self.receiving_inputs).start()
When I press any keys on my keyboard I do not get any events, however, moving the mouse around will return an event using this code.
The annoying thing is that this exact code works perfectly when not in a thread. i.e when in the program's main loop.
Just fyi I want to use a thread here to minimize the number of times pygame doesn't register a key press (which I'm assuming is due to other things in the mainloop).
Thanks in advance.
You don't get any events at all, because you have to get the events in the main thread.
See the documentation of pygame.event:
[...] The event subsystem should be called from the main thread.
It is only possible to post events from other thread, but the event queue has to be handled in the main thread.