import React, { useState, useEffect, useRef } from 'react'; import { useNavigate } from 'react-router-dom'; import cl from './KubikonStudio.module.css'; import RublocsLogo from '../components/RublocsLogo/RublocsLogo'; import useDeviceType from '../hooks/useDeviceType'; import KubikonDesktopOnlyStub from './KubikonDesktopOnlyStub'; import Icon from '../editor/Icon'; import DocIcon from './docsIcons'; /** * KubikonRules — «Правила создания игр» платформы Рублокс. * URL: /rules * * Отдельная страница: подробно расписано, какие игры можно создавать * и публиковать, чтобы их не заблокировали и они были популярными. * Опирается на реальную систему умной ленты Рублокса: * - автопроверка скриптов при публикации (опасные → очередь review); * - статусы игр draft / published / review / blocked; * - алгоритм ленты hot_score (Wilson-рейтинг + вовлечённость + * популярность + свежесть); * - мягкое автоскрытие (demoted) игр с низким рейтингом. * * Стиль и вёрстка повторяют вику (KubikonDocs.jsx): своя боковая * панель, hero, разделы с оглавлением. Все стили — в INLINE_STYLES, * чтобы страница была самодостаточной. Иконки — самописные SVG. */ // ── Маленькие хелперы разметки ────────────────────────────────────── // Плашка «можно» — зелёная const Ok = ({ children }) => (
{children}
); // Плашка «нельзя» — красная const No = ({ children }) => (
{children}
); // Жёлтая плашка-подсказка const Tip = ({ children }) => (
{children}
); // Карточка статуса игры const Status = ({ color, name, children }) => (
{name} — {children}
); // ── Контент: разделы правил ───────────────────────────────────────── // Каждый раздел: { id, icon, title, body }. body — готовый JSX. const RULES = [ { id: 'how-publish', icon: 'rocket', title: 'Как игра попадает в ленту', body: ( <>

В Рублоксе нет предварительной модерации каждой игры человеком. Ты сам нажимаешь «Опубликовать» — и игра почти сразу появляется в общей ленте. Это значит свободу, но и ответственность: правила нужно соблюдать самому.

Что происходит, когда ты жмёшь «Опубликовать»:

  1. Игра автоматически проверяется — система смотрит твои скрипты на опасный код.
  2. Если всё чисто — игра сразу в ленте, её видят все игроки.
  3. Если в скриптах нашлось что-то подозрительное — игра уходит на ручную проверку к админу (это бывает редко). После проверки её либо публикуют, либо отправляют на доработку.
