Сегодня я вам расскажу, как сделать аркадную игру-лабиринт.
Идея игры такова: по лабиринту бродит существо непонятной национальности, подбирает призы и закатывает чёрные шары в лунки. Когда все призы собраны и шары «рассованы» по лункам, существо должно добраться к выходу на следующий тур. Естественно, игра ведётся на время, сложность по мере прохождения туров возрастает. В общем, всё как в лучших домах Парижу и Лондона :). Вот как это выглядит во время работы:
Теперь давайте поговорим о реализации игры.
Карта игры будет храниться в массиве Discrразмером 20x15. В каждом элементе массива будет содержаться число, обозначающая какой элемент (главный герой, шар, пустое место) должен быть прорисован в данном месте карты. Также у нас будет массив Pictures 0x9 в котором будут храниться все графические фрагменты карты.Элементы массива Discr
как раз и ссылаются на индексы массива Pictures. Надеюсь, я понятно объяснил? К примеру у вас есть гипотетический метод Drawкоторый прорисовывает первый элемент карты, входным параметром которой должно быть графическое изображение:
Draw(Pictures[Discr[1, 1]]) .
Наши картинки будут размером 40x40 пикселей. Вот что будет содержаться в массиве Pictures:
0 - пустое пространство
1 - стена, обрамляющаялабиринт
2 - элемент стены из которых составлен лабиринт
3 - приз
4 - шар
5 - лунка для шаров
6 - выход закрытый
7 - выход открытый
8 - шар в лунке
9 - персонаж
Теперь поговорим о самих уровнях. Они будут закодированы в виде строки из тех же что и в массиве Discrчисел. Процедура-загрузчик карты будет разделять элементы строки и загонять их в массив.
В цикле выделяется память под графические элементы, которые затем подгружаются из внешних файлов. Далее вызывается процедура OnMap, Которая создаёт карту первого уровня и выводит лабиринт на экран. Эта процедура в зависимости от входящего параметра Levзагружает закодированный уровень из соответствующего компонента Text.
Дальше она посимвольно считывает строку и соответствующим образом записывает данные в массив Discr. Процедура Drawнастолько красива и лаконична, что приведу её текст целиком:
procedure TMain.Draw();
begin
x:=0;
y:=0;
For j:= 1 to 15 do
begin
For i:= 1 to 20 do
begin
Map.Canvas.draw(x, y, Pictures[Discr[i, j]].Graphic);
x:= x+40
end;
x:=0;
y:=y+40
end;
end;
А если заменить постоянные значения(15, 20, 40) переменными, передающимися как входные параметры, то процедура станет поистине универсальной.
procedure TMain.Draw(wid, hei, tile:integer);
begin
x:=0;
y:=0;
For j:= 1 to hei do
begin
For i:= 1 to wid do
begin
Map.Canvas.draw(x, y, Pictures[Discr[i, j]].Graphic);
x:= x+tile
end;
x:=0;
y:=y+tile
end;
end;
Эта процедура подходит для любой игры реализованной на основе массива!
Теперь рассмотрим, как наш персонаж двигается. Допустим, если в массиве Discrслева от позиции персонажа пусто, индекс с картинкой персонажа меняется с индексом картинки пустоты. Так же обрабатываются и остальные ситуации. Разберёмся, что значит
If Key = (vk_Left) then PersMove(-1, 0) else
If Key = (vk_Right) then PersMove(+1, 0) else …
Если подумать, перемещение персонажа вверх, вниз, влево, вправо операции одинаковые, если не считать различных приращений со знаками. Что и делается в процедуре PersMove.
Благодаря ей код обработки нажатия клавиш уменьшается в 4 раза.
Как мне кажется всё остальное довольно просто.
В данном алгоритме много нерациональных моментов, недоработок, но я сделал её как учебный проект, а не как полноценную программу.
Если что-то показалось вам непонятным, что-то не работает, или у вас есть конструктивные предложения, пишите мне.
До свидания!
Все отзывы, пожелания, предложения присылайте на glyclabs@mail.ru От вас зависит содержание рассылки, пишите! C уважением, Valar