kornerr

kornerr

На Пикабу
рейтинг 1 подписчик 1 подписка 5 постов 0 в горячем
Награды:
5 лет на Пикабу
5

Создание видеоигры на основе настольной игры Memory. Часть 05 (последняя): экран игры

Здравствуйте.

Сегодня мы заканчиваем создание простой видеоигры на основе настольной игры Memory.


ЧАСТЬ 5. ЭКРАН ИГРЫ


СОЗДАНИЕ ВЫДЕЛЯЕМЫХ ЭЛЕМЕНТОВ


1. Обновляем управление временем жизни экрана Game в классе Screens

Введём сообщающие переменные gameConfiguration и gameDeconfiguration. Они позволят нам оставить в enterGame() и leaveGame() лишь необходимый минимум. Остальную настройку будут производить подписчики gameConfiguration и gameDeconfiguration.


2. Убираем выход из экрана по нажатию кнопки мыши

Теперь мы будем использовать нажатие кнопки мыши для выделения элемента.


3. Обновляем сцену

Раньше у нас были сферы-заготовки. Удаляем их, оставляем пустую сцену.


4. Создаём структуру Item (Элемент)

Создаём структуру Item для внутреннего представления элемента игрового поля. Каждый элемент содержит:

* позицию (ряд, столбец)

* идентификатор

Элементы считаются равными, если их идентификаторы совпадают.


5. Создаём и отображаем элементы

Вводим setupItems() для:

* создания внутренних представлений элементов поля

* создания их визуальных представлений

* установки маски узла для последующего выделения

Также мы вводим itemPosition() для преобразования внутренней позиции элемента (ряд, столбец) в визуальную (x, y, z).


6. Реализуем выделение элементов

Последний шаг заключается в том, чтобы сделать элементы выделяемыми:

* класс Screens

** создаём setupGameConfiguration() для настройки позиции курсора мыши и камеры зрителя экрана игры (Game) с использованием gameConfiguration и gameDeconfiguration

* экран Game

** создаём setupSelection() для подписки на щелчок мыши и выбора узла сцены, находящегося под курсором мыши

** создаём tearSelectionDown() для удаления подписки на щелчок мыши в тех случаях, когда мы не хотим это разрешать

** создаём selectNode() для изменения массива selectedNodes и сообщении о его изменении с помощью selectedNodesReport

** создаём selectAllNodes() и deselectAllNodes() для упрощения выбора всех элементов поля либо снятия оного

** создаём setupSelectionColor() для выставления материала белого цвета у выбранных элементов


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

Изменённые файлы:

* Screens.h

* Game.h

* Item.h

Их содержимое: https://bitbucket.org/ogstudio-games/memory-colors-guide/src...

Веб-версия текущего результата: https://ogstudio.github.io/game-memory-colors/tutorial-5.1/m...


РИСУНКИ ЭЛЕМЕНТОВ И КЭШИРОВАНИЕ МАТЕРИАЛОВ


1. Добавляем шейдеры с рисунками

Наличие двух сфер одного цвета означает, что они совпадают. Для отображения 16 элементов нам нужно 8 пар этих элементов.

Добавим шейдеры со следующими рисунками:

* вертикальные линии

* горизонтальные линии

* наклонные линии (вертикальные линии при 45 градусах)

* шахматная доска

* повёрнутая шахматная доска (45 градусов)

* круги

Это даёт нам 6 различных рисунков. Ещё два "рисунка" будут полностью белыми и чёрными.

Итог:

2. Создаём класс Patterns (шаблоны, рисунки)

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


3. Разукрашиваем выбранные элементы рисунками

Заменяем setupSelectionColor() методом setupSelectionPattern(), который должен:

* создать экземпляр класса Patterns

* присвоить каждой сфере свой материал из Patterns


4. Анимация появления элементов

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

Создаём метод setupAnimationEntrance(), который:

* помещает все сферы в одну позицию

* помещает всю сцену за зрителем, что делает её невидимой для пользователя

* выбирает все сферы, что приводит к отображению всех рисунков

* анимирует движение сфер так, чтобы они оказались в области видимости зрителя

