Суть игры простая: прыгать с платформы на платформу и продержаться как можно дольше.
Первое, с чего нужно начать — это анимация. Изображать джампера будем простым кругом. Перед тем, как мы заставим его прыгать, научим его двигаться.
canv = Canvas(root, bg = 'white' ) |
canv.pack(fill = BOTH,expand = 1 ) |
jumper = canv.create_oval(x - r,y - r,x + r,y + r) |
Попробуем заставить его двигаться:
canv = Canvas(root, bg = 'white' ) |
canv.pack(fill = BOTH,expand = 1 ) |
jumper = canv.create_oval(x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Мяч двигается, но мы этого не видим. Дело в том, что все происходит слишком быстро. Замедлим процесс
canv = Canvas(root, bg = 'white' ) |
canv.pack(fill = BOTH,expand = 1 ) |
jumper = canv.create_oval(x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Оказалось, дело было не только в том, что изображение менялось слишком быстро. Оно вообще не менялось! И появилось только после того, как сработала команда mainloop()
Чтобы показать изображение раньше будем использовать canv.update()
canv = Canvas(root, bg = 'white' ) |
canv.pack(fill = BOTH,expand = 1 ) |
jumper = canv.create_oval(x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Вот теперь видно, что круг немного двигается. Добавим цикл:
canv = Canvas(root, bg = 'white' ) |
canv.pack(fill = BOTH,expand = 1 ) |
jumper = canv.create_oval(x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Теперь надо увеличить скорость смены кадров, т.е. уменьшить задержку. time.sleep(0.03)
будет в самый раз.
Если вы заметили мерцание, то сразу сообщу, что с мерцанием мы бороться не будем, просто смиримся с ним. Для создания игр больше подходят другие пакеты (pygame,kivy,..) но на данный момент наша задача — это обучение, а не создание красочных игры. Поэтому мы ограничимся tkinter’ом и не будем обращать внимание на мерцание. Kivy будет, но немного позже.
А теперь сделаем так, чтобы шарик менял скорость:
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Это первый способ замедления. Обратите внимание, что скорость становится отрицательной и круг начинает двигаться в обратном направлении. Это очень скоро нам пригодится для вертикальной составляющей скорости. А для горизонтальной больше подойдет другой способ:
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Теперь отработаем составляющую часть движения:
jumper = canv.create_oval(x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Как сделать так, чтобы шарик остановился в нижней части экрана? А лучше отскочил от нее и подпрыгнул вверх? Подсказка: используйте цикл while
**** тут должен быть спойлер *****
jumper = canv.create_oval(x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Теперь объединим движение по вертикали и по горизонтали:
jumper = canv.create_oval(x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Отскоки должны быть затухающими, чтобы после удара круг отскакивал вверх не на такую же высоту, а примерно на 70% от первоначальной высоты:
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Не очень-то получилось, правда?
Дело в том, что когда круг уходит ниже, чем 550, то он не всегда может вернуться обратно из-за того, что его обратная скорость стала меньше, чем была.
Например, при скорости 20 круг может пройти по таким координатам: 548, 568. В этот момент мы разворачиваем его, но скорость уменьшаем -20*-0.7 = 14 и он из 568 переходит в точку с y = 568-14 = 554, что ниже, чем 550. Все, круг попался: опять сработает условие y > 550 и опять мы развернем его. Результат вы уже видели.
Решение простое:
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Ну вот, теперь вылезла другая проблема: он прыгает и не успокаивается. Математическую сторону этой проблемы я предлагаю вам увидеть самостоятельно, я же дам самое простое решение:
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Jumper падает с ускорением, как положено, отскакивает, замедляется и … продолжает скользить по горизонтали. Смотрится не очень хорошо, не так ли?
canv.coords(jumper,x - r,y - r,x + r,y + r) |
Ну вот теперь просто замечательно! В момент касания земли джампер будет замедлять горизонтальную скорость, чтобы не скользить.
Теперь заставим его прыгать по щелчку мыши. Вы помните, как назначить обработку события? Как определить щелчок мыши на холсте?
***** тут должен быть спойлер *****
canv = Canvas(root, bg = 'white' ) |
canv.pack(fill = BOTH,expand = 1 ) |
canv.bind( '<1>' ,click) |
jumper = canv.create_oval(x - r,y - r,x + r,y + r) |
canv.coords(jumper,x - r,y - r,x + r,y + r) |
После того, как мы убедились, что щелчок мыши обрабатывается, можно начинать «пинать» джампера:
Остановим движение по горизонтали:
Добавим немного понимания геометрии, чтобы джампер прыгал в сторону мыши (это проще, поэтому начнем с такого варианта).


Чтобы рассчитать значение скорости мы найдем расстояние между точками и возьмем скорость как 1/10 этого расстояния.
На самом деле немного проще, так как составляющие скорости у нас две: vx и vy (скорость по горизонтали и скорость по вертикали). Находим проекцию расстояния между точками на оси, берем 1/10 часть от них — это и будут соответствующие значения скоростей.
1. Повторить все столько раз, сколько потребуется для понимания кода.
2. Повторить все столько раз, сколько потребуется, чтобы вы могли сами написать этот код.
Следующий урок будет сложнее: мы будем создавать движущиеся платформы. Если вы до конца не понимаете то, что сделано в этом уроке или не можете сами это повторить, то следующий урок будет просто наслоением непонимания. Повторите этот код, даже если для этого потребуется переписывать его 10 раз. (когда-то давно я запомнил с 15-го, несмотря на то, что придумал все это сам)
3. Добавьте цвет джамперу и фону.
4. Поиграйте со значениями скорости и ускорением падения. Сейчас он падает слишком медленно, на мой взгляд.
5. Сделайте отскок от стен слева и справа.