docs(studio): вики задача 20 — карточка #63 + статья «Сбор монет (лидерборды и достижения)»

Карточка g5 #63 guide-leaderstats (openProjectId 2616) + статья в docsLessons:
что получится, API leaderstats/achievements, 2 шага (таблица/достижения),
bindToStat, сохранение в БД. 3 скрина (scene/play/page) — донести вручную
(headless-студия не пускает после взлома, попрошу у пользователя).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
min 2026-06-06 10:04:57 +03:00
parent ce6e69a2e8
commit 7bb789f1af
2 changed files with 93 additions and 0 deletions

View File

@ -358,4 +358,9 @@ export const GAMES = [
desc: 'Одной строкой меняешь небо: голубой день, закат, звёздная ночь, космос. Облака, туман, далёкие горы и плавные переходы между пресетами.', desc: 'Одной строкой меняешь небо: голубой день, закат, звёздная ночь, космос. Облака, туман, далёкие горы и плавные переходы между пресетами.',
mechanics: ['game.scene.setSkybox({ preset })', 'game.scene.setClouds / setFog', 'skybox.fadeTo(opts, сек) — плавный переход', '6 пресетов: день/lowpoly/закат/ночь/космос', 'небо = единый источник света сцены', 'облака-дрейф + дымка горизонта'], mechanics: ['game.scene.setSkybox({ preset })', 'game.scene.setClouds / setFog', 'skybox.fadeTo(opts, сек) — плавный переход', '6 пресетов: день/lowpoly/закат/ночь/космос', 'небо = единый источник света сцены', 'облака-дрейф + дымка горизонта'],
previewShot: 'guide-skybox-scene.png', openProjectId: 2541, ready: true }, previewShot: 'guide-skybox-scene.png', openProjectId: 2541, ready: true },
{ id: 'guide-leaderstats', num: 63, group: 'g5', stars: 2, icon: 'trophy',
title: 'Сбор монет — лидерборды и достижения',
desc: 'Таблица лидеров справа-сверху (монеты/время/уровень) + всплывающие достижения с редкостью и звуком. Прогресс сохраняется в БД между сессиями.',
mechanics: ['game.leaderstats.define / me.add', 'HUD-таблица топ-10 (сортировка по primary)', 'game.achievements.define / unlock', 'bindToStat — авто-награда по статy', 'toast 4 редкости + очередь', 'кубок → страница достижений', 'сохранение в БД (savegame)'],
previewShot: 'guide-leaderstats-scene.png', openProjectId: 2616, ready: true },
]; ];

View File

@ -8691,6 +8691,94 @@ game.gui.onClick('btn-space', () => game.scene.skybox.fadeTo({ preset: 'space'
), ),
}, },
'guide-leaderstats': {
body: (
<>
<h3 className="lessonH">Что получится</h3>
<p>
Игра «собери монеты» с двумя системами удержания, как в Roblox:
<b> таблица лидеров</b> справа-сверху (монеты, время, уровень) и
<b> достижения</b> всплывающие награды с редкостью, звуком и
страницей-витриной. Прогресс <b>сохраняется в базе</b> закрыл
игру, вернулся завтра, а монеты и открытые ачивки на месте.
</p>
<Shot src="guide-leaderstats-play.png" wide
caption="Таблица лидеров справа-сверху + всплывающая плашка достижения «Терпеливый» при игре. Слева-снизу — кубок, открывающий страницу всех достижений." />
<h3 className="lessonH">Чему научишься</h3>
<ul>
<li><b>game.leaderstats.define(name, opts)</b> столбец таблицы:
иконка, цвет, формат (число / время / 1.2K), primary (по нему сортировка);</li>
<li><b>game.leaderstats.me.add('Монеты', 1)</b> изменить стат игрока
(ячейка жёлто мигает);</li>
<li><b>game.achievements.define([...])</b> объявить достижения
(id, название, описание, редкость, очки, скрытое);</li>
<li><b>game.achievements.unlock(id)</b> выдать достижение (плашка + звук);</li>
<li><b>game.achievements.bindToStat(id, 'Монеты', {'{'} gte: 10 {'}'})</b>
авто-награда при достижении значения стата;</li>
<li>прогресс сохраняется в БД и подгружается в новой сессии.</li>
</ul>
<h3 className="lessonH">Шаг 1. Таблица лидеров</h3>
<p>
Объяви столбцы. Первый <code>primary: true</code> по нему сортируются
игроки в топе. Дальше меняй значения через <code>me.add / me.set</code>.
</p>
<ScriptKind kind="global" />
<Code>{`game.leaderstats.define('Монеты', { initial: 0, format: 'number', icon: '🪙', color: '#ffd23a', primary: true });
game.leaderstats.define('Время', { initial: 0, format: 'time', icon: '⏱', color: '#7fd0ff' });
game.leaderstats.define('Уровень', { initial: 1, format: 'number', icon: '⭐', color: '#b48bff' });
// Время идёт само, монеты за подбор
game.every(1, () => game.leaderstats.me.add('Время', 1));
game.leaderstats.me.add('Монеты', 1);`}</Code>
<h3 className="lessonH">Шаг 2. Достижения</h3>
<p>
Объяви список достижений с редкостью (<code>common / rare / epic /
legendary</code> разный цвет плашки и звук). Выдавай явно через
<code>unlock</code> или автоматически через <code>bindToStat</code>.
</p>
<ScriptKind kind="global" />
<Code>{`game.achievements.define([
{ id:'first_coin', name:'Первая монета', description:'Подобрать монету', icon:'🪙', rarity:'common', points:5 },
{ id:'fifty_coins', name:'Полная сумка', description:'Собрать 50 монет', icon:'💰', rarity:'rare', points:25 },
]);
// Авто-награда: как только Монеты >= 50 плашка «Полная сумка» сама выедет
game.achievements.bindToStat('fifty_coins', 'Монеты', { gte: 50 });
// Явная выдача (на первой монете)
game.achievements.unlock('first_coin');`}</Code>
<Shot src="guide-leaderstats-page.png" wide
caption="Страница «Мои достижения» (кубок слева-снизу): открытые — цветные с рамкой по редкости, закрытые — серые с замком, сверху прогресс-бар." />
<Note>
Прогресс игрока (значения статов + открытые достижения) автоматически
сохраняется в базу и подгружается при следующем входе ничего
дописывать не нужно. Уже открытое достижение второй раз плашкой не
показывается (оно «навсегда»).
</Note>
<h3 className="lessonH">Почему это важно</h3>
<p>
Лидерборды и достижения главный механизм удержания: ребёнок
возвращается в игру за новым рекордом и новой ачивкой. Это основа
симуляторов, ферм и PvP в Roblox столбец «Coins / Wins / Level»
есть почти в каждой игре.
</p>
<Try>
Добавь стат «Рекорд» и достижение <code>'speedrun'</code>, которое
выдаётся через <code>bindToStat('Время', {'{'} lte: 30 {'}'})</code>,
если собрать все монеты быстрее 30 секунд.
</Try>
</>
),
},
}; };
/** Есть ли готовый текст урока для игры с таким id. */ /** Есть ли готовый текст урока для игры с таким id. */