So i have an algorithm that can find the best path to exit a maze. However the problem is i am unable to implement a keypress button to pause and to unpause the algorithm using the spacebar as the keypress. For example i expect the algorithm to pause(not exit the window) when i hit the spacebar and when i hit the spacebar again it should continue running. It should work like a toggle switch basically.
The codes are as follows:
# Import libraries
import turtle
import sys
import numpy as np
import os
from collections import deque
# Configure some basic settings for the map
bs = turtle.Screen() # Define the turtle screen
bs.bgcolor("black") # Set the background colour
bs.setup(width=0.9, height=0.9) # Setup the dimensions of the working window
.
.
.
.
.
.
.
in_motion = False
def stopMovement():
global in_motion
if in_motion == True:
in_motion == False
else:
in_motion == True
while True:
if not in_motion:
# Setting up classes
turtle.title("Breadth first search algorithm ; steps taken: 0")
title = title()
building = Building()
road = Road()
start = Start()
end = End()
searcher = Searcher()
route = Route()
sprite = sprite()
# Setting up lists
walls = []
path = []
routeCoords = []
visited = set()
frontier = deque()
solution = {}
# Activation
setupMaze(mazeSet)
search(start_x, start_y)
correctRoute(end_x, end_y)
sprite.moveSprite(end_x, end_y)
else:
bs.update()
bs.listen()
bs.onkeypress(stopMovement, 'space')
The if not in_motion part basically runs the functions for the algorithm. I have already tried implementing the switch to pause and unpause but it still does not seem to work. Help will be greatly appreciated!
Typo:
def stopMovement():
global in_motion
if in_motion == True:
in_motion == False
else:
in_motion == True
should be
def stopMovement():
global in_motion
if in_motion == True:
in_motion = False # here
else:
in_motion = True # and here
Two equal signs too much and such a big effect :)
Not having runnable code to debug, I'm going to suggest that in addition to the = vs. == typos that #Justlearnedit points out, I believe that your while True: is keeping the event handler from seeing the keyboard input as infinite loops have no place in an event-driven world. We should use timed events instead and I would reformulate your code something like:
# Import libraries
from turtle import Screen, Turtle
# ...
# Configure some basic settings for the map
screen = Screen() # Define the turtle screen
screen.bgcolor('black') # Set the background colour
screen.setup(width=0.9, height=0.9) # Setup the dimensions of the working window
# ...
in_motion = False
def flipMovement():
global in_motion
in_motion = not in_motion
def running():
if not in_motion:
screen.update()
else:
screen.title("Breadth first search algorithm ; steps taken: 0")
# Set up classes
title = title()
building = Building()
road = Road()
start = Start()
end = End()
searcher = Searcher()
route = Route()
sprite = sprite()
# Set up lists
walls = []
path = []
routeCoords = []
visited = set()
frontier = deque()
solution = {}
# Activation
setupMaze(mazeSet)
search(start_x, start_y)
correctRoute(end_x, end_y)
sprite.moveSprite(end_x, end_y)
screen.ontimer(running)
screen.onkeypress(flipMovement, 'space')
screen.listen()
running()
Related
#This section of the code enables the user to Start the game (Added Function)
def askToPlayGame(game):
response = input("Want to play SpaceWars? (Y/N)")
if response == "Y":
print("The Game Is Activated")
else:
# Responses other than "Y" (includes "N")
print("User Doesn't Want To Play SpaceWars")
print("Too Bad, May The Force Be With You!")
return response
GamePartsList = ["1"]
shouldShowEverything = True
for part in GamePartsList:
answer = (askToPlayGame(part) == "Y") #Is true if response was a yes.
shouldShowEverything = answer and True # Makes shouldShowEverything stay true only if all responses are True
# List OF Game Characters - (User Input)
print("Choose A SpaceWars Character!: ")
selected_character = ""
my_charectors = ["kylo-ren", "darth-vader", "luke-skywalker", "obi-wan"]
for character in range(0,len(my_charectors)):
print(str(character) +". " + my_charectors[character])
chosenCharacter = input("Chosen character: ")
selected_character = my_charectors[int(chosenCharacter)]
#All Imported Turtles
import turtle as trtl
import math
import time
import sys
import winsound
winsound.PlaySound("soundtrack.wav", winsound.SND_ASYNC)
#This Portion Of The Code Aids In Python Errors
print(sys.getrecursionlimit())
sys.setrecursionlimit(2000)
print(sys.getrecursionlimit())
wn = trtl.Screen()
wn.setup(width=1.0, height=1.0)
wn.bgpic("background.gif")
#this Portion Of The Code Adds The 2 SpaceShips
import turtle, os
spaceship = turtle.Turtle()
spaceship.penup()
spaceship.setposition(-650, -120)
spaceship.speed(10000)
wn.addshape(os.path.expanduser("spaceship.gif"))
spaceship.shape(os.path.expanduser("spaceship.gif"))
import turtle, os
spaceship_two = turtle.Turtle()
spaceship_two.penup()
spaceship_two.setposition(-650, 200)
spaceship_two.speed(10000)
wn.addshape(os.path.expanduser("spaceship2.gif"))
spaceship_two.shape(os.path.expanduser("spaceship2.gif"))
#This Portion Of The Code Creates The Charector's Shape And Position
import turtle, os
wn = turtle.Screen()
playercharacter = turtle.Turtle()
playercharacter.penup()
playercharacter.setposition(600, -85)
wn.addshape(os.path.expanduser(selected_character+".gif"))
playercharacter.shape(os.path.expanduser(selected_character+".gif"))
playercharacter_state = "steady"
time = 0
timeToWait = 0
#This portion of the code creates the timer, adds lasers, and ends the game at Survival Score 250
laser1 = trtl.Turtle()
laser1.penup()
laser1.setposition(-500, -120)
laser1.shape("arrow")
laser1.color("Red")
laser2 = trtl.Turtle()
laser2.penup()
laser2.setposition(-500, 200)
laser2.shape("arrow")
laser2.color("Red")
timer = 0
counter_interval = 550 #1000 = 1 second
timer_up = False
counter = turtle.Turtle()
counter.color("Dark Red")
counter.hideturtle()
counter.penup()
counter.goto(-775,350)
font_setup = ("Arial", 20, "normal")
def countdown():
global timer, timer_up, laser1, laser2
counter.clear()
counter.write("Survival Score: " + str(timer), font=font_setup)
timer += 1
counter.getscreen().ontimer(countdown, counter_interval)
if laser1.xcor() > 800 and laser2.xcor() > 800:
laser1.setposition(-500, -120)
laser2.setposition(-500, 200)
# Divides time by 50, gets the closest whole number, and multiplies that by 20 / As score goes up by +50, laser speed goes up by +20.
speedFactor = math.ceil(timer/50) * 20
laser1.forward(150 + speedFactor) #speed
laser2.forward(110 + speedFactor) #speed
countdown()
#This portion of the code enables the playercharacter to jump
def jump_playercharacter():
global playercharacter_state
if playercharacter_state == "steady":
playercharacter_state = "jump"
playercharacter.penup()
playercharacter.speed(1)
x = playercharacter.xcor()
y = playercharacter.ycor() + 410
playercharacter.setposition(x, y)
y = playercharacter.ycor() - 410
playercharacter.setposition(x, y)
# function for keys commands
def RunnerLeft():
playercharacter.setheading(180)
playercharacter.forward(15)
def RunnerRight():
playercharacter.setheading(0)
playercharacter.forward(15)
def RunnerMove():
playercharacter.forward(15)
wn = turtle.Screen()
wn.onkeypress(RunnerRight, "D")
wn.onkeypress(RunnerLeft, "A")
wn.onkeypress(RunnerRight, "d")
wn.onkeypress(RunnerLeft, "a")
wn.onkey(jump_playercharacter, "space")
wn.delay(-100)
wn.update()
wn.listen()
wn.mainloop()
I adeeded two turtles as spaceships, and with my timer, I made the "arrow" turtle shoot at my other turtle with imported starwars charectors at certiant cords specific to the tip of the spaceship while one goes faster than the other so I could jump over one while dodging the other. How could I define my image length and width for all my four charectors, as well as my "arrow" lasers, and add a collision detection to python turtle?
I'm making a game when the user has to move the car to dodge obstacles, Everything working except I can't get the game to and end. My goal is to end the game when the block hits the turtle.
The issue is I can't get the game to detect the turtles to detect their proximity and the exit or quit command doesn't work. Also I don't think the code pasted properly so adjust the indents if it doesn't work.
import turtle as trtl
import random as rand
import sys
#initialize turtles
turtle = trtl.Turtle(shape = "turtle")
block = trtl.Turtle(shape = "square")
drawer = trtl.Turtle()
blockList = []
wn = trtl.Screen()
#game configuration
turtle.pu()
turtle.goto(0,-150)
drawer.pu()
drawer.goto(0,-160)
drawer.pd()
drawer.pensize(10)
drawer.pencolor("blue")
drawer.forward(180)
drawer.left(90)
drawer.forward(300)
drawer.left(90)
drawer.forward(350)
drawer.left(90)
drawer.forward(300)
drawer.left(90)
drawer.forward(180)
drawer.hideturtle()
def turtleRight():
turtle.setheading(0)
turtle.pu()
turtle.forward(15)
def turtleLeft():
turtle.setheading(180)
turtle.pu()
turtle.forward(15)
#actions
wn.onkeypress(turtleRight, 'Right')
wn.onkeypress(turtleLeft, 'Left')
wn.listen()
for i in range(5):
app = block
blockList.append(app)
#functions
def draw_blocks(index):
blockList[index].penup()
blockList[index].shape("square")
wn.tracer(False)
blockList[index].setx(rand.randint(-150,150))
blockList[index].sety(rand.randint(0,125))
blockList[index].showturtle()
wn.tracer(True)
wn.update()
def drop_block(index):
blockList[index].penup()
blockList[index].clear()
blockList[index].speed(2)
blockList[index].sety(-150)
blockList[index].hideturtle()
draw_blocks(index)
xDistance = abs(turtle.xcor()-block.xcor())
yDistance = abs(turtle.ycor()-block.ycor())
if (xDistance < 20 and yDistance < 20):
sys.exit()
else:
drop_block(i)
for i in range(5):
drop_block(i)
wn.mainloop()
trtl.done()
Can anyone help..!?
The problem is that you're re-drawing the block and thus resetting its position before you're testing the distance.
Alter the function like so:
def drop_block(index):
blockList[index].penup()
blockList[index].clear()
blockList[index].speed(2)
blockList[index].sety(-150)
blockList[index].hideturtle()
xDistance = abs(turtle.xcor()-block.xcor())
yDistance = abs(turtle.ycor()-block.ycor())
print(xDistance, yDistance)
if (xDistance < 20 and yDistance < 20):
sys.exit()
else: # redraw blocks _after_ calculating distance
draw_blocks(index)
drop_block(i)
Here is my entire program. I want to change from using tkinter with a gui, to using pynput no gui for get_key events part of my code. Can anyone show me what code to use? This code is a talking vending machine that reads from the machine contents list, which is a file that gets updated by the vending machine company.
I dont want to use a gui as there will be no monitor attached. It's a Raspberry.
from gtts import gTTS
import pygame
from io import BytesIO
import sys
import time
import csv
pygame.init()
if sys.version_info[0] == 3:
# for Python3
from tkinter import *
else:
# for Python2
from Tkinter import *
def say(text):
tts = gTTS(text=text, slow=False, lang='en-us', lang_check=False)
fp = BytesIO()
tts.write_to_fp(fp)
fp.seek(0)
pygame.mixer.init()
pygame.mixer.music.load(fp)
pygame.mixer.music.play()
def load_list():
with open(r"/home/pi/VendyLogProject/vendylist.csv", mode="r") as infile:
return sorted(list(csv.reader(infile)))
def refresh_list():
global vl, vl2, baseposition
new_items = load_list()
if vl != new_items:
vl = new_items
vl2 = [item[0] for item in vl]
baseposition = vl[0]
vl = load_list()
vl2 = [item[0] for item in vl]
baseposition = vl[-1] # so when reading through it reads entry 0 first, then 1
def current(event=None):
global baseposition # baseposition was defined outside of the function, therefore we call global
say(baseposition[1]+baseposition[0])
def back(event=None):
global baseposition
currentposition = vl.index(baseposition)
if currentposition == 0:
baseposition = vl[-1]
say(baseposition[1]+baseposition[0])
else:
previousposition = int(currentposition) - 1 # previousposition is previous position
baseposition = vl[previousposition]
say(baseposition[1]+baseposition[0])
def forward(event=None):
global baseposition
currentposition = vl.index(baseposition)
if currentposition == (len(vl) - 1):
baseposition = vl[0]
say(baseposition[1]+baseposition[0])
else:
nextposition = int(currentposition) + 1 # nextposition is next position
baseposition = vl[nextposition]
say(baseposition[1]+baseposition[0])
def readnumber(int):
global vl
for item in vl:
global baseposition
currentposition = vl.index(baseposition)
if int == item[0]:
baseposition = vl[vl.index(item)]
say(baseposition[1]+baseposition[0])
def help():
say("Welcome to Vendy log! Use the plus and minus keys to go through the list of snacks or push a number to hear its contents!")
root = Tk()
prompt = ' VendyLog '
label1 = Label(root, text=prompt, width=len(prompt))
label1.pack()
#keys buffer
keybuf = []
def test_after():
if keybuf:
num = ''.join(keybuf)
keybuf.clear()
def get_key(event):
keybuf.append(event.char)
event.char = ''.join(keybuf)
root.after(500,test_after)
if event.char == '-':
back()
elif event.char == '+':
forward()
elif event.char == '.':
current()
elif event.char in vl2:
readnumber(event.char)
elif event.char == '00':
help()
elif event.char == '462.':
sys.exit()
def refresh_list_and_enqueue_next_refresh():
refresh_list()
root.after(60000, refresh_list_and_enqueue_next_refresh)
refresh_list_and_enqueue_next_refresh()
root.bind_all('<Key>', get_key)
root.mainloop()
I edited this comment because after I played with OpenGL and Pygame I found the answer of how to use pynput with tkinter.
This is the code sample what I write it to test if works.
# // Imports
import tkinter, pynput
from tkinter import messagebox
# // Global variables
# // If we define variable type I found that will speed up execution a little
root:object = tkinter.Tk()
app_title:str = "Tkinter and Pynput"
app_size:tuple = (300, 150)
listener_stop:bool = False
# // Logics Keyboard
class Keyboard:
# On button pressed
# On my case I found the "Fn" button from laptop is not triggered...
#staticmethod
def Pressed(key) -> bool:
# If listener_stop is True then stop listening
if listener_stop: print("Keyboard Events are stoped!"); return False
# Else show pressed key
else: print(f"Keyboard pressed: {key}")
# On button released
#staticmethod
def Released(key) -> None:
print(f"Keyboard released: {key}")
# Listen keybboard buttons
#staticmethod
def Listener() -> None:
k_listen = pynput.keyboard.Listener(on_press=Keyboard.Pressed,
on_release=Keyboard.Released
)
k_listen.start()
# // Logics Mouse
class Mouse:
# On move
#staticmethod
def Move(x, y) -> bool:
# If listener_stop is True then stop listening
if listener_stop: print("Mouse Events are stoped!"); return False
else: print(f"Mouse: Moved to {x}x{y}")
# On scroll
#staticmethod
def Scroll(x, y, dx, dy) -> None:
where = "down" if dy < 0 else "up"
print(f"Mouse: Scrolled {where} at {x}x{y}")
# On click
# On my case I found mouse wheel press is not triggered...
#staticmethod
def Click(x, y, button, pressed) -> None:
action = "pressed" if pressed else "released"
print(f"Mouse: {button} was {action} at {x}x{y}")
# Listen keybboard buttons
#staticmethod
def Listener() -> None:
m_listen = pynput.mouse.Listener(on_move=Mouse.Move,
on_click=Mouse.Click,
on_scroll=Mouse.Scroll
)
m_listen.start()
# // Logics Define GUI
class MainApp:
def __init__(self, master):
self.master = master
# Create tkinter interface
self.X = (self.master.winfo_screenwidth() - app_size[0]) // 2
self.Y = (self.master.winfo_screenheight() - app_size[1]) // 2
self.master.wm_title(app_title)
self.master.wm_geometry(f"{app_size[0]}x{app_size[1]}+{self.X}+{self.Y}")
# Magic hapen here :P
self.Screen(self.master)
self.InputEvents()
# Define Screen Informations
def Screen(self, root) -> None:
# Set the main frame
self.frm_main = tkinter.Frame(root)
self.frm_main.pack(expand=True, fill="x", side="top")
# Defain frame components
self.title = tkinter.Label(self.frm_main, text=app_title, font=("Comic Sans MS", 18, "bold"), fg="tomato")
self.title.pack(expand=False, fill="x", side="top")
# Input events
def InputEvents(self) -> None:
Keyboard.Listener()
Mouse.Listener()
# Safe Quit
def SafeQuit(self, master:object = root) -> None:
global listener_stop
if messagebox.askokcancel(f"{app_title} Quit", f"Are you shore you want to quit {app_title}?"):
# We need to make shore if the window was closed and
# listening event are still runing, then make them stop
# You will see in fact they are not stoped (from console point view)
# for that reason we check listener_stop on Mouse Move and on Keyboard Key press.
# If for some reason the app is quit and listener has not stoped then on first action did will stop
# Mouse move after app quit >> Mouse listener will stop
# Keyboard button pressed after app quit >> Keyboard listener will stops
if listener_stop == False:
listener_stop = True
print("Events Listening are stoped!")
master.destroy()
# // Run if this is tha main file
if __name__ == "__main__":
app:object = MainApp(root)
root.protocol("WM_DELETE_WINDOW", app.SafeQuit)
root.mainloop()
I updated the code again with stop lisening keyboard and mouse event.
PS: An updated version of them can be found on my github
def startgame():
start.state = False
print start.state
def restart():
end.state = False
start.state = True
print game.state, end.state
s.listen()
s.onkey(startgame, "Return")
s.onkey(restart, 'r')
# This Loop stops when you hit Enter
while start.state:
start.enter()
s.reset()
# I tried repeating it here but it doesn't work
while end.state:
end.enter()
s.reset()
game.state = 'playing'
Both loops are nested in a main while loop but the second one is nested in another while loop (If that helps) so it would look something like this
while True:
while start.state:
start.flash()
s.reset()
while True:
# main game code here
while end.state:
end.flash()
s.reset()
game.state = 'playing'
break
I simply want it to show the end screen and have 'Press r to play again' flash on screen until the player hits r and then it should restart the game and go back to the start screen. The end.state variable wont update during the while loop, but start.state does during its while loop.
Your drawn out (in time) while loops have no place in an event-driven environment like turtle. In general, we need to control everything with events, specifically timer events. Let's rewrite your code as a state machine. (Since I don't have your object classes, entities like start.state become globals like start_state in my example code.)
from turtle import Screen, Turtle
start_state = True
end_state = False
def start_game():
global start_state
start_state = False
def end_game():
global end_state
if not start_state:
end_state = True
def restart_game():
global end_state, start_state
end_state = False
start_state = True
def flash(text):
turtle.clear()
turtle.write(text, align="center", font=('Arial', 24, 'bold'))
color = turtle.pencolor()
turtle.pencolor(turtle.fillcolor())
turtle.fillcolor(color)
def game_states():
if start_state:
flash("Start")
elif end_state:
flash("End")
else:
flash("Playing")
screen.ontimer(game_states, 500)
screen = Screen()
turtle = Turtle()
turtle.hideturtle()
turtle.fillcolor(screen.bgcolor())
screen.onkey(start_game, 'Return')
screen.onkey(restart_game, 'r')
screen.onkey(end_game, 'e')
screen.listen()
game_states()
screen.mainloop()
The state machine rules are:
Start via <Return> -> Playing
Playing via <e> -> End and via <r> -> Start
End via <r> -> Start
I'm learning pygame by helping a friend make a Menu for his interactive TicTacToe game. It's simple enough, a title and 2 buttons for starting and exiting the game. He has the game done, I just need to link my menu to his game.
After fiddling with pygame, I finally finished making the images appear in the pygame window(I never thought that seeing text appear in a blank window for the first time could look so beautiful! T^T). I believe that the next step is to make the images act like buttons to call another python file.
Here is my simple code for the menu:
import pygame
from pygame.locals import *
from sys import exit
pygame.init()
resX, resY = 640, 480
windowObj = pygame.display.set_mode((resX,resY))
titleImg = pygame.image.load("title.png")
startImg = pygame.image.load("start.png")
exitImg = pygame.image.load("exit.png")
def width_center(img):
"""For horizontally setting an image."""
return resX/2 - x(img)/2
def height_center(img):
"""For vertically setting an image."""
return resY/2 - y(img)/2
def x(img):
"""Width of object."""
return img.get_width()
def y(img):
"""Height of object."""
return img.get_height()
while True:
pygame.display.update()
windowObj.fill((255,255,255))
windowObj.blit(titleImg,(width_center(titleImg), 30))
#This I want to link:
windowObj.blit(startImg,(width_center(startImg),height_center(startImg)-10))
windowObj.blit(exitImg,(width_center(exitImg),height_center(exitImg)+y(startImg)))
for i in pygame.event.get():
if i.type == QUIT:
exit()
Simply put, I want to know how to make the startImg call TTTClick.py. Should there also be a certain format for his TTTClick.py?
Thanks :)
If it's one project, you can have 'title screen' state, and 'game' states.
Psuedo code:
class Game():
def __init__(self):
self.done = False
self.state = "title"
def game_draw(self):
# game draw
def game_update(self):
# game event handling, and physics
def title_draw(self):
# title draw
def title_update(self):
# on event click
self.state = "game"
def loop(self):
# main loop
while not self.done:
if state == 'title':
title_update()
title_draw()
elif state == 'game':
game_update()
game_draw()
if __name__ == "__main__":
game = Game()
game.loop()
Note: x, height_center ect. already exist in pygame.Rect
# if Surface
titleImage.get_rect().width
# if Sprite
titleImage.rect.width
There's more, rect.center, rect.centerx, see the full listing at http://www.pygame.org/docs/ref/rect.html