Python time counter in Pygame-mouse events - python

I want to calculate the time of user's mouse events in Pygame, if user doesn't move his mouse about 15 seconds, then I want to display a text to the screen. I tried time module for that, but it's not working.
import pygame,time
pygame.init()
#codes
...
...
font = pygame.font.SysFont(None,25)
text = font.render("Move your mouse!", True, red)
FPS = 30
while True:
#codes
...
...
start = time.time()
cur = pygame.mouse.get_pos() #catching mouse event
end = time.time()
diff = end-start
if 15 < diff:
gameDisplay.blit(text,(10,500))
pygame.display.update()
clock.tick(FPS)
pygame.quit()
quit()
Well output is not what I want, I don't know how to calculate it if user doesn't move his mouse.
If I want to write a text when user's mouse in a special area, it's working like;
if 100 < cur[0] < 200 and 100 < cur[1] < 200:
gameDisplay.blit(text,(10,500))
But how can I calculate? I even couldn't find how to tell Python, user's mouse is on the same coordinates or not.Then I can say, if mouse coordinates changes, start the timer, and if it's bigger than 15, print the text.
Edit: You can assume it in normal Python without Pygame module, assume you have a function that catching the mouse events, then how to tell Python if coordinates of mouse doesn't change, start the timer, if the time is bigger than 15 seconds,print a text, then refresh the timer.

To display a text on the screen if there is no mouse movement within the pygame window for 3 seconds:
#!/usr/bin/python
import sys
import pygame
WHITE, RED = (255,255,255), (255,0,0)
pygame.init()
screen = pygame.display.set_mode((300,200))
pygame.display.set_caption('Warn on no movement')
font = pygame.font.SysFont(None, 25)
text = font.render("Move your mouse!", True, RED, WHITE)
clock = pygame.time.Clock()
timer = pygame.time.get_ticks
timeout = 3000 # milliseconds
deadline = timer() + timeout
while True:
now = timer()
if pygame.mouse.get_rel() != (0, 0): # mouse moved within the pygame screen
deadline = now + timeout # reset the deadline
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
screen.fill(WHITE)
if now > deadline: # no movement for too long
screen.blit(text, (10, 50))
pygame.display.flip()
clock.tick(60) # set fps

