create a button that can only be pressed once - python

i am trying to create a button that can only be pressed once for a game in python but i cant figure out how to set a variable that works in the def and does not change every time the function is run.
tut = turtle.Screen()._root
def bt1():
pressed = 1
x_turn = True
if (pressed == 1):
if (x_turn is True):
print("this button has not been pressed as player1")
x_turn == False
pressed = 0
else:
print ("this button has not been pressed as player2")
pressed = 0
x_turn == True
else:
print("this button has been pressed")
photo1 = Image.open(r"C:\image.png")
resize_photo1 =photo1.resize((50,50), Image.ANTIALIAS)
print_photo1 = itk.PhotoImage(resize_photo1)
Button(tut, image= print_photo1,command=bt1).pack(side= LEFT)

what i am gathering is that when this button is pressed you want it to set pressed to 0 so it can not run again but since you put the variable at the top every time the button is bressed it will set it to 1. to fix this all you want to do is....
tut = turtle.Screen()._root
global pressed
pressed = 1
global x_turn
x_turn = True
def bt1():
if (pressed == 1):
if (x_turn is True):
print("this button has not been pressed as player1")
x_turn == False
pressed = 0
This might work let me know if it does

x_turn = True
Try using this :
x_turn == True
I think here you’re missing the equals to sign and that’s why it is creating a problem.

Related

Stopping running while loop if conditions are met

The code below is intended to print out the contents of arrays, until either the mouse (left click) is released, or the end of the array is reached. How would I stop the while loop in the function logging_mouse, once the mouse is released?
running = False
i = 0
delta_x=[1,2,3]
delta_y = [3,2,1]
def logging_mouse(running,i):
while (running and i < len(delta_x)):
print(delta_x[i],delta_y[i])
i = i+1
running = False
def on_click(*args):
global running
global i
print(running)
i = args[3]
print(i)
if args[-1]:
if not running:
running = True
threading.Thread(target=logging_mouse(running,i)).start()
else:
running = False
i = 0
with Listener(on_click=lambda event1,event2,event3,event4: on_click(event1,event2,event3,i,event4)) as listener:
listener.join()
you need to actually use the args to the on_click function... you can detect whether or not a button is pressed down or released, the signature for on_click should be on_click(x,y,button,pressed) where x and y represent the location of the mouse press, button says which button was pressed, and pressed is True if the button is down and False if it was released

How do i detect which specific button in my controller is being released in pygame

i am trying to detect which button is being pressed from my controller and when it is released.
This is how far i have managed to get.
import pygame
pygame.init()
j = pygame.joystick.Joystick(0)
j.init()
try:
while True:
events = pygame.event.get()
for event in events:
if event.type == pygame.JOYBUTTONDOWN:
if j.get_button(1):
print("x")
elif j.get_button(2):
print("a")
elif event.type == pygame.JOYBUTTONUP:
print("button released")
except KeyboardInterrupt:
print("EXITING NOW")
j.quit()
i am new to programming and i dont entirely understand this piece of code.
this detects if x or a is being pressed and if any button is being released. I want it to detect if x or a is being pressed and when they are released.
Thanks for reading!
pygame.event.get() returns a list of events(events are a type of structure/object of pygame generated when the user does something moves mouse / presses buttons e.t.c.).then for each of those events you check if the they are the event you want(pygame.JOYBUTTONDOWN or event.type,pygame.JOYBUTTONUP).
you can only check if a button is pressed and then see which button is pressed.
if event.type == pygame.JOYBUTTONDOWN:
if j.get_button(1):
print("x")
elif j.get_button(2):
print("a")
to see when buttons get released best way i can think off is having a list of Button Status .When the status for a button changes you do something .
ButtonStatus[2];
ButtonStatus[0]=get_button(1);#a
ButtonStatus[1]=get_button(2);#x
if event.type == pygame.JOYBUTTONUP:
if ButtonStatus[0]!=get_button(1)
#status changed do yr code for button release a
pass;
if ButtonStatus[1]!=get_button(2)
#status changed do yr code for button release b
pass;
above code is a sample not actually compiled . general idea is to check when a button is released,check which button changes status and execute code accordingly.
So, i coded what i needed with the help of the other answers!
import pygame
pygame.init()
j = pygame.joystick.Joystick(0)
j.init()
r = 2
t = 5
b = 1
x = 3
try:
while True:
events = pygame.event.get()
for event in events:
if event.type == pygame.JOYBUTTONDOWN:
if j.get_button(1):
print("B")
b = 2
elif j.get_button(2):
print("X")
x = 5
elif event.type == pygame.JOYBUTTONUP:
if b == r :
print("b2")
b = 1
if x == t:
print("x2")
x = 3
except KeyboardInterrupt:
print("EXITING NOW")
j.quit()
This isn't robust in any way. You need to make new strings for every button you need.
You do that by copying the button with the biggest variables and just adding 3 to every variable in the code you coppied. Please answer the original post if you can give a better answer (which probably exists).Also, when u press multiple buttons at the same time and u release atleast one it thinks you have realeased all of them.

