И вот моя первая попытка выбраться на просторы Хабрахабр.
Недавно в свет вышла моя игра Evasion. Простая аркада, в которой нужно уклоняться от препятствия. Игра сама по себе легка в разработке, но в каждой простоте есть свои подводные камни. О парочке из них я и хочу поговорить в данной статье.
Красный шар движется в точку касания пальца.
Редактор уровней
Уровни в Evasion представлены в виде матрицы спрайтов, которые падают с определенной скоростью. Когда нижний ряд опускается ниже допустимых координат, он перемещается на самый верх. В итоге получается подобие конвейерной ленты. В момент перемещения меняются препятствия, соответственно и изображение на спрайтах. У каждого вида препятствия есть свой id. Информация об уровне хранится в двумерном массиве.
Таким способом меняются препятствия:
public static bool Next_M(int Series) // Получаем номер ряда { if (Set < 0) Set = 0; if (Set < mLvl) // Если уровень не закончился { // xR - количество столбцов в уровне for (int i = 0; i < xR; i++) { M_Load(Series, i, Level[i, Set]); // Меняем препятствия на те, которые содержатся в массиве Level } Set++; } else // Иначе финиш { for (int i = 0; i < xR; i++) { M_Load(Series, i, 0); } if (Finish) { Finish = false; return true; } } return false; }
Поначалу, чтобы создавать уровни, приходилось вводить стринговое выражение и его уже конвертировать в целочисленное значение.
Base[0] = "040900080205080202000204050000001500060001001515141314140706000705110704040004020406"; // Первый уровень во всей красе
Но быстро понял, что так дела не делаются. Процесс работы был медленным, муторным, а исправление ошибок каралось углубленным поиском иголки в стоге сена. Итогом стало решение создание быстрого и удобного редактора уровня.
Центральная лента опускается слайдами.
Редактор упростил разработку в несколько раз. Можно быстро построить уровень и там же его протестировать. И если в вашей игре есть возможность облегчить жизнь, создав редактор уровней, не поленитесь потратить на него своё время, оно того стоит. К тому же это можно преподнести, как дополнительную опцию в игре (если ваш редактор удобен в использовании обычным смертным).
Хоть редактор в Evasion присутствует, он только для ознакомления. Хотя и можно сделать сохранение уровней, возможность делится с друзьями и так далее. Но это уже совсем другая история…
Бесконечный режим
Не имея больших познаний в математике, рандоманая генерация уровня стала для меня непостижимой задачей. Единственным выходом было создание небольших блоков длиной в 3 – 5 спрайтов и их повторение. Скучная и нудная реализация, но другого выбора не было. Пока однажды, сидя в БФУ на паре математике, в голову не пришло одно единственное слово: множества!
Все препятствия можно разделить на множества:
- Все виды препятствий
- Все препятствия сверху (Подмножество первого массива)
- Все препятствия снизу
- Слева
- Справа
Те виды, у которых несколько препятствий попадают в несколько массивов сразу. Случайным образом узнаем, где вход, где выход и дистанцию между ними. Всё происходит в пределах одного ряда. В зависимости от дистанции узнаем, где и в каком месте исключить появление непроходимого места.
public static void Next_M(int S) { int Di = Math.Abs(In - Ou); // Узнаем дистанцию между входом и выходом if (Di == 0) // В зависимости от дистанции генерируем препятствие { List<int> Cut = Draw(0, 1); // 0 - исключаем препятствие снизу, 1 - сверху M_Load(S, In, Cut[StaticVolue.Rnd(0, Cut.Count)]); } else { List<int> Cut = new List<int>(); if (In > Ou) { Cut = Draw(0, 2); M_Load(S, In, Cut[StaticVolue.Rnd(0, Cut.Count)]); for (int C = In - 1; C >= Ou; C--) { if (C == Ou) { Cut = Draw(1, 3); M_Load(S, C, Cut[StaticVolue.Rnd(0, Cut.Count)]); } else { Cut = Draw(2, 3); M_Load(S, C, Cut[StaticVolue.Rnd(0, Cut.Count)]); } } } else { Cut = Draw(0, 3); M_Load(S, In, Cut[StaticVolue.Rnd(0, Cut.Count)]); for (int C = In + 1; C <= Ou; C++) { if (C == Ou) { Cut = Draw(1, 2); M_Load(S, C, Cut[StaticVolue.Rnd(0, Cut.Count)]); } else { Cut = Draw(2, 3); M_Load(S, C, Cut[StaticVolue.Rnd(0, Cut.Count)]); } } } } In = Ou; Ou = StaticVolue.Rnd(0, Matrix_Control.xR); }
static List<int> Draw(int A) { List<int> CellSet = new List<int>(); bool ice; for (int y = 0; y < AllCell.Length; y++) { ice = true; for (int i = 0; i < 9; i++) { if (AllCell[y] == EnterCell[A, i]) // Из всех видов исключаем те препятствия, которые содержатся в массиве A { ice = false; } } if (ice) CellSet.Add(AllCell[y]); } return CellSet; }
Вот такая реализация рандомного уровня получилась. Если у вас есть идеи, как это можно было бы сделать лучше, пишите в комментариях.
Музыкальное сопровождение
Хотелось сказать пару слов о музыке в игре.
Что, если ты студент и у тебя нету денег на хорошую музыку, а бесплатные варианты не устраивают? Тут есть два выхода: либо самому написать или же иметь хороших друзей, желательно со своей группой. Так уж получилось, что писать музыку самостоятельно я не умею, а вот с друзьями мне повезло.
Музыку для моей игры любезно предоставила наша местная Калининградская группа «Houston, we’ve got problems!» Для тех, кто любит post-rock, рекомендую ознакомиться с их творчеством.
На этом всё. Удачи всем в проектах.
ссылка на оригинал статьи http://habrahabr.ru/post/270655/
Добавить комментарий