#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. @БрайаНоакли Согласился. Я перестал кодировать, когда был принят другой ответ.