Simply game/2: различия между версиями

Материал из ALT Linux Wiki
Нет описания правки
Нет описания правки
Строка 5: Строка 5:
|Tag            = программирование
|Tag            = программирование
|Section        = игры
|Section        = игры
|Issue          =01
|Issue          = 01
}}
}}
{{review-nav
{{review-nav

Версия от 21:13, 9 мая 2013

ALT-review logo.png


Как написать простейшую стрелялку, используя двумерные массивы

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

Логический уровень:

Игровое поле вписывается в один экран и соответствует двумерному массиву (допустим 50*50), по нему при помощи стрелок курсора двигается герой, по пути собирая чего-нибудь (алмазики, монетки — не принципиально что). Периодически в разных точках игрового поля возникают враги, которые через определенный промежуток времени производят в вас выстрел, если герой находится на одной горизонтали или вертикали с ними. Соответственно, врага надо уничтожить до того, как он пальнет в вас, а иначе — GameOver.

Пуляем, разумеется, тоже по горизонтали/вертикали при помощи клавиши Space. Когда все алмазы собраны, происходит переход на следующий уровень, где врагов становится больше или они быстрее стреляют. В общем, смысл нашей учебной игрульки примерно понятен :-)

Математический уровень:

Всё действие этой игры происходит в двумерном массиве байтов (50*50). Соответственно, в пустых клеточках массива записаны "0", в клетке с нашим герем — "1", в клетках с алмазиками — "2", в клетках с врагами — "3" (как видим, остается еще довольно много значений для врагов разного уровня, препятствий, аптечек и т.п.).

На будущее: По поводу аптечек. Герой может быть убит не с первого попадания, а, например, с третьего (вводим в прогу переменную живучести героя, которая при каждом попадании уменьшается на единицу и при достижении "0" происходит Game Over). Тот же способ действует и в отношении врагов, только там проще — при попадании во врага будем уменьшать значение в ячейке массива, допустим, с "5" до "3", а при попадании во врага с назначенным ему значением "3" в ячейку вписывается "0", то есть, вместо него возникает пустая клетка. Но эти украшательства я описывать не буду. Поняв общие принципы, вы легко сможете на базе этого скелета сделать довольно играбельную поделку (кстати, можно еще и препятствия добавить, тогда игрушка начнет очень отдаленно напоминать спектрумовскую How to be a Hero с замороженными неподвижными монстрами и одним игровым экраном).

  1. Для начала нам нужна подпрограмма, обнуляющая массив и по случайному принципу заполняющая его клетки несколькими алмазиками. Она же выставляет начальные координаты нашего героя и записывает в соответствующую ячейку "1". Далее надо написать основное тело программы и прибить его гвоздями к таймеру.
  2. После того, как первая подпрограмма произвела инициализацию массива, включается таймер. Он генерирует раз в несколько секунд (допустим в 10) нового врага в свободную ячейку массива, выбираемую по случайному закону (понятно, что эта ячейка должна быть пустой, т.е. в ней записан "0"). Раз в 5 секунд тот же таймер запрашивает координаты героя (допустим они будут X,Y) и проверяет горизонталь (все ячейки массива от [0,Y] до [49,Y]) и вертикаль (ячейки от [X,0] до [X,49]) на наличие врага. Если на них обнаруживается хоть один враг, то он производит выстрел (надо написать красивую подпрограммку, которая при помощи спрайтов и звуков все это достойно оформит, но это уже привязано к конкретному языку, например, связка Python+PyGame отлично подходит для подобных задач). На самом деле это очень упрощенный алгоритм выстрела. Пока я писал всю эту теорию, придумал более правильный, но для учебной стрелялки он подходит плохо ввиду своей сложности.

Уровень взаимодействия с пользователем:

Всё, что касается нашего главного героя, его перемещений и стрельбы я вынес в этот уровень. На самом деле, сюда цепляется изрядный кусок математического уровня, что вполне естественно, ведь любые деления условны и эта структура сделана для упрощения труда кодера [для представителей младшего поколения объясню, что кодер – это человек, который пишет код :-)]

Итак, при нажатии стрелочек наш герой поворачивается и идет в соответствующую сторону, при нажатии на пробел он в эту же сторону стреляет (спецэффекты на вашей совести, мое дело — скелет программы).

Нам нужны следующие подпрограммы:

  1. Программа, рисующая игровое поле на экране, отрисовывающая алмазики и текущее положение героя (при его изменении). Эта же программа отрисовывает и новых врагов при их генерации таймером математического уровня (то есть, она приводит в соответствие изображение на экране c содержанием вашего массива).
  2. Обработчик событий, отслеживающий ваши манипуляции с клавиатурой после проверки граничных условий [а то ваш герой убежит за границы массива и лови его потом по монитору :-)] и наличия свободного поля в направлении движения (в ячейке массива должен быть "0" или алмазик "2", который увеличивает значение переменной «богатства» героя). При соблюдении этих условий герой перемещается на следующее поле (записывая по старым координатам "0", а в ячейку, соответствующую новому положению, — "1"). При нажатии пробела происходит выстрел в направлении движения, заключающийся в проверке содержания соответствующих клеток массива в этом направлении на наличие в них врага (идею можно подглядеть в последнем пункте Математического уровня). Только проверка (выстрел) делается не по 4-ём направлениям как для врага, а только в направлении движения.

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

Ботинки Билла

На будущее: Конечно, обработчик на первое нажатие стрелки должен (по идее) поворачивать героя в соответствующем направлении и только на следующее нажатие делать шаг вперед героем в этом направлении. Ведь это поле может быть занято, что не даст нашему герою развернуться на месте и пальнуть во врага. Получается довольно неприятная коллизия, но это проблема не большая, думаю, вы её решите, если будете писать подобную программу. Чтобы у вас не возникало мыслей, что я чистый теоретик, вот вам простая пулялочка на очень хорошей связке Python+PyGame (рекомендую всем писателям игр) http://kostyalamer.narod.ru/pygame03/pygame03.html

Понятно, что на учебную прогу и алгоритм, который я сочинил для этой статьи, она не похожа, но кое-какие общие элементы есть (например, процедура bah хорошо вписывается в контекст этой статьи). К тому же, в листинге я оставил немножко комментариев — если уж дочитали до этого места, то наверняка разберетесь при желании.


Будем считать тему написания простейших игрушек при помощи массивов законченной, остальное уже додумаете сами. Я же довольно давно закончил с игрушками (эти статьи дань спектрумовской молодости) и занялся совершено другими аспектами программирования (программирование апплетов для WindowMaker на python-е, но это уже совсем другая история, вряд ли интересная нашим читателям).

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

С уважением, Константин Коган (kostyalamer) __SHOWFACTBOX__