* убирает выделение со всех сфер, чтобы пользователь не знал, где какой элемент

* анимирует движение сфер так, чтобы поместить каждую в свою позицию


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

Изменённые файлы:

* Game.h

* Patterns.h

Их содержимое: https://bitbucket.org/ogstudio-games/memory-colors-guide/src...

Веб-версия текущего результата: https://ogstudio.github.io/game-memory-colors/tutorial-5.2/m...


СРАВНЕНИЕ ЭЛЕМЕНТОВ И АНИМАЦИЯ РЕЗУЛЬТАТА СРАВНЕНИЯ


1. Сравнение элементов

Создаём setupMatch() для сравнения двух выбранных элементов. Мы хотим сравнивать элементы по идентификатору:

* если их идентификаторы равны, то элементы совпадают

* иначе элементы не совпадают

Об успешном результате сообщаем с помощью matchSuccess, об отрицательном - matchFailure.


2. Анимация успешного и отрицательного результатов сравнения

Мы хотим получить следующие анимации:

* когда элементы совпадают

** сменить фон на белый

** удалить совпадающие элементы

** вернуть фон к прежнему состоянию

* когда элементы не совпадают

** мигнуть фоном с красным цветом два раза

** скрыть рисунки выбранных элементов

Создаём следующие методы экрана игры:

* setupMatchAnimation() для создания последовательностей по отображению успешного и отрицательного результатов сравнения

* configureBG() для сброса таймера фона и установки целевого цвета фона с начальной степенью влияния этого цвета на фон

* animateBG() для сообщения текущих значений целевого цвета фона и текущей степени влияния

* setupRemoval() для сброса таймера удаления и сброса скорости движения при удалении

* animateRemoval() для перемещения элементов из поля зрения зрителя

* reportRemovedNodesCount() для сообщения количества удалённых элементов

Экран игры теперь сообщает необходимый цвет фона и количество удалённых элементов. Но этого ещё не достаточно для смены фона.


3. Обновляем класс Screens для принятия цвета фона от экрана игры

Обновляем шейдер Flaring, используемый на фоне, для принятия:

* целевого цвета

* степени его влияния

Эти два параметра (shader uniforms) позволяют менять стандартный зелёный цвет на любой целевой с использованием степени влияния. Степень влияния варьируется от 0 (никак не влияет на конечное изображение) до 1 (конечное изображение полностью состоит из целевого цвета).

Обновляем класс Screens для передачи этих параметров в шейдер Flaring.

Создаём setupGameBackground() для подписки на targetColorReport и targetColorStrengthReport экрана игры. При наличии сообщений от них класс Screens передаёт целевой цвет и степень влияния в шейдер.


4. Выход из игры после удаления последней пары элементов

После того, как игровое поле осталось без элементов, необходимо перейти на конечный экран (Finish).

Обновляем экран игры для отправки exitReport после того, как все элементы были удалены.

Обновляем класс Screens для смены экрана на Finish после получения сообщения от exitReport.


ИТОГ


Мы создали игру "Memory: Colors" (Память: Цвета)!


Веб-версия результата: https://ogstudio.github.io/game-memory-colors/tutorial-5.3/m...

Показать полностью 3
6

Создание видеоигры на основе настольной игры Memory. Часть 04: начальный и конечный экраны

Здравствуйте.

Продолжаю рассказывать о создании простой видеоигры на основе настольной игры Memory.


ЧАСТЬ 4. НАЧАЛЬНЫЙ И КОНЕЧНЫЙ ЭКРАНЫ

В этой части я покажу, как создать начальный и конечный экраны, а также интересный фон.


ОТОБРАЖЕНИЕ ЗАГОЛОВКА


1. Добавляем проект mjin-text

Для отображения предложения необходимо использовать класс mjin::text::Sentence, который является частью mjin-text

Добавьте следующую строку в файл mjin.cfg:

hg http://bitbucket.org/ogstudio/mjin-text


2. Удаляем сферу

Удаляем сферу из setupScene(): оставляем лишь создание сцены и установку материала, причём меняем цвет материала на 0.5, 0.3, 0.7, т.к. этот цвет будет лучше смотреться на новом фоне.


