Pygame - keyboard input bug - multiple times print on screen - python-3.x

I'm trying to display the keyboard input on the screen using python3 but here's some issues with the code.
If I type rapidly, the letters get repeated. For example: If I type in zo quickly, the screen output is zozz but if I type slowly, it outputs zo
The shift key isn't working as expected. For example: If I press Left (or right) shift and z, it outputs Z but after I release Left shift and type z, it still outputs Z and the next time when I press z it outputs z. I don't know why this happening because I reset the shift flag at the end to 0
The capslock key isn't working as expected either. Once I press capslock, the output is all uppercase but when I press it again, the output does go into lowercase, it remains uppercase. I know here that the capsLock flag isn't working but I'm not able to debug it.
Any ideas on how to get past these issues?
import pygame
from pygame.locals import *
pygame.init()
def getch_mod():
inputStr = ''
shift = 0
capsLock = 0
a = 30
screen = pygame.display.set_mode((1000, 1000))
pygame.display.set_caption("Key Press Test")
f1=pygame.font.SysFont("comicsansms",24)
while True:
events = list(pygame.event.get())
for ev in events:
screen.fill((255,255,255))
text = f1.render('Enter password:', True, (0,0,0))
screen.blit(text,(10,10))
text = f1.render(inputStr, True, (0,0,0))
screen.blit(text, (100,a))
if (ev.type == pygame.QUIT):
return
if pygame.key.get_focused():
press = pygame.key.get_pressed()
for i in range(0,len(press)):
if (press[i] == 1):
name = pygame.key.name(i)
if (name == 'left shift' or name == 'right shift'):
shift = 1
break
if (name == 'caps lock'):
if (not capsLock):
capsLock = 1
else:
capsLock = 0
break
if (name != 'return' and name != 'left shift' and name != 'right shift' and name != 'caps lock'):
if (shift or capsLock):
name = name.upper()
inputStr += str(name)
shift = 0
pygame.display.update()
c = getch_mod()

Your code is very complex for what you're trying to do.
All you have to do is iterate over the event list and add the characters unicode representation to the string. Avoid calling pygame.key.get_pressed() since it doesn't take the order of the key press into account.
Also, don't have your logic in the event loop unless it's acting on a single event. Currently you're blitting the text for every event that happen, instead of for every frame.
Having pygame.key.get_focused in the event loop is unnecessary, since if a key event has been put in the event loop then the window have to have user focus.
Here's a short example on how to blit key input:
import pygame
pygame.init()
screen = pygame.display.set_mode((480, 720))
input_str = ''
comic_sans_font = pygame.font.SysFont("comicsansms", 24)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit()
elif event.type == pygame.KEYDOWN:
input_str += event.unicode
text = comic_sans_font.render(input_str, True, (0, 0, 0))
screen.fill((255, 255, 255))
screen.blit(text, (100, 200))
pygame.display.update()

Related

Update a checkbox based on selected values of another checkbox

