Акции в интернет-магазинах бывают разные, а вот как их сделать визуально интересными для клиента — всегда вопрос, мы попробовали превратить обычную акцию в которой есть обычные статистические показатели клиента в игру в стили Dendy.
Здесь пойдёт речь о том как идеи маркетинга по мотивации клиентов можно визуализировать в небольшую игру для браузера.
Этап 1. От идеи к пониманию того что нужно
В один прекрасный день(перед началом лета), в отделе маркетинга созрела идея об организации мотивирующей акции для оптового направления клиентов. Из исходных данных как обычно у нас имелось следующее:
- Некоторый идентификатор клиента
- Показатели клиента
- На какую общую сумму клиент приобрёл за некоторый промежуток времени
- Какие бренды приобретались клиентом за этот промежуток времени
- Как “честно” и ответственно клиент выполняет свои обязанности перед нами как перед поставщиками продукции
- Какие “особые” ценовые условия клиент имеет на основании своей работы с нами
- Некоторый набор инструментов мотивации
- Список “подарков” которые мы можем предложить клиенту за его сотрудничество и показатели
- “Улучшители” его текущих ценовых предложений
- Некоторый “Супер приз” самому… самому… самому ответственному и активному клиенту.
- Точка сосредоточения клиентов — личный кабинет с системой Онлайн-заказа, где мы можем что либо предлагать и о чём то важном сообщать.
- Учётная программа (“Жёлтая”) — где есть общая информация по каждому идентификатору клиента и его показателям.
С таким набором данных можно было бы организовать с ходу в личном кабинете:
- Баннер + “Купите вот это и получите вот это”
- Или таблицу с параметрами клиента, куда раз в сутки можно выгружать данные из учётной программы
- Так как сайт на 1С-Битрикс — можно сделать сложные “Правила корзины” для применения каких то скидок при соблюдении некоторых условий в зависимости от идентификатора клиента или сделать свою логику в рамках API с выводом некоторой статистики.
Всё это мы делали и делаем для информирования клиентов. Но в этом случаем захотелось попробовать что-то иное — создать игру — где показатели будут визуализироваться в абстрактные величины.
Этап 2. Итак, мы делаем игру и теперь ТЗ будет звучать так
Наша тематика это запчасти и по большей части — оптовые продажи автозапчастей, по этому была определена следующая структура игровой логики:
- В центре внимания — трасса по которой должен двигаться автомобиль
- Трасса где-то начинается и где-то заканчивается(старт и финиш), т.е трасса имеет заданную протяжённость в км.
- Старт — это точка отсчёта показателя — “пройденный путь”
- Финиш — это конечная точка по достижению которой мы можем предоставить клиенту особую привилегию или очень ценный приз.
- На трассе должны встречаться точки остановки(это может быть препятствие, остановка для принятия решения).
- Точка принятия решения (чекпоинт) — должна дать клиенту “плюшку” и возврат на старт либо отказ от “плюшки” и движение дальше.
- Препятствие — должно менять какие-то показатели.
- Для движения автомобиля будет использоваться топливо.
- Топливо это абстракция, литры которого получает клиент за соблюдение условия продаж + за выполнение задания/квестов.
- Расход топлива на 100 км. у автомобиля — это тоже абстракция которая зависит от показателей “честности” и “ответственности” клиента при соблюдении своих обязательств перед нами как перед поставщиками.
- Расход топлива должен быть в какой то градации и в разумных пределах.
При помощи “великого и могучего” получилось большую задачу разделить на мелкие подзадачи и подойти к пониманию выбора инструмента реализации. Что-бы не создавать “двухколёсного” для организации механики движения автомобиля был сделан выбор в пользу использования JavaScript каркаса.
Требования к игровому framework-у которые мы определили для себя стали следующие:
- 2D — карта
- Наложение спрайтов на карту
- Событийная модель
- “Быстрый старт”
- Документация
Всего было рассмотрено и опробовано 3-5 известных решений(в том числе малоизвестный PointJS). Всё что рассматривалось, действительно отличные движки для создания игр, но нужно было что-то лёгкое и был выбран enchantjs.
Enchantjs — простой движок с необходимым набором инструментов для создания несложной 2D игры.
Этап 3. Техническое проектирование
После того как мы наигрались с Enchantjs — пришло время набросать небольшую структура приложения.
— Таблицы и данные которые нужно сохранять (речь об MySQL)
- Сводная таблица текущих данных игрока( данные которые влияют на текущие параметры игры). Частично эта таблица модифицируется в процессе игры, частично из учётной программы.
- Изменения литров бензина. Это те абстракции которые клиент может заправить в свой виртуальный автомобиль. Сюда данные должны поступать только из учётной программы.
- История изменения километража. До куда добрался клиент на своём автомобиле, где у него закончился бензин, где он взял чекпоинт.
- Изменения расхода топлива. Например, сегодня у клиента автомобиль потребляет 9 л. на 100км, а завтра к клиенту появились замечания и его автомобиль увеличил расход до 11 л. на 100 км.
- Инфоблок в 1С-Битрикс, куда специалисты маркетинга будут заносить задания для клиентов.(сделай это… то … вот ещё это..., подтверди фоткой или ссылкой и получишь конфету или пониженный расход)
- Таблица с выполненными заданиями клиентов.
- Таблица чекпоинтов.(потребуется для отрисовки спрайтов с флажками на карте игры)
- Таблица подарков которые мы можем предоставить клиенту на чекпоинте.
- Таблица собранных чекпоинтов. (доехал клиент до чекпоинта, выбрал подарок и мы это записали)
- История расхода/прихода литров бензина. Т.е при движении есть расход, при заправке канистры — есть приход топлива. Эти данные нужны для информирования клиента.
— Компонент 1С — Битрикс
- Общий шаблон компонента
- Обработка запросов пользователя во время игры
- Обработка событий происходящих на поле игры
- Обработка действий совершаемых пользователем в интерфейсе управления игры
— Модуль 1С — Битрикс
- ORM всех требуемых таблиц
- Некоторые сервисные операции
- Агенты
— API для обмена с учётной программой
Обработка запросов на получение данных об игре учётной программой.
Обработка запросов на предоставление данных по игрокам учётной программой.
Этап 4. Реализация игровой сцены
В реализации приведу пример только того что касаемо enchantjs и сцены с игрой.
Для начала нам нужно создать сцену и сформировать карту для игры.
Карта строится из массива массивов, где каждый вложенный массив характеризует номер ячейки из исходно спрайта материала карты.
Части карты которые будут использованы в построении сцены игры
Исходник спрайта карты
enchant();//Подключаем библиотеку игры
var game = new Game(800,700);//Создание поля игры с шириной 800 и высотой 700
game.fps = 28; //Частота обновления кадров
game.scale = 1; //Увеличение карты
//Предзагрузка медиа(спрайты, картинки)
game.preload(‘red_car.gif’);
game.preload(‘airport.gif’);
game.preload(‘flag.gif’);
//Начало игры
game.onload = function() {
var scene=new SceneGame();//Главная сцена игры
game.pushScene(scene);
};
game.start();
Получили базовый синтаксис для создания сцены с игрой и запуска игры.
Суть в том что мы на HTML страницы отрисовываем прямоугольник на котором у нас будут происходить манипуляции с спрайтами.
Сразу оговорюсь, что при реализации игры, пришлось отказаться от событийной модели enchant и от концепции что все действия происходят в рамках изменения сцены под влиянием величины fps.
Определим главную сцену игры, отрисуем карту, расставим флажки и установим машинку на старт.
/**
* Главная сцена с картой
* @type {Scene}
*/
var SceneGame=Class.create(Scene,{
initialize:function(){
Scene.apply(this);
game = Game.instance;
var label=new Label('ООО Рога и Копыта');//Текстовый объект для карты
var map = new Map(32,32);//Размер части map.gif на которой умещается 1-н элемент карты
var car =new Car();//Объект характеризующий автомобиль
var points_list=[];
//Набор чекпоинтов для расстановке по маршруту
//Как раз это те данные из таблицы которые мы берём по флажкам чекпоинтов
for(var point_km in app_user.check_point){
var flag_position=curent_odometr_to_coordinat(point_km);//Наша спец функция, которая киллометры превращает в координаты x и y - для точной установки спрайта на карту.
var red_flag=new Redflag();//Объект описывающий 1-н чекпоинт флаг
red_flag.x=flag_position.x;//Позиция 1-ого флага по x
red_flag.y=flag_position.y;//Позиция 1-ого флага по y
red_flag.rotation=0;//Градус на который повёрнут спрайт
points_list.push(red_flag);
delete red_flag;
}
this.red_flag=red_flag;
this.car=car;
map.image = game.assets[‘map.gif’];//Предзагрузка исходного материала карты
//Это наша карта, которая строится из квадратиков исходной map.gif
var baseMap = [
[24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24],
[ 4, 1, 1, 1, 5, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 4, 1, 1, 1, 1, 5, 24, 24, 24, 24],
[12, 24, 24, 24, 0, 24, 51, 47, 5, 24, 24, 24, 24, 24, 24, 24, 24, 0, 24, 24, 24, 24, 12, 24, 24, 24, 24],
[12, 24, 24, 24, 0, 24, 24, 24, 0, 24, 24, 24, 24, 24, 24, 24, 24, 0, 24, 24, 24, 24, 12, 24, 24, 24, 24],
[12, 24, 24, 24, 0, 24, 24, 25, 0, 24, 24, 24, 24, 24, 24, 24, 24, 0, 24, 24, 24, 24, 12, 24, 24, 24, 24],
[12, 24, 24, 24, 0, 24, 24, 25, 0, 24, 24, 24, 24, 24, 24, 24, 24, 0, 24, 24, 24, 24, 12, 24, 24, 24, 24],
[12, 24, 24, 24, 0, 24, 24, 25, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 24, 24, 24, 24, 0, 24, 24, 24, 24],
[12, 24, 24, 24, 8, 1, 1, 1, 5, 47, 22, 44, 4, 1, 1, 1, 5, 0, 24, 24, 24, 24, 11, 24, 24, 24, 24],
[12, 24, 24, 24, 24, 24, 24, 24, 0, 24, 24, 24, 0, 24, 24, 24, 0, 0, 24, 24, 24, 24, 0, 24, 24, 24, 24],
[12, 24, 24, 24, 24, 24, 24, 24, 0, 24, 24, 24, 0, 24, 24, 24, 0, 0, 24, 24, 24, 24, 0, 24, 24, 24, 24],
[12, 24, 24, 24, 24, 24, 24, 24, 0, 24, 24, 24, 0, 24, 24, 24, 0, 0, 24, 24, 24, 24, 0, 24, 24, 24, 24],
[12, 24, 24, 24, 24, 24, 24, 24, 8, 1, 1, 1, 9, 24, 24, 24, 12, 0, 24, 24, 24, 24, 8, 1, 1, 1, 8],
[12, 24, 24, 24, 24, 24, 24, 4, 9, 57, 57, 24, 24, 24, 12, 24, 12, 8, 1, 1, 1, 1, 5, 24, 24, 24, 24],
[12, 24, 24, 24, 24, 24, 24, 0, 49, 24, 24, 24, 24, 24, 12, 24, 12, 24, 24, 24, 24, 24, 0, 24, 24, 24, 24],
[12, 24, 24, 24, 24, 24, 24, 0, 59, 50, 50, 50, 24, 24, 12, 24, 12, 24, 24, 24, 24, 24, 0, 24, 24, 24, 24],
[12, 24, 24, 24, 24, 24, 24, 8, 1, 1, 1, 1, 5, 24, 12, 24, 12, 24, 24, 24, 24, 24, 0, 24, 24, 24, 24],
[12, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 8, 1, 9, 24, 12, 51, 51, 51, 51, 24, 0, 24, 24, 24, 24],
[11, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 8, 1, 1, 1, 1, 1, 9, 24, 24, 24, 24]
];
}
map.loadData(baseMap);
this.addChild(map);//Добавляем карту на сцену
this.addChild(car);
for(var index_flag in points_list){//Расстановка созданных флажков - чекпоинтов
this.addChild(points_list[index_flag]);
}
});
Изображение карты
В результате получаем сцену с картой на которой есть дорога. На скриншоте флажки не указаны и не установлен автомобиль на старт(левый нижний угол).
Каждый объект спрайта в enchantjs как минимум постоянно содержит информацию о положении в системе координат, об угле поворота спрайта.
Набросок карты
Т.е. что-бы осуществить движение автомобиля по нарисованной карте, потребовалось:
- Описать его действий в пространстве при достижении изгиба трассы
- Описать действия автомобиля и направление движение в зависимости от угла поворота спрайта.
Т.е если у нас угол поворота 0 и так как у нас спрайт автомобиля начинает старт снизу вверх, то мы двигаемся к нулей точки координат по оси Y. Дальше мы встречаем изгиб трассы №1 и должны повернуть спрайт автомобиля на 90 градусов. Далее зная что мы расположены под углом 90 градусов — движемся по оси X до изгиба трассы № 2 и т.д.
Так мы научили автомобиль двигаться по нарисованной системе координат.
Для того что-бы привести взаимодействию автомобиля с дорогой в привычные нам величины — в дистанцию в пройденных км, потребовалось написать дополнительную функцию, которая принимает количество км. от 0 до 3000 и возвращает координаты точки на участке дороги.
Для движения автомобиля мы использовали setInterval который увеличивает значения x или у во время движения автомобиля
//Авто движение
var start=setInterval(function(){
var position=car.getElementMap(car.x,car.y);
position.map_num=map.checkTile(car.x,car.y);
var move_result=car.move_car(position);
//Жгём топливо и следим за баком
var fuel_one_km=fuel_consumption(app_user.fuel_road);//расход на 1Км
app_storage.fuel -=fuel_one_km;
app_storage.fuel=parseFloat((app_storage.fuel).toFixed(2));
if(app_storage.fuel<=0){
//Обновить данные пользователя
clearInterval(start);
console.log('Бенз закончился!');
//Здесь создаём своё событие, которое дальше обработаем в компоненте Битрикс
}
var check_point_km=check_car_checkpoint(app_storage.km)
//Обнаружение чекпоинта
if(typeof check_point_km.point_km!=='undefined') {
console.log('Флажок!');
//Здесь создаём своё событие, которое дальше обработаем в компоненте Битрикс
}
if(position.car_x>780) {
clearInterval(start);
}
},app_conf().game.move_car_fps);
Карта, машинка, флажки
Во время движения, на игровой сцене происходят события:
- Наезд на флажки
- Окончание топлива
- Достижение финиша
По достижению этих событиях создаются события которые обрабатываются в управляющем скрипте компонента 1С-Битрикс.
Далее … далее
Следующими этапами для завершения игровой системы было:
- Создание интерфейса с кнопками управления
- Реакция на события на поле с игрой
- Изменения параметров игры в зависимости от действий пользователя
- Проверка параметров автомобиля на back end
В результате получилась вот такая игра в ЛК
Скрин ЛК
И немного видео