3. Добавляем предложение

mjin::text::Sentence позволяет отобразить одну строку текста путём использования переданного узла сцены. Этот узел фактически является кистью для отрисовки текста.

Создаём setupTitle() со следующим функционалом:

* создание сферы в качестве кисти

* создание mjin::text::Sentence с текстом "Memory: Colors. Guide"

* добавление предложения к сцене


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

Изменённые файлы:

* main.cfg

* Start.h

Их содержимое: https://bitbucket.org/ogstudio-games/memory-colors-guide/src...

Веб-версия текущего результата: http://ogstudio.github.io/game-memory-colors/tutorial-4.1/mj...


ОТОБРАЖЕНИЕ ЗАГОЛОВКА НЕСКОЛЬКИМИ СТРОКАМИ


1. Т.к. mjin::text::Sentence умеет отображать лишь одну строку текста, то расположить этот текст на нескольких строках придётся самостоятельно.

Обновляем setupTitle():

* разбиваем приложение на три строки для каждого слова

* смещаем каждое слово на фиксированный отступ


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

Изменённые файлы:

* Start.h

Их содержимое: https://bitbucket.org/ogstudio-games/memory-colors-guide/src...

Веб-версия текущего результата: http://ogstudio.github.io/game-memory-colors/tutorial-4.2/mj...


ОТОБРАЖЕНИЕ ПОДСКАЗКИ


Пора отобразить подсказку под заголовком. Подсказка должна появляться спустя пару секунд и не вся целиком, а по буквам.

Существует много способов для подобной анимации, но мы воспользуемся классом mjin::report::Sequence. Он позволяет нам создавать ясное представление последовательности для анимации.


1. Настройка анимации

Создаём setupHint() со следующим функционалом:

* создание пустого предложения (mjin::text::Sentence)

* сброс таймера для учёта ожидания

* создание последовательности для анимации

mjin::report::Sequence входит в проект mjin-report, поэтому одной из сильных сторон этого класса является подписка и реакция на mjin::report::Variable.

Примерно так должна выглядеть последовательность:

this->hintSequence

.subscribe(&this->tickReport)

.call(delay)

.call(animate)

.unsubscribe(&this->tickReport)

;

Читается это так:

* подписываемся на tickReport

* при каждом вызове tickReport вызываем delay, который сообщает о своём завершении после истечения ожидания

* как только delay сообщил о завершении, вызываем animate на каждый вызов tickReport

* как только animate сообщил о завершении, отписываемся от tickReport


2. Задержка перед анимацией

Создаём delayHint() для представления задержки. Метод delayHint() должен вернуть:

* true, если он хочет сообщить о завершении, чтобы последовательность перешла к выполнению следующего элемента

* false, если он ещё не законил.

Для отсчёта времени используем osg::Timer


3. Добавление одной буквы за раз

Создаём displayHint() для добавления одной буквы за раз. После добавления всех букв возвращаем false.


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

Изменённые файлы:

* Start.h

Их содержимое: https://bitbucket.org/ogstudio-games/memory-colors-guide/src...

Веб-версия текущего результата: http://ogstudio.github.io/game-memory-colors/tutorial-4.3/mj...


СОЗДАНИЕ ИНТЕРЕСНОГО ФОНА И АНИМАЦИЯ ВЫХОДА С НАЧАЛЬНОГО ЭКРАНА


На текущий момент у вас мог возникнуть вопрос: "а может ли MJIN больше, чем отображать кубы и сферы?" Может намного больше. Для доказательства мы создадим фон с использованием интересного шейдера.


1. Поиск интересного шейдера