I want to have a select all checkbox in my PySimpleGUI. When the select all checkbox is selected, all other checkboxes should change to True, and if any other box is unchecked, the select all checkbox should change to false state?
I can do it through button clicks, but I couldn't find a way to update checkboxes based on values selected in an another checkbox?
import PySimpleGUI as sg
layout = [
[sg.Checkbox ('select all', key = 'checkbox')],
[sg.Checkbox ('value 1', key='check_value1')],
[sg.Checkbox ('value 2',key='check_value2')],
[sg.Button ('ON', key = 'ON')],
[sg.Button ('OFF', key = 'OFF')]
]
window = sg.Window ('Sample GUI', layout) .Finalize ()
while True: # Event Loop
event,values=window.read()
if event in (None, 'Exit'):
break
elif event == 'ON':
window ['checkbox']. Update (value = True)
elif event == 'OFF':
window ['checkbox']. Update (value = False)
print(event,values)
window.close ()
Is there any way to implement this?
Option value or first argument in method upgrade if True checks the checkbox, False clears it,
Demo code,
import PySimpleGUI as sg
sg.theme('DarkBlue')
layout = [
[sg.Checkbox('All checked', enable_events=True, key='Check_All'),
sg.Checkbox('All unchecked', enable_events=True, key='Uncheck_All')],
[sg.HorizontalSeparator()]] + [
[sg.Checkbox(f'check ({j}, {i})', enable_events=True, key=f'check{j}{i}')
for i in range(5)] for j in range(4)
]
window = sg.Window ('Sample GUI', layout, finalize=True)
while True: # Event Loop
event, values = window.read (timeout = 100)
if event == sg.WINDOW_CLOSED:
break
elif event == 'Check_All':
for j in range(4):
for i in range(5):
window[f'check{j}{i}'].update(True)
window['Uncheck_All'].update(False)
elif event == 'Uncheck_All':
for j in range(4):
for i in range(5):
window[f'check{j}{i}'].update(False)
window['Check_All'].update(False)
elif event.startswith('check'):
if not values[event]:
window['Check_All'].update(False)
else:
window['Uncheck_All'].update(False)
window.close ()
Update Of the method Value Switch parameters.
In the example below, if you press the ON button, a check will be entered, and if you press the OFF button, the check will be removed.
import PySimpleGUI as sg
from PySimpleGUI import Checkbox, Button
layout = [
[sg.Checkbox ('checkbox', key = 'checkbox')],
[sg.Button ('ON', key = 'ON')],
[sg.Button ('OFF', key = 'OFF')]
]
window = sg.Window ('Sample GUI', layout) .Finalize ()
while True: # Event Loop
event, values ​​= window.read (timeout = 100)
if event in (None, 'Exit'):
break
elif event == 'ON':
window ['checkbox']. Update (value = True)
elif event == 'OFF':
window ['checkbox']. Update (value = False)
window.close ()
For more you can refer to this docs also https://pysimplegui.readthedocs.io/en/latest/call%20reference/#checkbox-element

Pygame assistance [duplicate]

