Home > Software engineering >  How do I make the square move when a button is pressed on the keyboard? Tkinter, Python
How do I make the square move when a button is pressed on the keyboard? Tkinter, Python

Time:12-08

How do I make the square move when pressing the "d" button (for example) on the keyboard?

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("<KeyPress>", snake(x=x, y=y))

root.mainloop()

CodePudding user response:

An easy way is to use event.char. It returns the character of the button pressed. Then check which button it was and move it if it is 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("<Key>", snake)
root.mainloop()

CodePudding user response:

This is one way you can do it:

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("<Left>", left)
root.bind("<Right>", right)
root.bind("<Up>", up)
root.bind("<Down>", down)

root.mainloop()

First create root, and give geometry to it, in this case it is 450x450. After that create variables that will store height and width, and coordinates x and y. Then, create canvas (field) and in canvas specify where canvas will be located and geometry of canvas (and background color). When canvas is created, we create rectangle. Functions left, right, up and down will cover movement of rectangle on canvas. field.move(my_rectangle, x, y) - this line of code will move my_rectangle on canvas by x and y, or by left, right up or down, depends what is passed. root.bind("<Left>", left) - bind left arrow key to left function. Thats why event is parameter of fucntion.

CodePudding user response:

An alternative method

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("<KeyPress>", lambda event: snake.keypress(event))
root.after_idle(update_screen)
field.grid()
root.mainloop()

This uses an object for the snake with methods to react to key presses and redraw the snake. This deletes the existing rectangles and draws new ones rather than moving (might prove more useful for showing the different snake segments).

Advantage of this method, is that the snake can be made to move regardless of whether the user has pressed a button or not. If no button has been pressed the snake will continue in the same direction.

Once you have a more complex game, I'd expect your Snake class to contain a list of the different snake segments that get drawn each time. When the snake moves over a fruit, a new segment is added. See below for a moving snake with multiple segments

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) > 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("<KeyPress>", lambda event: snake.keypress(event))
root.after_idle(update_screen)
field.grid()
root.mainloop()
  • Related