Добавление интерактивности¶
Продолжим разбирать связку JavaScript и WebAssembly: добавим в реализацию игры жизни интерактив. Пользователь сможет переключать клетку «жива/мёртва» по клику и ставить игру на паузу — так удобнее рисовать паттерны.
Пауза и возобновление игры¶
Добавим кнопку, переключающую режим «играет / на паузе». В файле wasm-game-of-life/www/index.html вставьте кнопку сразу над <canvas>:
1 | |
В JavaScript wasm-game-of-life/www/index.js сделайте следующее:
-
Храните идентификатор, который вернул последний вызов
requestAnimationFrame, чтобы отменить анимацию черезcancelAnimationFrameс этим идентификатором. -
По клику на «play/pause» проверяйте, есть ли идентификатор запланированного кадра анимации. Если есть — игра идёт, нужно отменить кадр, чтобы
renderLoopбольше не вызывался (пауза). Если идентификатора нет — мы на паузе, вызываемrequestAnimationFrame, чтобы возобновить игру.
Так как цикл ведёт JavaScript, менять исходники Rust не нужно.
Введём переменную animationId для идентификатора из requestAnimationFrame. Когда кадр не запланирован, в ней хранится null.
1 2 3 4 5 6 7 8 9 10 11 | |
В любой момент по значению animationId видно, на паузе игра или нет:
1 2 3 | |
По клику на кнопку проверяем паузу или воспроизведение и либо снова запускаем renderLoop, либо отменяем следующий кадр. Заодно обновляем подпись на кнопке так, чтобы она показывала действие при следующем клике.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
Раньше мы запускали анимацию прямым вызовом requestAnimationFrame(renderLoop); замените это на вызов play, чтобы с самого начала на кнопке была правильная подпись.
1 2 | |
Обновите http://localhost:8080/ — по кнопке можно ставить игру на паузу и снимать с паузы.
Переключение состояния клетки по событию "click"¶
Раз пауза есть, добавим изменение клеток по клику.
Переключить клетку — значит сменить состояние «жива» ↔ «мёртва». Добавьте метод toggle для Cell в wasm-game-of-life/src/lib.rs:
1 2 3 4 5 6 7 8 | |
Чтобы переключить клетку в заданной строке и столбце, переводим пару (строка, столбец) в индекс в векторе клеток и вызываем toggle у этой клетки:
1 2 3 4 5 6 7 8 9 10 | |
Метод объявлен в блоке impl с атрибутом #[wasm_bindgen], чтобы его можно было вызывать из JavaScript.
В wasm-game-of-life/www/index.js подписываемся на клики по <canvas>: переводим координаты клика из системы страницы в координаты холста, затем в строку и столбец, вызываем toggle_cell и перерисовываем сцену.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
Соберите проект командой wasm-pack build в каталоге wasm-game-of-life, снова откройте http://localhost:8080/ — можно рисовать свои паттерны кликами по клеткам.
Упражнения¶
- Добавьте виджет
<input type="range">, чтобы задавать, сколько тиков выполняется за один кадр анимации. - Кнопка сброса вселенной в случайное начальное состояние по клику. Ещё одна кнопка — сброс во «все клетки мёртвы».
- По
Ctrl + кликвставляйте планер (глайдер), центрированный на целевой клетке. ПоShift + клик— пульсар (классический осциллятор в игре жизни).