Казуальные игры — документация разработчика
Документация содержит описание технологии создания казуальных игр для чатов Сервиса и адресована
разработчикам, желающие внести в чаты свои новинки и имеющие достаточный опыт программирования на
языке JavaScript. Если какие то моменты документации вам оказались не до конца понятны либо у вас
есть идеи по модернизации предложенного способа создания игр, вы можете направить свои вопросы и
пожелания по адресу august@august4u.net.
Документация построена по принципу "от простого — к сложному", разбита на шаги, на каждом из
которых рассматривается определенный фрагмент кода.
В чате имеются четыре встроенных игры:
- Пятнашки;
- Сапер (три уровня);
- Найди пару (две версии);
- Цветные линии.
Для подключения их к расширенному меню надо выполнить команду
/games.
1. Каркас игры, добавление игры в меню
Казуальные игры основываются на расширенном меню и создаются как подменю, используя базовый класс
august_menu_base. Инициализация игры начинается с загрузки модуля
http://august4u.ru/js/games.js и добавления игры в расширенное меню. Этот модуль производит
запуск расширенного меню и создает в нем раздел "Игры". Также в этом модуле находится базовый
класс august_game, от которого должны наследоваться все игры, далее идет описание методов
этого класса.
Пример 1. Каркас игры
Для просмотра этого примера выполните команду
/load http://august4u.net/developer/game_example1.js
Этот пример демонстрирует стартовый код, необходимый для загрузки модуля http://august4u.ru/js/games.js и
добавляет игру в раздел расширенного меню, код самой игры пустой. Здесь функция my_game1 —
это класс игры. В классе каждой игры необходимо определить переменную id, содержащую уникальный
идентификатор игры (как в меню), в примере он инициализируется значением "my_game_example1".
Добавление игры в раздел "Игры" осуществляется методом addGame.
// получить раздел с играми
var Games = AugustMenu.menu ("games")
// добавить игру
Games.addGame (new имя_класса_игры, название_игры)
где:
- имя_класса_игры — имя класса, реализующего игру.
- название_игры — название игры, которое отображается в расширенном меню.
2. Отображение игры, метод html()
Первый пример демонстрирует добавление игры в меню, но самой игры не создает. Чтобы отобразить игру на
экране требуется сформировать ее HTML-код, для этого необходимо в классе игры определить метод html().
Метод html() должен создать полный HTML-код игры и вернуть его в виде строки.
Пример 2. Отображение игры на экране
Для просмотра этого примера выполните команду
/load http://august4u.net/developer/game_example2.js
Пример создает прямоугольное игровое поле и два игровых элемента (квадрата) внутри него.
3. Отображение игры — постобработка кода, метод init(), метод root()
Для корректного отображения игры на экране метод html() должен вернуть полный код игры с
необходимым позиционированием всех элементов игры, задавая каждому элементу необходимые параметры
через атрибут style. Это не всегда является удобным способом позиционирования, более удобным
способом является постобработка, когда элементам готового кода присваиваются необходимые параметры.
Для постобработки необходимо определить метод init(). Метод init() всегда вызывается
за методом html(), что гарантирует наличие всех элементов на экране. Кроме того, в методе
init() определяется код, который не может быть выполнен в методе html() в силу
каких-либо обстоятельств.
Элементами игры являются DOM-узлы и необходимо иметь к ним доступ, чтобы в процессе игры можно было
ими управлять. Метод root() возвращает корневой узел игры и, используя методы и свойства интерфейса
Node, можно получить остальные элементы.
Важное замечание. На верхнем уровне DOM-дерева игры должен быть только один элемент. Все, что нужно
для этого сделать — это поместить весь код игры в контейнер, обычно для этого используется элемент DIV.
Пример 3. Позиционирование элементов игры
Для просмотра этого примера выполните команду
/load http://august4u.net/developer/game_example3.js
Пример 3 отличается от примера 2 лишь тем, что производит позиционирование элементов в методе init().
4. Положение окна игры на экране, отсоединение игры от расширенного меню, метод detach()
Игры основаны на расширенном меню, а разделы меню и подменю после клика на них исчезают с экрана, но
для игр такое поведение является недопустимым. Метод detach() отсоединяет игру от расширенного
меню и игра остается на экране постоянно. Убрать игру с экрана в этом случае можно только одним
способом — в разделе "Игры" выбрать меню "Скрыть активную игру".
По умолчанию положение окна игры определяется положением родительского меню, откуда была запущена игра.
Такое поведение является свойством расширенного меню. Используя набор опций OPTIONS, которые
определяют поведение подменю, имеется возможность выводить окно игры по центру окна чата, для этого
требуется всего лишь установить флаг CENTER.
Важное замечание. Параметр OPTIONS содержит флаги, которые определяют взаимодействие окна
игры и расширенного меню. Управление этими флагами должно быть крайне аккуратное, не допускается
непосредственное присваивание значений параметру OPTIONS, вместо этого должны использоваться
логические операции OR для установки флага и AND для сброса флага.
Пример 4. Отсоединение игры от расширенного меню, вывод окна игры по центру окна чата
Для просмотра этого примера выполните команду
/load http://august4u.net/developer/game_example4.js
5. Определение каскадной таблицы стилей, метод addCSS()
В предыдущих примерах стили элементам задавались непосредственно в коде через атрибут style.
Такой способ должен использоваться только для динамических стилей. Статические же стили правильнее
выносить в каскадную таблицу стилей и подключать ее при инициализации игры, а элементам игры
присваивать классы. Это также позволяет значительно сократить код.
Метод addCSS() подключает новую каскадную таблицу стилей к документу. В метод addCSS()
необходимо передать значение самой таблицы стилей, закодированную методом Base64. В конце этой
документации имеются онлайн утилита для кодирования текста и файлов методом Base64.
Пример 5. Подключение каскадной таблицы стилей
Для просмотра этого примера выполните команду
/load http://august4u.net/developer/game_example5.js
Каскадная таблица стилей из этого примера выглядит следующим образом:
div.my_game { border: 2px solid #ff0; background: #090; width: 200px; height: 150px; position: relative; overflow: hidden }
div.my_game>div { width: 50px; height: 50px; position: absolute }
div.my_game>div.chip_a { border: 1px solid #f00; background: #c00 }
div.my_game>div.chip_b { border: 1px solid #0ff; background: #0bb }
6. Управление игрой, обработка событий мышки, метод handler()
Казуальные игры в большинстве своем просты в управлении и обычно достаточно обрабатывать одиночный
клик мышки. Расширенное меню уже содержит перехватчик этого события и в коде игре необходимо только
определить обработчик, этим обработчиком является метод handler(). Метод handler()
принимает один аргумент — ссылку на элемент на котором произошло событие (клик мышкой).
Пример 6. Обработка клика мышкой
Для просмотра этого примера выполните команду
/load http://august4u.net/developer/game_example6.js
В примере обрабатываются клики по элементам игры (цветные квадратики).
7. Анимация, таймеры, объект AugustTimer
Привлекательность игры зависит как от качества графики, так и от плавности движений элементов игры
(анимации). Для создания в играх эффекта анимации используются таймеры. Объект AugustTimer
предназначен для управления выполнением функций через заданные промежутки времени.
Метод AugustTimer.start() осуществляет запуск таймера, параметры таймера передаются в
аргументе в формате JSON:
- timeout — интервал времени в миллисекундах с которым производится перезапуск таймера;
- callBack — функция-обработчик, которая запускается по истечении времени таймера, ей
передаются три аргумента:
1. id таймера;
2. количество времени, прошедшее с момента запуска таймера, в миллисекундах;
3. счетчик запусков;
- delay — необязательный, задержка в миллисекундах, через которую должен запуститься
таймер, если параметр не указан, используется значение timeout;
- once — необязательный, значение отличное от нуля указывает, что таймер является однократным и
функция-обработчик будет вызвана только один раз, после вызова функции-обработчика таймер удаляется автоматически.
Метод AugustTimer.start() возвращает id созданного таймера. Для остановки таймера используется
метод AugustTimer.stop(), которому необходимо передать id запущенного таймера.
Важное замечание. Минимальное значение, которое задает время перезапуска таймера, не должно быть меньше
10 милисекунд. На более ранних компьютерах реальное время перезауска для малых значений может оказаться
выше указанного и перезапуск таймера будет осуществляться с большим периодом. Также реальное время
перезауска зависит от операционной системы и браузера.
Пример 7. Анимация
Для просмотра этого примера выполните команду
/load http://august4u.net/developer/game_example7.js
8. Вывод текста и кнопки, метод text(), метод button(), метод del(), метод darken()
Метод text() предназначен для вывода текста в окно игры, метод может вызываться с одним, двумя
или тремя аргументами в зависимости от требований. В первом аргументе методу text() передается
сам текст, который необходимо отобразить. Второй аргумент — не обязательный, в нем передаются параметры
позиционирования текста в окне игры в формате JSON:
- l — значение отступа от левого края окна игры в пикселах;
- r — значение отступа от правого края окна игры в пикселах;
- t — значение отступа от верхнего края окна игры в пикселах;
- b — значение отступа от нижнего края окна игры в пикселах;
- w — ширина прямоугольной области вывода текста в пикселах;
- h — высота прямоугольной области вывода текста в пикселах;
- hor — смещение области вывода по горизонтали относительно центра в
пикселах, используется только при выводе текста по центру, отрицательное значение смещает
область вывода влево, положительное — вправо;
- vert — смещение области вывода по вертикали относительно центра в пикселах,
используется только при выводе текста по центру, отрицательное значение смещает область вывода
вверх, положительное — вниз.
По умолчанию (если второй аргумент не передан или передан как null), текст выводится по центру окна.
В третьем аргументе, при необходимости, передаются параметры кнопки, которую нужно выводить вместе
с текстом, параметры передаются в формате JSON:
- t — текст кнопки;
- c — название класса для кнопки, описание стиля для данного класса производится
в каскадной таблице стилей;
- a — идентификатор кнопки, по которому определяется нажатие данной кнопки.
Обработка нажатия кнопки производится в методе handler().
Для определения стиля выводимого текста необходимо в каскадной таблице стилей определить стиль для
селектора div.text.
Метод button() предназначен для вывода на экран одной кнопки, метод может вызываться с одним
или с двумя аргументами. Первый аргумент задает параметры кнопки, второй — параметры
позиционирования кнопки. Оба аргумента по формату описания параметров идентичны аналогичным аргументам
метода text(). По умолчанию (без второго аргумента) кнопка выводится по центру окна.
Важное замечание. При составлении стилей для оформления кнопок следуют принимать во внимание, что
кнопка состоит из двух элементов: внешний — контейнер, это HTML элемент DIV и внутренний
— HTML элемент A. Присвоение класса, название которого передается в параметрах при вызове
методов text() и button(), производится внешнему контейнеру.
Методы text() и button() возвращают ссылку на созданный элемент. В дальнейшем ее
можно использовать для удаления текста или кнопки из окна игры. Удаление элементов производится
методом del().
Метод darken() затемняет окно игры, уровень затемнения зависит от переданного числа в
аргументе, значение должно находиться в диапазоне от 0 до 100, чем больше число, тем темнее будет
окно, при значении 100 окно становится черным, нулевое значение отключает затемнение. Затемнение
окна можно использовать для сигнализации того, что игра закончилась, на затемненном окне также
лучше виден текст.
Пример 8. Текст и кнопка
Необходимо определить стили для текста и кнопки, каскадная таблица стилей будет выглядеть следующим образом:
div.my_game8 { border: 2px solid #ff0; background: #090; width: 200px; height: 150px; position: relative; overflow: hidden }
div.my_game8>div.chip { width: 50px; height: 50px; position: absolute; display: none }
div.my_game8>div.chip_a { border: 1px solid #f00; background: #c00 }
div.my_game8>div.chip_b { border: 1px solid #0ff; background: #0bb }
div.my_game8>div.text { position: absolute; text-align: center; white-space: normal; color: #ff0; font: bold 15px verdana }
div.my_game8 div.game_btn { margin: 25px 0 }
div.my_game8 div.game_btn>a { cursor: default; text-decoration: none; padding: 7px 15px; font: bold 15px arial; color: #99c; background: #06c; border-radius: 7px; box-shadow: inset 0 0 10px 0 #fff }
div.my_game8 div.game_btn>a:hover { color: #fff; background: #09f }
Для просмотра этого примера выполните команду
/load http://august4u.net/developer/game_example8.js
9. Статистика игры, время игры, рекорд игры, панель, перемещение окна игры, окончание игры,
метод initPanel(), метод panel(), метод move(), метод start(), метод end()
В процессе игры игроку будет интересно знать свою статистику — количество кликов, сделанных
во время игры, время, прошедшее с начала игры, и рекорд игры. Вывод статистики можно организовать,
например, в дополнительной панели под игровым полем.
Метод initPanel() предназначен для создания панели с определенным набором полей, а метод
panel() — для вывода значений в эти поля, оба этих метода принимают параметры в
формате JSON. Конфигурация панели задается параметрами метода initPanel(), где имена
ключей являются идентификаторами полей, а значения определяют текстовые строки, выводимые на экран.
Значения полей задаются параметрами метода panel(), где именами ключей являются те же
идентификаторы полей, что были определены в методе initPanel(), а значения —
значения полей для вывода на экран.
Имеются два предопределенных идентификатора для выполнения встроенных функций, это:
- record — поле для вывода рекорда игры;
- time — поле для вывода времени игры.
Метод panel(), вызванный без параметров, обнуляет все поля панели.
Метод move() позволяет перемещать окно игры при захвате его мышкой, в качестве аргумента
методу должна передаваться ссылка на элемент окна игры, который используется для перемещения, таким
элементом, например, может служить панель игры. Вместо метода move() для тех же целей можно
использовать и метод detach(), когда он вызывается с аргументом, кроме своей основной
функции, он выполнит функцию метода move().
Метод start() запускает таймер, отсчитывающий время игры, вызвать его можно, например, при
первом клике мышкой в игре.
По окончании игры должен вызываться метод end(). Метод end() производит следующие
действия: останавливает таймер игры, присоединяет игру к расширенному меню, записывает результат
игры в базу данных, затемняет окно игры и выводит на экран текст с сообщением, какое место занял
игрок в этой игре. Если игра предусматривает досрочное завершение игры при неудаче (например,
подрыв на мине в игре "сапер"), то дополнительно можно вывести соответствующее сообщение (при
этом результат в базу данных не заносится). Метод end() принимает до трех аргументов:
- результат игры для записи в базу данных, параметры передаются в формате JSON, допустимыми
являются следующие ключи:
- c — количество кликов, сделанных во время игры;
- s — очки, набранные в игре;
- параметры кнопки для запуска новой игры, параметры в точности соответствуют третьему аргументу
метода text();
- текст, который выводится при досрочном завершении игры (неудаче), если такое предусмотрено игрой.
Пример 9. Статистика игры, перемещение окна, окончание игры
Необходимо определить стили для текста и кнопки, каскадная таблица стилей будет выглядеть следующим образом:
div.my_game9 { border: 2px solid #ff0; background: #090; width: 200px; height: 150px; position: relative; overflow: hidden }
div.my_game9>div.chip { width: 50px; height: 50px; position: absolute; display: none }
div.my_game9>div.chip_a { border: 1px solid #f00; background: #c00 }
div.my_game9>div.chip_b { border: 1px solid #0ff; background: #0bb }
div.my_game9>div.panel { position: absolute; bottom: 1px; left: 1px; right: 1px; padding: 3px 4px; background: #00b; color: #ff9; font: bold 12px verdana; overflow: hidden }
div.my_game9>div.text { position: absolute; text-align: center; white-space: normal; color: #ff0; font: bold 15px verdana }
div.my_game9>div.text>div.place1 { font-size: 40px; color: gold }
div.my_game9>div.text>div.place2 { font-size: 40px; color: silver }
div.my_game9>div.text>div.place3 { font-size: 40px; color: #cd7f32 }
div.my_game9 div.game_btn { margin: 25px 0 }
div.my_game9 div.game_btn>a { cursor: default; text-decoration: none; padding: 7px 15px; font: bold 15px arial; color: #99c; background: #06c; border-radius: 7px; box-shadow: inset 0 0 10px 0 #fff }
div.my_game9 div.game_btn>a:hover { color: #fff; background: #09f }
Селекторы div.place1, div.place2 и div.place3 определяют стили цифр 1, 2 и 3
в сообщении о занятом игроком месте, выводимом методом end().
Для просмотра этого примера выполните команду
/load http://august4u.net/developer/game_example9.js
10. Сортировка мест в рейтинге
В зависимости от игры сортировка мест в рейтинге может осуществляться по определенному параметру,
для этого в наборе опций OPTIONS необходимо установить соответствующий флаг. Допускаются
следующие флаги:
- SORTBYTIME — сортировка по времени игры (используется по умолчанию);
- SORTBYCLICKS — сортировка по количеству кликов;
- SORTBYSCORE — сортировка по набранным очкам.
11. метод attach(), метод saveScore(), метод out()
Описанных выше методов достаточно для управления игрой, однако, есть несколько методов, которые
могут оказаться полезными при программировании игр.
Метод attach() присоединяет игру к расширенному меню. Присоединение игры необходимо для того,
чтобы игру можно было скрыть с экрана после ее окончания. Присоединенная игра будет скрыта с экрана
сразу же после клика на окно игры, либо через некоторое время после перемещения указателя мышки
за пределы игрового окна. Метод attach() используется методом end() и они не должны
вызываться совместно.
Метод saveScore() предназначен для записи результатов игры в базу данных. Метод принимает
два аргумента:
- идентичен первому аргументу метода end();
- callback-функция, которая будет вызвана по окончании записи результата игры в базу данных чата
(производится обращение к серверу), в аргументе этой функции передается место (ответ от сервера),
которое занял игрок по результату игры.
Метод saveScore() используется методом end() и они не должны вызываться совместно.
Простой пример использования метода saveScore():
this.saveScore ({ c: ClickCount }, function ( n ) {
if (n === false)
// произошла сетевая ошибка, ответ от сервера не получен
return
this.text (n ? "Вы заняли " + n + "-е место" : "Вы не вошли в таблицу рекордов", null, { t: "OK", c: "button", a: "ok" })
})
Метод out() предназначен для вставки кода или текста в элемент с заданным id. Метод
имеет две формы вызова. Первая форма производит вставку кода только в один элемент, для этого
метод out() вызывается с двумя аргументами: 1. id элемента, 2. код. Вторая форма
производит вставку кода в несколько элементов, для этого случая метод out() вызывается с
одним аргументом, в котором передается массив пар, каждая пара — это массив из двух элементов:
1. id элемента, 2. код, т.е. каждая пара соответствует первой форме метода out().
12. Использование графики
Использовать графику в играх можно обычным способ — загружать ее с сервера отдельными файлами
(прописывая в элементах IMG адреса картинок), но в этом случае игра не должна начинаться, то тех
пор, пока не будут подгружены все графические файлы, иначе может возникнуть ситуация, когда игра
стартовала, но оказалась не прорисована до конца. Другим способом использования графики является
помещение графических файлов непосредственно в код программы, тем самым гарантируется наличие всей
графики в памяти перед стартом игры. В этом случае необходмо содержимое графических файлов
преобразовать в строки методом Base64, а элементам IMG прописывать специальные значения.
Примеры включения графических файлов непосредсвенно в код для разных форматов графики
// для формата gif
var gif = "строка_данных_gif_картинки_закодированная_методом_base64"
IMG1.src = "data:image/gif;base64," + gif
// для формата png
var png = "строка_данных_png_картинки_закодированная_методом_base64"
IMG2.src = "data:image/png;base64," + png
// для формата jpeg
var jpeg = "строка_данных_jpeg_картинки_закодированная_методом_base64"
IMG3.src = "data:image/jpeg;base64," + jpeg
Кроме того, используя такой подход, для одной и тоже игры можно легко менять оформление, загружая
только файл с нужным набором графики. На примерах игр "сапер" и "найди пару" демонтируется
универсальность данного метода.
Для изменения стандартного оформления игры "сапер" выполните команду
/load http://august4u.ru/js/game.minesweeper20.js
Для запуска новой игры "найди пару" с новыми картинками и другим размером поля выполните команду
/load http://august4u.ru/js/game.twins.aladdin.js
Утилита для кодирования текста и файлов методом Base64
Скопируйте текст в первое поле и во втором поле получите закодированное значение. Для кодирования
файлов перенесите мышкой файл в первое поле. Данная утилита не работает в браузерах Internet Explorer
ниже 10-й версии.