Tkinter и перемещение с помощью bind работает неправильно

Рейтинг: 0Ответов: 1Опубликовано: 21.05.2023

Используя команду after(1000//fps) и bind('a', lambda e: player.move('a', e)), я заметил, что увеличивая fps с 30 до 100, скорость персонажа не меняется (т.е. удерживая клавишу персонаж идёт с той же скоростью). Отсюда два вопроса:

Правильно ли я заметил? (Если что, то все 100 кадров обрисовываются, я замерял)

И если это так, то как сделать перемещение "правильнее"?

import random as rnd
from tkinter import Canvas

FPS = 30


class Player():
    def __init__(self, canvas: Canvas):
        self.color = self.__create_random_color()
        self.pos = [500, 500]
        self.canvas = canvas
        self.size = [100, 100]
        self.object = self.canvas.create_oval(self.pos[0], self.pos[1], self.pos[0] + self.size[0],
                                              self.pos[1] + self.size[1], fill=self.color)
        self.t = 0

    def move(self, key, e):
        match key:
            case 'a':
                self.pos[0] -= 5
            case 'd':
                self.pos[0] += 5
            case 'w':
                self.pos[1] -= 5
            case 's':
                self.pos[1] += 5

    def tick(self):
        self.t += 1
        self.canvas.coords(self.object, self.pos[0], self.pos[1], self.pos[0] + self.size[0],
                           self.pos[1] + self.size[1])

    def __create_random_color(self) -> str:
        r = hex(rnd.randrange(0, 200))[2:]
        g = hex(rnd.randrange(0, 200))[2:]
        b = hex(rnd.randrange(0, 200))[2:]
        if len(r) < 2:
            r = '0' + r
        if len(g) < 2:
            g = '0' + g
        if len(b) < 2:
            b = '0' + b

        return f'#{r}{g}{b}'


app = tk.Tk()
app.title('main')
app.geometry('1000x1000')

canvas = Canvas(app, width=1000, height=1000)
player = Player(canvas)

canvas.pack()


def game():
    player.tick()
    app.after(1000 // FPS, game)


app.bind('a', lambda e: player.move('a', e))
app.bind('w', lambda e: player.move('w', e))
app.bind('s', lambda e: player.move('s', e))
app.bind('d', lambda e: player.move('d', e))

game()
app.mainloop()

Просто меняйте FPS и смотрите на скорость передвижения. Она не меняется, а хотелось бы!

Ответы

▲ 0Принят

Решение состоит в отслеживании нажатия и отпускания клавиш. Т.е. bind надо сделать на <KeyPress> и <KeyRelease>, и хранить список клавиш, которые в данный момент нажаты