Как сделать интересный платформер
Разработка уровней для платформера
В предыдущей статье я представил вам 11 советов по созданию веселого платформера. В статье были даны общие советы, которые охватывали широкий круг задач игрового дизайна. Данная же статья рассматривает конкретно процесс разработки уровней для платформера. Этот процесс содержит методические рекомендации и охватывает пункты от начальной идеи до заключительного игрового уровня.
Эта статья не рассказывает о планировании. Однако, вы должны помнить о нем, проектируя уровни. Размер уровня и количество ресурсов, которое он содержит напрямую зависит от числа людей, работающих над ним, а так же от времени, данного на его завершение.
1. Определитесь с визуальной темой
Выберите визуальную тему для уровня. Вы можете выбрать устоявшуюся, широко распространенную среди игр, тему, такую как ‘Лес’, ‘Лед’, ‘Лава’ или ‘Замок’. Или сотворите что-то более творческое, например ‘Завод по созданию клонов в стиле стимпанк’, ‘Страшный сон психолога’ или ‘Кафе-мороженое Купидона’. Спросите мнение о визуальной теме всех в вашей команде.
2. Составьте список
Составьте список того, что игрок должен испытать на уровне: все, что он делает, видит, узнает, слышит и с чем сталкивается. Список должен включать в себя особые и обычные предметы.
В течении всей статьи под термином «предмет» будет пониматься предмет из списка. Это не только игровой предмет (бонусы, ключи, двери), но и события (обнаружение первой запертой двери), враги, и игровая механика (двойной прыжок).
Запишите сколько раз встречается обычный предмет (например, на уровне нужно собрать 50 монет или игрок должен победить 10 фехтовальщиков). Эти цифры приблизительны и они помогут вам определить сложность уровня. Например, на первом уровне могут быть два опасных тролля, а на втором уровне их будет четыре. Позвольте всем членам команды внести свой вклад в список.
Следующие примеры используются в изображениях, включенных в эту статью:
Особые предметы:
Обычные предметы:
3. Сделайте приблизительную схему
Набросайте очень приблизительную схему всего уровня. Эта схема должна показать весь путь, который игрок проделает за уровень. Считайте это проектировочной схемой улиц города, только без зданий.
Вы можете сделать несколько схем прежде, чем остановитесь на одной. Обычно, причина изменения схемы одна из:
Приблизительная схема целого уровня
4. Сделайте приблизительные наброски особых предметов
Игроки должны найти каждый предмет из списка, который вы создали в пункте 2, где-то на уровне. Также они могут найти несколько предметов в одной области. Сделайте приблизительные наброски каждой области, в которых игрок найдет особые предметы из списка.
Используйте символы, чтобы обозначить различные объекты на уровне, например «E» для «врагов», «P» для «бонусов», «К» для «ключей», «L» для переключателя, «D» для дверей. Также делайте записи на своих набросках.
При создании наброска четко разграничьте отрицательное и положительное пространство. В отрицательном пространстве (на наброске обозначено белым цветом) игрок может двигаться, когда как положительное пространство (отмечено диагональными линиями) представляет собой пол, стены, платформы, где игрок не может двигаться.
Эти эскизы помогут вам сосредоточится на расположении каждой маленькой области, не волнуясь о том, помещаются ли они в полную схему уровня. Думайте об этом, как о проектировании здания, полностью игнорируя его местоположение.
Вы можете сделать эскизы для некоторых или всех обычных предметов, но это не обязательно. Обычные предметы перемещаются при более подробной схеме или при тестировании уровня, в конце они могут оказаться совершенно в других местах, чем планировалось.
Примеры приблизительных эскизов
Особый предмет 1: Первая встреча с врагом.
Особый предмет 2: Обнаружение первого бонуса.
Особый предмет 3: Изучение двойного прыжка.
Особый предмет 4: Изучение разрушаемой окружающей среды.
Особый предмет 5: Нахождение первой запертой двери.
Особый предмет 6: Нахождения ключа для запертой двери.
Особый предмет 7: Использование рычага, чтобы активировать движущуюся платформу.
5. Сделайте детальную схему
Нарисуйте подробную схему уровня. Используйте приблизительную схему (из пункта 3) как направление. Подробная схема должна включать в себя все особые предметы (скопируйте наброски из предыдущего пункта) и обычные предметы. После копирования набросков вам, возможно, понадобится их слегка изменить (например, изменить размер, отразить по горизонтали).
Поместите столько обычных предметов в детальную схему, сколько сможете. Оставшиеся обычные предметы будет можно добавить при построении уровня в редакторе.
Пример детальной схемы.
Местоположение определенных пунктов на детальной схеме.
6. Постройте первоначальный план
Используйте редактор уровней, чтобы построить первоначальный план, используя детальную схему (из предыдущего шага) как чертеж. При постройке, возможно, понадобится изменить размер некоторых областей. Это происходит потому, что набросок не вычерчен в масштабе. Также используйте редактор, чтобы добавить все оставшиеся обычные предметы на уровень. Например, в вашем списке 20 врагов, но на детальном плане их всего 15. Добавьте остальные 5 на данном этапе.
Постройте первоначальный план прежде, чем будете добавлять все визуальные детали. Другими словами, используйте ограниченное количество графики в первоначальном плане, чтобы иметь возможность легко что-то изменить. Например, если у вас есть пять изображений с травой, используйте только одно для первоначального плана. Вы сможете добавить оставшиеся четыре в пункте 8, тем самым украсив уровень.
В этом пункте графика уровня может быть незавершенной, в этом случае можно использовать «заполнитель» графики. Это хорошее решение, если «заполнитель» имеет схожие цвета с конечной графикой, потому, что цвета влияют на ощущение уровня.
7. Сыграйте в уровень
Первоначальный план предназначен для того, чтобы сыграть в уровень и определить насколько он забавный и как много у игрока займет времени, чтобы пройти его. Сыграйте в уровень и сбалансируйте свой план. Дайте другими сыграть в свой уровень.
Изменения в плане могут заключаться в следующем:
Важное примечание: к тому времени, как вы спроектируете и построите уровень, механика геймплея должна быть смоделирована и доведена до ума, с использованием временного уровня для тестов. Если к тому времени ваш геймплей не был согласован, есть риск, что вам придется изменить свои уровни при изменении геймплея. Например, вы решили, что игрок должен прыгать выше, тогда вам придется переместить множество платформ, чтобы подогнать их под новую высоту прыжка. Изменения геймплея обычно приводят к дальнейшей цепочке изменений по принципу домино.
8. Украсьте уровень
Как только вас будет устраивать планировка уровня и его играбельность, останется лишь добавить детали, включающие финальную графику и звук. Пройдите уровень заново, чтобы убедится в том, что ваши ощущения не изменились, после добавления всей графики. Есть вероятность, что уровень будет воспринят по другому: либо лучше, либо хуже. Например, задний фон был однотонный, а финальный фон состоит из детализированной картинки, из-за которой становится трудно разглядеть врагов. В этом случае следует изменить оттенок фона или изменить врагов, в зависимости от того, что окажется быстрее.
Дополнительная литература
Супер братья Марио 3 – Уроки дизайна уровня (Radek Koncewicz)
Уроки дизайна уровня (Anna Anthropy)
Создаем платформер за четыре вечера
Сразу оговорюсь: речь пойдет о гейм-девелопменте для души. Чтобы не стыдно было показать игру миру — придется попотеть подольше.
Как и многие, я стал программистом из-за детской мечты написать собственную игру. Со временем я посвятил себя другой области, но однажды решил во что бы то ни стало воплотить мечту в жизнь. Здесь я хочу поделиться своим опытом, чтобы, возможно, вдохновить вас.
1. Цель
Моей целью было создание классического платформера, но с такими сюжетом, персонажами и уровнями, которые интересны мне. Я хотел сделать игру своими силами и специально для себя; при этом сделать ее с минимальными затратами сил и своего свободного времени.
2. Поиск инструментов
Конечно, создавать геймплей с нуля неразумно. Я начал с поиска конструкторов и сред разработки игр и нашел достаточно большой список на сайте [http://gcup.ru/load/konstruktory_igr/12]. Отдельного внимания хочу удостоить конструкторы, позволяющие быстро создать тематические игры: например, Open Zelda [http://openzelda.net/] или Mario Worker [http://www.softendo.com/game/Mario%20Worker]. Настоящий клад для фанатов.
Не редкость и конструкторы, которые позволяют создавать игры классических жанров (в том числе и платформеры), и при этом вообще не требуют навыков программирования. Например, 001 Game Creator [http://www.engine001.com/] или Rune Sword [http://www.runesword.com/].
При всей своей функциональности, подобные конструкторы в некоторой мере ограничивают творца в возможностях. Кроме того, большинство фич этих инструментов, таких как портирование игр на Андроид, платные.
Среди прочих средств проектирования игр, мое внимание привлек Tululoo Game maker [http://tululoo.com/].
Преимущества налицо: полностью бесплатный инструмент, объединяющий в себе удобство готового движка с вариативностью программирования специфических аспектов игры. К тому же, готовая игра представляет собой веб-страницу на HTML5 с javascript, что позволяет выложить игру в интернет. Самым большим неудобством можно считать отсутствие отладчика. И все же, это вариант отлично решает мою задачу, поэтому на нем я и остановился.
3. Быстрый старт в Tululoo Game maker
Для тех, кто заинтересовался созданием игры с помощью Tululoo Game Maker, я рассмотрю несколько этапов работы для более быстрого и приятного старта.
4. Редактирование персонажа
Следует отметить, что в коде объекта obj_player сосредоточена основная механика игры — через взаимодействие игрока с остальными объектами игрового мира. Событие Step выполняется по таймеру каждый кадр; количество кадров в секунду настраивается при редактировании уровней (я принял значение по умолчанию — 60 кадров в секунду). Сейчас в событии Step обрабатывается нажатие клавиш и столкновение игрока с объектами ландшафта. Первым делом заменим изображение игрока на нашего героя. Нового персонажа я нарисовал в пэинте в двух вариантах: смотрящим влево и вправо, и добавил получившиеся рисунки в спрайты на вкладке Sprites. После загрузки каждой картинки по кнопке Edit можно перейти к редактированию изображения, где есть полезная опция Erase color, — с помощью нее можно стереть фон, добившись тем самым правильного контура.
Теперь необходимо вернуться к редактированию объекта obj_player и указать для него один из новых спрайтов.
Поработаем с кодом: научим объект игрока поворачиваться влево и вправо. Для этого будем менять картинку персонажа между левосторонней и правосторонней, используя свойство sprite_index (более полное описание API можно увидеть в хелпе).
obj_player событие Step:
В самом начале кода редактируем строки:
Запускаем и радуемся. Анимацию шагов делать сложнее, поэтому не буду рассматривать здесь эту процедуру.
5. Добавление объектов
Код игрока придется подредактировать: при контакте со снарядом противника obj_player будет уничтожаться. Также вынесем объект игрока в глобальную переменную.
obj_player событие Creation:
obj_player событие Collision with obj_enemy_bullet:
obj_enemy_1 событие Creation:
obj_enemy_1 событие Step:
6. Редактирование уровней
Последний шаг, важный для создания полноценного платформера — создание уровней. В Tululoo для этого весьма простой интуитивно понятный интерфейс: в конструкторе на вкладке Scenes набрасываем нужные объекты в игровую зону — и готово. Конечно, дизайн уровней — важный и самый трудоемкий процесс. Здесь настоящий простор для воображения.
Отдельно опишу часть кода, отвечающую за переключение между уровнями. Для это используется функция room_goto_next (более полное описание API можно увидеть в хелпе).
obj_player событие Step:
Заменим последнюю строку кода на:
Результирующий код этого события будет выглядеть так:
obj_player событие Step:
7. Резюме
Существует множество способов простого создания игры своей мечты. Я разобрал лишь один из них; возможно, кто-то сможет найти более удобные инструменты, — прошу оставлять ваши отзывы о них в комментариях. Желаю Вам творческих успехов!
Создаем платформер за 30 минут
Здравствуйте! Сегодня мы будем писать платформер, используя C++, Box2D и SFML, а также редактор 2D карт для игр Tiled Map Editor.
Вот результат (карта создавалась 5 минут + во время сьемки игра тормозила + экран не так растянут — дефект Bandicam):
Исходники и exe — внизу статьи.
Что, где, когда?
Box2D
Эту библиотеку мы будем использовать для симуляции физики в платформере (столкновение с блоками, гравитация). Возможно, не стоило для одних только блоков юзать эту библиотеку, но красиво жить не запретишь 😉
Почему именно Box2D? Потому что это самая распространенная и бесплатная физическая библиотека
Почему SFML? Вначале я хотел использовать библиотеку SDL, но она сильно ограничена в возможностях по сравнению с SFML, многое пришлось бы дописывать самому. Спасибо автору SFML за сэкономленное время!
Ее используем для отрисовки графики
Tiled Map Editor
Что делает тут Tiled Map Editor?
Вы когда-нибудь пробовали создавать карты для игр? Спорим, что вашей первой картой было что-то наподобие такого.
Это довольно неэффективное решение! Гораздо лучше написать что-то вроде редактора карт, но задним числом мы понимаем, что это не делается за 5 минут, а приведенная выше «карта» — вполне.
Создание карты
Скачиваем TME с официального сайта
Создаем новую карту «Файл->Создать. »
Ориентация должна быть ортогональной (если вы не делаете изометрический платформер), а формат слоя XML, мы будем считывать именно этот формат
Кстати, ни формат слоя, ни размер тайлов нельзя будет поменять в созданной карте.
Тайлы
Затем идем в «Карта->Новый набор тайлов. », загружаем наш тайлсет:
В итоге у вас получится что-то вроде этого:
В чем смысл слоев тайлов?
Почти в каждой игре есть многослойные карты. Первый слой — земля (лед, чернозем, etc), второй слой — здания (казармы, форт, etc, причем фон прозрачен), третий — деревья (ель, пихта, etc, фон тоже прозрачен). То есть рисуется сначала первый слой, поверх него накладывается второй слой, а потом уже третий.
Процесс создания слоев запечатлен на следующих 4 скриншотах:
Объекты
Что такое объект в TME?
Объект имеет свое имя, тип, а также параметры со значениями.
За объекты отвечает эта панель
Вы вполне можете узнать, что делает каждая из кнопок, сами.
Теперь попробуем создать объект.
Удаляем слой «Колобоша», вместо него создаем слой объектов, допустим, с тем же названием «Колобоша». Выбираем «Вставить тайл-объект» из панели для объектов (или можете выбрать любую фигуру — Shape), нажимаем на тайл Колобоши и просто ставим объект в какое-нибудь место.
После чего нажимаем правой кнопкой мыши на объект и нажимаем на «Свойства объекта. ». Измените имя объекта на Kolobosha.
После чего сохраните карту.
В общем, ничего архисложного в редакторах карт нету. Пора переходить к считыванию карты.
Считывание карты
Для считывания XML файлов создана отличная библиотека TinyXML, скачайте ее исходники.
Создайте проект Visual Studio. Подключите файлы TinyXML (или просто запихайте все эти файлы в проект, за исключением xmltest.cpp 🙂 )
Теперь подключаем includ’ы и lib’ы SFML в «Проект->Свойства». Если не знаете, как это делать — добро пожаловать в Гугл
Создаем Level.h для карт
Дальше идет структура объекта
Разберем её.
Как уже говорилось, в TME каждый объект может иметь параметры. Параметры берутся из XML файла, записываются в properties, и потом их можно получить любой из первых трех функций. name — имя объекта, type — его тип, rect — прямоугольник, описывающий объект. И наконец, sprite — спрайт (изображение) — часть тайлсета, взятая для объекта. Спрайта может и не быть.
Теперь идет структура слоя — она очень проста
В слое есть прозрачность (да, да, мы можем делать полупрозрачные слои!) и список из тайлов.
Дальше идет класс Level:
LoadFromFile загружает карту из указанного файла. Это сердце класса Level.
GetObject возвращает первый объект с указанным именем, GetObjects возвращает список объектов с указанным именем. Вообще-то, по-хорошему, следовало использовать тип (type) объекта, но мне было удобнее вылавливать блоки и игрока через имя, так как в редакторе имя показывается сверху объекта, а тип — нет.
Draw рисует все тайлы (не объекты!), беря себе экземпляр RenderWindow.
Теперь создаем Level.cpp:
Первым мы обрабатываем структуру объектов
Для Layer реализация не нужна, переходим к Level:
Остальные функции Level:
Протестируем его.
Создаем main.cpp и пишем:
Карта может выглядеть как угодно!
Можете поиграться с объектами:
Когда вы наиграетесь с объектами, наступит пора Box2D:
Коробки-коробочки
Мы хотим создать 3D-экшон платформер, суть такова…
На карте расположены объекты — с названиями player — игрок, enemy — враг, block — блок, money — монетки.
Мы загружаем игрока, заставляем его повиноваться нажатиям клавиши и силе Ньютона.
Враги ходят туда-сюда, отталкивают слишком близко находящегося игрока и погибают, если игрок прыгает на них
Блоки закрепляются «в воздухе» как статичные объекты, на них игрок может прыгать
Монеты ничего не дают, просто исчезают при столкновении с игроком
Открываем main.h, стираем то, что там было написано, и пишем:
Здесь у нас подключены level.h и Box2D.h. iostream нужен для вывода в консоль, random — для генерации направления движения врага.
Далее идут игрок и векторы, каждому врагу, монетке, игроку полагается свой Object и b2Body (тело в Box2D).
Внимание — блокам этого не полагается, так как они взаимодействуют с игроком только на уровне физики Box2D, а не в игровой логике.
srand(time(NULL)) нужен для рандома.
Загружаем карту, создаем b2World, передавая ей гравитацию. Кстати, гравитация может исходить из какого угодно направления, и гравитация из (0,10) действует сильнее (0,1). Потом мы берем нужный нам размер тайлов
Далее создаем тела блоков:
Блоки — статические тела, они не имеют массы и висят в воздухе:
Тут мы устанавливаем позицию блоков. Дело в том, что если просто указать позицию такую же, как у объекта, нас будет ждать коварная ошибка.
Создаем тело блока в world. Далее мы с телом не работаем (в смысле, нигде не храним):
Каждому телу принадлежит несколько shape — фигур. Я не буду подробно разбирать эту тему, так как блокам (и остальным телам) хватает всего-то одного прямоугольника.
Связываем фигуру с телом.
Затем мы делаем то же самое с врагами, монетами и игроком, за небольшими различиями:
Означает, что тело не может вращаться.
Все тела созданы, осталось инициализировать графику!
Хорошо понятный код, создает окно с указанным размером и заголовком:
Тут мы создаем вид (View) для окна.
Зачем это надо? Для того, чтобы придать игре пиксельный стиль, мы умножаем размер экрана на 2 с использованием sf::View и все картинки рисуются в 2 раза выше и шире.
Окно закрывается по нажатию на красный крестик. Такой код был ранее:
Тут уже интереснее! Мы добавляем скорость игроку по нажатию клавиш WAD:
Тут мы обновляем физический мир Box2D. Первый аргумент принимает частоту обновления мира (раз в 1/60 секунд), а также количество velocityIterations и positionIterations. Чем выше значение последних двух аргументов, тем реальнее получается физика игры. Так как у нас нету никаких сложных фигур, как в AngryBirds, а только прямоугольники, то нам достаточно по разу.
Здесь мы обрабатываем столкновение игрока с другими телами:
Обработка столкновения с монетами.
Если какая монета столкнулась с игроком, она просто уничтожается и стирается из векторов:
Если враг сталкивается с игроком, проверяется, выше игрок врага или нет. Если игрок выше врага, то он стирается, а игрок подскакивает вверх.
Если иначе, то игрок отскакивает от врага:
Игрок движется направо или налево в соотвествии с его текущим положением относительно врага.
Если скорость врага равна 0, то ему скорость придается вновь — он движется либо направо, либо налево. Визуально это выглядит как движение рывками.
Работа с графикой. Берем позицию игрока, изменяем центр вида и используем наш вид
Устанавливаем спрайтам игрока, монет и врагов позиции, полученные из b2Body:
Очищаем окна, рисуем тайлы карты, потом игрока, монеты и врагов, после чего представляем окно.