You should add:
start = time.time()
cur = None
before while loop.
You should also change start = time.time() in while loop to:
if cur != pygame.mouse.get_pos():
start = time.time()
Also you could use pygame.time (it's similar to time but measure time in milliseconds)

In your code, the while True: code block is continuously running. The cur = pygame.mouse.get_pos() function is non blocking. This means it does not wait for mouse input - it will return straight away. So you need to initialize the start and cur variables before your while True: code block and then check the mouse position constantly in your loop.
If cur has changed since the last time the loop ran, then reset the start variable to the current time, and if the difference between the current time and start becomes larger than your 15 seconds, you can display the text.

You can also do that even without getting time, since you can calculate the pause as an integer counter through your FPS. Consider following example. Note that if the cursor is out of the window, the values of its positon will not change even if you move the cursor.
import pygame
pygame.init()
clock = pygame.time.Clock( )
DISP = pygame.display.set_mode((600, 400))
FPS = 25
Timeout = 15
Ticks = FPS*Timeout # your pause but as an integer value
count = 0 # counter
MC = pygame.mouse.get_pos()
MC_old = MC
MainLoop = True
while MainLoop :
clock.tick(FPS)
pygame.event.pump()
Keys = pygame.key.get_pressed()
if Keys[pygame.K_ESCAPE]:
MainLoop = False
MC = pygame.mouse.get_pos() # get mouse position
if (MC[0]-MC_old[0] == 0) and (MC[1]-MC_old[1] == 0) :
count = count + 1
else : count = 0
if count > Ticks :
print "What are you waiting for"
count = 0
MC_old = MC # save mouse position
pygame.display.flip( )
pygame.quit( )

Related

Disable Pygame MOUSEBUTTONDOWN/UP update on a given area/image after it's clicked once

I am new to python and Pygame. I am trying to make a Schulte table game.
Here's what the game is doing:
I have a 5 * 5 grid of total 25 pictures of numbers from 1-25.
(5*5 Schulte grid)
The number position is displayed in random order.
When you tap the correct number's picture, the number changes color. When you click on the wrong number, a sound is played to indicate the wrong click, and the number does not change color.
(Image changing colors or mouse click)
There's a start button and the restart button.
And finally, it displays the total elapsed time it took you to click all the numbers in order.
The program works as intended. Once a button is clicked, the colored number image is updated and a counter for each click is updated. But the problem is, if I click again on an already clicked number image, it keeps updating the counter.
For example, picture 1 is clicked, it turns red and now the click counter is 1. Then if I click again on the same picture 1, the program keep updating the counter. This way, if the counter reaches 25 even though I have not clicked all of the number pictures from 1-25 in order, the game will be over. I have tried to use pygame.event.set_allowed(pygame.MOUSEBUTTONDOWN), but it does not work(perhaps I don't know where in the loop to use it).
I am not sure where and how to exactly include this logic that the Mousebutton click will not update after a single click on the same picture. Please refer to the code below. Any help/tips is greatly appreciated. Thanks!
import pygame # import pygame library
import sys # import sys library
import random # import random library
import numpy as np # import numpy library
import itertools # Import the itertools library
import time # import time library
# Initialize settings
pygame.init() # Initialize pygame
size = width, height = 240, 320 # set the window size
screen = pygame.display.set_mode(size) # display the window
pygame.display.set_caption("Schulte Grid") # Give the window a name
# Image preparation
Xpts = [0, 48, 96, 144, 192]
Ypts = [0, 48, 96, 144, 192]
map = np.array(list(itertools.product(Xpts, Ypts))) # 25 picture coordinates
# load sound
wavFileName = 'sounds/fire.wav'
sndTrack = pygame.mixer.music.load(wavFileName)
# Timer text preparation
myfont = pygame.font.SysFont('Comic Sans MS', 60)
GREEN = (0, 255, 0)
BLUE = (0, 0, 128)
def ready():
global list1
list1 = [[i] for i in range(25)]
random.shuffle(list1)
# start interface
def start(start_page):
while start_page:
for event in pygame.event.get(): # Traverse all events
if event.type == pygame.QUIT: # if click to close the window, exit
sys.exit() # exit
screen.blit(pygame.image.load(
"pic/start-0.png"), (30, 190)) # show start screen
global t_x, t_y
t_x, t_y = pygame.mouse.get_pos() # Get the position of the mouse
if 30 <= t_x <= 200 and 190 <= t_y <= 250: # 18*50 #Mouse over the picture
screen.blit(pygame.image.load("pic/start-1.png"),
(30, 190)) # Get the mouse position and change color when moving to a certain position
if event.type == pygame.MOUSEBUTTONDOWN and 30 <= t_x <= 200 and 190 <= t_y <= 250:
start_page = False # start page
game_page = True # game page
global time_start # Define the global variable to start timing
time_start = time.time() # timing
pygame.display.flip() # update all display
# game interface
def gamepage(game_page):
# A variable is added here to make sure to start with the smallest number.
zero = 0
waiting_for_sleep_to_over = False
# The status of the question interface, it is guaranteed that only one question will be generated.
pic_zero = 1
while game_page:
while pic_zero:
for i in range(25): # must be 25 here
screen.blit(pygame.image.load(
"pic/pic" + str(*list1[i - 1]) + ".png"), map[i])
pic_zero = 0
for event in pygame.event.get(): # Traverse all events
if event.type == pygame.QUIT: # if click to close the window, exit
sys.exit()
for i in range(25):
# Determine the mouse position and whether it is pressed down. :
if event.type == pygame.MOUSEBUTTONDOWN and map[i][0] <= event.pos[0] <= map[i][0] + 48 and map[i][1] <= event.pos[1] <= map[i][1] + 48:
# print(i)
if int(*list1[i-1]) <= zero:
screen.blit(pygame.image.load(
"pic/qic" + str(*list1[i-1]) + ".png"), map[i]) # Display the color map
# waiting_for_sleep_to_over = True
zero = zero + 1
# if event.type == pygame.MOUSEBUTTONDOWN and map[i][0] <= event.pos[0] <= map[i][0] + 48 and map[i][1] <= event.pos[1] <= map[i][1] + 48:
# waiting_for_sleep_to_over = FALSE
# pygame.event.set_blocked(pygame.MOUSEBUTTONDOWN)
# time.sleep(0.5)
# zero = zero
# pygame.event.clear()
# pygame.event.set_allowed(pygame.MOUSEBUTTONDOWN)
print(zero)
if zero == 25:
time_end = time.time() # end timing
time_c = round(
time_end - time_start, 2) # time spent running
print('time cost:', int(time_c), 's')
textImage = myfont.render(
str(time_c) + 's', True, GREEN, BLUE)
screen.blit(textImage, (30, 250))
# screen.blit(pygame.image.load("pic/start-0.png"), (30, 210))
if event.type == pygame.MOUSEBUTTONDOWN and 30 <= t_x <= 210 and 200 <= t_y <= 250:
start_page = True
game_page = False
pygame.display.flip() # update all display
else:
pygame.mixer.music.play() # play music on error
pygame.display.flip() # update all display
# main loop
start_page = True
game_page = True
while True:
ready()
start(start_page)
gamepage(game_page)
The line if int(*list1[i-1]) <= zero: should be if int(*list1[i-1]) == zero:.

Is there a way to get pygame to detect what color my cursor is on

I'm trying to make a game where it spawns another circle every time you click on a circle. And the error i'm getting is "TypeError: 'bool' object is not callable". I'm looking for a solution that doesn't completly change the code since i'm new and want to understand the code myself. But at this point i'll take any help.
import pygame
import random
import time
from pygame.math import Vector2
# Define some colors
BLACK = (0, 0, 0)
WHITE = (247, 247, 247)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
YELLOW = (225,225,0)
tuple1 = (247, 247, 247, 255)
# Setup
pygame.init()
# Set the width and height of the screen [width,height]
surface = pygame.display.set_mode( (2560, 1440) )
pygame.display.set_caption("My Game")
# Loop until the user clicks the close button.
done = False
# Used to manage how fast the screen updates
clock = pygame.time.Clock()
# Hide the mouse cursor
pygame.mouse.set_visible(0)
# Speed in pixels per frame
x_speed = 0
y_speed = 0
# Current position
cursor = pygame.image.load('cursor.png').convert_alpha()
pygame.image.load("pattern.jpg")
background_image = pygame.image.load("pattern.jpg").convert()
circposy = 770
circposx = 1280
# -------- Main Program Loop -----------
while done ==False:
# --- Event Processing
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
if event.type == pygame.MOUSEBUTTONDOWN:
done = True
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# --- Drawing Code
surface.fill(WHITE)
# First, clear the screen to WHITE. Don't put other drawing commands
# above this, or they will be erased with this command.\
player_position = pygame.mouse.get_pos()
a = 0
b = 1
p=player_position[a]
o=player_position[b]
player_position = (p,o)
pygame.draw.circle(surface,RED,[circposx,circposy], 40)
tuple2 = surface.get_at(pygame.mouse.get_pos())
print (tuple2)
q = p - 2545
w = o - 2545
surface.blit( cursor, (q, w) )
a=0
result = tuple(map(int, tuple2)) > tuple1
print (result)
while event.type == pygame.MOUSEBUTTONDOWN:
done = True
if result == True():
a+1
surface.fill(WHITE)
pygame.draw.circle(surface,RED,[circposx + randint, circposy+randint],40)
print (a)
# Go ahead and update the screen with what we've drawn.
pygame.display.flip()
# Limit frames per second
clock.tick(144)
# Close the window and quit.
pygame.quit()
cursor.png
The short answer is that the code is trying to call True(), which isn't a function.
while event.type == pygame.MOUSEBUTTONDOWN:
done = True
if result == True(): # <<-- HERE
a+1
surface.fill(WHITE)
pygame.draw.circle(surface,RED,[circposx + randint, circposy+randint],40)
Simply change this to True.
But you will also need to define what randint is a few lines lower. Did you mean random.randint( 0, 500 ) or suchlike? And fixing this leads to another error, because the surrounding loop to this code, is an infinite loop:
while event.type == pygame.MOUSEBUTTONDOWN: # <<-- HERE
done = True
if result == True:
a+1
surface.fill(WHITE)
rand_x = random.randint( 0, 500 )
rand_y = random.randint( 0, 500 )
pygame.draw.circle(surface,RED,[circposx + rand_x, circposy+rand_y],40)
Because there is no way event.type can ever change inside that loop. This should probably read:
if event.type == pygame.MOUSEBUTTONDOWN:
If I may make some suggestions:
Put all your event handling to a single place.
There's some doubling-up of event handling, and it would have prevented that infinite loop.
Move your screen dimensions into variables
SCREEN_WIDTH = 2560
SCREEN_HEIGHT = 1440
Instead of having constant numbers through the code (e.g.: 2545) make these functions of the screen size.
SCREEN_MARGIN = SCREEN_WIDTH - round( SCREEN_WIDTH * 0.10 )
q = p - SCREEN_MARGIN
If you want to detect what color your cursor is on, you can use pyautogui. Make sure you have pyautogui installed. type pip install pyautogui. If it doesn't install successfully, you already have it installed.
# Import everything
import pygame
import pyautogui
from pyautogui import *
# Initialize
pygame.init()
# Get mouse position
mouse_pos = pygame.mouse.get_pos()
x = mouse_pos[0]
y = mouse_pos[1]
# Get Color
r = pyautogui.pixel(x,y)[0]
g = pyautogui.pixel(x,y)[1]
b = pyautogui.pixel(x,y)[2]
color = [r,g,b]
Hopefully, you found this helpful!

pygame.time.wait() crashes the program

In a pygame code I wannted to do a title that changes colors.
I tried to do a simple title that changes colors, but it not even turned the color to blue (or do it for a second), and the program crash. The code:
title_font = pygame.font.SysFont("monospace", TITLE_SIZE)
while True:
title = title_font.render("game", 5, RED)
game_display.blit(title, TITLE_POS)
pygame.display.update()
pygame.time.wait(2000)
title = title_font.render("game", 5, BLUE)
game_display.blit(title, TITLE_POS)
pygame.display.update()
pygame.time.wait(3000)
title = title_font.render("game", 5, RED)
game_display.blit(title, TITLE_POS)
pygame.display.update()
pygame.time.wait(2000)
It also happens with pygame.time.delay(), and I don't know where is the problem...
Don't use pygame.time.wait or delay because these functions make your program sleep for the given time and the window becomes unresponsive. You also need to handle the events (with one of the pygame.event functions) each frame to avoid this.
Here are some timer examples which don't block: Countdown timer in Pygame
To switch the colors, you can just assign the next color to a variable and use it to render the text.
import pygame
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
title_font = pygame.font.SysFont('monospace', 50)
BACKGROUND_COLOR = pygame.Color('gray12')
BLUE = pygame.Color('blue')
RED = pygame.Color('red')
# Assign the current color to the color variable.
color = RED
timer = 2
dt = 0
done = False
while not done:
# Handle the events.
for event in pygame.event.get():
# This allows the user to quit by pressing the X button.
if event.type == pygame.QUIT:
done = True
timer -= dt # Decrement the timer by the delta time.
if timer <= 0: # When the time is up ...
# Swap the colors.
if color == RED:
color = BLUE
timer = 3
else:
color = RED
timer = 2
screen.fill(BACKGROUND_COLOR)
title = title_font.render('game', 5, color)
screen.blit(title, (200, 50))
pygame.display.flip()
# dt is the passed time since the last clock.tick call.
dt = clock.tick(60) / 1000 # / 1000 to convert milliseconds to seconds.
pygame.quit()

Can't click on image again, what's wrong with my pygame code?

Okay, I'am trying to create a Tom and Jerry game with the pygame library.
The game focuses on catching mice by clicking on them as they appear in their holes. The problem
is that sometimes a cat appears instead of a mouse and should the player erroneously click on the
cat (s)he looses all earned points, but the game continues.
The mouse is an image of a mouse and the cat is an image of an cat.
If you click on the mouse, you get mouse, otherwise the cat gets the points.
The code is a mess, that's because I don't know what I'am doing and just set an another event loop because then it works, because it runs after I create the mouse. It works to click on the mouse but then you click somewhere else and after that it's like you did not clicked on the mouse.
The mouse is created in a loop and is supposed to wait for 5 seconds and if you click on the mouse within these seconds then an appropriate message prints out in the console ,,Jerry clicked!" else "1 click". If you don't click on the mouse within 5 seconds a image covers the mouse so she disappears.
Now, what I'am trying to do right now is to print the message 1 click when the player does not click on anything but print 1 click jerry clicked when the player clicks on the mouse. I have a image of the mousehole and then I put the mouse on the mousehole, that is, on an another image.
This code works with one image at least:
pygame.init()
width=350;
height=400
screen = pygame.display.set_mode( (width, height ) )
pygame.display.set_caption('clicked on image')
redSquare = pygame.image.load("images/red-square.png").convert()
x = 20; # x coordnate of image
y = 30; # y coordinate of image
screen.blit(redSquare , ( x,y)) # paint to screen
pygame.display.flip() # paint screen one time
running = True
while (running):
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
# Set the x, y postions of the mouse click
x, y = event.pos
if redSquare.get_rect().collidepoint(x, y):
print('clicked on image')
#loop over, quite pygame
pygame.quit()
My problem is that, when I click on the mouse and then I don't click on the mouse I can't click on the mouse again at another position.
So what's wrong? What I'am doing wrong here?
Here is my code:
import pygame
from pygame import *
from random import *
init()
run = True
screen = (800,800)
screen = display.set_mode(screen)
xpos = 0
ypos = 0
mouseorcatxpos = 5
mouseorcatypos = 0
mousehole = image.load("mousehole.png").convert()
cat = image.load("tom.png")
jerry = image.load("jerry.png")
def makeholes():
global ypos
global xpos
for holey in range(1,9):
for holex in range(1,9):
screen.blit(mousehole,(xpos,ypos))
display.flip()
xpos += 100
ypos += 100
xpos = 0
def mouseorcat():
global xpos
mouseorcatxpos = 5
ypos = 0
for mousecaty in range(1,9):
pygame.event.pump()
for mousecatx in range(1,9):
randommouse = randint(1, 3)
randomcat = randint(1, 10)
if(randommouse == 2):
screen.blit(jerry, (mouseorcatxpos, ypos))
display.flip()
for event in pygame.event.get():
if (event.type == MOUSEBUTTONDOWN):
if jerry.get_rect().collidepoint(xpos, ypos) == False:
print("l clicked!")
x, y = event.pos
if jerry.get_rect().collidepoint(xpos, y):
print("JERRY CLICKED!!")
x, y = event.pos
print(x, y)
time.wait(5000)
#screen.blit(mousehole, (mouseorcatxpos - 5, ypos))
display.flip()
elif(randomcat == 2):
screen.blit(cat, (mouseorcatxpos, ypos))
display.flip()
time.wait(1500)
screen.blit(mousehole, (mouseorcatxpos-5, ypos))
display.flip()
mouseorcatxpos += 100
mouseorcatxpos = 0
ypos += 100
makeholes()
while run == True:
for event in pygame.event.get():
mouseorcat()
if event.type == QUIT:
run = False
I rewrote your game to show you how I would do it.
To keep track of the time and to limit the framerate I used a pygame.time.Clock and a timer variable. The clock returns the time in milliseconds since clock.tick was called the last time, which is used to increase the timer variable. The cat just replaces the mouse after two seconds and the mouse is set to a new position. I use pygame.Rects to store the positions, but you could also use lists or tuples.
import sys
import random
import pygame
pygame.init()
size = (800, 800)
screen = pygame.display.set_mode(size)
# Images replaced by pygame.Surface. Do that too
# in the future before you post your code.
mousehole = pygame.Surface((40, 40)).convert()
mousehole.fill(pygame.Color(30, 30, 30))
cat = pygame.Surface((40, 40)).convert()
cat.fill(pygame.Color(110, 110, 130))
jerry = pygame.Surface((40, 40)).convert()
jerry.fill(pygame.Color(190, 130, 0))
# Create the background image and blit the holes.
background = pygame.Surface(size).convert()
for holey in range(8):
for holex in range(8):
background.blit(mousehole, (holex*100, holey*100))
def new_position():
"""Return a random position between 0-700 in steps of 100."""
return (random.randrange(0, 701, 100), random.randrange(0, 701, 100))
def main():
fps = 30
clock = pygame.time.Clock()
jerry_rect = jerry.get_rect() # Stores jerry's position and size.
jerry_rect.topleft = new_position() # New random position.
# The cat is outside of the screen first.
cat_rect = cat.get_rect(topleft=(-100, -100))
points = 0
timer = 0
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.MOUSEBUTTONDOWN:
if jerry_rect.collidepoint(event.pos):
points += 1
print('Jerry caught! Points:', points)
timer = 0
jerry_rect.topleft = new_position()
else:
print('Missed. Points:', points)
# Run logic.
timer += clock.tick(fps) / 1000 # timer + seconds since last tick.
if timer > 2: # Cat catches mouse after 2 seconds.
cat_rect.topleft = jerry_rect.topleft
jerry_rect.topleft = new_position()
timer = 0
points = 0
print('Tom caught Jerry.')
# Draw.
# Clear the screen by blitting the bg.
screen.blit(background, (0, 0))
screen.blit(jerry, jerry_rect)
screen.blit(cat, cat_rect)
pygame.display.flip()
if __name__ == '__main__':
main()
pygame.quit()
sys.exit()
Side notes:
Don't use star imports (from module import *), because that can make code harder to read. If you want you can use from pygame.locals import *, if it's the only star import.
Don't use global variables, because they can make code harder to read, understand and maintain. Pass variables to functions as arguments and then return the result.
Update: Some notes about your program:
The first big problem is that your game has two event loops and the important one is deeply nested inside of two other for loops and a if. The event loop should be directly under the main while loop (one indentation level (when you have more experience you can put it into a function or class method)).
The two for loops seem to have the purpose to let the code run until randommouse or randomcat are 2. To run code until a condition is met is the purpose of a while loop. But in this case you should better just pick a random number and write the if/elif conditions so that they always apply. For example, you want a 2/3 chance for mouse and 1/3 for a cat,
random_number = random.randint(1, 3)
if random_number < 3:
print("2/3 probability. It's a mouse")
else:
print("1/3 probability. It's a cat")
Or use random.choice with a list:
>>> random.choice(['mouse', 'mouse', 'cat'])
'mouse'
time.wait(5000) shouldn't be used because the game just hangs in this time. You can't even close the window. Limit the framerate and get the time since the last tick with a pygame.time.Clock.
pygame.event.pump() is not needed.
If you call get_rect() without an argument, the rect is positioned at (0, 0).
if jerry.get_rect().collidepoint(xpos, y):
That's the reason why clicking on jerry only works in the top row, and because you use the global xpos here. Since xpos is 0, the whole top row counts as Jerry.
You can pass coordinates to get_rect like so (you can also use center or other args instead of topleft):
jerry_rect = jerry.get_rect(topleft=(50, 100))
I'm sorry but I don't think I can simply fix your code. I've tried it several times, but I always end up re-writing it completely.
I begin by extracting the event loop out of the two nested for loops, then remove these loops, create rects for the mouse and cat, fix the collision detection, add a timer and so on. Take a close look at my example and try to rewrite your game in a similar way, and keep asking questions if you don't understand something.

pygame.key.set_repeat for Joystick

I'm building a menu using pygame and I want to make it navigable using a specific gamepad. Ideally I want to be able to press and hold *down" on the D-pad repeatedly, or get something like on a keyboard where the first button press has a delay before repeatedly entering the same character (seemingly).
I'm trying to emulate the pygame.key.set_repeat(...) function for a Joystick. my approach so far has been
pygame.time.set_timer(pygame.USEREVENT, 10)
DELAY_TIME = 0.250 #ms
y_delay = True
while not done:
for event in pygame.event.get():
y_axis = gamepad.get_axis(1)
if y_axis > 0.5: # pushing down
main_menu.move_down()
redraw() #redraw everything on the surface before sleeping
if y_delay:
time.sleep(DELAY_TIME)
y_delay = False #don't delay the next time the y axis is used
elif y_axis < -0.5: #pushing up
# repetitive I know, but I'm still working on it
main_menu.move_up()
redraw()
if y_delay:
time.sleep(DELAY_TIME)
y_delay = False
else:
y_delay = True # delay the next time
my issue is if someone taps up or down faster than DELAY_TIME they are limited to the DELAY_TIME before they can move again. Also if someone releases and depresses the up/down button within the time.sleep interval, python never sees that it was released at all and doesn't allow for a delay.
Maybe there's a way to do this using events or mapping the joystick to keys somehow? qjoypad doesn't cut it for me, and joy2keys is trash. I would need to do the mapping within the python program.
Sleep causes the program to halt execution, so it's not a viable option. You can also do this without using set_timer and events. I did it using a couple of flags and pygame.time's get_ticks.
import pygame
from pygame.locals import *
def main():
pygame.init()
pygame.display.set_mode((480, 360))
gamepad = pygame.joystick.Joystick(0)
gamepad.init()
delay = 1000
neutral = True
pressed = 0
last_update = pygame.time.get_ticks()
while True:
for event in pygame.event.get():
if event.type == QUIT:
return
move = False
if gamepad.get_axis(1) == 0:
neutral = True
pressed = 0
else:
if neutral:
move = True
neutral = False
else:
pressed += pygame.time.get_ticks() - last_update
if pressed > delay:
move = True
pressed -= delay
if move:
print "move"
last_update = pygame.time.get_ticks()
if __name__ == "__main__":
main()
pygame.quit()
When get_axis indicates no motion, the neutral flag is set, and the pressed timer is reset, causing the move flag to remain unset. When the neutral flag is unset, if it's newly set, the move flag is set. If it's not newly set, the pressed timer increases, and move is set only if the pressed timer is greater than delay.

Categories