Как заставить квадрат двигаться при нажатии кнопки на клавиатуре? Tkinter, Питон

#python #tkinter

Вопрос:

Как заставить квадрат двигаться при нажатии кнопки «d» (например) на клавиатуре?

 from tkinter import * root = Tk() root.title('Snake') root["width"] = 400 root["height"] = 400  field = Canvas(root)  x = 0 y = 0  def snake(x, y):  field.create_rectangle(10, 20, 30, 40)  field.grid(row=x, column=y)  x  = 1  y  = 1  return(x, y)   root.bind("lt;KeyPressgt;", snake(x=x, y=y))  root.mainloop()  

Комментарии:

1. Есть ли какая-либо причина для return инга x и y . Кроме того, этот код не работает.

2. Как вы определяете направление, в котором должен двигаться квадрат? Знает ли квадрат, что «стрелка вверх» означает перемещение вдоль оси y на определенное количество пикселей? Решение этих вопросов для себя может привести вас к вашей цели.

3. @белый Во-первых, я хочу, чтобы он двигался в любом направлении, а затем записывал движения в разных направлениях с помощью разных кнопок

4. Вот почему вам нужна подсказка для нажатия клавиши к действию. Что-то в этом роде if key == 'left': do something для каждого возможного/принятого ключа.

Ответ №1:

Простой способ-это использовать event.char . Он возвращает символ нажатой кнопки. Затем проверьте, какая это была кнопка, и переместите ее, если она есть w,a,s,d

 from tkinter import * root = Tk() root.title('Snake') root["width"] = 400 root["height"] = 400  field = Canvas(root) rect = field.create_rectangle(10, 20, 30, 40) field.grid(row=0, column=0)  def snake(event):  x = 0 # Default  y = 0  if event.char == 'w':  y = -10   if event.char == 'a':  x = -10   if event.char == 's':  y = 10    if event.char == 'd':  x = 10   field.move(rect,x,y)   root.bind("lt;Keygt;", snake) root.mainloop()  

Ответ №2:

Это один из способов, которым вы можете это сделать:

 import tkinter as tk from tkinter import Canvas  root = tk.Tk() root.title('Snake') root.geometry("450x450")  w = 400 h = 400 x = w//2 y = h//2  field = Canvas(root, width=w, heigh=h, bg="white") field.pack(pady=5)  my_rectangle = field.create_rectangle(10, 20, 30, 40)   def left(event):  x = -10  y = 0  field.move(my_rectangle, x, y)   def right(event):  x = 10  y = 0  field.move(my_rectangle, x, y)   def up(event):  x = 0  y = -10  field.move(my_rectangle, x, y)   def down(event):  x = 0  y = 10  field.move(my_rectangle, x, y)   root.bind("lt;Leftgt;", left) root.bind("lt;Rightgt;", right) root.bind("lt;Upgt;", up) root.bind("lt;Downgt;", down)  root.mainloop()  

Сначала создайте root и отдайте geometry ему, в данном случае это так 450x450 . После этого создайте переменные , которые будут хранить height и width , и coordinates x and y . Затем создайте canvas ( field ) и canvas укажите, где canvas будет находиться и geometry canvas background color ). Когда canvas создается, мы создаем rectangle . Функции left, right, up and down будут охватывать перемещение rectangle по холсту. field.move(my_rectangle, x, y) — эта строка кода переместит my_rectangle на холсте по x и y или влево, вправо вверх или вниз, в зависимости от того, что передается. root.bind("lt;Leftgt;", left) — привязать клавишу со стрелкой влево к left function . Вот почему event это parameter fucntion так .

Ответ №3:

Альтернативный метод

 from tkinter import * root = Tk() root.title('Snake') root["width"] = 400 root["height"] = 400  field = Canvas(root)  SIZE = 50  class Snake:  def __init__(self,x,y,canvas):  self.x = x  self.y = y  self.canvas = canvas  self.direction = (SIZE,0)  def keypress(self,event):  if event.keysym == 'Right':  self.direction = (SIZE,0)  if event.keysym == 'Left':  self.direction = (-SIZE,0)  if event.keysym == 'Up':  self.direction = (0,-SIZE)  if event.keysym == 'Down':  self.direction = (0,SIZE)   def move(self):  self.x  = self.direction[0]  self.y  = self.direction[1]        def redraw(self):  self.canvas.delete('snake')  self.move()  self.canvas.create_rectangle(self.x,self.y,self.x SIZE,self.y SIZE,fill="green",tag="snake")    def update_screen():  snake.redraw()  root.after(1000,update_screen)  snake = Snake(0,0,field)   root.bind("lt;KeyPressgt;", lambda event: snake.keypress(event)) root.after_idle(update_screen) field.grid() root.mainloop()  

При этом используется объект для змеи с методами реагирования на нажатия клавиш и перерисовки змеи. Это удаляет существующие прямоугольники и рисует новые, а не перемещает (может оказаться более полезным для отображения различных сегментов змеи).

Преимущество этого метода заключается в том, что змею можно заставить двигаться независимо от того, нажал пользователь кнопку или нет. Если ни одна кнопка не была нажата, змея продолжит движение в том же направлении.

Как только у вас появится более сложная игра, я бы ожидал, что ваш класс змей будет содержать список различных сегментов змей, которые рисуются каждый раз. Когда змея перемещается по плоду, добавляется новый сегмент. Смотрите ниже для движущейся змеи с несколькими сегментами

 from tkinter import * root = Tk() root.title('Snake') root["width"] = 400 root["height"] = 400  field = Canvas(root)  SIZE = 10  class Snake:  def __init__(self,x,y,canvas):  self.x = x  self.y = y  self.canvas = canvas  self.direction = (SIZE,0)  self.segments = [(self.x,self.y)]  self.length = 5  def keypress(self,event):  if event.keysym == 'Right':  self.direction = (SIZE,0)  if event.keysym == 'Left':  self.direction = (-SIZE,0)  if event.keysym == 'Up':  self.direction = (0,-SIZE)  if event.keysym == 'Down':  self.direction = (0,SIZE)   def move(self):  self.x  = self.direction[0]  self.y  = self.direction[1]  new_segment = (self.segments[-1][0] self.direction[0],self.segments[-1][1] self.direction[1])  self.segments.append(new_segment)  if len(self.segments) gt; self.length:  self.segments.pop(0)      def redraw(self):  self.canvas.delete('snake')  self.move()  for seg in self.segments:    self.canvas.create_rectangle(seg[0],seg[1],seg[0] SIZE,seg[1] SIZE,fill="green",tag="snake")  #self.canvas.create_rectangle(self.x,self.y,self.x SIZE,self.y SIZE,fill="green",tag="snake")    def update_screen():  snake.redraw()  root.after(1000,update_screen)  snake = Snake(0,0,field)   root.bind("lt;KeyPressgt;", lambda event: snake.keypress(event)) root.after_idle(update_screen) field.grid() root.mainloop()  

Комментарии:

1. Это крайне неэффективно. Нет необходимости перерисовывать весь объект, чтобы переместить его. На холсте есть move метод, который можно использовать для перемещения существующего объекта. В конкретном случае игры со змеей все, что вам нужно сделать, это удалить последний сегмент и нарисовать новый сегмент спереди. . Нет необходимости перемещать все промежуточные сегменты.

2. @БрайаНоакли Согласился. Я перестал кодировать, когда был принят другой ответ.