Как сделать чтобы моя программа останавливалась при нажатии Escape, а при повторном нажатии продолжала работать
Хотел сделать паузу в своей небольшой игре, но столкнулся с проблемой, что все работает наоборот, да и метод у меня не особо хороший в плане кода, подскажите пожалуйста как сделать чтобы моя игра останавливалась при нажатии Escape, а при повторном нажатии продолжалась
import os
import sys
import random
from PIL import Image, ImageTk
from tkinter import Tk, Frame, Canvas, ALL, NW, Button
from keyboard import *
from time import *
import threading
class Cons:
roadSpeed = 80
class Game(Canvas, Button):
def __init__(self, parent = None):
super().__init__(
parent, width=1024, height=900, highlightthickness=0, background="black"
)
self.start()
self.pack()
def start(self):
self.inGame = True
self.score = 0
self.barrierX = 128
self.barrierY = -500
self.loadImages()
self.createObjects()
self.locateBarrier()
self.bind_all("<Key>", self.keyPressed)
self.after(100, self.onTimer)
def loadImages(self):
self.icar = Image.open("ttt.png")
self.car = ImageTk.PhotoImage(self.icar)
self.ienemy = Image.open("enemy.png")
self.barrier = ImageTk.PhotoImage(self.ienemy)
self.iroad = Image.open("1396441575.png")
self.road = ImageTk.PhotoImage(self.iroad)
def createObjects(self):
self.create_image(512, 502, image=self.road, tag="road")
self.create_image(128, 650, image=self.car, tag="car")
self.create_text(
30, 10, text="Счет: {0}".format(self.score),
tag="score", fill="white"
)
def moveLeft(self):
car = self.find_withtag("car")
x1, y1, x2, y2 = self.bbox(car)
if x1 - 256 > 2:
self.move(car[0], -256, 0)
def moveRight(self):
car = self.find_withtag("car")
x1, y1, x2, y2 = self.bbox(car)
if x1 + 256 < 1022:
self.move(car[0], 256, 0)
def checkBarrierCollision(self):
barrier = self.find_withtag("barrier")
car = self.find_withtag("car")
x1, y1, x2, y2 = self.bbox(car)
overlap = self.find_overlapping(x1, y1, x2, y2)
for i in overlap:
for j in range(0, len(barrier)):
if barrier[j] == i:
self.inGame = False
def moveRoadAndBarrier(self):
road = self.find_withtag("road")
cnt = 0
for i in range(len(road)):
x, y = self.coords(road[i])
if y < 450:
cnt += 1
if cnt == 0:
self.create_image(512, -450, image=self.road, tag="road")
self.tag_lower("road")
barrier = self.find_withtag("barrier")
cnt = 0
x, y = self.coords(barrier[0])
if y < 1024:
cnt += 1
if cnt == 0:
self.locateBarrier()
road = self.find_withtag("road")
z = 0
while z < len(road):
self.move(road[z], 0, Cons.roadSpeed)
z += 1
z = 0
while z < len(barrier):
self.move(barrier[z], 0, Cons.roadSpeed)
z += 1
def locateBarrier(self):
barrier = self.find_withtag("barrier")
for i in range(0, len(barrier)):
self.delete(barrier[i])
self.score += 1
r = random.randint(1, 3)
for i in range(r):
r1 = random.randint(1, 4)
r2 = r1 - 1
self.create_image(256 * r2 + 128, -20, image=self.barrier, tag="barrier")
def keyPressed(self, e):
car = self.find_withtag("car")
x, y = self.coords(car)
key = e.keysym
leftKey = "Left"
if key == leftKey and x >= 128:
self.moveLeft()
rightKey = "Right"
if key == rightKey and x <= 896:
self.moveRight()
def onTimer(self):
road = self.find_withtag("road")
for i in range(len(road)):
x, y = self.coords(road[i])
if y == 1502:
self.delete(road[i])
self.drawScore()
self.checkBarrierCollision()
if self.inGame:
self.moveRoadAndBarrier()
self.after(100, self.onTimer)
else:
self.gameOver()
def drawScore(self):
score = self.find_withtag("score")
self.itemconfigure(score, text="Счет: {0}".format(self.score))
def gameOver(self):
self.delete(ALL)
self.create_text(self.winfo_width() / 2, self.winfo_height() / 2,
text="Игра окончена со счетом {0}".format(self.score), fill="blue")
class Car(Frame):
def __init__(self):
super().__init__()
self.master.title('ооаоаа')
self.board = Game()
self.pack()
root = Tk()
ooaoaa = Car()
root.mainloop()
Ответы (2 шт):
Автор решения: dik saratower
→ Ссылка
используйте модуль keyboard
import keyboard
stop = False
def stopgame():
global stop
if(stop == False):
stop = True
print("Пауза")
else:
stop = False
print("Продолжаем")
keyboard.add_hotkey('esc', stopgame)
keyboard.wait()
Автор решения: Kers
→ Ссылка
Как вариант через потоки:
import keyboard
import time
import threading
stop = True # По умолчанию программа на паузе
def key_pause():
keyboard.add_hotkey('esc', stopgame)
keyboard.wait()
def stopgame():
global stop
if stop == False:
stop = True
else:
stop = False
def my_pause():
global stop
while stop:
time.sleep(1)
def main():
print("Start")
# обработка паузы
my_pause()
print("END")
if __name__ == "__main__":
task1 = threading.Thread(target=key_pause, daemon=True)
task1.start()
main()
Из нюансов для наглядности программа стартует на паузе esc по сути меняет состояние переменной stop. А в местах где будет вызвана my_pause() будет проводится проверка на паузу.
Также данную логику можно реализовать через threading.Event()
import keyboard
import threading
import time
# Обработка нажатия esc
# По нажатия будет вызвана функция stopgame
def key_pause():
keyboard.add_hotkey('esc', stopgame)
keyboard.wait()
# Функция stopgame просто меняет состояние event-та
def stopgame():
if event.is_set():
event.clear() # False
else:
event.set() # True
# функция с которой запускается ваша программа
def main():
# Какой-то ваш код
print("Start")
# обработка паузы
# Вставьте этот код в программе где хотите чтобы
# была проверка на паузе программа или нет.
# если да то программа зависнет пока event не изменится
event.wait()
# Какой-то ваш код
print("END")
if __name__ == "__main__":
event = threading.Event() # Создаем event
# запускаем в отдельном потоке проверку надатия esc
task1 = threading.Thread(target=key_pause, daemon=True)
task1.start()
# начальная функция Вашей игры.
main()
Ваш код:
import os
import sys
import random
from PIL import Image, ImageTk
from tkinter import Tk, Frame, Canvas, ALL, NW, Button
from time import *
import threading
from keyboard import *
import keyboard
class Cons:
roadSpeed = 80
class Game(Canvas, Button):
def __init__(self, parent = None):
super().__init__(
parent, width=1024, height=900, highlightthickness=0, background="black"
)
self.start()
self.pack()
def start(self):
self.inGame = True
self.score = 0
self.barrierX = 128
self.barrierY = -500
self.loadImages()
self.createObjects()
self.locateBarrier()
self.bind_all("<Key>", self.keyPressed)
self.after(100, self.onTimer)
def loadImages(self):
self.icar = Image.open("ttt.png")
self.car = ImageTk.PhotoImage(self.icar)
self.ienemy = Image.open("enemy.png")
self.barrier = ImageTk.PhotoImage(self.ienemy)
self.iroad = Image.open("1396441575.png")
self.road = ImageTk.PhotoImage(self.iroad)
def createObjects(self):
self.create_image(512, 502, image=self.road, tag="road")
self.create_image(128, 650, image=self.car, tag="car")
self.create_text(
30, 10, text="Счет: {0}".format(self.score),
tag="score", fill="white"
)
def moveLeft(self):
car = self.find_withtag("car")
x1, y1, x2, y2 = self.bbox(car)
if x1 - 256 > 2:
self.move(car[0], -256, 0)
def moveRight(self):
car = self.find_withtag("car")
x1, y1, x2, y2 = self.bbox(car)
if x1 + 256 < 1022:
self.move(car[0], 256, 0)
def checkBarrierCollision(self):
barrier = self.find_withtag("barrier")
car = self.find_withtag("car")
x1, y1, x2, y2 = self.bbox(car)
overlap = self.find_overlapping(x1, y1, x2, y2)
for i in overlap:
for j in range(0, len(barrier)):
if barrier[j] == i:
self.inGame = False
def moveRoadAndBarrier(self):
event.wait() # <<< Можно вызватиь тут
road = self.find_withtag("road")
cnt = 0
for i in range(len(road)):
x, y = self.coords(road[i])
if y < 450:
cnt += 1
if cnt == 0:
self.create_image(512, -450, image=self.road, tag="road")
self.tag_lower("road")
barrier = self.find_withtag("barrier")
cnt = 0
x, y = self.coords(barrier[0])
if y < 1024:
cnt += 1
if cnt == 0:
self.locateBarrier()
road = self.find_withtag("road")
z = 0
while z < len(road):
self.move(road[z], 0, Cons.roadSpeed)
z += 1
z = 0
while z < len(barrier):
self.move(barrier[z], 0, Cons.roadSpeed)
z += 1
def locateBarrier(self):
barrier = self.find_withtag("barrier")
for i in range(0, len(barrier)):
self.delete(barrier[i])
self.score += 1
r = random.randint(1, 3)
for i in range(r):
r1 = random.randint(1, 4)
r2 = r1 - 1
self.create_image(256 * r2 + 128, -20, image=self.barrier, tag="barrier")
def keyPressed(self, e):
# event.wait() # <<< Можно вызватиь тут
car = self.find_withtag("car")
x, y = self.coords(car)
key = e.keysym
leftKey = "Left"
if key == leftKey and x >= 128:
self.moveLeft()
rightKey = "Right"
if key == rightKey and x <= 896:
self.moveRight()
def onTimer(self):
road = self.find_withtag("road")
for i in range(len(road)):
x, y = self.coords(road[i])
if y == 1502:
self.delete(road[i])
self.drawScore()
self.checkBarrierCollision()
if self.inGame:
self.moveRoadAndBarrier()
self.after(100, self.onTimer)
else:
self.gameOver()
def drawScore(self):
score = self.find_withtag("score")
self.itemconfigure(score, text="Счет: {0}".format(self.score))
def gameOver(self):
self.delete(ALL)
self.create_text(self.winfo_width() / 2, self.winfo_height() / 2,
text="Игра окончена со счетом {0}".format(self.score), fill="blue")
class Car(Frame):
def __init__(self):
super().__init__()
self.master.title('ооаоаа')
self.board = Game()
self.pack()
def key_pause():
add_hotkey('esc', stopgame)
wait()
def stopgame():
if event.is_set():
event.clear() # False
else:
event.set() # True
if __name__ == "__main__":
event = threading.Event() # Создаем event
task1 = threading.Thread(target=key_pause, daemon=True)
task1.start()
root = Tk()
ooaoaa = Car()
root.mainloop()