Java Android. Урок 13 (“Делаем игру Salvador”)

Продолжаем делать игру, как мы её назвали “Salvador” (Спаситель).

Верю, что вы по честному делаете домашние задания, по этому уже поняли, что отсчет координат на экране выглядит так:

Само домашнее задание должно быть как-то так:

Тут для того чтобы всё было в порядке, основные переменные класса я вынес как общие. Сам код их объявления тоже немного изменил:

Заметьте, всё что можно посчитать сразу, я делаю во время создания GameEngine, потому что потом это будет некогда. Дело в том, что при работе onDraw нужно максимально быстро отработать всё, что связано по потоком пользовательского интерфейса (об этом я говорил на одном из прошлых уроков). По этому в момент отрисовки лишние вычисления нам не нужны. Казалось бы это мелочи, но они накапливаются и потом приводят к тому, что нужно делать ревизию кода и выявлять где что неоптимизированно, т.к. пользовательский интерфейс начинает подтормаживать.

Так, далее я изменил и сам метод onDraw() , сделал его таким:

)))….)))….ну да, так удобнее потом искать все проблемы. drawTopper() – это мой метод, который будет рисовать только ту верхнюю рамку со всеми её элементами. Когда будем тестировать, так будет удобно сразу понять в какой части программы глючит отображение элементов верхней рамки, а где самого игрового поля (не придётся судорожно лазить по коду чтобы что-то найти и тем более вспомнить через какое-то время где тут что находится). Ну и саму эту процедуру тоже я сделал немного по другому:

После чего получаем нужный результат.

Заметьте, для отрисовки белой рамки сканера я использовал drawLine() определенной толщины, а не drawRect(), по этому и методы инициализации в onCreate() немного отличаются. Для прямоугольника нужно определить метод заполнения внутри прямоугольника, а для линий – указать тип линий и их толщину.

Теперь давайте изобразим розового нематериального слона в вакууме космический корабль игрока, но не в конечном и неизменном виде, а пока в виде круга. Для этого, как можно догадаться, я тоже сделаю отдельный метод:

Инициализация будет такой:

, а объявление таким:

Обратите внимание на комментарий – это координаты корабля игрока НЕ на всём игровом поле, которое занимает сейчас 6 экранов (параметр areaScreenCount), а координаты только на экране. Дело в том, что корабль игрока никогда не должен выходить за пределы экрана, он им управляет и должен всегда иметь визуальный контакт с ним, но при этом координаты корабля в пространстве будут другие. Единственное исключение – это можно оставить координату Y для координат на экране и координаты в пространстве игрового поля пока одинаковыми, но кто его знает, может мы потом захотим и по вертикали сделать тоже самое.

Однако, продолжать тестировать будет проблемно, пока у нас нет ориентиров на экране. Хорошим ориентиром был бы ландшафт местности; Давайте его изобразим. Для начала мне понадобится новый класс, который я размещу прямо внутри MainAcrivity. Он будет хранить координаты, но не по отдельности, как это мы делали, например, для размера экрана (X и Y в различных переменных), а внутри одной переменной класса. Делаю я это исключительно для удобства (иначе пришло бы создавать два отдельных ArrayList):

ArrayList – это специальный объект Java очень похожий на массив, но не обладает какой-то размерностью. Т.е. его размер может динамически меняться. Работает он несколько медленнее, чем массив, по этому им злоупотреблять особо не стоит, однако пока он необходим. Дело в том, что мы сейчас точно не знаем какой у нас будет ландшафт и точно с этим не определились, ни размер, ни параметры; потом сделаем просто преобразование ArrayList в более быстродействующий объект – массив, и будем уже использовать его.

Итак, создали набор для хранения координат, давайте теперь автоматически сгенерируем ландшафт. Сделаю я это чуть сложнее, чем пареную репу (+ заодно добавлю инициализацию earthPaint для будущей отрисовки):

Заметьте, после основного цикла случайной генерации координаты по Y, я добавил ещё один элемент, взяв его из самой первой координаты. Как наверно вы уже догадались, это было сделано чтобы последний рельефный элемент по Y был точно таким же как и первый – чтобы вершина или впадина совпала, а рельеф Земли замкнулся в единую циклическую поверхность.

Переменна randObject, как можно догадаться, объявляется так:

Вывод на игровое поле будем слегка сложнее:

В результате получаем так:

Задание по уроку:

1. Изучите код отрисовки drawTopper(), вы должны хорошо понимать, что делает каждая определенная команде, какую линию рисует и почему параметры вычисляются именно так. Попробуйте произвольно изменить некоторые параметры и посмотрите на измение результата, как это отразится на изображении того или иного элемента.

2. Оптимизируйте алгоритм отрисовки ландшафта так, чтобы приложение не пыталось отрисовать точки, которые находятся за пределами экрана (их же всё равно не видно).

3. Создайте ArrayList для хранения координат космических кораблей инопланетян. Сгенерируйте 10 штук и условно их представьте тоже кругами:

Если всё получилось как нужно – молодцы! Если нет, давайте разберёмся что не так.

Урок 12 Урок 14

El Vinto, 2023 (Copyright)

Добавить комментарий