Шейдеры можно найти на ShaderToy ( http://shadertoy.com/ ), где есть огромное количество красивых шейдеров. Тем не менее, далеко не каждый шейдер подходит для мобильных платформ, т.к. зачастую производительность устройств с Android и iOS сильно отстаёт от десктопов.

Мы будем использовать шейдер Flaring: https://www.shadertoy.com/view/lsSGzy


2. Добавление шейдера

Создаём файлы shader.h/cpp со следующими функциями:

* vertexShaderWithTimer()

** передаёт информацию о вершинах во фрагментный шейдер

** создаёт необходимый минимум переменных ShaderToy для последующего использования во фрагментном шейдере

* fragmentShaderHeader()

** устанавливает высокую степень точности для опереаций с плавающей точкой на GLES

** предоставляет переменные ShaderToy

* fragmentShaderFooter()

** предоставляет main()

** использует результат mainImage() от ShaderToy

* fragmentShaderFlaring()

** принимает на вход ширину и высоту окна отображения

** предоставляет шейдер Flaring

** использует процедурный шум


3. Создание фона

Фон представляет из себя расположенный за сценой куб размером 1000 x 1000 x 1.

Создаём setupBG() со следующим функционалом:

* создание куба 1000 x 1000 x 1

* помещение его на задний план

* присвоение кубу шейдера Flaring


4. Обновление сцены

Ранее мы использовали зрителя OpenSceneGraph, чтобы тот фокусировался на всех узлах сцены при каждой смене экрана. Теперь же у нас есть отдельный узел для фона, который всегда должен находиться на заднем плане, поэтому мы больше не можем использовать зрителя для фокусировки на узлах.


Удаляем фокусировку зрителя при каждой смене экрана из setupScene(). Это также приводит к удалению автоматического управления ориентацией камеры зрителем, поэтому нам нужно задать ориентацию камеры самостоятельно. Создаём для этого createCameraManipulator().


5. Создание анимации выхода с экрана

Нам осталось добавить анимацию выхода с начального экрана (полёт заголовка и подсказки в направлении пользователя) после нажатия клавиши мыши.

Обновляем setupExit() и создаём там последовательность следующего вида:

this->exitSequence

.subscribeOnce(&this->mouseReport)

.subscribe(&this->tickReport)

.call(MJIN_REPORT_MANY(this->animateExit()))

.unsubscribe(&this->tickReport)

.report(&this->exitReport)

;

Читается это так:

* подписываемся на mouseReport и слушаем лишь первое сообщение

* после первого сообщения mouseReport подписываемся на tickReport

* анимируем выход так, чтобы заголовок и подсказка летели в направлении пользователя

* после завершения анимации отписываемся от tickReport

* сообщаем exitReport для уведомления о завершении начального экрана


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

Изменённые файлы:

* Start.h

* Screens.h

* shaders.h/cpp

Их содержимое: https://bitbucket.org/ogstudio-games/memory-colors-guide/src...

Веб-версия текущего результата: http://ogstudio.github.io/game-memory-colors/tutorial-4.4/mj...


СОЗДАНИЕ ЗАГОЛОВКА И ДОМАШНЕЙ СТРАНИЦЫ КОНЕЧНОГО ЭКРАНА


Конечный экран содержит предложение "Victory", т.к. проиграть в этой игре нельзя. Также через пару секунд отображаем адрес домашней страницы.

Всё делаем почти так же, как в случае с начальным экраном.

Изменённые файлы:

* Finish.h

Их содержимое: https://bitbucket.org/ogstudio-games/memory-colors-guide/src...


РЕЗУЛЬТАТ

Мы создали начальный и конечный экраны, а также добавили интересный фон.

Веб-версия результата: http://ogstudio.github.io/game-memory-colors/tutorial-4.5/mj...

Показать полностью 5
0

Создание видеоигры на основе настольной игры Memory. Часть 03: заготовки экранов

Здравствуйте.

Продолжаю рассказывать вам, как создать простую кросс-платформенную видеоигру на основе настольной игры Memory.


Напоминаю, что мои публикации преследуют следующие цели:

1. обучение вас созданию игр;

2. получение обратной связи по обучению.


ЧАСТЬ 3. ЗАГОТОВКИ ЭКРАНОВ

В этой части я покажу, как создать три экрана и как переключаться между ними по щелчку мыши.


СОЗДАНИЕ НОВОГО ПРОЕКТА (memory-colors-guide)


1. Делаем копию (fork) проекта mjin-application-sample

Проект mjin-application-sample мы разбирали в предыдущей части.

Я назову копию memory-colors-guide.


2. Обновляем название проекта в исходных файлах

Необходимо обновить следующие файлы:

* CMakeLists.txt

** Название проекта

** Название библиотеки

* main.cpp

** Заменить пространство имён mjin::application::sample на memory::colors::guide

** Ввести функцию memory::colors::guide::tearDownScene(), которая потребуется позднее


3. Собираем проект и удостоверяемся, что он работает

Выполняем команду:

~/mjin/projects/mjin/wale-build ~/mjin/projects mjin-player memory-colors-guide linux,web


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

На текущий момент у нас тот самый куб, что мы получили в предыдущей части.

Текущие файлы:

* CMakeLists.txt

* main.cpp

Их содержимое: https://bitbucket.org/ogstudio-games/memory-colors-guide/src...

Веб-версия текущего результата: http://ogstudio.github.io/game-memory-colors/tutorial-3.1/mj...


СОЗДАНИЕ СТАРТОВОГО ЭКРАНА (Start)


1. Создаём класс Screens

Создадим класс Screens для управления экранами.

Обязанности Screens:

* перемещение между экранами

** переменные screen и screenReport

* создание и удаление экранов, подписка их на события

** функции setupStart(), enterStart(), leaveStart()

* ввод

** функции setupInput(), tearDownInput()

* сцена

** функции setupScene(), tearDownScene()


1.1. Перемещение между экранами

Перемещение между экранами контролирует пара меременных:

* SCREEN screen;

** SCREEN - это простое перечисление (enum) со всеми возможными экранами + отсутствие экрана (значение NONE)

* mjin::report::Variable screenReport;

** mjin::report::Variable (часть проекта mjin-report) является так называемой "сообщающей переменной".

** Цель сообщающей переменной в доставке сообщений, т.е. она является издателем сообщений (event publisher). Популярным подходом для рассылки сообщений обычно является наследование класса вроде EventBase и переопределение его методов для обработки событий. Вместо этого я решил реализовать систему рассылки и подписок в виде отдельных экземпляров. На мой взгляд, использование наследования для расширения функционала сущности является не самым лучшим способом. Поэтому я выбрал композицию вместо наследования.

** При изменении значения переменной screen тот, кто это изменение сделал, должен также вызвать screenReport.report() для оповещение заинтересованных в изменении участников.


1.2. Создание и удаление экранов, подписка их на события

Каждая смена экрана приводит к тому, что один из экранов становится видимым. Т.к. мы не хотим засорять память невидимыми экранами, мы будем создавать экран лишь при переходе на него. А при выходе с него будем этот экран удалять.


Следующие функции контролируют жизненный цикл экрана Start:

* setupStart()

** создаёт подписку на screenReport для получения уведомлений о смене экранов. Если подписка видит переход на экран Start, то она вызывает enterStart(). Если же подписка видит выход с экрана Start, она вызывает leaveStart().

* enterStart() создаёт экран, после чего настраивает его. Настройка включает в себя:

** добавление сцены экрана Start к графу сцены

** подписка на события ввода

** перевод на следующий экран после выхода с текущего

* leaveStart() отписывает экран Start от событий, после чего удаляет его


1.3. Ввод

Для получения ввода нам необходимо зарегистрировать mjin::input::Mouse (часть проекта mjin-input) в OpenSceneGraph в качестве обработчика событий (event handler). Мы используем mjin::input::Mouse для получения событий о нажатии кнопок мыши и изменении позиции курсора (позднее).


1.4. Сцена

Класс Screens содержит собственный граф сцены, который удаляется и добавляется в основной при каждой смене экрана. Данная операция заставляет камеру OpenSceneGraph центрироваться на всех объектах в сцене.


2. Используем класс Screens в main.cpp

Нам не нужен более куб. Нам нужно заменить код в setupScene() созданием экземпляра класса Screens. А в tearDownScene() добавить удаление этого экземпляра.


3. Создаём класс стартового экрана (Start)

Класс Start отвечает у нас за:

* отображение, метод setupScene()

* выход с экрана, метод setupExit()


3.1. Отображение экрана Start

Вместо старого скучного куба у нас теперь будет модная сфера!

Создание сферы делается одним вызовом mjin::scene::createSphere() (часть проекта mjin-scene). Эта функция создаёт сферу с заданным радиусом.

Вместо того, чтобы писать собственноручно шейдер для одного цвета, мы используем mjin::render::createSingleColorMaterial() (часть проекта mjin-application, который мы уже используем).


3.2. Выход с экрана Start

На текущий момент мы хотим выходить с экрана Start по нажатию на кнопки мыши. Для этого мы подписываем exitReport на mouseReport. Подписка в классе Screens делает уже непосредственную смену экранов при получении события от exitReport.


4. Добавление проектов mjin-input, mjin-report, mjin-scene в качестве зависимостей

Для того, чтобы собрать приложение с указанными проектами в качестве зависимостей, нам необходимо заполнить файл mjin.cfg, который нужно положить в корень нашего проекта.

Содержимое должно выглядеть следующим образом:

hg http://bitbucket.org/ogstudio/mjin-input

hg http://bitbucket.org/ogstudio/mjin-report

hg http://bitbucket.org/ogstudio/mjin-scene


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

На текущий момент у нас должны быть следующие файлы:

* CMakeLists.txt

* mjin.cfg

* main.cpp

* Screens.h

* Start.h

Их содержимое: https://bitbucket.org/ogstudio-games/memory-colors-guide/src...

Веб-версия текущего результата: http://ogstudio.github.io/game-memory-colors/tutorial-3.2/mj...

Нажмите кнопку мыши, что приведёт к исчезновению сферы. Магия!


СОЗДАНИЕ ИГРОВОГО (Game) И КОНЕЧНОГО (Finish) ЭКРАНОВ


Пора создать два оставшихся экрана - Game и Finish. Они очень похожи на экран Start, но есть следующие отличия:

* Игровой экран (Game) содержит две сферы вместо одной

* Конечный экран (Finish) содержит три сферы, и с него нельзя выйти (нет exitReport)


РЕЗУЛЬТАТ

Теперь файлы должны быть следующие:

* CMakeLists.txt

* mjin.cfg

* main.cpp

* Screens.h

* Start.h

* Game.h

* Finish.h

Их содержимое: https://bitbucket.org/ogstudio-games/memory-colors-guide/src...

Веб-версия результата: http://ogstudio.github.io/game-memory-colors/tutorial-3.3/mj...

Нажимайте кнопку мыши на каждом экране, чтобы увидеть их смену.


ЗАКЛЮЧЕНИЕ

Мы создали заготовки трёх экранов и переходы между ними по нажатию кнопки мыши. Со следующей части мы начнём заполнять эти экраны.


Предыдущие части:

Часть 01. Функционал: https://pikabu.ru/story/sozdanie_nastolnoy_igryi_chast_01_fu...

Часть 02. Отображение куба: https://pikabu.ru/story/sozdanie_videoigryi_na_osnove_nastol...

Показать полностью 3
2

Создание видеоигры на основе настольной игры Memory. Часть 02: отображение куба

Создание видеоигры на основе настольной игры Memory. Часть 02: отображение куба

Здравствуйте, товарищи.


Продолжаю рассказывать вам, как создать простую кросс-платформенную видеоигру на основе настольной игры Memory.

Спасибо тем, кто не просто ставил минусы моей предыдущей публикации, а потратил пару минут своей жизни на комментарии. Все замечания постарался учесть.


Напоминаю, что мои публикации преследуют следующие цели:

1. обучение вас созданию игр;

2. получение обратной связи по обучению.


ЧАСТЬ 2. ОТОБРАЖЕНИЕ КРАСНОГО КУБА.


Требования.

Все инструкции ниже предполагают у вас наличие установленной системы Xubuntu 16.04 (именно Xubuntu, не Ubuntu, не Lubuntu, не Kubuntu и не прочие варианты).

Такой выбор обусловлен следующими причинами:

1. не удалось в разумные сроки создать скрипты для Windows

2. машина с Xubuntu может собирать (в полной конфигурации) под 4 платформы: Windows, Android, Linux, Web (Emscripten)

3. если вы найдёте в себе силы создать игру, то установить Xubuntu вы точно осилите


В этой публикации я покажу, как собирать под Linux и Web.


Рекомендую ставить Xubuntu в VirtualBox, т.к. это позволит вам иметь изолированное окружение для экспериментов. В VirtualBox игра отлично работает. Плюсом будет и то, что можно создавать снимки состояния виртуальной машины, чтобы при необходимости откатываться.


Подготовка минимального окружения для сборки


1. Установка инструментов сборки

Выполните следующую команду для установки необходимых инструментов сборки:

sudo apt install git mercurial build-essential cmake libopenscenegraph-dev


2. Создание структуры директорий MJIN

Выполните следующую команду для создания необходимой структуры директорий MJIN:

mkdir -p ~/mjin/projects


3. Копирование хранилища MJIN

Выполните следующую команду для клонирования MJIN:

hg clone http://bitbucket.org/ogstudio/mjin ~/mjin/projects/mjin


Замечание: игра использует технологию MJIN (собственная разработка).


4. Установка средств разработки Emscripten и завершение подготовки окружения

Выполните скрипт Питона с помощью следующей команды:

~/mjin/projects/mjin/wale-install


Скрипт делает следующее:

1. проверяет факт запуска на Xubuntu 16.04

2. устанавливает средства сборки Emscripten

3. проверяет наличие средств сборки Windows, Android, Linux, Emscripten (и выдаёт предупреждения, если чего-то нет)

4. копирует минимальный набор проектов MJIN и зависимостей:

** mjin-player (проигрыватель, основной бинарник)

** mjin-application (связующее звено между mjin-player и конкретным приложением)

** mjin-application-sample (пример приложения, отображающего куб)

** OpenSceneGraph (основа основ)


Сборка примера приложения


Выполните следующую команду для сборки под Linux и Web:

~/mjin/projects/mjin/wale-build ~/mjin/projects mjin-player mjin-application-sample linux,web


Запуск примера приложения


1. Linux

~/mjin/projects/mjin-application-sample/build/mjin-player/linux/mjin-player

2. Web

firefox ~/mjin/projects/mjin-application-sample/build/mjin-player/web/mjin-player.html


Описание исходного кода примера


Всё приложение расположено в одном единственном файле main.cpp ( http://bitbucket.org/ogstudio/mjin-application-sample/src/ti... ). Рассмотрим этот файл подробнее.


1. Пространство имён

Т.к. приложение называется mjin-application-sample, то почти весь код находится в пространстве имён mjin::application::sample


2. Журналирование

Как видно из кода, setupLogging() создаёт канал MJIN для журнала, после чего регистрирует его в OpenSceneGraph.

tearDownLogging() убирает регистрацию канала в OpenSceneGraph, что также этот канал и удаляет.


3. Отображение

setupRendering() принимает зрителя (viewer) OpenSceneGraph и его размер. Этот размер используется для задания размера области просмотра (viewport) внутри setupCamera().

Также заметьте использование директивы MJIN_PLATFORM_DESKTOP, благодаря которой мы отключаем многопоточность для всех платформ, кроме настольных (desktop).

setupScene() создаёт модель и назначает ей шейдеры. Заметьте использование директивы MJIN_PLATFORM_WEB для включения VBO на вебе, т.к. display lists (используются по умолчанию) не работают на вебе.


4. Реализация интерфейса mjin-application (callbacks)

В самом конце файла распологаются функции, объявленные в mjin-application, которые необходимо определить, т.к. их вызывает mjin-player. Эти функции описывают жизненный цикл приложения MJIN:

* создание приложения: setup()

* создание контекста отображения: setupViewer()

* отображение кадра: frame()

* удаление контекста отображения: tearDownViewer()

* удаление приложения: tearDown()

Заметьте, что функции находятся в пространстве имён mjin::application и что функции удаления как контекста, так и приложения вызываются лишь на настольных платформах.


Обзор файла сборки CMakeLists.txt ( http://bitbucket.org/ogstudio/mjin-application-sample/src/ti... ) оставлю как домашнее задание: там меньше 20 строк.


ЗАКЛЮЧЕНИЕ


Мы создали первое простейшее приложение MJIN, которое отображает куб. Конечно, кубом никого не удивишь, но это лишь начало.


Веб-версия сборки этой части самоучителя: https://ogstudio.github.io/game-memory-colors/tutorial-02/mj...



Предыдущая (первая) часть: https://pikabu.ru/story/sozdanie_nastolnoy_igryi_chast_01_fu...

Показать полностью 1

Создание настольной игры. Часть 01: функционал.

Здравствуйте, товарищи.


Хочу рассказать и подробно показать, как создать простую кросс-платформенную (Linux, macOS, Windows, Android, iOS, Web) настольную игру.


ПРЕДИСЛОВИЕ.


Мысль сделать это именно здесь родилась после чтения публикаций GooDCrafter о создании игры TerraPath. Где-то на 15-й его публикации я задал себе вопрос: "А чем я хуже?"

Мои публикации преследуют следующие цели:

1. обучение вас созданию игр;

2. получение обратной связи по обучению.


Данная серия публикаций расскажет и покажет создание игры "Память: Цвета" (Memory: Colors). Wikipedia даёт следующее определение ( https://en.wikipedia.org/wiki/Concentration_(game) ) этой игре: Концентрация, она же Память или просто Пары, является карточной игрой, в которой все карты лежат рубашкой кверху. На каждом ходу игрок переворачивает две карты. Цель игры в том, чтобы убрать со стола совпадающие пары карт.


Вот так выглядит веб-версия игры, которую мы создадим с нуля: https://ogstudio.github.io/game-memory-colors/0.3/mjin-playe...


ЧАСТЬ 1:  ФУНКЦИОНАЛ.

Прежде чем нырять в код, мы должны понять, что из себя представляет игра.


Игровые экраны.

Игра содержит три экрана:

1. Начало (Start)

2. Игра (Game)

3. Завершение (Finish)

Давайте пройдёмся по всем экранам и составим список из единиц функционала. Будем обозначать одну единицу функционала как Ф-<число>.


Экран начала (Start screen).

Это простой экран приветствия.


Ф-01. Заголовок

Сразу после запуска игры экран содержит лишь заголовок (включая версию выпуска), отображающийся на трёх строках:

Ф-02. Описание

Через пару секунд начинает появляеться описание, по одной букве за раз:

Ф-03. Анимация выхода с экрана начала

После клика или тапа заголовок и описание начинают лететь в сторону пользователя:

Ф-04. Выход с экрана начала

После того, как заголовок и описание улетели, перемещаем пользователя на следующий экран.


Экран игры (Game screen).

На этом экране мы собственно играем.


Ф-05. Игровое поле

Как видно, игровое поле состоит из 16 кругов в виде сетки 4x4. Все круги с одинаковым узором, что означает их положение "рубашкой кверху".


Ф-06. Выбор элемента

После выбора элемента можно увидеть узор круга:

Ф-07. Сопоставление двух элементов

После выбора второго круга мы получаем

1. либо промах:

2. либо совпадение:

Ф-08. Анимация промаха

Как вы заметили, в случае промаха фон мигает красным цветом.


Ф-09. Анимация совпадения

В случае совпадения:

1. фон меняет цвет;

2. круги улетают в сторону пользователя.


Ф-10. Окончание игры

После того, как всег круги были убраны с игрового поля, перемещаем пользователя на следующий экран.


Экран завершения (Finish screen).

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


Ф-11. Победа

Сначала мы отображаем на экране лишь слово "VICTORY" (ПОБЕДА):

Ф-12. Домашняя страница

Через пару секунд выводим адрес домашней страницы:

ПОСЛЕСЛОВИЕ.

Мы рассмотрели довольно много функционала, который заметен с первого взгляда.

Далее в ходе разработки мы обнаружим дополнительный функционал, который не был заметен сразу.


На этом заканчиваю первую часть. Задавайте вопросы. Комментируйте.

До скорой встречи!


PS1: Домашняя страница у нас болеет после недавней смены хостинга, поэтому заранее прошу прощения. Мы её вылечим в ближайшее время.

PS2: Хранилище с игрой: https://bitbucket.org/ogstudio-games/memory-colors

Показать полностью 9
Отличная работа, все прочитано!