как заставить этот прямоугольник двигаться, пока не будет нажата новая клавиша? - PullRequest
2 голосов
/ 05 августа 2020
• 1000 oop. Я попытался поместить этот оператор if в bottom, потому что я думал, что функция root.mainloop() заставляет программу работать с l oop, но это тоже не сработало.
import tkinter as tk

root = tk.Tk()

x1 = y1 = 250
direc = "none"

score = 0
walls = ["250 250"]

score_box = tk.Label(root, text=score)
score_box.pack()

canvas = tk.Canvas(root, width=500, height=500)
canvas.pack()

canvas.create_rectangle(x1, y1, x1+10, y1+10)

def draw_rect():
    canvas.create_rectangle(x1, y1, x1+10, y1+10, fill="green")

def score_add():
    global score, x1, y1
    score += 1
    score_box["text"] = score
    coords = str(x1) + " " + str(y1)
    if coords in walls:
        print(f"you lose! your final score was {score}")
        root.destroy()
    walls.append(coords)


def move(event):
    global x1, y1, direc
    if event.char == "d":
        x1 += 10
        direc = "right"
    draw_rect()
    if event.char == "a":
        x1 -= 10
        direc = "left"
    draw_rect()
    if event.char == "s":
        y1 += 10
        direc = "down"
    draw_rect()
    if event.char == "w":
        y1 -= 10
        direc = "up"
    draw_rect()
    score_add()

# doesn't run at all
if direc == "up":
    y1 -= 10
    print("test")
    draw_rect()
    score_add()

# runs once only at the start
print("hello")

root.bind("<Key>", move)

root.mainloop()

Любая помощь будет принята с благодарностью

Ответы [ 2 ]

2 голосов
/ 05 августа 2020

Вы можете использовать after(), чтобы прямоугольник двигался:

import tkinter as tk

dx = dy = 0
delay = 100  # in milliseconds, adjust it to set difficulty

WIDTH = HEIGHT = 500
SIZE = 10

score = 0
x1, y1 = WIDTH//2, HEIGHT//2
walls = [(x1, y1)]


def draw_rect():
    canvas.create_rectangle(x1, y1, x1+SIZE, y1+SIZE, fill="green")

def score_add():
    global score
    score += 1
    score_box["text"] = score
    coords = (x1, y1)
    if coords in walls or x1 < 0 or x1 >= WIDTH or y1 < 0 or y1 >= HEIGHT:
        print(f"you lose! your final score was {score}")
        root.destroy()
    walls.append(coords)

def move():
    global x1, y1
    if dx or dy:
        x1 += dx
        y1 += dy
        draw_rect()
        score_add()
    root.after(delay, move)

def set_direction(event):
    global dx, dy
    if event.keysym == 'Up':
        dx, dy = 0, -SIZE
    elif event.keysym == 'Down':
        dx, dy = 0, SIZE
    elif event.keysym == 'Left':
        dx, dy = -SIZE, 0
    elif event.keysym == 'Right':
        dx, dy = SIZE, 0


root = tk.Tk()

score_box = tk.Label(root, text=score)
score_box.pack()

canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT)
canvas.pack()

root.bind("<Key>", set_direction)

draw_rect() # draw the starting rectangle
move() # start the moving loop

root.mainloop()
1 голос
/ 05 августа 2020

Я подумал об использовании потоковой передачи, чтобы прямоугольник двигался до тех пор, пока не будет нажата другая клавиша направления. У меня есть код, который вы можете попробовать, заменив функцию move следующей измененной частью -

from threading import Lock, Thread
from time import sleep

key_press_delay = .5  # Half a second

# Simulates last valid key press to be repeated
def hold_key_press_thread():
    global x1, y1, direc, char, key_press_delay
    loop = True
    while loop:
        if char == "d":
            x1 += 10
            direc = "right"
        elif char == "a":
            x1 -= 10
            direc = "left"
        elif char == "s":
            y1 += 10
            direc = "down"
        elif char == "w":
            y1 -= 10
            direc = "up"
        draw_rect()
        score_add()
        sleep(key_press_delay)

char = ' '
key_lock = Lock()
key_thread = Thread(target=hold_key_press_thread)
key_thread.setDaemon(True)

def move(event):
    global char, key_lock, key_thread
    key_lock.acquire()
    char = event.char
    key_lock.release()

    if not key_thread.is_alive():
        key_thread.start()

Обратите внимание, что у него могут быть проблемы, о которых я не знаю или которые нежелательны для того, что вы хотите. Например, нажатие клавиши может быть потеряно, пока поток находится в спящем режиме. Я также хотел бы узнать о других более эффективных способах сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...