I am making a game in pygame 1.9.2.
It's a faily simple game in which a ship moves between five columns of bad guys who attack by moving slowly downward. I am attempting to make it so that the ship moves left and right with the left and right arrow keys. Here is my code:
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location-=1
if location==-1:
location=0
if keys[K_RIGHT]:
location+=1
if location==5:
location=4
It works too well. The ship moves too fast. It is near impossible to have it move only one location, left or right. How can i make it so the ship only moves once every time the key is pressed?
You can get the events from pygame and then watch out for the KEYDOWN event, instead of looking at the keys returned by get_pressed()(which gives you keys that are currently pressed down, whereas the KEYDOWN event shows you which keys were pressed down on that frame).
What's happening with your code right now is that if your game is rendering at 30fps, and you hold down the left arrow key for half a second, you're updating the location 15 times.
events = pygame.event.get()
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
location -= 1
if event.key == pygame.K_RIGHT:
location += 1
To support continuous movement while a key is being held down, you would have to establish some sort of limitation, either based on a forced maximum frame rate of the game loop or by a counter which only allows you to move every so many ticks of the loop.
move_ticker = 0
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if move_ticker == 0:
move_ticker = 10
location -= 1
if location == -1:
location = 0
if keys[K_RIGHT]:
if move_ticker == 0:
move_ticker = 10
location+=1
if location == 5:
location = 4
Then somewhere during the game loop you would do something like this:
if move_ticker > 0:
move_ticker -= 1
This would only let you move once every 10 frames (so if you move, the ticker gets set to 10, and after 10 frames it will allow you to move again)
pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is 1, otherwise 0. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement:
while True:
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= speed
if keys[pygame.K_RIGHT]:
x += speed
if keys[pygame.K_UP]:
y -= speed
if keys[pygame.K_DOWN]:
y += speed
This code can be simplified by subtracting "left" from "right" and "up" from "down":
while True:
keys = pygame.key.get_pressed()
x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed
The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action or movement:
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x -= speed
if event.key == pygame.K_RIGHT:
x += speed
if event.key == pygame.K_UP:
y -= speed
if event.key == pygame.K_DOWN:
y += speed
See also Key and Keyboard event
Minimal example of continuous movement: replit.com/#Rabbid76/PyGame-ContinuousMovement
import pygame
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
rect = pygame.Rect(0, 0, 20, 20)
rect.center = window.get_rect().center
vel = 5
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
print(pygame.key.name(event.key))
keys = pygame.key.get_pressed()
rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * vel
rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * vel
rect.centerx = rect.centerx % window.get_width()
rect.centery = rect.centery % window.get_height()
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), rect)
pygame.display.flip()
pygame.quit()
exit()
Minimal example for a single action: replit.com/#Rabbid76/PyGame-ShootBullet
import pygame
pygame.init()
window = pygame.display.set_mode((500, 200))
clock = pygame.time.Clock()
tank_surf = pygame.Surface((60, 40), pygame.SRCALPHA)
pygame.draw.rect(tank_surf, (0, 96, 0), (0, 00, 50, 40))
pygame.draw.rect(tank_surf, (0, 128, 0), (10, 10, 30, 20))
pygame.draw.rect(tank_surf, (32, 32, 96), (20, 16, 40, 8))
tank_rect = tank_surf.get_rect(midleft = (20, window.get_height() // 2))
bullet_surf = pygame.Surface((10, 10), pygame.SRCALPHA)
pygame.draw.circle(bullet_surf, (64, 64, 62), bullet_surf.get_rect().center, bullet_surf.get_width() // 2)
bullet_list = []
run = True
while run:
clock.tick(60)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
bullet_list.insert(0, tank_rect.midright)
for i, bullet_pos in enumerate(bullet_list):
bullet_list[i] = bullet_pos[0] + 5, bullet_pos[1]
if bullet_surf.get_rect(center = bullet_pos).left > window.get_width():
del bullet_list[i:]
break
window.fill((224, 192, 160))
window.blit(tank_surf, tank_rect)
for bullet_pos in bullet_list:
window.blit(bullet_surf, bullet_surf.get_rect(center = bullet_pos))
pygame.display.flip()
pygame.quit()
exit()
import pygame
pygame.init()
pygame.display.set_mode()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); #sys.exit() if sys is imported
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_0:
print("Hey, you pressed the key, '0'!")
if event.key == pygame.K_1:
print("Doing whatever")
In note that K_0 and K_1 aren't the only keys, to see all of them, see pygame documentation, otherwise, hit tab after typing in
pygame.
(note the . after pygame) into an idle program. Note that the K must be capital. Also note that if you don't give pygame a display size (pass no args), then it will auto-use the size of the computer screen/monitor. Happy coding!
I think you can use:
pygame.time.delay(delayTime)
in which delayTime is in milliseconds.
Put it before events.
Try this:
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if count == 10:
location-=1
count=0
else:
count +=1
if location==-1:
location=0
if keys[K_RIGHT]:
if count == 10:
location+=1
count=0
else:
count +=1
if location==5:
location=4
This will mean you only move 1/10 of the time. If it still moves to fast you could try increasing the value you set "count" too.
The reason behind this is that the pygame window operates at 60 fps (frames per second) and when you press the key for just like 1 sec it updates 60 frames as per the loop of the event block.
clock = pygame.time.Clock()
flag = true
while flag :
clock.tick(60)
Note that if you have animation in your project then the number of images will define the number of values in tick(). Let's say you have a character and it requires 20 sets images for walking and jumping then you have to make tick(20) to move the character the right way.
Just fyi, if you're trying to ensure the ship doesn't go off of the screen with
location-=1
if location==-1:
location=0
you can probably better use
location -= 1
location = max(0, location)
This way if it skips -1 your program doesn't break
make something like this, but based on time delay. i call my function first time immediately and then lunch timer, and while button is pressed i call it every button_press_delta seconds
from time import time
before main loop:
button_press_delta = 0.2
right_button_pressed = 0
while not done:
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
if not right_button_pressed:
call_my_function()
right_button_pressed = 1
right_button_pressed_time_start = time()
if right_button_pressed:
right_button_pressed_time = (
time() - right_button_pressed_time_start)
if right_button_pressed_time > button_press_delta:
call_my_function()
right_button_pressed_time_start = time()
else:
right_button_pressed = 0
You should use clock.tick(10) as stated in the docs.
all of the answers above are too complexicated i would just change the variables by 0.1 instead of 1
this makes the ship 10 times slower
if that is still too fast change the variables by 0.01
this makes the ship 100 times slower
try this
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location -= 0.1 #or 0.01
if location==-1:
location=0
if keys[K_RIGHT]:
location += 0.1 #or 0.01
if location==5:
location=4
To slow down your game, use pygame.clock.tick(10)

How to simulate a morse-tapper in Python3 [duplicate]

I am making a game in pygame 1.9.2.
It's a faily simple game in which a ship moves between five columns of bad guys who attack by moving slowly downward. I am attempting to make it so that the ship moves left and right with the left and right arrow keys. Here is my code:
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location-=1
if location==-1:
location=0
if keys[K_RIGHT]:
location+=1
if location==5:
location=4
It works too well. The ship moves too fast. It is near impossible to have it move only one location, left or right. How can i make it so the ship only moves once every time the key is pressed?
You can get the events from pygame and then watch out for the KEYDOWN event, instead of looking at the keys returned by get_pressed()(which gives you keys that are currently pressed down, whereas the KEYDOWN event shows you which keys were pressed down on that frame).
What's happening with your code right now is that if your game is rendering at 30fps, and you hold down the left arrow key for half a second, you're updating the location 15 times.
events = pygame.event.get()
for event in events:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
location -= 1
if event.key == pygame.K_RIGHT:
location += 1
To support continuous movement while a key is being held down, you would have to establish some sort of limitation, either based on a forced maximum frame rate of the game loop or by a counter which only allows you to move every so many ticks of the loop.
move_ticker = 0
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if move_ticker == 0:
move_ticker = 10
location -= 1
if location == -1:
location = 0
if keys[K_RIGHT]:
if move_ticker == 0:
move_ticker = 10
location+=1
if location == 5:
location = 4
Then somewhere during the game loop you would do something like this:
if move_ticker > 0:
move_ticker -= 1
This would only let you move once every 10 frames (so if you move, the ticker gets set to 10, and after 10 frames it will allow you to move again)
pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is 1, otherwise 0. Use pygame.key.get_pressed() to evaluate the current state of a button and get continuous movement:
while True:
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
x -= speed
if keys[pygame.K_RIGHT]:
x += speed
if keys[pygame.K_UP]:
y -= speed
if keys[pygame.K_DOWN]:
y += speed
This code can be simplified by subtracting "left" from "right" and "up" from "down":
while True:
keys = pygame.key.get_pressed()
x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * speed
y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * speed
The keyboard events (see pygame.event module) occur only once when the state of a key changes. The KEYDOWN event occurs once every time a key is pressed. KEYUP occurs once every time a key is released. Use the keyboard events for a single action or movement:
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x -= speed
if event.key == pygame.K_RIGHT:
x += speed
if event.key == pygame.K_UP:
y -= speed
if event.key == pygame.K_DOWN:
y += speed
See also Key and Keyboard event
Minimal example of continuous movement: replit.com/#Rabbid76/PyGame-ContinuousMovement
import pygame
pygame.init()
window = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()
rect = pygame.Rect(0, 0, 20, 20)
rect.center = window.get_rect().center
vel = 5
run = True
while run:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
print(pygame.key.name(event.key))
keys = pygame.key.get_pressed()
rect.x += (keys[pygame.K_RIGHT] - keys[pygame.K_LEFT]) * vel
rect.y += (keys[pygame.K_DOWN] - keys[pygame.K_UP]) * vel
rect.centerx = rect.centerx % window.get_width()
rect.centery = rect.centery % window.get_height()
window.fill(0)
pygame.draw.rect(window, (255, 0, 0), rect)
pygame.display.flip()
pygame.quit()
exit()
Minimal example for a single action: replit.com/#Rabbid76/PyGame-ShootBullet
import pygame
pygame.init()
window = pygame.display.set_mode((500, 200))
clock = pygame.time.Clock()
tank_surf = pygame.Surface((60, 40), pygame.SRCALPHA)
pygame.draw.rect(tank_surf, (0, 96, 0), (0, 00, 50, 40))
pygame.draw.rect(tank_surf, (0, 128, 0), (10, 10, 30, 20))
pygame.draw.rect(tank_surf, (32, 32, 96), (20, 16, 40, 8))
tank_rect = tank_surf.get_rect(midleft = (20, window.get_height() // 2))
bullet_surf = pygame.Surface((10, 10), pygame.SRCALPHA)
pygame.draw.circle(bullet_surf, (64, 64, 62), bullet_surf.get_rect().center, bullet_surf.get_width() // 2)
bullet_list = []
run = True
while run:
clock.tick(60)
current_time = pygame.time.get_ticks()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
bullet_list.insert(0, tank_rect.midright)
for i, bullet_pos in enumerate(bullet_list):
bullet_list[i] = bullet_pos[0] + 5, bullet_pos[1]
if bullet_surf.get_rect(center = bullet_pos).left > window.get_width():
del bullet_list[i:]
break
window.fill((224, 192, 160))
window.blit(tank_surf, tank_rect)
for bullet_pos in bullet_list:
window.blit(bullet_surf, bullet_surf.get_rect(center = bullet_pos))
pygame.display.flip()
pygame.quit()
exit()
import pygame
pygame.init()
pygame.display.set_mode()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit(); #sys.exit() if sys is imported
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_0:
print("Hey, you pressed the key, '0'!")
if event.key == pygame.K_1:
print("Doing whatever")
In note that K_0 and K_1 aren't the only keys, to see all of them, see pygame documentation, otherwise, hit tab after typing in
pygame.
(note the . after pygame) into an idle program. Note that the K must be capital. Also note that if you don't give pygame a display size (pass no args), then it will auto-use the size of the computer screen/monitor. Happy coding!
I think you can use:
pygame.time.delay(delayTime)
in which delayTime is in milliseconds.
Put it before events.
Try this:
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
if count == 10:
location-=1
count=0
else:
count +=1
if location==-1:
location=0
if keys[K_RIGHT]:
if count == 10:
location+=1
count=0
else:
count +=1
if location==5:
location=4
This will mean you only move 1/10 of the time. If it still moves to fast you could try increasing the value you set "count" too.
The reason behind this is that the pygame window operates at 60 fps (frames per second) and when you press the key for just like 1 sec it updates 60 frames as per the loop of the event block.
clock = pygame.time.Clock()
flag = true
while flag :
clock.tick(60)
Note that if you have animation in your project then the number of images will define the number of values in tick(). Let's say you have a character and it requires 20 sets images for walking and jumping then you have to make tick(20) to move the character the right way.
Just fyi, if you're trying to ensure the ship doesn't go off of the screen with
location-=1
if location==-1:
location=0
you can probably better use
location -= 1
location = max(0, location)
This way if it skips -1 your program doesn't break
make something like this, but based on time delay. i call my function first time immediately and then lunch timer, and while button is pressed i call it every button_press_delta seconds
from time import time
before main loop:
button_press_delta = 0.2
right_button_pressed = 0
while not done:
keys = pygame.key.get_pressed()
if keys[pygame.K_RIGHT]:
if not right_button_pressed:
call_my_function()
right_button_pressed = 1
right_button_pressed_time_start = time()
if right_button_pressed:
right_button_pressed_time = (
time() - right_button_pressed_time_start)
if right_button_pressed_time > button_press_delta:
call_my_function()
right_button_pressed_time_start = time()
else:
right_button_pressed = 0
You should use clock.tick(10) as stated in the docs.
all of the answers above are too complexicated i would just change the variables by 0.1 instead of 1
this makes the ship 10 times slower
if that is still too fast change the variables by 0.01
this makes the ship 100 times slower
try this
keys=pygame.key.get_pressed()
if keys[K_LEFT]:
location -= 0.1 #or 0.01
if location==-1:
location=0
if keys[K_RIGHT]:
location += 0.1 #or 0.01
if location==5:
location=4
To slow down your game, use pygame.clock.tick(10)

pygame event keys are not responding even though idle is not showing an error?

import pygame
from pygame import *
pygame.init
pygame.display.init
pygame.display.set_caption("Test")
bg = pygame.image.load("bg.jpg")
human = pygame.image.load("human1.bmp")
display_screen = pygame.display.set_mode((1000,500))
keyboard_input = 0
clock = pygame.time.Clock()
def screen_Quit():
running = False
while not running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
keyboard_input = (90)
print("Left arrow key has been pressed.")
if event.key == pygame.K_RIGHT:
keyboard_input = (-90)
print("Right arrow key has been pressed.")
if event.key == pygame.K_UP:
keyboard_input = (20)
print("Up arrow key has been pressed.")
if event.key == pygame.K_DOWN:
keyboard_input = (-20)
print("Down arrow key has been pressed.")
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT:
keyboard_input = (0)
print("Left arrow key has been released.")
if event.key == pygame.K_RIGHT:
keyboard_input = (0)
print("Right arrow key has been released.")
if event.key == pygame.K_UP:
keyboard_input = (0)
print("Up arrow key has been released.")
if event.key == pygame.K_DOWN:
keyboard_input = (0)
print("Down arrow key has been released.")
# this code here has been left for later --> print(event)
display_screen.blit(bg, [0,0])
display_screen.blit(human, [50,87])
pygame.display.update()
clock.tick(60)
screen_Quit()
pygame.quit
quit()
I don't understand the problem, I have posted my full code as the problem might be something else. The problem I've been having with the program is the event keys in python it's not responding to the input which is the keyboard I'm using pygame to create a game but cannot understand why the event keys are not working. I have checked everywhere and cannot understand. The code seems fine to me, python idle is not giving any errors I'm even getting input in the idle but the character doesn't move there should be no reason for it not to move.
Here is a picture and a link to a video that goes more in depth into the problem (I created the video myself):
an image of the problem
Link to video:
https://www.youtube.com/watch?v=QVFaiuF9KY8&feature=youtu.be
Video will most likely be more useful than image.
Short Answer
Your code doesn't have any commands that tell the image to move. I fixed this and posted the full working code at the bottom. If you want a more in depth explanation, read on.
Explanation
If that is your full code, then the problem is that first of all you don't even have any code in the first place that tells the character to move. And second of all your pygame.display.update() is outside the while loop, so any changes made to the screen don't show.
For every event you just told python to print a message:
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
keyboard_input = (90)
print("Left arrow key has been pressed.")
What you want to do is add another line there to actually move the character.
This can be done by changing it's x and y position. I recommend using sprites for this, but for now since you are using an image, we'll just stick to that.
To change the position of an image you have to run a new window.blit() with the desired (x,y). This means that you will have to constantly iterate this if you're going to need to move it around a lot, so it's better to put it INSIDE the running while loop. So bring this part of your code on indentation forward:
display_screen.blit(bg, [0,0])
display_screen.blit(human, [50,87])
pygame.display.update()
clock.tick(60)
screen_Quit()
pygame.quit
quit()
So now the screen get's regularly updated. The second thing you want to do is create 2 new variables x and yand change
display_screen.blit(human, [50,87])
to
display_screen.blit(human, [x,y])
This basically means that you character now gets blitted to the screen at the position YOU choose, not at a fixed position that doesn't change. So now you can add + to the x position whenever the left key is clicked, or - from the x position whenever the right key is clicked!
Here is the full working code:
import pygame
from pygame import *
pygame.init
pygame.display.init
pygame.display.set_caption("Test")
bg = pygame.image.load("bg.jpg")
human = pygame.image.load("human1.bmp")
display_screen = pygame.display.set_mode((1000,500))
keyboard_input = 0
clock = pygame.time.Clock()
running = False
x=0
y=0
moving = "none"
white = (255,255,255)
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
moving = "left"
print("Left arrow key has been pressed.")
elif event.key == pygame.K_RIGHT:
moving = "right"
print("Right arrow key has been pressed.")
elif event.key == pygame.K_UP:
moving = "up"
print("Up arrow key has been pressed.")
elif event.key == pygame.K_DOWN:
moving = "down"
print("Down arrow key has been pressed.")
else:
moving = "hello"
if moving == "left":
x -= 5
if moving == "right":
x += 5
if moving == "up":
y -= 5
if moving == "down":
y += 5
# this code here has been left for later --> print(event)
display_screen.blit(bg,[0,0])
display_screen.blit(human, [x,y])
clock.tick(60)
pygame.display.update()
You never update the position of your player and just blit it at [50,87]. If you want it to move, you first have to store the position, e.g. player_pos = [50, 87] and define variables for the velocity velocity_x = 0, then set the velocity in the event loop if a key gets pressed:
if event.key == pygame.K_RIGHT:
velocity_x = 5
and update the position in the while loop:
player_pos[0] += velocity_x
player_pos[1] += velocity_y

How can I add a delay to a mouse click in pygame?

I'm attempting to make a store in my game, but am having issues with pygame.mouse.get_pressed(). When the user clicks on a button, the program thinks that they clicked on it more than once, therefore using more credits than the user intended. I would like to add a delay so that the game doesn't do this. I would like 1 click to represent them buying one object. I have tried reducing the framerate for that window, but the result is the same. Here is the code I currently have.
This is where all the mouse action occurs.
def button(x, y, w, h, ic, ac, action = None):
global paused
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + w > mouse[0] > x and y + h > mouse[1] > y:
pygame.draw.rect(gameDisplay, ac, (x, y, w, h))
if click[0] == 1 and action == Game:
Game()
if click[0] == 1 and action == quitgame:
sys.exit()
if click[0] == 1 and action == None:
paused = False
if click[0] == 1 and action == StartScreen:
save()
StartScreen()
if click[0] == 1 and action == LootScreen:
LootScreen()
if click[0] == 1 and action == open_common_drop:
open_common_drop()
if click[0] == 1 and action == open_rare_drop:
open_rare_drop()
else:
pygame.draw.rect(gameDisplay, ic, (x, y, w, h))
This is where the loot store is currently at.
def LootScreen():
global current_drops
loot = True
while loot:
for event in pygame.event.get():
if event.type == pygame.QUIT:
save()
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_t:
open_common_drop()
elif event.key == pygame.K_y:
open_rare_drop()
if event.key == pygame.K_ESCAPE:
StartScreen()
gameDisplay.fill(gray)
title('Loot Chests!')
button(400, 150, 260, 50, blue, bright_blue, open_common_drop)
button(695, 150, 260, 50, red, bright_red, open_rare_drop)
button(display_width * 0.42, display_height / 1.15, 255, 50, red, bright_red, StartScreen)
game_display_text('Open Common Chest (T)', 407, 165)
game_display_text('Open Rare Chest (Y)', 725, 165)
game_display_text('You Got: %s' % current_drops, 50, display_height / 2)
game_display_text('Credits: %.2f' % player_loot_data['credit_count'], 15, 15)
game_display_text('Main Menu', display_width * 0.47, display_height / 1.13)
game_display_text('Janus\': %s' % player_loot_data['loot_data_one'] , 950, 500)
game_display_text('Peace of Minds: %s' % player_loot_data['loot_data_two'], 950, 535)
pygame.display.update()
clock.tick(30)
You will need to use a bool switch in your button function. Here I re-worked the function in a way that should work.
def button(x, y, w, h, ic, ac, action = None, held):
global paused
mouse = pygame.mouse.get_pos()
click = pygame.mouse.get_pressed()
if x + w > mouse[0] > x and y + h > mouse[1] > y:
pygame.draw.rect(gameDisplay, ac, (x, y, w, h))
if click[0] == 1:
if held == False:
if action == Game:
Game()
elif action == quitgame:
sys.exit()
elif action == None:
paused = False
elif action == StartScreen:
save()
StartScreen()
elif action == LootScreen:
LootScreen()
elif action == open_common_drop:
open_common_drop()
elif action == open_rare_drop:
open_rare_drop()
held = True
else:
held = False
else:
pygame.draw.rect(gameDisplay, ic, (x, y, w, h))
return held
As you see, there is a new variable held added to the function to process whether the button is held or not. Held is taken and returned here, so it won't reset every time the function is called.
With that down, let me show you why I wrote it that way, and just how this logic works at its core.
import pygame
#
display = pygame.display.set_mode((800,600))
clock = pygame.time.Clock()
#
held = False # Variable to handle if mouse button is held
#
RUNNING = True
while RUNNING:
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
RUNNING = False
#
button = pygame.mouse.get_pressed() # Get mouse state
if button[0]: # Check if left mouse button is pressed
if held == False: # Check if button is held down
print(True) # If button is not held down, print true
held = True # Set held eqaual to true for next iteration
else: # If left mouse button is not pressed
held = False # held is set to false, alowing event to happen again
#
display.fill((0,0,0))
#
pygame.display.flip()
#
pygame.quit()
The above is a very simple stand alone program that also implements the held variable to monitor if the mouse button is held. In this program, the variable held is first declared as False as the mouse is not being pressed. Then, within the main loop, pygame.mouse.get_pressed() is called to get the mouse input, and is immediately followed by a check for the left mouse button. If the left mouse button is pressed, a check for held will happen. If it is false, the program will print True. held is then set to True for the next iteration. The else: statement will fire if the left mouse button is not held down and reset held to its default False state.
I would suggest a timed bool switch. Here's an example that should help out.
import time
boolswitch = False
timer = 0.0
clock = time.time()
x = time
while True:
if timer > 0.25:
boolswitch = True
timer = 0.0
else:
x = time.time()
timer += (x-clock)
clock = x
if boolswitch:
click = pygame.mouse.get_pressed()
if click[0] == 1:
boolswitch = False
clock = time.time()

Resources