- Установить
nodejs
- Скачать этот репозиторий
mcap.zip
- В терминале (консоле) выполнить команду
npm install
- Установить rollup глобально
npm install rollup -g
- Запустить сборку скриптов
npm run dev
- Отктыть в браузере страницу
http://localhost:9000
- Открыть инструменты разработчика браузера
F12
Для начала необходимо объявить персонажей. Откройте файл ./src/$root/characters.yaml Внутри которого можно зарегестрировать персонажей. От чьего лица будут идти реплики
Например. Реплики в нутри скрипта мы пишем так
# $root/characters.yaml
- id: $, # Знак доллора ипользуется как алиас для реплики - строчки
name: Автор
- id: a,
name: Алиса
#label.yaml
- Привет Мир! # name = Автор
- Вторая реплика
- Третья реплика
- a: Четвертая реплика # name = Алиса
- $: Пятая реплика # name = Автор
YAML использует синтаксис ключ/значение
key: value
'my key': Hello world!
- key: test1
key: test 2 #Недопускается использование одинаковых ключей в одном объекте
В синтаксисе yaml используется система отступов, как в Python. Каждый отступ с двумя пробелами представляет новый уровень.
level1:
level2:
Level3:
{
level1: {
level2: {
level3: {}
}
}
}
Можете поэксперементировать в онлайн редакторе
http://nodeca.github.io/js-yaml/
https://onlineyamltools.com/convert-yaml-to-json
Рабочая область это папка ./src/scenes
Внутри неё папки первого уровня являются сценами. Внутри скрипта мы будет обращаться по этим именам
/scenes
├───$root
├───scene_1
├───scene_2
├───scene_3 # имена сцен можно создавать произвольные кроме $root
Такая файловая структура собирается в файл /public/scenes/vn.json
{
$root: {},
scene_1: {},
scene_2: {},
scene_3: {}
}
/scenes
├───$root
│ ├───assets
│ │ ├───background.png #имена файлов станут id для доступа к этим файлам
│ │ └───audio1.mp3
│ ├───data
│ │ ├───файл_с_текстовыми_данными.txt
│ │ └───файл_с_текстовыми_данными.php
│ └───$init.yaml #точка входа в игру
├───scene_2
│ └───$init.yaml
#Внутри каждой сцены желательно создавать файл $init.yaml
#в первом объекте которого, будет описываться какой экран отобразить
#а так же аудио и прочие элементы. Это не обязательно, но упростит отладку новеллы.
Внутри сцены лежат файлы с раширением yaml это так называемые метки (label) Если иначе выразится то сцена является Томом книги, а метки являются главами.
scene.label
volume.chapter
vn.json
{
$root: {
assets: [
{name: 'background', url: './scenes/assets/background.png'},
{name: 'audio1', url: './scenes/assets/audio1.mp3'}
],
data: {
'файл_с_текстовыми_данными.txt': 'Текст в формате json',
'файл_с_текстовыми_данными.php': '<?php print "текст"; ?>'
},
$init: [
"Реплика номер 1",
"Реплика номер 2",
"Реплика номер 3",
{ jump: 'scene_2.$init' }
]
},
scene_2: {
$init: [
"Реплика номер 4"
]
}
}
В качестве описания сценария используется yaml
это язык описания структур данных.
📎 - плагины включены в библиотеку vnjson.js
character | Обработчик реплик персонажей 📎 |
jump | Прыжок между сценами и метками 📎 |
next | Переход на следующий объект скрипта 📎 |
target | Прыжок по якорям внутри label 📎 |
timeout | Вызывает другие плагины по истечению времени 📎 |
debug | Вывод сообщений об ошиках |
dialog-box | Диалоговое окно |
menu | Внутриигровое меню |
clear | Скрывает все компоненты и отключает аудио |
assets-loader | Загрузка медиа ресурсов |
audio | Воспроизведение аудио |
sound-hover | Воспроизводит звук при наведении на кнопки |
show | Отображает персонажей на экране |
term | Выводит код с подсведкой синтаксиса |
slide | Отображает изображение по центру экрана |
hands | В диалоговом окне два слота (руки) |
screen | Переключение экранов |
scene | Отоброжение заднего фона внутри экрана |
animate | Добавление анимации к элементам |
embed | Подключение сторонних ресурсов через iFrame |
inv | Инвентарь |
Все ключевые слова первого уровня являются плагинами. По своей сути это назание событий которое вызываются когда игрок дойдет по скрипту до этого ключевого слова.
Плагины предустановлены и находятся внутри папки ./src/plugins
Этот плагин отвечает за обработку реплик песонажей, Но явно нигде не вызывается.
На базе этого плагина работает плагин dialog-box
- Реплика 1 # реплика от имени автора
- Реплика 2
- $: Реплика 3 # так же реплика от имени автора
- a: Реплика от Алисы
scene: background1 #scene/assets/background1.ong
Символ $
зарезервирован для повествования от лица автора.
Так же от имени автора выводятся реплики без указания индификатора персонажа
Персонажей необходимо предварительно зарегестрировать внутри файла /scenes/$root/characters.yaml
/scenes
├───$root
│ ├───charactes.yaml
#charactes.yaml
- id: $ # Является алиасом для реплики без параметров [ - Реплика ] = [ $: Реплика ]
name: "" # Автор
nameColor: '#e0b33f' # Цвет имени персонажа
replyColor: '#f2cd11' # Цвет реплики персонажа
- id: a # обязательный параметр
name: Алиса # обязательный параметр
nameColor: '#49de58' # цвет необходимо писать в ковычках
replyColor: '#a4deaa'
logo: capitan # Можно хранить дополнительные параметры
age: 17
bio: -
Плагин [ characters ] берёт зарегестрированные id персонажей и случает когда они встретятся по мере прохождения скрипта. Потом плагин dialog-box получает эти данные и выводит в диалоговое окно
Делает прыжки между сценами (scene), и между метками (label) внутри сцен
scene1/part1.yaml
- У лукоморья дуб зелёный
- Златая цепь на дубе том
- И днём и ночью кот учёный
- Всё ходит по цепи кругом
- jump: part2 # Прыжок в метку part2 внутри этой же сцены
scene1/part2.yaml
- Идёт направо — песнь заводит,
- Налево — сказку говорит.
- jump: scene2.$init # Прыжок в другую сцену
Можно делать прыжки на конкретную позицию внутри скрипта scene.label.index
Позиция внутри label
(метки) отсчитывается с нуля
scene2/$init.yaml
- Там чудеса: там леший бродит,
- Русалка на ветвях сидит
- jump: $root.$init.3
После того как был совершён прыжок, вызывается событие this.emit('init', scene)
# Прыжок на конкретную метку
http://localhost:9000/?jump=scene.label
# Прыжок на метку по умолчанию $init
http://localhost:9000/?jump=scene # default $init
Выполняет текущий объект контекста и перескакивает на следующий объект скрипта не дожидаясь действий пользователя
- scene: bg1
next: true
- $: Привет Мир!
Плагин [ target ] делает прыжок внутри текущей главы/метки в помеченное место (якорь) которое маркируется ключевым словом [ _test ] с символом нижнего подчёркивания в начале
- $: Там на неведомых дорожках
target: _mark1 # jump to _mark1
- $: Следы невиданных зверей;
_mark2: true
- Избушка там на курьих ножках
- Стоит без окон, без дверей;
- $: Там лес и дол видений полны;
jump: $root.$init # make a jump from this label
- $: Там о заре прихлынут волны
_mark1: true
- На брег песчаный и пустой,
- И тридцать витязей прекрасных
- target: _mark2 # jump to _mark2
Выполняет другие плагины по истечению таймера (в миллисекундах)
- timeout:
exec:
jump: $root.$init
timer: 1000
# ./src/scenes/$root/package.yaml
debug: false #true
F12 - инструменты разработчика F5 - Обновить страницу Ctrl+R - Обновить страницу Ctrl+Shift+R - Обновить страницу без кэша
Является надстройской над плагином character
Выводит реплику текущего персонажа, а так же его имя.
- dialog-box: true # отобразить компонент диалогового окна
- dialog-box: false # скрыть компонент диалогового окна
- dialog-box: clear # очишает диалоговое окно от реплики и имени персонажа
Плагин для внтуриигрового меню.
- menu:
luna: Отправиться на Луну
mars: Лучше на Марс
next: Пожалуй останусь на Земле #Можно внутри можно использовать [ next ]
#next
- Земля
### ### ##
- menu:
$: Куда бы мне отправить #Вопрос от автора
luna: Отправиться на Луну
mars: Лучше на Марс
### ### ##
- menu:
a: Куда бы мне отправить #Вопрос от Алисы
luna: Отправиться на Луну
mars: Лучше на Марс
### ### ##
- menu:
a: Куда бы мне отправить #Вопрос от Алисы
luna: Отправиться на Луну
disabled: Лучше на Марс #Не активный пункт меню
disabled_23: Еще один заблокированный пункт
next: Дальше
#Что бы заблокировать пункт меню используется ключевое слово [ disable ]
#Но так как заблокировавнных пунктов может быть несколько, а ключи внутри объекта
#не могут повторяться, то к ключевому слову пожно прибавить какой-нибудь префикс disabled_24
- $: Пример с маркировкой
_mark1: true
- menu:
luna: Отправиться на Луну
mars: Лучше на Марс
_mark1: В начало
Отключает воспроизведение текущей аудиодорожки, а так же скрывает все компоненты
- clear: all
Загрузка медиа ресурсов Вызывается не явно. По срабатыванию события .emit('setTree')
Излучает события
.emit('preload')
.emit('load', asset)
.emit('postload')
/scenes
├───$root
│ ├───assets
│ │ ├───background.png #имена файлов станут id для доступа к этим файлам
│ │ └───audio1.mp3
./public/scenes/vn.json
{
"$root": {
"assets": [
{ "name": "background", "url": "./scenes/assets/background.png" },
{ "name": "audio1", "url": "./scenes/assets/audio1.mp3" }
]
}
}
После чего предзагруженные медиа ресурсы можно использовать во время прохождения визуальной новеллы
- scene: background
audio:
name: audio1
action: play
speed: 0.3
volume: 0.01
loop: true
- audio:
name: audio1
action: play
speed: 0.3
volume: 0.01
loop: true
- audio: false # stop
Так же можно воспроизвести звук в отдельном аудио канале
- sound: audio1
Вызывается не явно. Только при наведении игроком на кнопку с классом .sound-hover
<div class="sound-hover">Кнопка со звуком</div>
Ключевое слово show не используеся. Но в этом плагине, обрабатываются другие события
Отвечает за отображение персонажей на экране stream
- center: characterImage_1
- left: characterImage_2
- right: characterImage_3
- center: false # очистить элемент персонажа
- left: false #
- right: false #
Отображает изображение по центру экрана, сохраняя при этом фактический размер изображения
- slide: characterImage_1
- slide: false
- slide:
name: characterImage_1
css:
top: 320px
border: 15px dashed orange
Свойство css
принимает любые css свойства. Фактически является
оберткой метода jQuery.css
- hands: true
- hand-left: imageName1
- hand-right: imageName2
- hands: false
Компонент для вывода кода с подсведкой синтаксиса
- term: lesson_1.py #planeText[extname]
- term: lesson_1.lua
- term: imageName # выводит изображение в компоненте терминала
- term: false # скрыть терминал
/scenes
├───$root
│ ├───assets
│ ├───data
│ │ ├───lesson_1.lua
│ │ └───lesson_1.py
./public/scenes/vn.json
{
"$root": {
"data": {
"lesson_1.lua": "...",
"lesson_1.py": "..."
}
}
}
Экран это div элемент с короторый находится на первом уровне внутри элемента #screen . У элемента экрана есть id и класс .screen
<div id="screen">
<div id="screenName" class="screen">
Первый экран
</div>
</div>
Предустановленно два экрана. Один для главного меню и один для потока игры. Размеры экрана шираина 1024px высота: 768px
Отображает изображение на заднем фоне экрана #stream
scene: imagename
Изображения для сцен лучше сжимать, что бы они меньше весили в качестве формата для фона рекомендую использовать .webp или .jpg
Файлам находящимся в папках assets и data необходимо задавать уникальные имена
Обёртка вокруг метода jQuery.animate({})
- animate: selector: .dialog-box duration: 1000 #время выполнения анимации в милисекундах css: background-color: red opacity: 0.5
Встраивает сторонние ресурсы через iFrame элемент.
Которые необходимо разместить в файле
./src/scenes/$root/embed.yaml
yt-salut: <iframe <iframe width="100%" height="100%" src="https://www.youtube.com/embed/a_o-P-lIDEA?start=50"></iframe>
3d-conni: <iframe <iframe width="100%" height="100%" src="https://sketchfab.com/models/d0c68158e3f5482f87a9d89ada23c0bc/embed"> </iframe>
yt-salut
- это индификатор по которому iframe будет вызываться из YAML
скрипта
Каждый индификатор автоматически регистрируется с как плагин
- yt-salut: true
- yt-salut: false
Инвентарь
./scenes/$items/assets
- изображения
./scenes/$items/store.yaml
- описание предметов
- inv: true
- Создаем сцену [ $items ], а внутри неё папку [ assets ] и ложим в неё файлы с предметами
- Далее внутри этой сцены создаем файл в котором будет описываться
- n: Название ему необходимо задать store.yaml
inv-set: gear # должно быть описано внутри ./scenes/$items/store.yaml
- Внутри него описываем структуру предметов
- a: В оный день, когда над миром новым
- a: Бог склонял лицо свое, тогда
inv-get: gear
- a: Солнце останавливали словом,
- a: Словом разрушали города.
- jump: $init