Пишем простую игру в 1С на встроенном языке
Содержание
Игру на платформе 1С:Предприятие создают в Конфигураторе: делают обработку, рисуют поле на табличном документе или в поле HTML, а движение фигур задают обработчиком ожидания — это и есть игровой цикл. Встроенного языка 1С для этого хватает: массивы, циклы и работа с координатами здесь ровно те же, что в учётных задачах.
Платформа не игровой движок, поэтому подход выбирают заранее. Для пошаговых и сеточных игр — змейка, 2048, тетрис, крестики-нолики — достаточно «родных» средств 1С. Для плавной графики, звука и управления с клавиатуры удобнее встроить HTML5-canvas в поле HTML, а 1С оставить роль оболочки и хранилища рекордов.
С чего начать: обработка и объекты метаданных
Основу игры удобно держать в обработке. Два варианта:
- 🧩 Внешняя обработка (
.epf) — отдельный файл. Ничего не меняет в основной конфигурации, легко передать коллеге. Запускается черезФайл → Открытьв режиме 1С:Предприятие. - 🗂 Обработка в составе конфигурации — встроена в прикладное решение, доступна из командного интерфейса. Нужна, если игра — часть большого решения.
Для эксперимента берите внешнюю обработку : быстрее итерации, не нужно обновлять конфигурацию базы после каждой правки. Выбор способа зависит от жанра: сеточные игры (змейка, тетрис, 2048, сапёр) целиком собираются на табличном документе и чистом коде 1С; аркады с плавным движением и спрайтами разумнее вести в поле HTML.
Внутри обработки создают одну управляемую форму. На форму добавляют реквизиты:
- реквизит типа
ТабличныйДокумент— если рисуете поле ячейками; - числовые реквизиты
Счёт,Рекорд, координаты активной фигуры; - служебные флаги
ИграИдёт,Пауза.
Отдельные объекты метаданных (справочники, регистры) для самой игры не нужны. Они понадобятся только под таблицу рекордов — об этом ниже.
Учебная версия платформы для таких экспериментов подходит: разработка в Конфигураторе доступна, ограничение — размер базы и отсутствие клиент-серверного режима. Для игры этого достаточно.
Игровое поле: на чём рисовать картинку
Готового холста в 1С нет, поэтому поле собирают из того, что есть. Два рабочих способа.
Способ 1. Табличный документ. Поле — это сетка ячеек. Каждую клетку красят через свойство ЦветФона, а состояние хранят в двумерном массиве. Перед игрой у документа скрывают сетку и заголовки и включают «только просмотр», чтобы читатель не правил ячейки.
&НаКлиенте
Процедура Перерисовать()
ПолеИгры.Очистить();
ПолеИгры.ОтображатьСетку = Ложь;
ПолеИгры.ОтображатьЗаголовки = Ложь;
Для Стр = 1 По ВысотаПоля Цикл
Для Кол = 1 По ШиринаПоля Цикл
Клетка = ПолеИгры.Область(Стр, Кол, Стр, Кол);
Клетка.ВысотаСтроки = 12;
Клетка.ШиринаКолонки = 2;
Если Поле[Стр][Кол] = 1 Тогда
Клетка.ЦветФона = WebЦвета.Синий;
Иначе
Клетка.ЦветФона = WebЦвета.Белый;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Чтобы клетки выглядели квадратными, подбирают высоту строки и ширину колонки опытным путём — единицы у них разные. Палитру берут из WebЦвета: так не придётся задавать цвет числовыми кодами. Поле 20×20 ячеек рисуется мгновенно, 100×100 уже заметно задумается при полной перерисовке — размер подбирайте под жанр.
Способ 2. Поле HTML. В реквизит типа «Строка» кладут HTML-страницу с тегом <canvas>, а всю отрисовку ведёт JavaScript внутри поля. 1С только задаёт начальную разметку и принимает обратно счёт. Способ даёт плавную анимацию и не упирается в ограничения табличного документа.
| Способ отрисовки | Когда выбрать | Чем неудобен |
|---|---|---|
| Табличный документ | Сеточные и пошаговые игры, чистый код на 1С | Грубая «пиксельная» картинка, нет плавности |
| Поле HTML + canvas | Нужны анимация, звук, клавиатура | Логика уходит в JS, сложнее отлаживать |
Управление в управляемой форме проще всего сделать экранными кнопками «Влево», «Вправо», «Вверх», «Вниз». Полноценный перехват стрелок клавиатуры в управляемой форме ограничен — если он критичен, ведите ввод в поле HTML.
Игровой цикл: обработчик ожидания вместо таймера
Отдельного таймера в 1С нет — его роль играет обработчик ожидания. Метод ПодключитьОбработчикОжидания раз за разом вызывает вашу клиентскую процедуру через заданный интервал. В ней вы двигаете объекты, проверяете столкновения и перерисовываете поле.
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ВысотаПоля = 20;
ШиринаПоля = 20;
СоздатьПоле();
ПодключитьОбработчикОжидания("ШагИгры", 0.3);
КонецПроцедуры
&НаКлиенте
Процедура ШагИгры()
Если Не ИграИдёт Тогда
Возврат;
КонецЕсли;
ДвигатьОбъект();
ПроверитьСтолкновения();
Перерисовать();
КонецПроцедуры
Интервал задают в секундах, для динамики ставят небольшое значение. В старых релизах минимум был около секунды, в актуальных платформах допускается дробный интервал. Если нужен темп выше, чем успевает обработчик, делайте несколько шагов логики за один вызов или переносите цикл в поле HTML.
Остановить игру — ОтключитьОбработчикОжидания("ШагИгры"). Скорость меняют так: отключили старый обработчик и подключили заново с меньшим интервалом. На этом же приёме делают постепенное ускорение — за каждые N очков уменьшаете интервал на долю секунды и переподключаете обработчик.
Паузу делают флагом Пауза: обработчик продолжает тикать, но в начале ШагИгры вы выходите по Возврат, пока пауза включена. Это надёжнее, чем отключать и включать обработчик по кнопке.
Обработчик ожидания работает на клиенте. Не вызывайте внутри него серверные процедуры на каждом шаге — обращение к сервере каждый тик заметно тормозит игру. Всю логику движения держите в клиентском коде.
Движение объектов и проверка столкновений
Состояние поля удобно хранить в массиве массивов: Поле[Строка][Колонка], где 0 — пусто, 1 — занято. Координаты активной фигуры — в отдельных реквизитах.
Движение — это смена координат на каждом шаге. Перед тем как применить ход, проверяют, свободна ли целевая клетка и не вышла ли фигура за границы.
&НаКлиенте
Функция КлеткаСвободна(Стр, Кол)
Если Стр < 1 ИЛИ Стр > ВысотаПоля
ИЛИ Кол < 1 ИЛИ Кол > ШиринаПоля Тогда
Возврат Ложь; // вышли за поле
КонецЕсли;
Возврат Поле[Стр][Кол] = 0;
КонецФункции
&НаКлиенте
Процедура ДвигатьОбъект()
НовСтр = ТекСтрока + СмещениеСтр;
НовКол = ТекКолонка + СмещениеКол;
Если КлеткаСвободна(НовСтр, НовКол) Тогда
Поле[ТекСтрока][ТекКолонка] = 0;
ТекСтрока = НовСтр;
ТекКолонка = НовКол;
Поле[ТекСтрока][ТекКолонка] = 1;
Иначе
ОбработатьСтолкновение();
КонецЕсли;
КонецПроцедуры
Столкновения в большинстве игр сводятся к двум проверкам: граница поля и занятая клетка. От типа игры зависит реакция: змейка на стену — конец партии, тетрис-фигура упёрлась в дно — фиксируется, а на её месте появляется новая.
Механика конкретных игр ложится на этот же каркас:
- 🐍 Змейка. Тело — очередь координат. На каждом шаге добавляете клетку спереди и убираете сзади. Съели цель — заднюю клетку не убираете, змейка растёт. Столкновение с собственным телом ищется проверкой, не занята ли новая клетка головой же.
- 🧱 Тетрис. Фигура — набор из четырёх координат. Падение вниз на шаг, поворот — пересчёт координат вокруг центра. После фиксации проверяете заполненные строки и сдвигаете поле вниз.
- 🔢 2048. Сетка чисел. Нажатие сдвигает все плитки в одну сторону, одинаковые соседние — складываются. Поле хранит не
0/1, а само число в клетке.
Кнопки управления меняют не координаты напрямую, а вектор смещения СмещениеСтр / СмещениеКол. Тогда объект продолжает двигаться сам, а игрок лишь задаёт направление. Командам кнопок можно назначить горячую клавишу в свойствах команды формы — это ускоряет управление, когда стрелки недоступны.
Звук и мультимедиа: честно о возможностях
Здесь у платформы слабое место. Универсального средства проиграть произвольный звуковой файл в тонком и веб-клиенте нет. Поэтому:
- 🔇 Способ 1 на табличном документе звук, как правило, оставляют без звука — это нормально для учебной игры.
- 🔊 Способ 2 через поле HTML звук решается штатно: внутри HTML используют тег
<audio>и проигрывают его из JavaScript при событиях игры (съел яблоко, собрал линию).
Картинки спрайтов проще всего тоже держать в поле HTML. Если остаётесь на табличном документе, роль «графики» выполняет цвет ячеек — для сеточных игр этого достаточно. Иконки и мелкие картинки (цель, бонус) можно выводить отдельным полем картинки на форме, подгружая изображение из макета или библиотеки картинок конфигурации.
Не закладывайтесь на тяжёлое мультимедиа: платформа оптимизирована под учётные задачи, а не под рендер. Чем больше анимации и звука нужно — тем сильнее аргумент в пользу поля HTML с canvas.
Сохранение счёта и таблицы рекордов
Личный рекорд одного пользователя хранят в хранилище общих настроек — отдельные объекты метаданных не нужны:
&НаСервере
Процедура СохранитьРекордНаСервере(Значение)
ХранилищеОбщихНастроек.Сохранить("Игра", "Рекорд", Значение);
КонецПроцедуры
&НаСервере
Функция ПрочитатьРекордНаСервере()
Возврат ХранилищеОбщихНастроек.Загрузить("Игра", "Рекорд");
КонецФункции
Если нужна общая таблица рекордов для всех игроков, заведите справочник или регистр сведений
с полями: имя игрока, очки, дата. После партии добавляете запись, а для экрана рекордов строите запрос с сортировкой по очкам по убыванию и ограничением ПЕРВЫЕ 10. Регистр сведений удобен, когда на одного игрока нужен один лучший результат: периодичность не ставьте, ключом сделайте имя игрока и перезаписывайте запись, если новый счёт выше.
Для одиночной игры хранилище настроек проще и не требует менять конфигурацию. Таблица рекордов оправдана, когда в базе несколько пользователей и есть смысл соревноваться.
Сохранять счёт логично в конце партии, а не на каждом шаге — иначе снова упрётесь в лишние обращения к серверу. Проверьте, что Загрузить возвращает пустое значение при первом запуске — иначе арифметика с рекордом упадёт на Неопределено.
Отладка и публикация готовой игры
Отлаживают игру штатными средствами Конфигуратора:
- Запуск под отладчиком —
F5(запускает 1С:Предприятие с подключённой отладкой). - Точки останова —
F9на нужной строке, выполнение встанет на ней. - Табло —
Shift+F9, чтобы посмотреть значения координат и массива поля на каждом шаге. - Пошаговое выполнение —
F11(с заходом в процедуру) иF10(без захода).
Удобный приём: временно увеличьте интервал обработчика до нескольких секунд — успеете разглядеть каждый шаг цикла в отладчике. Частая ошибка начинающих — ставить точку останова внутри цикла перерисовки: отладчик будет останавливаться на каждой клетке. Ставьте её в начало ШагИгры, а массив поля смотрите целиком в Табло.
Распространяют игру тремя путями:
- 📁 Файлом
.epf— отдаёте обработку, пользователь открывает её черезФайл → Открыть. В прикладном решении открытие внешних обработок должно быть разрешено настройками. - 🧩 В составе конфигурации — добавляете обработку в основную конфигурацию, выводите команду в интерфейс и обновляете конфигурацию базы.
- 🌐 Публикацией на веб-сервере —
Администрирование → Публикация на веб-серверев Конфигураторе (нужен Apache или IIS). После этого игра открывается в браузере через веб-клиент.
Веб-публикация особенно уместна для варианта с полем HTML: canvas и звук в браузере работают предсказуемо.
Частые ошибки при разработке игры
Разберём промахи, которые не видны из пошаговой инструкции.
Ещё одна типичная причина «тормозов» — перерисовка всего поля целиком, когда изменились одна-две клетки. На больших полях перекрашивайте только затронутые ячейки.
Частые вопросы
Нужна ли платная лицензия, чтобы написать игру в 1С?
Можно ли сделать игру без Конфигуратора?
Будет ли игра работать в веб-клиенте?
Насколько быстрый игровой цикл можно сделать на обработчике ожидания?
Как потом отдать игру другому человеку?
.epf. Получателю нужно, чтобы в его базе было разрешено открытие внешних обработок, иначе файл не запустится.