Code beyond the Onclick and Listen doesn't get executed

this is my first time posting here.
I'm trying to make a Title Screen before getting the user in my game. When I hit enter, I want to break out of the While loop into a the main game loop, or go into the next section of the While loop. However, when I hit enter and the onkey use my Enter function which sets the In_title to False, it doesn't seem to respond with anything. (this is in python with turtle, also I'm working using replit.)
I've created a variable named in_title = True.
I've tried breaking out of the while loop using if in_title == false then break.
import turtle
import random
import math
import time
#set up for the screen title.
screen_size = [500,500]
screen_color = "#1a2645"
t = turtle.Turtle()
screen = t.getscreen()
screen.setup(screen_size[0],screen_size[1])
screen.bgcolor(screen_color)
screen.tracer(0)
t.ht()
game_state = 1 #to see if the game is still runninng. #0, 1 are no, yes.
in_title = True #to see if the game is in title or not.
select = turtle.Turtle()
select.color("yellow")
select.speed(0)
select.up()
select.setx(-80) #putting it in the middle of the text.
select.sety(30)
#all of the entity here:
player = {"p": turtle.Turtle(), "lives": 3, "color": "white", "rad": 15}
player["p"].ht()
harm = {"color": "red", "rad": 10}
num_harm = 10
good = {"g": turtle.Turtle(), "color": "white", "rad": 8}
good["g"].ht()
#universal movement function.
def moving_harm(h,rad): #function to move the harm objects.
if h.ycor() == (250 + rad/2):
h.up()
h.setx(random.randrange(-250,250))
h.sety(h.ycor() - 5)
screen.update()
if (h.ycor() != 250 + rad/2) and (h.ycor() != -250 - rad/2):
h.sety(h.ycor() - 5)
if (h.ycor() == (-250 - rad/2)):
h.sety(250 + rad/2)
screen.update()
def up():
if game_state == 1:
select.sety(30) #hard coded the number so it's in the middle.
print(select.ycor())
screen.update()
# def down():
# def left():
# def right():
def enter():
global in_title
if (game_state == 1):
if(select.ycor() == 30):
select.down()
select.forward(150)
select.setheading(180)
select.color("white")
select.forward(150)
screen.update()
time.sleep(0.2)
screen.clear()
screen.update()
time.sleep(0.1)
screen.setup(screen_size[0],screen_size[1])
screen.bgcolor(screen_color)
in_title = False
#main menu operation:
def main_game():
global game_state
#writing out the tittle screen.
menu = turtle.Turtle()
menu.up()
menu.sety(150)
menu.color("white")
menu.write("Sorta a Side Scroller Game", align="center", font=("Arial", 22, "normal"))
menu.sety(100)
menu.write("By Silver", align="center", font=("Arial", 15, "normal"))
menu.ht()
menu.sety(25)
menu.write("Start game", align="center", font=("Arial", 15, "normal"))
#create all the harm turtles:
for i in range(num_harm):
h = "h"+str(i+1)
harm[str(h)] = turtle.Turtle()
harm[str(h)].up()
harm[str(h)].ht()
#handle control at the title screen.
screen.onkey(enter, "Enter")
if in_title == False:
print("got passed that")
main_game()
screen.listen()
screen.update()
screen.mainloop()
no error message where given.
The way you have it, main_game() only is called once, right before screen's main loop begins. That means that this fragment
if in_title == False:
print("got passed that")
happens once and then control flow leaves main_game() forever, and the screen main loop begins.
Since the fragment only exists in main_game(), and main_game() isn't set to be called on any button press or called from anywhere else in the code, that fragment will never be called ever again. So, the if in_title == False: will never be encountered and print("got passed that") will never happen, even when in_title is False.
In this case, there is a place you already know is going to have control flow when in_title == False, and that is at the end of enter. So, you could put the code you have in mind there. This is the solution I suggested in the comments:
def enter():
global in_title
if (game_state == 1):
if(select.ycor() == 30):
# ...
in_title = False
print("got passed that")
#main menu operation:
def main_game():
# ...
screen.onkey(enter, "Enter")

Tkinter getting key pressed event from a function

I have the following code,
If I press 'Left Arrow Key', it only prints move player to left
But I need a functionality in which pressing the given arrow key moves the player in the given direction.
Is there a way in which I can detect key press event in my move_dir function
PS: fairly new to python
import Tkinter as tk
move = 1
pos = -1
def move_dir():
global move
global pos
while move ==1:
if pos == 0:
print 'move player to left'
elif pos == 1:
print 'move player to right'
elif pos == -1:
print 'stop moving!'
def kr(event):
global move
global pos
global root
if event.keysym == 'Right':
move = 1
pos = 0
move_dir()
print 'right ended'
elif event.keysym == 'Left':
move = 1
pos = 1
move_dir()
print 'left ended'
elif event.keysym == 'Space':
move = 0
move_dir()
elif event.keysym == 'Escape':
root.destroy()
root = tk.Tk()
print( "Press arrow key (Escape key to exit):" )
root.bind_all('<KeyRelease>', kr)
root.mainloop()
If you're wanting to animate something, you should use after to set up an animation loop. An animation loop looks like this:
def animate():
<draw one frame of your animation>
after(<delay>, animate)
You can put whatever code you want to draw a frame. In your case it sounds like you want to move something left or right. The <delay> parameter defines your frame rate. For example, to get 30FPS your delay would be about 33 (1000ms / 30). The only important thing to be aware of is that <draw one from of your animation> needs to run pretty quickly (10's of milliseconds or less) in order to not block the GUI.
For your particular problem, you can set a variable to define the direction when the user presses a key, then unset the variable when they release the key. Your event handler and animate function might look something like this:
def animate():
if direction is not None:
print "move player to the ", direction
after(33, animate)
def on_keypress(event):
global direction
if event.keysym == "Left":
direction = "left"
elif event.keysum == "right":
direction = "right"
def on_keyrelease(event):
global direction
direction = None
See how that works? When you press a key it defines the direction. Then, every 33 milliseconds you check for the direction, and move your player if the direction is defined. When the user releases the button, the direction becomes undefined and the movement stops.
Putting it all together, and using a class to avoid using global variables, it looks something like the following. This creates a ball on a canvas which you can move left, right, up and down:
import Tkinter as tk
class Example(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.direction = None
self.canvas = tk.Canvas(width=400, height=400)
self.canvas.pack(fill="both", expand=True)
self.canvas.create_oval(190, 190, 210, 210,
tags=("ball",),
outline="red", fill="red")
self.canvas.bind("<Any-KeyPress>", self.on_press)
self.canvas.bind("<Any-KeyRelease>", self.on_release)
self.canvas.bind("<1>", lambda event: self.canvas.focus_set())
self.animate()
def on_press(self, event):
delta = {
"Right": (1,0),
"Left": (-1, 0),
"Up": (0,-1),
"Down": (0,1)
}
self.direction = delta.get(event.keysym, None)
def on_release(self, event):
self.direction = None
def animate(self):
if self.direction is not None:
self.canvas.move("ball", *self.direction)
self.after(50, self.animate)
if __name__ == "__main__":
root = tk.Tk()
Example(root).pack(fill="both", expand=True)
root.mainloop()
EDIT 4
You have a while loop that you want to combine with the Tkinter mainloop.
In this case you want to move when the key is pressed and stop moving when a key is released.
The code below allows you to do this:
import Tkinter as tk
from guiLoop import guiLoop # https://gist.github.com/niccokunzmann/8673951#file-guiloop-py
direction = 0
pos = 0 # the position should increase and decrease depending on left and right
# I assume pos can be ... -3 -2 -1 0 1 2 3 ...
#guiLoop
def move_dir():
global pos
while True: # edit 1: now looping always
print 'moving', direction
pos = pos + direction
yield 0.5 # move once every 0.5 seconds
def kp(event):
global direction # edit 2
if event.keysym == 'Right':
direction = 1 # right is positive
elif event.keysym == 'Left':
direction = -1
elif event.keysym == 'Space':
direction = 0 # 0 is do not move
elif event.keysym == 'Escape':
root.destroy()
def kr(event):
global direction
direction = 0
root = tk.Tk()
print( "Press arrow key (Escape key to exit):" )
root.bind_all('<KeyPress>', kp)
root.bind_all('<KeyRelease>', kr)
move_dir(root)
root.mainloop()
To see how this is implemented you can read the source code or read the second answer by Bryan Oakley.
EDIT 3
There is no way to detect a keypress in the move_dir function directly.
You can use root.update() in your move_dir function to make it possible for kr, kp to be executed when root.update is called. root.update() alse repaints the windows so that changes can be seen by the user.
root.mainloop() can be seen as while True: root.update()

Pygame and Livewires button press not working?

so in my menu in a game I'm creating a picture is displayed which shows how to play the game, and I have some code so that when the player presses the b button it returns to the main menu, but this doesn't work, can someone help me please?
def manual():
image = games.load_image("options.jpg")
games.screen.background = image
if games.keyboard.is_pressed(games.K_b):
menu()
games.screen.mainloop()
the 'menu()' is another function which has all the main menu code in it
Here is the menu function
def menu():
pygame.init()
menubg = games.load_image("menubg.jpg", transparent = False)
games.screen.background = menubg
# Just a few static variables
red = 255, 0, 0
green = 0,255, 0
blue = 0, 0,255
size = width, height = 640,480
screen = pygame.display.set_mode(size)
games.screen.background = menubg
pygame.display.update()
pygame.key.set_repeat(500,30)
choose = dm.dumbmenu(screen, [
'Start Game',
'Manual',
'Show Highscore',
'Quit Game'], 220,150,None,32,1.4,green,red)
if choose == 0:
main()
elif choose == 1:
manual()
elif choose == 2:
print("yay")
elif choose == 3:
print ("You choose Quit Game.")
I think is_pressed() in manual() doesn't wait for your press so you call mainloop() so I think you never leave that loop.
I see other bad ideas in your code like:
menu() call manual() which call menu() which call manual() etc. - use return and use loop in menu()
every time you call menu() you call pygame.init() and pygame.display.set_mode() - you should use it only once.
EDIT:
I don't know how games.keyboard.is_pressed() works (because there is no that function in PyGame) but I think manual() could be:
def manual():
image = games.load_image("options.jpg")
games.screen.background = image
while not games.keyboard.is_pressed(games.K_b):
pass # do nothing
# if `B` was pressed so now function will return to menu()
and you have to create loop in menu:
running = True
while running:
choose = dm.dumbmenu(screen, [
'Start Game',
'Manual',
'Show Highscore',
'Quit Game'], 220,150,None,32,1.4,green,red)
if choose == 0:
main()
elif choose == 1:
manual()
# if 'B' was press manual() will return to this place
elif choose == 2:
print("yay")
elif choose == 3:
running = False
print ("You choose Quit Game.")

Categories

Resources