Пока игра в статусе «черновик», её видишь только ты. Тестируй сколько угодно — публикуй, только когда игра реально готова и в неё интересно играть. ), }, { id: 'statuses', icon: 'flag', title: 'Статусы игры — что они значат', body: ( <>

У каждой твоей игры есть статус. Вот что они означают:

игра ещё не опубликована, её видишь только ты. Можно свободно тестировать и переделывать. игра в общей ленте, в неё играют все. Главное состояние успешной игры. в игре нашли подозрительные скрипты, её смотрит админ. Пока проверяет — игра не в ленте. игра нарушила правила. Её убрали из ленты. Причину админ пишет в комментарии — исправь и можно опубликовать заново.

Отдельно есть «мягкое скрытие»: даже опубликованная игра может выпасть из ленты, если в неё совсем не играют или ставят сплошные дизлайки. Она не блокируется — её по-прежнему можно найти поиском и открыть по ссылке, но в рекомендациях её не показывают. Подробнее — в разделе «Как стать популярным».

), }, { id: 'allowed', icon: 'sparkles', title: 'Какие игры можно публиковать', body: ( <>

Рублокс — площадка для детей и подростков. Можно публиковать любые игры, в которые было бы не стыдно поиграть на уроке. Примеры хороших жанров:

Платформеры и паркур — прыгай по платформам, доберись до финиша, собирай монетки. Гонки и аркады — проедь трассу на время, обгони соперников, уворачивайся от препятствий. Головоломки и квесты — лабиринты, кнопки и двери, логические загадки. Тиры и «выживалки» — стрельба по мишеням, мультяшные зомби, защита базы. Бой допустим, если он мультяшный и без крови. Симуляторы и «тайкуны» — построй город, ферму, магазин; собирай ресурсы, прокачивай постройки. Ролевые игры и приключения — исследуй мир, говори с NPC, выполняй задания. Мини-игры и обучалки — викторины, игры на реакцию, игры, которые чему-то учат. Не знаешь, с чего начать — открой вику, раздел «50 игр-уроков». Там готовые игры разных жанров с пошаговыми инструкциями: бери за основу и делай свою. ), }, { id: 'forbidden-content', icon: 'warning', title: 'Что публиковать запрещено — контент', body: ( <>

Игру заблокируют, если в ней есть что-то из списка ниже. Это правила про содержание игры — текст, картинки, название, тему.

Жестокость и кровь. Реалистичное насилие, кровь, расчленёнка, сцены смерти людей. Мультяшный «бой» без крови — можно, реализм — нельзя. Взрослый контент. Любая эротика, намёки на секс, раздетые персонажи. Площадка детская — это под строгим запретом. Мат и оскорбления. Нецензурная брань в названии, описании, в текстах внутри игры, на табличках и в репликах NPC. Вражда и травля. Оскорбление людей по национальности, религии, полу; призывы кого-то травить; буллинг конкретных игроков. Опасное и противозаконное. Пропаганда наркотиков, алкоголя, курения, оружия; инструкции, как навредить себе или другим. Страшный «шок-контент». Скример-игры, цель которых — напугать; крик и страшные лица «в лоб». Лёгкая «страшилка» в мультяшном стиле — можно. Реклама и обман. Реклама посторонних сайтов, «накрутка», просьбы прислать деньги или данные аккаунта, фейковые «розыгрыши». Чужое. Нельзя выдавать чужую игру за свою. Скопировал чужую игру целиком и опубликовал как свою — это нарушение. Простое правило: если ты не показал бы эту игру учителю или родителям — её не стоит публиковать. ), }, { id: 'forbidden-scripts', icon: 'shield', title: 'Что запрещено в скриптах', body: ( <>

Скрипты в игре выполняются в песочнице — у них нет доступа к «настоящему» интернету и к чужим данным. При публикации система автоматически проверяет код. Если она находит опасные команды — игра уходит на ручную проверку.

В скриптах нельзя использовать:

Выполнение «кода из строки»eval, {' '}Function(...). Так прячут вредоносный код, поэтому это запрещено. Сетевые запросыfetch, {' '}XMLHttpRequest, WebSocket к чужим адресам. Игра не должна сама лазить в интернет. Доступ к странице браузераwindow, {' '}document, localStorage, {' '}cookie. Скрипт игры работает только с игровым миром через game.*, не со страницей. Попытки «зависить» игру нарочно — бесконечные циклы без выхода, создание миллионов объектов, чтобы у других всё затормозило. Всё, что нужно для игры, уже есть в безопасном API {' '}game.*: движение игрока, спавн объектов, очки, звуки, интерфейс. Полный список — в вике, раздел про скрипты. Если пишешь игру по урокам из вики — запрещённый код туда просто не попадёт.

Важно: автопроверка не наказывает за случайность. Если игра честная, а слово просто совпало — админ увидит это при ручной проверке и опубликует игру.

), }, { id: 'reports', icon: 'bug', title: 'Жалобы игроков и блокировки', body: ( <>

Под каждой игрой есть кнопка «Пожаловаться». Если игроки массово жалуются на твою игру — её посмотрит админ. Найдёт нарушение — заблокирует.

За что чаще всего прилетает жалоба и блокировка:

Если твою игру заблокировали:

  1. прочитай комментарий админа — там написана причина;
  2. исправь то, на что указали;
  3. опубликуй игру заново.
Не пытайся обойти блокировку: переименовать игру и залить то же самое снова, спамить одинаковыми играми, делать несколько аккаунтов. За это блокируют уже не игру, а аккаунт. ), }, { id: 'popular', icon: 'trophy', title: 'Как сделать игру популярной', body: ( <>

В ленте Рублокса игры показываются не по порядку, а по «рейтингу интереса». Чем интереснее игра, тем выше она в рекомендациях. На рейтинг влияют четыре вещи:

Лайки и дизлайки. Игроки голосуют после игры. Важно не само число лайков, а их доля: маленькая честная игра с одними лайками обгоняет большую с дизлайками.
Сколько в неё играют. Чем больше игрок проводит времени в игре и не закрывает её через 10 секунд — тем выше рейтинг.
Количество запусков. Сколько раз игру вообще открыли. Популярные игры поднимаются выше.
Свежесть. Новым играм лента даёт «фору» — их какое-то время показывают чаще, чтобы их успели заметить.

Что реально делать, чтобы игра нравилась людям:

Дай игроку понятную цель. С первых секунд должно быть ясно: куда идти и что делать. «Добеги до флага», «собери 10 монет», «победи всех зомби». Сделай красивую обложку и честное название. По карточке игрок решает, заходить ли. Обложка должна показывать саму игру, а не что-то постороннее. Добавь звук. Игра без звука кажется «мёртвой». Звук на прыжок, на монетку, на победу и проигрыш — и игра сразу живее. Сделай так, чтобы было не слишком сложно и не слишком скучно. Начало — лёгкое, дальше — постепенно сложнее. Если игрок умирает на первой секунде, он закроет игру. Проверь игру перед публикацией. Пройди её сам от начала до конца. Нет ли мест, где застреваешь, не падаешь ли сквозь пол, доходит ли дело до победы. Обновляй игру. Чини баги, добавляй уровни. Лента любит игры, которые живут и развиваются. Не пытайся «накрутить» рейтинг: лайкать свою игру с кучи аккаунтов, просить друзей спамить запуски. Система это замечает, и игра наоборот падает в ленте. ), }, { id: 'checklist', icon: 'target', title: 'Чек-лист перед публикацией', body: ( <>

Пройдись по списку перед тем, как нажать «Опубликовать». Если на все пункты ответ «да» — игру можно публиковать.

{[ 'В игре есть понятная цель, и игрок сразу её понимает.', 'Игру можно пройти от начала до конца — я проверил сам.', 'Нигде нет мата, грубостей и обидных надписей.', 'Нет жестокости, крови и взрослого контента.', 'Название и обложка честно показывают, что это за игра.', 'Игра не тормозит и не вылетает.', 'В игре есть звук на главные события.', 'Это моя игра, а не копия чужой.', 'Я не использовал запрещённый код в скриптах.', ].map((t, i) => (
{t}
))}
Сомневаешься, можно ли публиковать игру — лучше спроси учителя или оставь её черновиком. Заблокированная игра портит твой профиль, а исправить и переопубликовать можно всегда. ), }, ]; const KubikonRules = () => { const navigate = useNavigate(); const { isDesktop } = useDeviceType(); const mainRef = useRef(null); // активный раздел для подсветки в оглавлении const [activeSec, setActiveSec] = useState(RULES[0].id); // подсветка активного раздела при скролле useEffect(() => { const main = mainRef.current; if (!main) return; const onScroll = () => { const top = main.scrollTop + 140; let cur = RULES[0].id; for (const r of RULES) { const el = main.querySelector(`#rule-${r.id}`); if (el && el.offsetTop <= top) cur = r.id; } setActiveSec(cur); }; main.addEventListener('scroll', onScroll); return () => main.removeEventListener('scroll', onScroll); }, []); if (!isDesktop) { return ; } const scrollToSec = (id) => { const main = mainRef.current; const el = main && main.querySelector(`#rule-${id}`); if (el) main.scrollTo({ top: el.offsetTop - 16, behavior: 'smooth' }); }; return (
{/* === Левая боковая панель === */} {/* === Основной контент === */}

Правила создания игр

Какие игры можно публиковать, чтобы их не заблокировали и в них играли

{/* Hero */}
Правила платформы

Создавай игры, которые полюбят

В Рублоксе ты публикуешь игры сам, без долгой модерации. Эти правила помогут: твою игру не заблокируют, а игроки будут в неё играть. Прочитай их один раз — и всё будет получаться.

{/* Body: оглавление + разделы */}
{RULES.map((r) => (

{r.title}

{r.body}
))} {/* Финальный CTA */}
Готов создавать?
Открой вику с 50 играми-уроками — там готовые игры с инструкциями. Бери за основу и делай свою по этим правилам.
); }; // ══════════════════════════════════════════════════════════════════ // Инлайн-стили — страница самодостаточна, не зависит от вики. // ══════════════════════════════════════════════════════════════════ const INLINE_STYLES = ` .rulesHero { background: linear-gradient(135deg, #3357ff 0%, #1e2da5 60%, #6d28d9 100%); background-size: 200% 200%; animation: rulesGradient 16s ease-in-out infinite; border-radius: 28px; padding: 36px 40px; margin-bottom: 28px; color: #fff; display: flex; align-items: center; gap: 24px; box-shadow: 0 24px 56px rgba(51, 87, 255, 0.28); } @keyframes rulesGradient { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } } .rulesHeroContent { flex: 1; min-width: 0; } .rulesHeroBadge { display: inline-flex; align-items: center; gap: 6px; background: rgba(255, 255, 255, 0.20); border: 1px solid rgba(255, 255, 255, 0.30); color: #fff; padding: 5px 14px; border-radius: 999px; font-size: 11px; font-weight: 800; letter-spacing: 1.4px; text-transform: uppercase; margin-bottom: 12px; } .rulesHeroTitle { margin: 0 0 10px; font-size: 32px; font-weight: 900; color: #fff; letter-spacing: -1px; line-height: 1.1; text-shadow: 0 2px 12px rgba(0, 0, 0, 0.18); } .rulesHeroDesc { margin: 0; font-size: 15px; color: rgba(255, 255, 255, 0.94); line-height: 1.55; max-width: 680px; } .rulesHeroEmoji { flex-shrink: 0; color: #fff; opacity: 0.92; animation: rulesFloat 6s ease-in-out infinite; filter: drop-shadow(0 12px 24px rgba(0, 0, 0, 0.20)); } @keyframes rulesFloat { 0%, 100% { transform: translateY(0) rotate(-2deg); } 50% { transform: translateY(-10px) rotate(3deg); } } /* === Body: оглавление + контент === */ .rulesBody { display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: 28px; align-items: flex-start; } .rulesToc { position: sticky; top: 8px; background: #fff; border: 1px solid #e5e7eb; border-radius: 16px; padding: 12px 8px; box-shadow: 0 4px 16px rgba(15, 23, 42, 0.04); } .rulesTocTitle { display: flex; align-items: center; gap: 8px; padding: 6px 12px 10px; font-size: 13px; font-weight: 900; color: #0f172a; border-bottom: 1px solid #eef2f7; margin-bottom: 6px; } .rulesTocTitle svg { color: #3357ff; flex-shrink: 0; } .rulesTocItem { display: block; width: 100%; padding: 8px 12px; background: transparent; border: none; border-radius: 9px; color: #475569; font-size: 12.5px; font-weight: 700; cursor: pointer; text-align: left; transition: all 160ms ease; font-family: inherit; line-height: 1.4; } .rulesTocItem:hover { background: #f1f5f9; color: #0f172a; } .rulesTocItemActive, .rulesTocItemActive:hover { background: linear-gradient(135deg, #3357ff 0%, #1e2da5 100%); color: #fff; } .rulesContent { min-width: 0; display: flex; flex-direction: column; gap: 18px; } /* === Раздел правил === */ .ruleChapter { background: #fff; border: 1px solid #e5e7eb; border-radius: 18px; padding: 24px 28px; box-shadow: 0 4px 16px rgba(15, 23, 42, 0.04); scroll-margin-top: 16px; } .ruleTitle { display: flex; align-items: center; gap: 12px; margin: 0 0 16px; font-size: 20px; font-weight: 900; color: #0f172a; letter-spacing: -0.4px; padding-bottom: 12px; border-bottom: 1px solid #eef2f7; } .ruleTitle__ico { flex-shrink: 0; width: 38px; height: 38px; border-radius: 11px; background: linear-gradient(135deg, #3357ff 0%, #1e2da5 100%); color: #fff; display: flex; align-items: center; justify-content: center; } .ruleText { color: #334155; font-size: 14.5px; line-height: 1.65; } .ruleText p { margin: 0 0 12px; } .ruleText p:last-child { margin-bottom: 0; } .ruleText ul, .ruleText ol { margin: 0 0 12px; padding-left: 22px; } .ruleText li { margin-bottom: 8px; line-height: 1.55; } .ruleText li:last-child { margin-bottom: 0; } .ruleText b { color: #0f172a; font-weight: 800; } .ruleText code { background: #e0e8ff; color: #3357ff; padding: 2px 7px; border-radius: 6px; font-family: Consolas, Menlo, "Courier New", monospace; font-size: 13px; font-weight: 700; } /* === Плашки можно / нельзя / совет === */ .ruleBox { display: flex; gap: 11px; align-items: flex-start; border-radius: 11px; padding: 12px 14px; margin: 10px 0; font-size: 13.5px; line-height: 1.55; border: 1px solid; border-left-width: 4px; } .ruleBox__ico { flex-shrink: 0; line-height: 0; margin-top: 1px; } .ruleBox--ok { background: #f0fdf4; border-color: #bbf7d0; border-left-color: #16a34a; color: #14532d; } .ruleBox--ok .ruleBox__ico { color: #16a34a; } .ruleBox--no { background: #fef2f2; border-color: #fecaca; border-left-color: #dc2626; color: #7f1d1d; } .ruleBox--no .ruleBox__ico { color: #dc2626; } .ruleBox--no code { background: #fee2e2; color: #b91c1c; } .ruleBox--tip { background: #fffbeb; border-color: #fde68a; border-left-color: #f59e0b; color: #78350f; } .ruleBox--tip .ruleBox__ico { color: #b45309; } .ruleBox--tip code { background: #fef3c7; color: #92400e; } /* === Список статусов === */ .statusList { display: flex; flex-direction: column; gap: 4px; margin: 12px 0; } .statusRow { display: flex; gap: 11px; align-items: flex-start; background: #f8fafc; border: 1px solid #eef2f7; border-radius: 10px; padding: 11px 14px; } .statusDot { flex-shrink: 0; width: 12px; height: 12px; border-radius: 50%; margin-top: 4px; } .statusName { color: #0f172a; font-weight: 800; } .statusText { color: #475569; } /* === Факторы рейтинга === */ .factorList { display: flex; flex-direction: column; gap: 8px; margin: 12px 0; } .factorRow { display: flex; gap: 12px; align-items: flex-start; background: #f5f7ff; border: 1px solid #e0e8ff; border-radius: 11px; padding: 12px 14px; } .factorIco { flex-shrink: 0; width: 32px; height: 32px; border-radius: 9px; background: #fff; border: 1px solid #d6e0ff; color: #3357ff; display: flex; align-items: center; justify-content: center; } /* === Чек-лист === */ .checkList { display: flex; flex-direction: column; gap: 6px; margin: 12px 0; } .checkItem { display: flex; gap: 11px; align-items: center; background: #f0fdf4; border: 1px solid #bbf7d0; border-radius: 10px; padding: 10px 14px; font-size: 13.5px; color: #14532d; line-height: 1.45; } .checkBox { flex-shrink: 0; width: 20px; height: 20px; border-radius: 6px; background: #16a34a; color: #fff; display: flex; align-items: center; justify-content: center; } /* === Финальный CTA === */ .rulesCta { background: linear-gradient(135deg, #3357ff 0%, #1e2da5 100%); border-radius: 24px; padding: 32px; text-align: center; color: #fff; box-shadow: 0 16px 40px rgba(51, 87, 255, 0.32); margin-top: 8px; } .rulesCtaIcon { display: flex; justify-content: center; color: #fff; margin-bottom: 10px; } .rulesCtaTitle { font-size: 22px; font-weight: 900; margin-bottom: 8px; } .rulesCtaText { font-size: 14px; color: rgba(255, 255, 255, 0.90); margin: 0 auto 20px; max-width: 520px; line-height: 1.55; } .rulesCtaBtn { padding: 12px 26px; background: #fff; color: #3357ff; border: none; border-radius: 10px; font-size: 14px; font-weight: 900; cursor: pointer; font-family: inherit; } .rulesCtaBtn:hover { transform: translateY(-2px); } /* Адаптив */ @media (max-width: 980px) { .rulesBody { grid-template-columns: 1fr; } .rulesToc { position: static; } .rulesHero { flex-direction: column; padding: 28px 24px; text-align: center; } .ruleChapter { padding: 20px; } } `; export default KubikonRules;