Pygame Overlays - python

Okay, so I want to make an overlay screen.
So whenever the keypress is p then the screen pauses and a screen pops up saying
: "Press 'q' to quit or 'c' to continue,"
something like that.
Can anyone tell me how?

The easiest way to do this is using a submodule, then to create a new loop for blit()-ing to the screen and event handling for this pause menu.
(This is methodology only; this is how I work my projects.)
Update: 13/12/11
The following excerpt of code is from the "parent" module. This is just the loop section of code. What you're looking for is the line button.doAction(screen), which basically tells PyGame to execute the applicable submodule (not important; you just need to call the "child" function as you would normally).
while mainRunning:
# --- Event Catching & Handling ---
for event in pygame.event.get():
# Quit PyGame safely upon exit
if event.type == pygame.QUIT:
mainRunning = False
# Make the buttons do actions
if event.type == pygame.MOUSEBUTTONUP:
mousePos = pygame.mouse.get_pos()
for button in menuList:
X = button.getXPos()
Y = button.getYPos()
if X[0] < mousePos[0] < X[1] and Y[0] < mousePos[1] < Y [1]:
button.doAction(screen)
pygame.display.flip()
pygame.quit()
So if we say that the function we wanted was playGame.levelChoose() - remember, this is [submodule].[function] - then the loop in the "child" would be:
def levelChoose(screen, playerData, playerName):
levelChooseRunning = True
while levelChooseRunning:
# --- Event Catching & Handling ---
for event in pygame.event.get():
# Quit PyGame safely upon exit
if event.type == pygame.QUIT:
levelMenuRunning = False
pygame.display.flip()
(Of course, much code has been ommitted from these examples; if you'd like to pick apart the full files, they're over here on GitHub)
Let me know if there's more questions, because this probably just confused you some more...

Related

Pygame action when no joystick event

So i'm building an application that controls a mini drone and to control the drone i use DragonRise Inc. PC TWIN SHOCK Gamepad USB joystick in Pygame. What i want it to do, is go through a while loop every 70ms and check if there is a Pygame joystick event. If so than execute some code. If not, then execute some other piece of code.
What I've read online is that is done by checking if the length of the pygame.event.get() list is greater than 0. If so, there is motion, if not (else) no motion. But unfortunately this doesn't work well.
The situation is when i push the joystick axis up, it executes not only the block of code associated with pygame.JOYAXISMOTION event but also the else block of code.
Anyone know how to fix this, or have a better solution ?
import time
import pygame
done = False
deadzone = 0.1
pygame.init()
pygame.joystick.init()
joystick = pygame.joystick.Joystick(0)
joystick.init()
while not done:
events = pygame.event.get()
if len(events) > 0:
for event in events:
if event.type == pygame.JOYAXISMOTION:
if joystick.get_axis(1) < -1 * deadzone:
print('Throttle Up')
if joystick.get_axis(1) > deadzone:
print('Throttle Down')
else:
print('No Event')
time.sleep(0.07)
You don't have to evaluate the JOYAXISMOTION at all. pygame.joystick.Joystick.get_axis gets the current position of an axis. Just evaluate the position with a 70ms interval. Use pygame.time.Clock.tick instead of time.sleep:
clock = pygame.time.Clock()
while not done:
clock.tick(70)
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
axis_pos = joystick.get_axis(1)
if axis_pos < -1 * deadzone:
print('Throttle Up')
elif axis_pos > deadzone:
print('Throttle Down')
else:
print('No Event')

pygame.mouse.get_pressed() not responding

