Getting dict value from for loop in Python - python-3.x

tl;dr:
I have a Scene class and scene01 and scene02, both instances of Scene. scene01 have a button.
This button is inside a dictionary named buttons, e.g. {button_next : scene02}
The for loop goes like this:
def loop(self): #SCENE LOOP
while True:
for event in pg.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pg.quit()
sys.exit()
for k, v in self.buttons.items():
if 'click' in k.handleEvent(event):
self.goto(v)
pg.display.update()
'click' in k.handleEvent(event) is from the PygButton widget. It return when there is a mouse click over the button. Button being an instance of the PygButton() class.
goto() checks if the value from the key-value pair is 'quit' (calling the app to quit) or an instance of Scene, e.g. scene01, calling the scene loop, drawing the new screen and new buttons.
The app starts, the first scene is there as is its buttons, but there is no response from a click on them. Escape quits the app so the loop is working. And exiting the app through the escape doesn't return anything from the IDLE.
I think the problem is on the goto() method and/or how I'm calling the value from the dictionary, but I'm stuck.
Help?

Your indentation seems off. Are you sure you want the second for loop to run only if the user quits because that is how you have set it up. Try this instead:
def loop(self): #SCENE LOOP
while True:
for event in pg.event.get():
if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE):
pg.quit()
sys.exit()
for k, v in self.buttons.items():
if 'click' in k.handleEvent(event):
self.goto(v)
pg.display.update()

Related

Pygame- Keys held down : some caracters are written more than once when pressing a key

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)}")

Client networking with Pygame [duplicate]

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.

pygame: pygame.KEYDOWN not working

import pygame
pygame.init()
events = pygame.event.get()
while True:
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_1:
print('this should work!!')
I am new to both python and pygame , just trying to test the keydown event but it doesn't works....please help!
You need to set up some display properties before you can use keyboard events. No window, no key events. So add something like this before the while loop and it should work:
WIDTH=600
HEIGHT=480
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
Normally, you'd also set up a clock using clock = pygame.time.Clock(), frames per second used in clock.tick(frames_per_second), some objects/players/rects etc. before the loop but I'll leave that to you.
Here's your code with a bare minimum display setup that'll enable key events:
import pygame
pygame.init()
WIDTH=600
HEIGHT=480
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
while True:
events = pygame.event.get()
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_1:
print('this DOES work! :)')
Because Pygame only runs on Python v3.2 and below I can't test this right now.
But if i'm not totally off my meds I think this is because you're not updating the display.
Consider this change:
import pygame
pygame.init()
events = pygame.event.get()
while True:
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_1:
print('this should work!!')
pygame.display.flip()
This will update the display AND trigger the events occuring in the display.
If you don't do this you'll end up with a stale window that doesn't trigger, render or produce anything really except maybe a initial render.
Equally, in many GL libraries you need to empty the event buffer otherwise the same effect will occur. Meaning you'll end up with a stale window that just "hangs" because events are trying to "get in" to the buffer, but you havn't emptied it on a regular basis. (Some graphic libraries even require you to poll the event pool even if it's empty just to "release" the event queue).
So keep in mind when working with graphics:
Always call the event buffer (even if it's empty)
Always flip/update your scene, or your application goes stale

how to fullscreen my game using pygame in Python 3.3?

In Python2.7 I could use pygame.display.set_mode((x,y),FULLSCREEN,32) to fullscreen my game.
But in Python 3.3 the FULLSCREEN is not defined in pygame and I couldn't find the right number to achieve it.
Also,I could not find the right way to use pygame.event.set_blocked().
You have to use pygame.FULLSCREEN instead of just FULLSCREEN.
screen = pygame.display.set_mode([0,0], pygame.FULLSCREEN)
About the set_blocked case, basically you will be blocking an event from happening. For example, just to illustrate I can ask user before game loop if he/she wants to use mouse or keyboard.
value = input("mouse or keyboard: ")
if value == "m":
pygame.event.set_blocked(pygame.KEYDOWN)
else:
pygame.event.set_blocked(pygame.MOUSEBUTTONDOWN)
And in event loop, pygame will ignore the blocked component.
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
player.jump(current_level.wall_list)
if event.type == pygame.MOUSEBUTTONDOWN:
player.jump(current_level.wall_list)

Python sqlite3 - sqlite objects created in a thread can only be used in that same thread [duplicate]

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.

Resources