Рисование и анимация в TkInter

Испольуем Canvas

В процессе работы над вторым проектом мы успели познакомится с библиотекой tkInter. В этом разделе мы научимся рисовать и передвигать объекты, а затем - создадим несложную компьютерную игру. Начнем же! 🏎

Для рисования в окне tkInter, в него нужно добавить Canvas - холст.

from tkinter import *

tk = Tk()
# создаем холст размером 640 на 640 пикселей с белым фоном внутри основного окна
c = Canvas(tk, width=640, height=640, bg='white')
c.pack()

# тут будет код для рисования

mainloop()

На холсте мы сможем рисовать прямоугольники, произвольные многоугольники, линии и овалы.

Полная документация - http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html (Раздел 8).

Рисуем дом

Начнем с простых геометрических фигур. Вот как устроено рисование прямоугольника:

А вот так - треугольника:

Если совместить вместе, то получится... дом! 🏠

from tkinter import *

tk = Tk()
c = Canvas(tk, width=640, height=640, bg='white')
c.pack()

# рисуем прямоугольник зеленого цвета
c.create_rectangle(30, 60, 130, 120, fill='green')

# рисуем треугольник (полигон с тремя вершинами) синего цвета
c.create_polygon(30, 60, 80, 10, 130, 60, fill='blue')

mainloop()

Как сделать его лучше? Напиши программу, которая рисует домик с заданными размером, цветом крыши и первого этажа по нажатию кнопки. Для ввода размеров и цветов используйте Entry. Для очистки canvas можно использовать команду c.delete("all").

Деревня

А теперь супер-задание - используй циклы, чтобы нарисовать целую деревню!

Анимация

Теперь мы можем комбинировать геометрические фигуры, но вот только для игры этого недостаточно - объекты должны двигаться! Для начала научимся рисовать овалы:

Для того, чтобы оживить наш рисунок, нам нужно научится перемещать объекты. Для этого используется функция move.

from tkinter import *

tk = Tk()
c = Canvas(tk, width=640, height=640, bg='white')
c.pack()

# сохраняем номер соданной фигуры в переменную
my_favorite_oval = c.create_oval(0, 0, 50, 50, fill='blue')

def moveBall():
    # передвигаем наш овал на 10 пикселей по обеим осям
    c.move(my_favorite_oval, 10, 10)
    # повторяем через 100 мс (1 секунда)
    c.after(100, moveBall)

# спустя 1 секунду (100 мс) после запуска выполнить moveBall
c.after(100, moveBall)

mainloop()

Отталкиваемся от стен

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

Что дальше?

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

Но вот только для этой игры метеоритов нам понадобится много, а заводить отдельную четверку переменных для каждого из десятка метеоритов - неудобно. Хорошо бы как-то хранить их в одном месте. И так правда можно, для этого используются списки.