the code is as follows
import pygame
pygame.init()
info = pygame.display.Info()
win = pygame.display.set_mode(((info.current_h//10)*10,(info.current_w//10)*10))
running = True
while running:
if pygame.mouse.get_pressed() == (1,0,0):
Mouse = pygame.mouse.get_pos()
X = (Mouse[0]//10)*10
Y = (Mouse[1]//10)*10
print(X)
print(Y)
pygame.draw.rect(win,(255,255,255),(X,Y,10,10))
pygame.display.update()
the Problem is the pygame window itself does not respond when i run the program and click it does not even print X or Y
i tried adding some delay thinking maybe pygame does not like how fast it is
You have to implement an event loop and to get the events messages with pygame.event.get(). At least you have to invoke pygame.event.pump():
For each frame of your game, you will need to make some sort of call to the event queue. This ensures your program can internally interact with the rest of the operating system. If you are not using other event functions in your game, you should call pygame.event.pump() to allow pygame to handle internal actions.
Since pygame.mouse.get_pressed() returns a sequence of booleans you have to use subscription to evaluate the state of a button:
buttons = pygame.mouse.get_pressed()
if buttons[0]:
# [...]
I recommend to add an event loop to the application:
import pygame
pygame.init()
info = pygame.display.Info()
win = pygame.display.set_mode(((info.current_h//10)*10,(info.current_w//10)*10))
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
buttons = pygame.mouse.get_pressed()
if buttons[0]:
Mouse = pygame.mouse.get_pos()
X = (Mouse[0]//10)*10
Y = (Mouse[1]//10)*10
print(X)
print(Y)
pygame.draw.rect(win,(255,255,255),(X,Y,10,10))
pygame.display.update()
There's a couple of issues here.
First is that pygame.mouse.get_pressed() returns a tuple of button states, something like ( True, False, False ). But it only returns a valid state after pygame.event.get() has been called. Ref: https://www.pygame.org/docs/ref/mouse.html#pygame.mouse.get_pressed
The easiest way to achieve what it looks like you are trying to do, is to first wait for a MOUSEBUTTONDOWN (or MOUSEBUTTONUP) event, and then check the location of the click and state of the buttons.
# Main loop
while not done:
# Handle user-input
for event in pygame.event.get():
if ( event.type == pygame.QUIT ):
done = True
elif ( event.type == pygame.MOUSEBUTTONUP ):
# On mouse-click
mouse_x, mouse_y = event.pos
mouse_buttons = pygame.mouse.get_pressed()
if ( mouse_buttons[0] ): # ( True, ... )
X = ( mouse_x // 10 ) * 10
Y = ( mouse_y // 10 ) * 10
print( "Mouse-click at %d, %d -> %d, %d" % ( mouse_x, mouse_y, X, Y ) )
pygame.draw.rect( win, (255,255,255), (X,Y,10,10) )
The pygame.mouse.get_pressed() returns Boolean values such as True or False but doesn't store actual mouse cursor press position. So try instead to use this in your main loop:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
Hope this helps. More on pygame.mouse commands here
https://www.pygame.org/docs/ref/mouse.html#pygame.mouse.get_pressed
As you can see, mouse.get pressed returns a sequence of boolean variables, not a tuple of integers as you were evaluating it to.
Before running the while loop, print pygame.mouse.get_pressed() to see how it works and what it returns specifically in your program.
pygame.mouse.get_pressed() returns a tuple of boolean, something like (False,True,False).
So if you want to check whether left click is pressed for example you would do
mouse=pygame.mouse.get_pressed() #(True,False,False)
if mouse[0]: #If first mouse button pressed AKA left click.
#your code
Regarding the screen freezing, you need an event loop inside your main while to get event messages.
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
Without it the pygame screen will freeze.
Hope this helps you fix your code.

PyGame separate thread for keyboard input handling [duplicate]

This question already has answers here:
Framerate affect the speed of the game
(1 answer)
Pygame snake velocity too high when the fps above 15 [duplicate]
(1 answer)
Closed 2 years ago.
I am making a game with snake-like movement. I think, that the best way to achieve a good result, is to make separate thread for handling user's keyboard input. Here is my function that i want to run in separate thread:
def _handle_keyboard_input(self):
while self.is_running:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
self._set_velocity(-1, 0)
elif event.key == pygame.K_RIGHT:
self._set_velocity(1, 0)
elif event.key == pygame.K_UP:
self._set_velocity(0, -1)
elif event.key == pygame.K_DOWN:
self._set_velocity(0, 1)
def _set_velocity(self, x, y):
self._velocity_x = x
self._velocity_y = y
Although i worry, whether constantly looping through that while will load the CPU too much. I thought about adding pygame.time.delay() delays, but then I'm not sure if i will "hit" the right moment for the KEYDOWN event (graphic that i found on this site below).
I don't want to use pygame.key.get_pressed() because i don't want to prioritize any keys (in example if left and up arrow were pressed at the same time, I would have to choose one of them).
What is the best approach to this?
Note pygame.event.get() removes the events from the queue. If you have multiple event loops (even in different threads) then you'll miss events. It is unnecessary to handle the events more often then the display is update, because state changes become only "visible" after an update of the display. Since the events are stored in a queue, it is not necessary to get the events at the "right" moment, pygame.event.get() gets and removes all the pending events from the queue.
If you want to move the snake every 500 milliseconds, then I recommend to use pygame.time.Clock. The method tick returns the number of milliseconds that have been passed since the previous call.
Sum up the milliseconds and move the snake when sum exceeds 500:
clock = pygame.time.Clock()
count_ms = 0
FPS = 100
run = True
while run:
passed_ms = clock.tick(FPS)
# event loop
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
# [...]
count_ms += passed_ms
if count_ms >= 500:
count_ms = count_ms % 500
# move and draw snake
# [...]
pygame.display.flip()

How to switch between multiple while statements in Python

I am working on a program and i need to switch through different loops.
this works thought when i try to switch back to the previous loop i crashes.
Any suggestions?
P.S. the bellow are examples
e.g. Function = Home
(change loop)
Function = txtbox
(change loop)
Function = Home (Crashes here)
import pygame, sys, time, random
from pygame.locals import *
import math
import sys
import os
# set up pygame
pygame.init()
# set up the window
WINDOWWIDTH = 1200
WINDOWHEIGHT = 650
windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 1, 32)
pygame.display.set_caption("Mango")
Function = "Home"
font = pygame.font.SysFont("Fonts", 30)
#colors
TEXTCOLOR = (255, 255, 255)
TEXTCOLORS = (255, 0, 0)
# run the game loop
while Function == "Home":
# check for the QUIT event
events = pygame.event.get()
for event in events:
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONUP:
Function = "txtbox"
break
pygame.display.flip()
while Function == "txtbox":
events = pygame.event.get()
# process other events
for event in events:
if event.type == pygame.MOUSEBUTTONUP:
Function = "Home"
break
pygame.display.flip()
It doesn't crash. It simply finishes execution when Function is set to "Home" in the last loop. That loop simply ends.
Try enclosing those two while loops inside another while loop that runs forever.
while True:
while Function == "Home":
# check for the QUIT event
events = pygame.event.get()
for event in events:
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONUP:
Function = "txtbox"
break
pygame.display.flip()
while Function == "txtbox":
events = pygame.event.get()
# process other events
for event in events:
if event.type == pygame.MOUSEBUTTONUP:
Function = "Home"
break
pygame.display.flip()
You're on a good track.
Try this:
extract every state of your game to a function,
have a variable that knows which state is currently "active".
Example code:
def home():
events = pygame.event.get()
for event in events:
...
if something_happened:
switch_state(txtbox)
def txtbox():
events = pygame.event.get()
for event in events:
...
if something:
switch_state(home)
Function = home # assign the function itself to a variable
def switch_state(new_state):
global Function
Function = new_state
...
while True:
Function() # call the function which is currently active
Next steps:
Write the states as objects, instead of functions (so that they can keep some data about themselves - for example you'd have a state "Level" and all data about the particular level in it)
Instead of one global Function(), keep a list of states, so that you can push a new state on top, and then pop it and go back to whatever state you've been on previously. This will let you manage multiple game screens easily.

Is it me or is pygame.key.get_pressed() not working?

okay, so I am making a basic space-ship game.
I can't get rotation to work because it scrambles the bitmap, but that's for another question.Should I even use a gif? any other filetype suggestions?
back to the actual point here, so:
k = pygame.key.get_pressed()
yeah, self explanatory. this doesn't work, as it returns each key as pressed.
so, somewhere else:
d = k[pygame.K_d]
and another line:
print d
and another:
if d:
So, k returns as each key on the keyboard pressed.
d returns 0 indefinitely, whether or not d is pressed.
d is always 0.
the statement about d therefore is never true.
Why is this happening?
You might be confused by what get_pressed() is actually doing. From the docs:
Returns a
sequence of boolean values representing the state of every key on the
keyboard. Use the key constant values to index the array. A True value
means the that button is pressed.
Getting the list of pushed buttons with this function is not the
proper way to handle text entry from the user. You have no way to know
the order of keys pressed, and rapidly pushed keys can be completely
unnoticed between two calls to pygame.key.get_pressed(). There is also
no way to translate these pushed keys into a fully translated
character value. See the pygame.KEYDOWN events on the event queue for
this functionality.
In other words, when you call get_pressed(), you are getting a representation of the state of the keyboard at the time of get_pressed() being called.
For example, let's say one second into your game you call get_pressed(). You'll get back a structure that lists all of the keys on the keyboard and if they are pressed (they will all be false).
At two seconds into your game, you press a key. If you look at the same structure that you were looking at earlier, it will STILL say that everything is not pressed, because you're still looking at the state of the keyboard as it was a second ago. However, if you called get_pressed() again, you'd get back a new, updated structure, and this new structure should show that the key is pressed.
One way to solve this would be to do the following:
while True:
# Update Stuff
# Draw Stuff
state = pygame.key.get_pressed()
# Now check the keys
Now, you're getting up-to-date information on the keyboard.
One thing that should be noted is that using the functionality above, you could STILL potentially miss a keyboard press. If the update functionality took a long time, a key could potentially be pressed then unpressed in a small enough time that you wouldn't have called get_pressed() when the key was down.
If this might be a problem, you will probably want to use the event loop instead. Something like...
is_moving = False
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN and event.key == pygame.K_d:
is_moving = True
elif event.type == pygame.KEYUP and event.key == pygame.K_d:
is_moving = False
For mixing (1) event and (2) keystate inputs, it looks like
import pygame
from pygame.locals import *
done = False
while not done:
for event in pygame.event.get():
# any other key event input
if event.type == QUIT:
done = True
elif event.type == KEYDOWN:
if event.key == K_ESC:
done = True
elif event.key == K_F1:
print "hi world mode"
# get key current state
keys = pygame.key.get_pressed()
if keys[K_SPACE]:
#repeating fire while held
fire()
I like the same to be true for KEYDOWN and KEYUP,
You have to poll events. One way you can do it is
while not done:
for event in pygame.event.get():
# any other key event input
if event.type == QUIT:
done = True
elif event.type == KEYDOWN:
if event.key == K_ESC:
done = True
player.handle_event(event)
then in Player()
def handle_event(self, event):
if event.type == KEYDOWN:
if event.key == K_f: print 'Player.f pressed'

Categories