На Zenn автор проекта «1 деплой в день» показал «Пачин! Крепость орехов» — браузерную игру примерно на 15 секунд. В ней нужно защищать три дорожки. В devlog автор разобрал промпт, ошибки логики и статистики, а ещё — вертикальную запись игры.
Коротко
Здесь интересно, как автор описывает поведение игры. Что считать одним действием? Что делать с нажатием во время перезарядки? По каким условиям раунд должен закончиться? Когда ответы на такие вопросы заданы заранее, результат проще проверить.
В игре нужно выбрать дорожку, а не ловить прицел
Из глубины к крепости идут теневые шары по левой, центральной и правой дорожкам. Игрок отбивается орехами. У него три лепестка: если тень добирается до крепости, один пропадает, а тень исчезает. Игра продолжается. Финальную большую тень нужно отогнать четырьмя попаданиями.
«Это игра про выбор: по какой дорожке стрелять сейчас, а не про тонкое движение прицела».
Так можно перевести ключевую формулировку автора Zenn. Она сразу задаёт механику: игрок выбирает одну из трёх дорожек и не целится внутри полосы. Нажимать можно кнопки дорожек, соответствующие трети Canvas, или клавиши 1, 2 и 3 на компьютере.
После каждого выстрела игра ждёт 0,38 секунды. Частые клики не создают новые снаряды. Если игрок нажал во время перезарядки, игра запоминает последнюю дорожку и стреляет по ней, когда орудие готово.
После пяти попаданий подряд следующий выстрел летит сразу по трём дорожкам. На экране это залп из трёх снарядов, а в статистике — одно действие игрока.
Один залп из трёх снарядов — один выстрел в статистике
Тут и обнаружился тихий баг. Если считать каждое попадание отдельно, а выстрел — как одно нажатие, точность после раша могла превысить 100%. Три снаряда попадали по разным целям, а статистика записывала три попадания при одном выстреле.
Автор добавил отдельный volleyId — идентификатор залпа — для каждого вызова fireLane(). Попадания с одинаковым volleyId засчитываются только один раз. Так статистика стала учитывать действия игрока, а не число объектов на экране.
Такая ошибка может появиться в интерактивах и мини-играх, где одно действие запускает несколько эффектов. Сначала стоит решить, что именно считается событием: клик, залп, попытка или успешное завершение. Иначе эффект красивый, а цифры уже врут.
Победу и поражение проверяют по состоянию игры
На первом круге ручного тестирования автор поймал зависание: врагов на экране уже не было, лепестки ещё оставались, но игра продолжала висеть в состоянии playing. Появление и уничтожение большой тени зависели от отдельных событий. Один из путей не переводил игру в финальное состояние.
Автор свёл условия окончания в одну проверку и добавил её в каждый цикл обновления. Игра заново оценивает, завершился ли спавн волн, жива ли большая тень, сколько врагов осталось и сколько лепестков у игрока. Теперь финал зависит от текущего состояния, а не от того, сработал ли нужный обработчик в нужный момент.
Автор вручную проверил три сценария: ставить приоритет на центральную дорожку, сначала атаковать ближайшего врага и продолжать после потери лепестка. По его отчёту, в двух из трёх прохождений игрок победил. Раунд заканчивался за 15–20 секунд. Ещё автор проверял, не остаются ли после перезапуска старый снаряд или таймер.
Для маленькой игры такие проверки проще провести до полировки графики: пройти игру разными способами, перезапустить и проверить конечные состояния. Если неясно, когда игрок выиграл или проиграл, фон эту проблему не спрячет.
Для вертикального видео автор убрал transform: scale()
В devlog есть режим ?capture=1 для вертикальной записи под TikTok и другие короткие видео. Сначала автор попробовал увеличить игровую область через CSS transform: scale(). На экране 1080×1920 контейнер .play-shell оставался шириной 540 пикселей, а над игрой сохранялась большая пустая зона. Стиль загружался, но реальные размеры элемента не менялись так, как ожидалось.
Вместо transform автор задал контейнеру реальную ширину 93vw с максимумом 1000 пикселей. Функция fitCaptureLayout() синхронизирует CSS-переменную --capture-shell-w и inline width элемента. При изменении окна она пересчитывает раскладку. Canvas растягивается на ширину родителя через width: 100%, а внутреннее разрешение 540×560 остаётся прежним.
Для записи есть автоматический проигрыш с заранее заданным временем нажатий через CAPTURE_FIRES. Он занимает 12–15 секунд. Правила игры, скорость снарядов, перезарядка и условия победы остаются теми же, что и в обычной версии. В ролике проходит тот же сценарий.
- Для вертикального режима меняйте фактическую ширину контейнера, а не только визуальный масштаб.
- Подгоняйте Canvas к родителю. Его внутреннюю рабочую сетку без необходимости менять не нужно.
- Заранее задайте тайминг нажатий для короткого прогона.
- После изменения ширины проверьте getBoundingClientRect().width на реальном размере экрана.
- Для превью автор снимал отдельный кадр с HUD через ?promo=shot. Размер изображения — 540×692.
Такой захват пригодится креаторам, которые записывают демо веб-интерактива, виджета или прототипа для Reels и Shorts. Автоматические нажатия при этом должны следовать той же логике, что и действия обычного игрока. Иначе ролик покажет сценарий, который в самой игре повторить нельзя.
Промпт описывает поведение, а не только жанр
В devlog автор предлагает не ограничиваться просьбой вроде «сделай игру, где можно стрелять по нажатию». В ней не сказано, как обрабатывать быстрые клики, что делать с вводом во время перезарядки и когда заканчивать игру. Ниже — промпт автора на японском. Перед адаптацией под свой проект поменяйте число дорожек, длительность, усиление и условия победы. Правила ввода и завершения лучше описать точно.
HTML・CSS・JavaScriptとCanvasで、左・中央・右の3レーンから迫る影を撃ち返す約15秒の防衛ゲームを作ってください。発射後0.38秒は再装填し、連打で弾は増やさず、装填中の入力は最後の1レーンだけ予約して装填完了時に1発だけ撃ってください。5連続命中の次の1発だけ3レーン同時に飛ばしてください。月花は3枚で、影が届くと1枚消えますがその影も消えて続行し、最後の大影4発で勝利してください。勝利・敗北は毎フレーム状態から再評価し、敵が消えたあと playing で止まらないようにしてください。Из чего собран промт
- 概要使用HTML/CSS/JS和Canvas制作3路防御游戏
HTML・CSS・JavaScriptとCanvasで、左・中央・右の3レーンから迫る影を撃ち返す約15秒の防衛ゲームを作ってください。 - メカニクス发射后0.38秒装填,不连发,装填中只预约最后一路
発射後0.38秒は再装填し、連打で弾は増やさず、装填中の入力は最後の1レーンだけ予約して装填完了時に1発だけ撃ってください。 - 特殊攻撃5连击后下一发三路齐射
5連続命中の次の1発だけ3レーン同時に飛ばしてください。 - ルール3枚月花,影到达消失,大影4发胜利
月花は3枚で、影が届くと1枚消えますがその影も消えて続行し、最後の大影4発で勝利してください。 - 終了条件每帧重新评估胜负,敌人消失后不停止playing
勝利・敗北は毎フレーム状態から再評価し、敵が消えたあと playing で止まらないようにしてください。
В промпте заданы жанр и технологии, но ещё и конкретные границы поведения. Для другого интерактива можно сохранить ту же логику описания: действие пользователя, задержка или ограничение, повторный ввод, условия успеха и провала, защита от зависшего состояния. Тест-кейсы всё равно стоит написать отдельно: промпт проверку не заменит.
Ты — опытный full-stack-разработчик и продуктовый дизайнер. Умеешь создавать простые инструменты для малого бизнеса, проектировать понятные интерфейсы, продумывать складские процессы и добавлять уместный юмор. Твои сильные стороны: удобный UX, автономные веб-приложения, надёжная работа с данными и практичные решения без лишней сложности.
Создай рабочий MVP веб-приложения «Складской Енот: охота за потерянными коробками». Оно помогает небольшому магазину, мастерской или интернет-бизнесу учитывать товары, находить их на складе и вовремя замечать низкие остатки. Енот — дружелюбный персонаж, который превращает рутину в короткие игровые миссии, но не отвлекает от работы.
Сделай приложение одним автономным HTML-файлом с CSS и JavaScript внутри. Оно должно запускаться локально в браузере без установки библиотек, сборщиков, сервера и внешних сервисов. Адаптируй интерфейс для компьютера и телефона. Храни данные в localStorage, чтобы они сохранялись после перезагрузки.
На главном экране покажи общее количество товаров, число позиций с низким запасом и приветствие от Енота. Добавь список товаров с названием, кодом или артикулом, категорией, количеством, минимальным запасом, местом хранения и статусом. Реализуй добавление, редактирование и удаление товара, изменение количества кнопками «−» и «+», поиск по названию и коду, а также фильтры: все товары, мало осталось, запас в норме. Перед удалением запрашивай подтверждение; для пустого списка покажи подсказку.
В форме проверяй обязательные поля: название не должно быть пустым, а количество и минимальный запас — неотрицательными целыми числами. Если данные некорректны, объясни, что исправить. Считай запас низким, когда количество меньше или равно минимальному запасу. После успешных действий показывай короткое подтверждение.
Добавь поле для ввода или вставки штрихкода. Учти, что USB-сканер может вводить код как клавиатура. Если камера и настоящее сканирование не реализованы, честно сообщи об этом и не имитируй работу функции.
Создай раздел «Миссии енота» с короткими полезными подсказками на основе данных: например, предложи проверить остаток товара с низким запасом или похвали пользователя, если таких товаров нет. Не оформляй закупки автоматически и не выдумывай цены или сведения о поставщиках.
Работай последовательно: определи структуру данных и сценарии пользователя, спроектируй интерфейс, реализуй функции и проверь крайние случаи. Не добавляй серверную синхронизацию, оплату, CRM и другие функции, не нужные для простого MVP. В ответе кратко перечисли готовые возможности и объясни запуск. Затем выведи полный исполняемый код одним блоком — его можно сохранить как index.html и открыть в браузере. Не используй многоточия, заглушки и пропущенные обработчики. После кода предложи несколько идей развития, явно обозначив их как будущие улучшения. Пиши понятно для человека без технического опыта; юмор пусть будет лёгким и добрым.Из чего собран промт
- 角色設定你是经验丰富的全栈开发者和产品设计师
Ты — опытный full-stack-разработчик и продуктовый дизайнер. Умеешь создавать простые инструменты для малого бизнеса, проектировать понятные интерфейсы, продумывать складские процессы и добавлять уместный юмор. Твои сильные стороны: удобный UX, автономные веб-приложения, надёжная работа с данными и п - 任務概要创建仓库浣熊MVP,帮助小企业管理库存
Создай рабочий MVP веб-приложения «Складской Енот: охота за потерянными коробками». Оно помогает небольшому магазину, мастерской или интернет-бизнесу учитывать товары, находить их на складе и вовремя замечать низкие остатки. Енот — дружелюбный персонаж, который превращает рутину в короткие игровые м - 技術要件单HTML文件,本地运行,适配移动端,localStorage存储
Сделай приложение одним автономным HTML-файлом с CSS и JavaScript внутри. Оно должно запускаться локально в браузере без установки библиотек, сборщиков, сервера и внешних сервисов. Адаптируй интерфейс для компьютера и телефона. Храни данные в localStorage, чтобы они сохранялись после перезагрузки. - UI機能主界面显示统计、商品列表、增删改查、搜索过滤
На главном экране покажи общее количество товаров, число позиций с низким запасом и приветствие от Енота. Добавь список товаров с названием, кодом или артикулом, категорией, количеством, минимальным запасом, местом хранения и статусом. Реализуй добавление, редактирование и удаление товара, изменение - バリデーション表单验证必填字段,显示错误提示
В форме проверяй обязательные поля: название не должно быть пустым, а количество и минимальный запас — неотрицательными целыми числами. Если данные некорректны, объясни, что исправить. Считай запас низким, когда количество меньше или равно минимальному запасу. После успешных действий показывай корот - 追加機能添加条码输入字段,诚实说明未实现扫描
Добавь поле для ввода или вставки штрихкода. Учти, что USB-сканер может вводить код как клавиатура. Если камера и настоящее сканирование не реализованы, честно сообщи об этом и не имитируй работу функции. - ミッション创建浣熊任务区,基于数据提供提示
Создай раздел «Миссии енота» с короткими полезными подсказками на основе данных: например, предложи проверить остаток товара с низким запасом или похвали пользователя, если таких товаров нет. Не оформляй закупки автоматически и не выдумывай цены или сведения о поставщиках. - 作業手順按步骤工作,输出完整代码,未来改进建议
Работай последовательно: определи структуру данных и сценарии пользователя, спроектируй интерфейс, реализуй функции и проверь крайние случаи. Не добавляй серверную синхронизацию, оплату, CRM и другие функции, не нужные для простого MVP. В ответе кратко перечисли готовые возможности и объясни запуск.
Картинка поддерживает механику, а не спорит с ней
Визуальный замысел игры — лесная крепость в духе ксилографии, дорожки как деревянная игрушка и растения с утренней росой. В палитре — тёмно-зелёный, цвет бумаги, ореховый и голубой оттенки. Враги похожи на округлые листья и тени. При попадании они не разлетаются на осколки, а распускаются обратно в листья.
Глубину автор передаёт простой псевдоперспективой: дальние дорожки и враги меньше, ближние — крупнее. При попадании дорожка загорается от переднего плана вглубь. Перезарядка отображается на пушке и кнопках, а постоянные частицы не отвлекают от нажатий.
Персонажа-проводника Бурапи автор поместил поверх Canvas отдельным прозрачным слоем. Тот не закрывает врагов и кнопки. Для промо-интерактива это хороший ориентир: персонаж добавляет игре характер, но не мешает нажимать на нужные элементы.
Сначала проверьте ввод и финал, потом полируйте эффект
Этот devlog не обещает, что длинный промпт сразу выдаст готовый продукт. Здесь полезнее сам подход: описать состояния, заметить расхождение между залпом и статистикой, вручную проверить сценарии и измерить размер контейнера в режиме захвата.
Если собираете игру или интерактив для рекламного ролика, я бы начал с трёх вещей: что считается одним вводом, как обрабатываются повторные нажатия и когда игра должна закончиться. Потом проверьте крайние случаи вручную. Для вертикальной записи убедитесь, что изменились реальные размеры игрового поля, а автоматический прогон использует те же правила, что и обычная версия.
В такой мини-игре я бы сначала проверил ввод, учёт действий и условия финала. Эффекты можно докрутить потом.
Источникzenn.dev
