Предыдущие части: Настройки игры, Игровые уровни, Строим глазки, Таблица рекордов, Шрифт, Остановите музыку, Включите звук, Жизни и модальные окна, Подсчёт очков, Главное меню, Геймплей, Есть ли у него душа, Организация ввода, View, Визуализация поля, Загрузка уровня, INI-файл, Пишем Питона на Питоне!
Код для этой части находится в ветке improvements на github. Вы можете смотреть там все файлы онлайн и также скачать зип-архив всей ветки.
В этом выпуске разберёмся с некоторыми назревшими доделками:
- Размер логотипа нужно адаптировать под разные разрешения экрана
- Хвост питона укорачивается очень медленно
- Управление должно быть более отзывчивым и исключать неправильное поведение питона
А теперь по порядку.
1. Размер логотипа
Логотип используется на нескольких игровых экранах, начиная с главного:
Сам логотип это картинка шириной 1280 пикселов:
Поэтому, если ширина экрана 1280 пикселов, то картинка будет занимать ровно ширину экрана. Если же ширина экрана будет больше, то справа от картинки появится пустое место. Если меньше – картинка будет усечена справа.
Чтобы логотип всегда находился по центру и не имел зазоров по краям, применим смешанную технику. Логотип будет состоять из центральной части:
и повторяющейся части:
Центральная часть будет располагаться всегда по центру, а с помощью повторяющейся части мы "замостим плиткой" отступы слева и справа до края экрана:
В общем, нарезаем нужные части и переписываем код. Лого присутствует в представлениях главного меню, настроек игры, таблицы рекордов, конца игры и ввода имени. Надо изменить 5 представлений... И тут мы можем заслуженно порадоваться, так как предусмотрительно отнаследовали все эти представления от одного LogoView, и значит исправить нужно только одно.
В конструкторе добавляем код, чтобы один раз отцентрировать логотип, и сохраняем его горизонтальную координату (logo_x) в отдельной переменной. В методе render() берём текущие координаты левого и правого края логотипа (left_side и right_side). Пока координата левого края больше нуля, сдвигаем координату влево на ширину плитки и рисуем плитку. На правой координате тоже рисуем плитку и сдвигаем координату вправо. Проверять её не нужно. Так как логотип расположен по центру, то справа поместится столько же плиток, сколько слева.
Теперь логотип всегда будет по центру и без зазоров, а на маленьких экранах (800*600) он будет обрезаться более красиво адекватно:
2. Хвост питона
Когда питон врезается в препятствие или идёт на выход, его хвост начинает укорачиваться. Пока хвост не укоротится полностью, ничего не происходит, игрок просто сидит и смотрит. Если хвост очень длинный, придётся смотреть довольно долго.
В контроллере GameController используется переменная speed, которая задаёт задержку перемещения питона. Она получена эмпирически и (пока) не регулируется. Идея состоит в том, что когда питон находится в состоянии, когда у него сокращается хвост, задержку надо уменьшать в два раза, например.
Это достигается добавлением одного условия, которое проверяет, в каком режиме находится питон, и прибавляет к счетчику либо полную задержку, либо половину.
3. Управление
С управлением связан один обидный нюанс. Питон ползёт со скоростью примерно 8 кадров в секунду. Значит, изменить направление движения он тоже может не чаще, чем 8 раз в секунду.
Контроллер GameController может назначать питону направление с любой частотой, но питон отработает это направление только раз в 1/8 секунды.
Следовательно, появляются "пропущенные направления". Происходит это так:
- Игрок оценивает ситуацию и решает быстро развернуться назад. Для этого он последовательно нажимает две стрелки. Например, питон ползёт вверх, а игрок нажимает вправо и вниз, чтобы развернуть его.
- Контроллер, получив стрелку вправо, назначает питону движение вправо. Затем, получив стрелку вниз, назначает движение вниз.
- Но питон не успел сдвинуться между двумя нажатиями стрелок. И когда ему наступает время двигаться, его направление уже установлено вниз. А направление вправо не было отработано. Так как питон двигался вверх, он начинает отрабатывать текущее направление и движется вниз, то есть наезжает сам на себя. И умирает.
Первоначальной идеей было буферизовать направления. То есть пока направления не отработаны, они накапливаются в буфере. Только после того, как питону настало время двигаться, из буфера берётся следующее направление.
Я, однако, решил попробовать по-другому и посмотреть, что получится. Решение простое: как только питону задаётся новое направление (которое отличается от текущего), счётчик задержки сбрасывается на ноль. И тогда питон сразу отработает это направление. Но в то же время это приведёт к тому, что питон в эти моменты будет двигаться быстрее – фактически с максимальной скоростью, с какой игрок может нажимать на стрелки. Я попробовал это сделать, и результат мне на самом деле понравился. Быстро меняя направление движения, можно заставить питона двигаться "ступеньками по диагонали" быстрее (похоже на распрыжку в Quake). Но и играть так сложнее. Если игроку так нравится, то пусть играет.
На этом пока всё. В следующем выпуске поработаем над балансом вознаграждений игрока и попробуем скомпилировать из проекта .exe-файл.
Читайте дальше: