Как написать свою змейку на Java за 15 минут

В предыдущей статье мы писали сапёра за 15 минут, теперь займёмся классической змейкой.

В этот раз нам снова понадобятся:

  • 15 минут свободного времени;
  • Настроенная рабочая среда, т.е. JDK и IDE (например Eclipse);
  • Библиотека LWJGL (версии 2.x.x) для работы с Open GL. Обратите внимание, что для LWJGL версий выше 3 потребуется написать код, отличающийся от того, что приведён в статье;
  • Спрайты, т.е. картинки самой змеи и фрукта, который она будет есть. Можно чисто символически нарисовать самому, или скачать использовавшиеся при написании статьи.

Подключение библиотек

В прошлый раз у многих возникли с этим вопросом проблемы, поэтому мне показалось уместным посвятить этому немного времени. Во-первых, выше я дал ссылку на скачивание архива с библиотеками, которые использую я, чтобы не было путаницы с версиями и вопросов, где найти что-то. Папку из архива требуется поместить в папку проекта и подключить через вашу IDE.

Во-вторых, у многих пользователей InteliJ IDEA возникли проблемы как раз с их подключением. Я нашёл в сети следующий видеогайд:

После того, как я сделал всё в точности по нему, у меня библиотеки подключились корректно и всё заработало.

Работа с графикой

С этой стороны наша задача мало отличается от той, что мы выполняли при написании Сапёра. Снова создаём класс GUI, который будет хранить и обновлять состояние всех графических элементов. Если точнее:

  • Класс будет выполнять инициализацию OpenGL:
  • Должен хранить текущие состояния ячеек:
  • Должен отрисовывать эти самые ячейки:
  • И обновляться, когда этого запросит главный цикл:

Как вы можете видеть, здесь я уже использовал несколько констант. Для них был создан отдельный класс Constants с public static полями. Вот он целиком:

Enum Sprite, который отвечает за подгрузку текстур, полностью идентичен тому, что мы писали для Сапёра, за исключением того, что нам нужно только две текстуры — для змеи и для ягод. Вот код:

Механика игры

Самое время поговорить о том, как наша змея будет, собственно, перемещаться. Вам наверняка доводилось видеть вывески, вокруг которых по кругу бегают огоньки? Разумеется, сами лампочки в них не перемещаются, просто каждый тик последняя гаснет, а первая зажигается. Таким же образом будет перемещаться и наша змея.

Несложно подсчитать, что каждая лампочка должна гореть столько тиков, какова длина «змеи». Значит, мы должны сообщить клетке, в которую попадает змея, что она должна гореть определённое количество секунд, а каждый тик уменьшать это число у каждой клетки с ненулевым таймером, и менять спрайт, если змея из клетки уже выползла (т.е. таймер стал равен нулю). В случае же необходимости удлинить цепочку, достаточно просто не уменьшать время «горения» клеток на каком-то тике. Именно поэтому метод update() у классов Cell и GUI принимает параметр — если он равен false, значит, змея что-то съела.

Пишем класс клетки

Добавляем геттер и сеттер для состояния клетки поля в GUI

Добавляем метод, создающий начальное поле в GUI

Просто инициализируем OpenGL, затем массив Cell[][] cells и заполняем последний клетками со случайным полем state.

Главный управляющий класс

Готово!

P.S. Исходники можно скачать здесь (архив всей папки проекта).

Пётр Соковых, транслятор двоичного кода в русский язык