docs(studio): вики — рецепты скриптов, контекст для нейронки, Team Create, актуализация
Новые разделы: «Скрипты: рецепты» (S1-S12: килблок/касание/исчезновение/телепорт/ свойства примитивов/таймеры/враги/сохранение), «Контекст для нейронки» (полный game-API одним copy-paste блоком для ChatGPT), «Вместе с друзьями» (V1-V3 Team Create). Раздел «Системы» дополнен G7-G12 (лидерборды/floaters/инвентарь/небо/ меню/машины). Иконка users. 80 секций вики. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
fbf7ef680b
commit
ab11ac0b4e
@ -104,6 +104,123 @@ export const Shot = ({ src, caption, wide }) => (
|
||||
// DOCS — разделы вики A-J
|
||||
// ══════════════════════════════════════════════════════════════════
|
||||
|
||||
// ════════════════════════════════════════════════════════════
|
||||
// AI_CONTEXT — полный справочник API скриптов Рублокса одним
|
||||
// текстом для вставки в нейросеть. Держать в синхроне с
|
||||
// ScriptSandboxWorker.js при добавлении новых game-API.
|
||||
// ════════════════════════════════════════════════════════════
|
||||
const AI_CONTEXT = `Ты — помощник по написанию скриптов для онлайн-конструктора 3D-игр «Рублокс» (аналог Roblox, движок Babylon.js). Скрипты пишутся на JavaScript. Всё доступно через глобальный объект game. Ниже — полный API. Пиши ТОЛЬКО рабочий код, используя ТОЛЬКО эти методы. Не выдумывай команды. Координаты в метрах, повороты в РАДИАНАХ (90°=Math.PI/2).
|
||||
|
||||
=== ДВА ВИДА СКРИПТОВ ===
|
||||
1) Глобальный — в категории «Скрипты», запускается 1 раз при старте. Управляет всей сценой.
|
||||
2) На объекте — висит на примитиве/модели/блоке. В нём доступен game.self — сам объект-носитель.
|
||||
Всегда указывай пользователю, КУДА писать скрипт.
|
||||
|
||||
=== ИГРОК game.player ===
|
||||
.position -> {x,y,z}; .yaw, .pitch (рад); .forward -> {x,y,z} (куда смотрит); .hp, .maxHp, .alive
|
||||
.teleport(x,y,z); .damage(n); .kill(); .heal(n); .respawn()
|
||||
.setSpeed(mul); .setJumpPower(mul); .setGravityMul(mul); .setInputBlocked(bool)
|
||||
.giveTool(toolId, {equip:true}); .removeTool(id); .setSkin(slug); .setTeam(name)
|
||||
.isKeyDown('w'|'a'|'s'|'d'|'space'|'shift'...); .boostJump(strength); .setDoubleJump(bool)
|
||||
.setCameraMode('first'|'third'|'front'); .playEmote('wave'|'dance'|'cheer'|'sit')
|
||||
|
||||
=== ОБЪЕКТ-НОСИТЕЛЬ game.self (только в скрипте на объекте) ===
|
||||
.ref ('primitive:N'); .position -> {x,y,z}; .kind
|
||||
.onTouch(fn) — игрок коснулся; .onUntouch(fn) — отошёл
|
||||
.onClick(fn) — клик мышью по объекту
|
||||
.onInteract(fn, {text:'Открыть', key:'e', distance:4, holdDuration:0}) — действие по клавише E
|
||||
.move(x,y,z); .rotateY(rad); .setColor('#hex'); .setVisible(bool); .setCollide(bool)
|
||||
.setLabel(text, {color,height}); .clearLabel(); .delete()
|
||||
|
||||
=== СЦЕНА game.scene ===
|
||||
spawn(type, opts) -> объект. type: 'cube'|'sphere'|'cylinder'|'cone'|'pyramid'|'torus'|'wedge'|'plane' (примитивы), 'model:ID', 'block:ID', 'vehicle:car', 'light:point', 'billboard', 'trigger'.
|
||||
opts: {x,y,z, sx,sy,sz, rotationX,rotationY,rotationZ, color:'#hex', material:'matte'|'neon'|'metal'|'glass'|'studs', name, anchored:true(висит)/false(падает), canCollide, visible, mass, lifetime(сек до авто-удаления)}
|
||||
delete(ref); move(ref,x,y,z); setRotation(ref,rx,ry,rz); setColor(ref,'#hex'); setMaterial(ref,name); setVisible(ref,bool); setCollide(ref,bool); setOpacity(ref,0..1); setScale(ref,sx,sy,sz)
|
||||
setLabel(ref,text,opts); clearLabel(ref); setData(ref,key,val); getData(ref,key)
|
||||
find(name)->[...]; findOne(name)->объект|null; all('primitive'|'model'|'block')
|
||||
tag(ref,tag); untag(ref,tag); hasTag(ref,tag); getTagged(tag)->[refs]
|
||||
clone(ref,{dx,dy,dz}); spawnParticles('fire'|'smoke'|'sparks'|'magic'|'explosion'|'confetti', {x,y,z}, {duration,count,color})
|
||||
setSkybox({preset:'clear-summer-day'|'sunset'|'starry-night'|'space'|'cloudy'}); setFog({color,density}); setClouds({enabled,cover,speed})
|
||||
spawnNpc(modelType, {x,y,z,hp,name,speed}) -> npc. npc: .position, .hp, .follow('player'|ref), .moveTo(x,z), .stop(), .say(text,sec), .damage(n), .setSpeed(s), .onDeath(fn), .remove()
|
||||
|
||||
=== ОБЪЕКТ-ПРОКСИ (то, что вернул spawn/findOne) ===
|
||||
obj.ref; obj.position; obj.color='#hex'; obj.material='neon'; obj.scale=2; obj.opacity=0.5; obj.visible=false; obj.canCollide=false; obj.position={x,y,z}
|
||||
obj.move(x,y,z); obj.rotateY(rad); obj.onTouch(fn); obj.onClick(fn); obj.onInteract(fn,opts); obj.clone({dx,dy,dz}); obj.destroy(); obj.tween(props,opts); obj.setLabel(t,opts); obj.addTag(t)
|
||||
|
||||
=== HUD game.ui ===
|
||||
.score = N (счётчик в углу); .timer = N (таймер mm:ss); .showText('текст', сек) (крупно по центру)
|
||||
.set(id, text, {x,y,color,size}) (своя метка, x/y в %); .remove(id); .clear()
|
||||
|
||||
=== GUI (кнопки/панели на экране) game.gui ===
|
||||
create('button'|'text'|'frame'|'image', {name,x,y,w,h,text,bg:'#hex',color,fontSize,borderRadius}) -> id
|
||||
onClick(id, fn); update(id, {text,...}); show(id); hide(id); remove(id); tween(id, props, {duration})
|
||||
|
||||
=== ТАЙМЕРЫ И КАДРЫ ===
|
||||
game.onTick(fn) — каждый кадр, fn(dt) dt=сек с прошлого кадра
|
||||
game.after(сек, fn) -> id — один раз через N сек
|
||||
game.every(сек, fn) -> id — повторять каждые N сек
|
||||
game.cancel(id) — отменить таймер
|
||||
game.tween(ref, props, {duration, easing:'linear'|'ease'|'bounce'|'elastic', yoyo, repeat:-1, onDone}) — анимация свойств (props: x,y,z, rotationX/Y/Z, sx/sy/sz, color, opacity)
|
||||
|
||||
=== СОБЫТИЯ ===
|
||||
game.onKey('w', fn); game.onKeyUp('w', fn); game.onClick(fn) (fn({point,target}))
|
||||
game.onPlayerDied(fn); game.onHpChange(fn); game.onPlayerJump(fn); game.onMobKilled(fn)
|
||||
game.broadcast(name, data) — послать сообщение всем скриптам
|
||||
game.onMessage(name, fn) — принять сообщение (fn(data))
|
||||
|
||||
=== ФИЗИКА game.physics ===
|
||||
raycast(origin, dir, {maxDistance}) -> {hit, ref, point, distance} (синхронно, для стрельбы)
|
||||
applyImpulse(ref, {x,y,z}); setVelocity(ref, {x,y,z}); explode({x,y,z}, radius, {damage}); passThrough(refОrTag, bool)
|
||||
|
||||
=== ЭФФЕКТЫ game.fx ===
|
||||
damageFloater(posОrRef, value, {isCrit,isHeal,isMiss,color}) — всплывающая цифра урона
|
||||
autoMobFloaters(true) — авто-цифры над всеми мобами
|
||||
beam({from,to,color,width}) -> луч; pointer({from,to,preset:'quest'}); trail(ref,{color,width})
|
||||
|
||||
=== ЗВУК game.sound ===
|
||||
play('coin'|'jump'|'win'|'lose'|'click'|'hit'|'pickup' | 'sound_N', {volume,pitch,at:{x,y,z},loop}) -> {stop()}
|
||||
|
||||
=== КАМЕРА game.camera ===
|
||||
shake(amp, sec); setFov(deg); focusOn(ref,{distance,height}); cutscene([{x,y,z}...], {lookAt,segDuration}); reset()
|
||||
|
||||
=== ОКРУЖЕНИЕ game.environment ===
|
||||
setSkyColor('#hex'); setFog({enabled,color,density}); setTimeOfDay(0..24)
|
||||
|
||||
=== ИНВЕНТАРЬ / ПРЕДМЕТЫ ===
|
||||
game.items.define([{id,name,emoji,rarity:'common'|'rare'|'epic'|'legendary',maxStack,onUseEffect:'heal:50'}])
|
||||
game.inventory.give(id,count); .take(id,count); .has(id); .open(); .list()
|
||||
|
||||
=== ЛИДЕРБОРД И ДОСТИЖЕНИЯ ===
|
||||
game.leaderstats.define('Монеты', {initial:0}); game.leaderstats.me.add('Монеты', 1); .me.set(name,val); .me.get(name)
|
||||
game.achievements.define([{id,name,description,icon,rarity}]); game.achievements.unlock(id)
|
||||
|
||||
=== СОХРАНЕНИЕ (между сессиями) game.save ===
|
||||
.merge(namespace, {patch:{поле:знач}, increment:{счётчик:дельта}, max:{рекорд:знач}})
|
||||
.get(namespace, fn) (fn(data|null)); .increment(ns,key,delta); .leaderboard(ns,key,'desc',fn)
|
||||
|
||||
=== МОДАЛКИ game.modal ===
|
||||
.dialog(npcName, [строки], onDone); .confirmation(title, body, onYes, onNo); .lootbox([{name,color,icon,rarity}], onPick); .close()
|
||||
|
||||
=== УТИЛИТЫ ===
|
||||
game.log(...) — в консоль; game.random(min,max,целое?); game.clamp(v,min,max); game.lerp(a,b,t); game.distance(a,b) (точки или ref); game.format.time(сек,'mm:ss'); game.format.number(n,'short')
|
||||
|
||||
=== ВАЖНЫЕ ПРАВИЛА ===
|
||||
- Повороты в РАДИАНАХ (Math.PI/2 = 90°).
|
||||
- Счётчики/общую логику держи в ОДНОМ глобальном скрипте; объекты шлют game.broadcast (скрипты объектов не видят переменные друг друга).
|
||||
- spawn примитива: тип без префикса ('cube'), модели — с 'model:', машина — 'vehicle:car'.
|
||||
- material только: matte, neon, metal, glass, studs.
|
||||
- Для сбора предмета: game.self.onTouch(()=>{ game.broadcast('coin'); game.self.delete(); }).
|
||||
- Не используй require() и DOM/window — только game.* и обычный JS.
|
||||
|
||||
ПРИМЕР (килблок-лава, скрипт НА объекте):
|
||||
game.self.onTouch(() => { game.player.kill(); game.ui.showText('Лава!', 2); });
|
||||
|
||||
ПРИМЕР (сбор монет, глобальный скрипт):
|
||||
let s = 0; game.ui.score = 0;
|
||||
game.onMessage('coin', () => { s++; game.ui.score = s; game.sound.play('coin'); });
|
||||
|
||||
Теперь напиши скрипт под мою задачу (она ниже). Укажи, КУДА его вставить (глобальный или на объект).`;
|
||||
|
||||
export const DOCS = [
|
||||
// ════════════════════════════════════════════════════
|
||||
// РАЗДЕЛ A — ОСНОВЫ
|
||||
@ -2029,6 +2146,167 @@ game.log('Игроков в комнате:', game.players.count());
|
||||
// когда новый игрок зашёл
|
||||
game.onPlayerJoin((p) => {
|
||||
game.ui.showText(p.name + ' присоединился!', 2);
|
||||
});`}</Code>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'leaderstats',
|
||||
title: 'G7. Лидерборды и достижения',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
<b>Лидерборд</b> — таблица очков игроков справа-сверху (как
|
||||
в Roblox). Объяви стат и меняй значение:
|
||||
</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`game.leaderstats.define('Монеты', { initial: 0, icon: 'coin' });
|
||||
game.leaderstats.define('Уровень', { initial: 1 });
|
||||
|
||||
game.leaderstats.me.add('Монеты', 5); // +5 текущему игроку
|
||||
game.leaderstats.me.set('Уровень', 2); // задать значение
|
||||
const c = game.leaderstats.me.get('Монеты');`}</Code>
|
||||
<p>
|
||||
<b>Достижения</b> — всплывающие ачивки с редкостью и звуком:
|
||||
</p>
|
||||
<Code>{`game.achievements.define([
|
||||
{ id: 'first_coin', name: 'Первая монетка', description: 'Собери монету', icon: 'coin', rarity: 'common' },
|
||||
{ id: 'rich', name: 'Богач', description: '100 монет', icon: 'trophy', rarity: 'legendary' }
|
||||
]);
|
||||
game.achievements.unlock('first_coin');
|
||||
// или авто-разблокировка по статy:
|
||||
game.achievements.bindToStat('rich', 'Монеты', 100);`}</Code>
|
||||
<Note>
|
||||
Лидерборд и достижения сохраняются в БД и подтягиваются при
|
||||
следующем входе игрока.
|
||||
</Note>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'damage-floaters',
|
||||
title: 'G8. Облачка урона (damage floaters)',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
Всплывающие <b>цифры урона</b> над врагом — как в RPG. Самый
|
||||
простой способ — авто-режим (цифры над всеми мобами при уроне):
|
||||
</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`game.fx.autoMobFloaters(true);`}</Code>
|
||||
<p>Ручной вызов в нужный момент:</p>
|
||||
<Code>{`game.fx.damageFloater(enemy.position, 25); // обычный урон
|
||||
game.fx.damageFloater(enemy.position, 100, { isCrit: true }); // крит — крупно, жёлтый
|
||||
game.fx.damageFloater('player', 30, { isHeal: true }); // лечение, зелёный
|
||||
game.fx.damageFloater(pos, 0, { isMiss: true }); // промах MISS`}</Code>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'items-inventory',
|
||||
title: 'G9. Предметы и инвентарь с редкостями',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
Полноценный инвентарь (сетка + хотбар, стаки, редкости).
|
||||
Сначала опиши предметы, потом выдавай:
|
||||
</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`game.items.define([
|
||||
{ id: 'berry', name: 'Ягоды', emoji: '🍓', rarity: 'common', maxStack: 16 },
|
||||
{ id: 'potion', name: 'Зелье', emoji: '🧪', rarity: 'rare', maxStack: 8, onUseEffect: 'heal:50' },
|
||||
{ id: 'sword', name: 'Меч', emoji: '⚔️', rarity: 'legendary', maxStack: 1 },
|
||||
]);
|
||||
|
||||
game.inventory.give('sword', 1);
|
||||
game.inventory.give('berry', 5); // стак`}</Code>
|
||||
<p>Сбор предмета с земли (скрипт на предмете):</p>
|
||||
<ScriptKind kind="object" on="собираемый предмет" />
|
||||
<Code>{`game.self.onInteract(() => {
|
||||
game.inventory.give('berry', 2);
|
||||
game.self.delete();
|
||||
}, { text: 'Собрать', key: 'e', distance: 3 });`}</Code>
|
||||
<Note>
|
||||
Редкости: common (серый), uncommon (зелёный), rare (голубой),
|
||||
epic (фиолетовый), legendary (золотой). Окно инвентаря —
|
||||
клавиша <kbd className="kbd">I</kbd>, drag-drop, ПКМ-меню.
|
||||
</Note>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'sky-environment',
|
||||
title: 'G10. Небо, облака, туман, время суток',
|
||||
body: (
|
||||
<>
|
||||
<p>Кастомное небо одной строкой — пресеты:</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`game.scene.setSkybox({ preset: 'sunset' });
|
||||
// пресеты: clear-summer-day | lowpoly-roblox | cloudy | sunset | starry-night | space`}</Code>
|
||||
<p>Облака, туман и плавный переход:</p>
|
||||
<Code>{`game.scene.setClouds({ enabled: true, cover: 0.5, speed: 0.02 });
|
||||
game.scene.setFog({ color: '#dddddd', density: 0.006 });
|
||||
game.scene.skybox.fadeTo({ preset: 'starry-night' }, 3); // плавно за 3 сек`}</Code>
|
||||
<p>Простое управление цветом неба и временем суток:</p>
|
||||
<Code>{`game.environment.setSkyColor('#0a1024'); // тёмное небо
|
||||
game.environment.setTimeOfDay(0); // ночь (0..24)
|
||||
game.environment.setTimeOfDay(12); // полдень`}</Code>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'modal-menu-loading',
|
||||
title: 'G11. Диалоги, меню, экран загрузки',
|
||||
body: (
|
||||
<>
|
||||
<p><b>Диалог NPC</b> построчно:</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`game.modal.dialog('Староста', [
|
||||
'Привет, путник!',
|
||||
'Собери 10 монет и возвращайся.',
|
||||
], () => game.ui.showText('Квест начат!', 2));`}</Code>
|
||||
<p><b>Окно Да/Нет</b> и <b>лутбокс</b>:</p>
|
||||
<Code>{`game.modal.confirmation('Выход', 'Точно выйти?', () => game.player.respawn(), null);
|
||||
|
||||
game.modal.lootbox([
|
||||
{ name: 'Меч', color: '#f0ad4e', rarity: 'legendary' },
|
||||
{ name: 'Щит', color: '#5bc0de', rarity: 'rare' },
|
||||
], (item) => game.ui.showText('Выпал: ' + item.name, 3));`}</Code>
|
||||
<p><b>Экран загрузки</b> при переходе между уровнями:</p>
|
||||
<Code>{`game.loading.show({
|
||||
style: 'ken-burns',
|
||||
placeName: 'Глава 2 — Шахта',
|
||||
studioName: 'Моя студия',
|
||||
duration: 2
|
||||
});
|
||||
game.loading.onHide(() => game.ui.showText('Добро пожаловать!', 2));`}</Code>
|
||||
<Note>
|
||||
Стартовый экран загрузки игры настраивается без кода —
|
||||
см. раздел вики «Экран загрузки» (карточка в разборе игр) и
|
||||
вкладку «Стартовый экран» в настройках проекта.
|
||||
</Note>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'vehicles-menu',
|
||||
title: 'G12. Машины и главное меню',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
<b>Машина</b>, на которой можно ездить (вход hold-F, WASD руль):
|
||||
</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`game.scene.spawn('vehicle:car', { x: 0, y: 1, z: 0, name: 'Тачка' });
|
||||
game.onVehicleEnter(() => game.ui.showText('За рулём! WASD — ехать', 2));
|
||||
game.onVehicleExit(() => game.ui.showText('Вышел', 1));`}</Code>
|
||||
<p><b>Главное меню</b> игры с живой камерой и кнопкой ИГРАТЬ:</p>
|
||||
<Code>{`game.mainMenu.show({
|
||||
title: 'МОЯ ИГРА',
|
||||
camera: 'orbit',
|
||||
playButtonText: 'ИГРАТЬ',
|
||||
patchNotes: { title: 'Что нового', items: ['Добавлены машины', 'Новая карта'] },
|
||||
onPlay: () => game.ui.showText('Поехали!', 2)
|
||||
});`}</Code>
|
||||
</>
|
||||
),
|
||||
@ -2398,4 +2676,632 @@ game.onTick(() => {
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ════════════════════════════════════════════════════
|
||||
// РАЗДЕЛ — СКРИПТЫ: ГОТОВЫЕ РЕЦЕПТЫ
|
||||
// ════════════════════════════════════════════════════
|
||||
{
|
||||
id: 'recipes',
|
||||
icon: 'code',
|
||||
title: 'Скрипты: рецепты',
|
||||
summary: 'Готовые мини-скрипты, которые можно скопировать и вставить: килблок, сбор предметов, исчезновение и телепорт при касании, кнопки, таймеры, все свойства примитивов.',
|
||||
sections: [
|
||||
{
|
||||
id: 'recipes-howto',
|
||||
title: 'S1. Куда писать скрипты',
|
||||
body: (
|
||||
<>
|
||||
<p>В Рублоксе есть <b>два вида скриптов</b>:</p>
|
||||
<ul>
|
||||
<li><b>Глобальный</b> — создаётся в иерархии в категории
|
||||
<b> «Скрипты»</b> (кнопка «+»). Запускается один раз при
|
||||
старте игры. В нём управляешь всей сценой через
|
||||
<code> game.scene</code>, <code>game.player</code>, <code>game.ui</code>.</li>
|
||||
<li><b>На объекте</b> — вешается прямо на примитив/модель/блок.
|
||||
В нём работает <code>game.self</code> — это сам объект-носитель.
|
||||
Удобно для «этот блок убивает», «этот сундук открывается».</li>
|
||||
</ul>
|
||||
<Note>
|
||||
В рецептах ниже над каждым примером написано, <b>куда его
|
||||
писать</b>. Просто скопируй код и вставь в нужный скрипт.
|
||||
</Note>
|
||||
<p>
|
||||
Полезное: <code>game.log(...)</code> печатает в консоль (значок
|
||||
«Консоль» внизу) — для отладки. <code>game.player.position</code>
|
||||
— где сейчас игрок (<code>{'{x, y, z}'}</code>).
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'recipes-touch',
|
||||
title: 'S2. Касание объекта (onTouch)',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
Самое частое событие — <b>игрок коснулся объекта</b>. Вешаем
|
||||
скрипт на объект и подписываемся через <code>game.self.onTouch</code>.
|
||||
</p>
|
||||
<ScriptKind kind="object" on="любой объект (плита, зона, предмет)" />
|
||||
<Code>{`// Игрок наступил на объект — показать надпись и звук
|
||||
game.self.onTouch(() => {
|
||||
game.ui.showText('Ты коснулся плиты!', 2);
|
||||
game.sound.play('click');
|
||||
});
|
||||
|
||||
// Когда игрок ушёл с объекта
|
||||
game.self.onUntouch(() => {
|
||||
game.ui.showText('Отошёл', 1);
|
||||
});`}</Code>
|
||||
<p>
|
||||
Можно подписаться и на <b>чужой</b> объект из глобального
|
||||
скрипта — найди его по имени:
|
||||
</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`const trap = game.scene.findOne('Ловушка');
|
||||
trap.onTouch(() => game.player.damage(20));`}</Code>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'recipes-killblock',
|
||||
title: 'S3. Килблок — урон и смерть при касании',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
<b>Килблок</b> — объект, который наносит урон или мгновенно
|
||||
убивает, когда игрок его коснулся (лава, шипы, кислота).
|
||||
</p>
|
||||
<ScriptKind kind="object" on="блок-ловушку (лава, шипы)" />
|
||||
<Code>{`// Мгновенная смерть при касании
|
||||
game.self.onTouch(() => {
|
||||
game.player.kill();
|
||||
game.ui.showText('💀 Ты сгорел в лаве!', 2);
|
||||
});`}</Code>
|
||||
<p>Если хочешь не убивать сразу, а наносить урон:</p>
|
||||
<Code>{`// Урон 25 при касании (учитывает кадры неуязвимости)
|
||||
game.self.onTouch(() => {
|
||||
game.player.damage(25);
|
||||
game.camera.shake(0.2, 0.3); // лёгкая тряска
|
||||
});`}</Code>
|
||||
<p>
|
||||
<b>Постоянный урон</b>, пока игрок стоит в зоне (например,
|
||||
ядовитое облако) — урон каждые 0.5 сек, пока касается:
|
||||
</p>
|
||||
<Code>{`let inside = false;
|
||||
game.self.onTouch(() => { inside = true; });
|
||||
game.self.onUntouch(() => { inside = false; });
|
||||
game.every(0.5, () => {
|
||||
if (inside) game.player.damage(5);
|
||||
});`}</Code>
|
||||
<Try>
|
||||
Сделай красный неоновый куб, повесь на него скрипт смерти —
|
||||
получится лава. Поставь его в проёме как преграду.
|
||||
</Try>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'recipes-disappear',
|
||||
title: 'S4. Исчезновение при касании (сбор монет)',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
Предмет <b>исчезает</b>, когда игрок его коснулся — основа
|
||||
сбора монеток, ключей, бонусов.
|
||||
</p>
|
||||
<ScriptKind kind="object" on="монетку / собираемый предмет" />
|
||||
<Code>{`// Простое исчезновение + звук
|
||||
game.self.onTouch(() => {
|
||||
game.sound.play('coin');
|
||||
game.self.delete();
|
||||
});`}</Code>
|
||||
<p>
|
||||
Со <b>счётчиком</b>: предмет сообщает глобальному скрипту,
|
||||
тот считает. На монетке:
|
||||
</p>
|
||||
<Code>{`game.self.onTouch(() => {
|
||||
game.broadcast('coin'); // сообщить всем скриптам
|
||||
game.self.delete();
|
||||
});`}</Code>
|
||||
<p>В глобальном скрипте — приём и счёт:</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`let score = 0;
|
||||
game.ui.score = 0;
|
||||
game.onMessage('coin', () => {
|
||||
score = score + 1;
|
||||
game.ui.score = score; // обновить счётчик в углу
|
||||
if (score >= 10) game.ui.showText('🏆 Собрал все!', 3);
|
||||
});`}</Code>
|
||||
<Note>
|
||||
<b>Не</b> ставь счётчик на саму монетку — каждая монетка это
|
||||
свой скрипт, они не видят переменные друг друга. Считай в
|
||||
одном глобальном скрипте, монетки только шлют
|
||||
<code> game.broadcast</code>.
|
||||
</Note>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'recipes-teleport',
|
||||
title: 'S5. Телепорт и смена позиции при касании',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
При касании <b>переместить игрока</b> (портал) или
|
||||
<b> сдвинуть сам объект</b> (движущаяся платформа).
|
||||
</p>
|
||||
<p><b>Портал</b> — телепорт игрока в точку:</p>
|
||||
<ScriptKind kind="object" on="портал" />
|
||||
<Code>{`game.self.onTouch(() => {
|
||||
game.player.teleport(0, 20, 50); // x, y, z назначения
|
||||
game.sound.play('win');
|
||||
game.camera.shake(0.15, 0.2);
|
||||
});`}</Code>
|
||||
<p>
|
||||
<b>Сдвинуть сам объект</b> при касании (например, опустить
|
||||
мост). <code>game.self.move</code> ставит новую позицию:
|
||||
</p>
|
||||
<Code>{`let opened = false;
|
||||
game.self.onTouch(() => {
|
||||
if (opened) return;
|
||||
opened = true;
|
||||
const p = game.self.position;
|
||||
game.self.move(p.x, p.y - 3, p.z); // уехал вниз на 3 м
|
||||
});`}</Code>
|
||||
<p>
|
||||
<b>Плавно</b> сдвинуть — через <code>game.tween</code> (анимация):
|
||||
</p>
|
||||
<Code>{`// дверь уезжает вбок за 1 секунду
|
||||
const p = game.self.position;
|
||||
game.self.onTouch(() => {
|
||||
game.tween(game.self.ref, { x: p.x + 4 }, { duration: 1, easing: 'ease' });
|
||||
});`}</Code>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'recipes-primitive-props',
|
||||
title: 'S6. Все свойства примитивов из скрипта',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
Любой примитив можно <b>создать</b> и <b>менять</b> из
|
||||
скрипта. Вот все свойства и как их задать.
|
||||
</p>
|
||||
<ScriptKind kind="global" />
|
||||
<p><b>Создать примитив</b> со всеми свойствами:</p>
|
||||
<Code>{`const box = game.scene.spawn('cube', {
|
||||
x: 0, y: 2, z: 0, // позиция
|
||||
sx: 2, sy: 1, sz: 3, // размер по осям (ширина/высота/глубина)
|
||||
rotationX: 0, rotationY: 0.8, rotationZ: 0, // поворот в радианах
|
||||
color: '#ff5533', // цвет (hex)
|
||||
material: 'neon', // matte | neon | metal | glass | studs
|
||||
name: 'МойКуб',
|
||||
anchored: true, // true = висит на месте; false = падает (физика)
|
||||
canCollide: true, // false = игрок проходит насквозь
|
||||
visible: true,
|
||||
mass: 5, // масса (если anchored:false)
|
||||
});`}</Code>
|
||||
<p>Типы примитивов для <code>spawn</code>:</p>
|
||||
<Code>{`'cube' 'sphere' 'cylinder' 'cone' 'pyramid' 'torus' 'wedge' 'cornerwedge' 'plane'`}</Code>
|
||||
<p><b>Менять свойства</b> уже существующего объекта:</p>
|
||||
<Code>{`game.scene.setColor(box, '#00ff88'); // цвет
|
||||
game.scene.setMaterial(box, 'glass'); // материал
|
||||
game.scene.setVisible(box, false); // спрятать
|
||||
game.scene.setCollide(box, false); // сделать проходимым
|
||||
game.scene.setOpacity(box, 0.4); // полупрозрачность (1=видно, 0=невидимо)
|
||||
game.scene.setScale(box, 3, 1, 1); // новый размер
|
||||
game.scene.move(box, 5, 2, 0); // переместить
|
||||
game.scene.setRotation(box, 0, 1.57, 0); // повернуть (радианы)
|
||||
game.scene.setLabel(box, 'Привет!', { color:'#fff', height: 2.5 });`}</Code>
|
||||
<p>
|
||||
Удобнее — через <b>объект-прокси</b> (присваивание свойств):
|
||||
</p>
|
||||
<Code>{`const obj = game.scene.findOne('МойКуб');
|
||||
obj.color = '#ffd700';
|
||||
obj.material = 'metal';
|
||||
obj.scale = 2; // равномерный масштаб
|
||||
obj.opacity = 0.5;
|
||||
obj.visible = false;
|
||||
obj.canCollide = false;
|
||||
obj.position = { x: 0, y: 10, z: 0 };
|
||||
obj.rotateY(1.57);
|
||||
obj.destroy(); // удалить`}</Code>
|
||||
<Note>
|
||||
<b>Радианы:</b> поворот задаётся в радианах, не градусах.
|
||||
90° = <code>Math.PI/2</code> ≈ 1.57, 180° = <code>Math.PI</code> ≈ 3.14.
|
||||
</Note>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'recipes-anim',
|
||||
title: 'S7. Движение, вращение, мигание (onTick и tween)',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
<b>Вращающийся объект</b> (монета, портал) — крутим каждый
|
||||
кадр через <code>game.onTick</code> (dt = время кадра):
|
||||
</p>
|
||||
<ScriptKind kind="object" on="вращающийся объект" />
|
||||
<Code>{`let angle = 0;
|
||||
game.onTick((dt) => {
|
||||
angle = angle + dt * 2; // скорость вращения
|
||||
game.self.rotateY(angle);
|
||||
});`}</Code>
|
||||
<p><b>Парение вверх-вниз</b> (плавно качается):</p>
|
||||
<Code>{`const start = game.self.position;
|
||||
let t = 0;
|
||||
game.onTick((dt) => {
|
||||
t = t + dt;
|
||||
const dy = Math.sin(t * 2) * 0.4; // амплитуда 0.4 м
|
||||
game.self.move(start.x, start.y + dy, start.z);
|
||||
});`}</Code>
|
||||
<p><b>Пульсация размера</b> через tween (бесконечно туда-обратно):</p>
|
||||
<Code>{`game.tween(game.self.ref, { sy: 1.4 }, {
|
||||
duration: 0.6, easing: 'ease', yoyo: true, repeat: -1
|
||||
});`}</Code>
|
||||
<p><b>Мигание цветом</b> каждые полсекунды:</p>
|
||||
<Code>{`let on = false;
|
||||
game.every(0.5, () => {
|
||||
on = !on;
|
||||
game.self.setColor(on ? '#ff0000' : '#330000');
|
||||
});`}</Code>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'recipes-button-door',
|
||||
title: 'S8. Кнопка по E и дверь',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
<b>Взаимодействие по клавише E</b> (как в Roblox ProximityPrompt)
|
||||
— через <code>game.self.onInteract</code>. Появляется подсказка
|
||||
«[E] …» когда игрок рядом.
|
||||
</p>
|
||||
<ScriptKind kind="object" on="кнопку / рычаг / сундук" />
|
||||
<Code>{`game.self.onInteract(() => {
|
||||
game.ui.showText('Открыто!', 2);
|
||||
game.broadcast('open-door');
|
||||
}, { text: 'Открыть', key: 'e', distance: 4 });`}</Code>
|
||||
<p>На двери — глобальный/объектный скрипт, который её открывает:</p>
|
||||
<ScriptKind kind="object" on="дверь" />
|
||||
<Code>{`const closed = game.self.position;
|
||||
game.onMessage('open-door', () => {
|
||||
// плавно уехать вверх (открыться)
|
||||
game.tween(game.self.ref, { y: closed.y + 4 }, { duration: 1, easing: 'ease' });
|
||||
game.self.setCollide(false); // через неё можно пройти
|
||||
});`}</Code>
|
||||
<Note>
|
||||
<code>holdDuration: 1</code> в опциях onInteract — держать E
|
||||
1 секунду (для важных действий). <code>distance</code> —
|
||||
с какого расстояния появляется подсказка.
|
||||
</Note>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'recipes-gui-timer',
|
||||
title: 'S9. Надписи на экране, таймер, кнопки GUI',
|
||||
body: (
|
||||
<>
|
||||
<p><b>HUD-надписи</b> в углу и по центру:</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`game.ui.score = 0; // счётчик «Очки: 0» в углу
|
||||
game.ui.score = 50; // обновить
|
||||
game.ui.timer = 60; // таймер mm:ss в углу
|
||||
game.ui.showText('Старт!', 2); // крупно по центру на 2 сек
|
||||
game.ui.set('hp', 'Жизни: 3', { x: 50, y: 90, color: '#fff' }); // своя метка
|
||||
game.ui.remove('hp'); // убрать метку`}</Code>
|
||||
<p><b>Обратный отсчёт</b> и проигрыш по времени:</p>
|
||||
<Code>{`let time = 30;
|
||||
game.ui.timer = time;
|
||||
const id = game.every(1, () => {
|
||||
time = time - 1;
|
||||
game.ui.timer = time;
|
||||
if (time <= 0) {
|
||||
game.cancel(id);
|
||||
game.ui.showText('Время вышло!', 3);
|
||||
game.player.kill();
|
||||
}
|
||||
});`}</Code>
|
||||
<p><b>Кнопка на экране</b> (GUI) и обработка клика:</p>
|
||||
<Code>{`const btn = game.gui.create('button', {
|
||||
name: 'start', text: 'НАЧАТЬ', x: 50, y: 80,
|
||||
w: 20, h: 8, bg: '#3a6ee0', color: '#fff', fontSize: 18, borderRadius: 12
|
||||
});
|
||||
game.gui.onClick(btn, () => {
|
||||
game.ui.showText('Поехали!', 2);
|
||||
game.gui.hide(btn);
|
||||
});`}</Code>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'recipes-spawn-fall',
|
||||
title: 'S10. Спавн, падение, проверка падения вниз',
|
||||
body: (
|
||||
<>
|
||||
<p><b>Спавнить объекты с неба</b> каждую секунду (ловилка):</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`game.every(1, () => {
|
||||
const x = game.random(-10, 10);
|
||||
game.scene.spawn('sphere', {
|
||||
x: x, y: 20, z: 0,
|
||||
color: '#ffd700', material: 'neon',
|
||||
anchored: false, // будет падать (физика)
|
||||
lifetime: 8 // само исчезнет через 8 сек
|
||||
});
|
||||
});`}</Code>
|
||||
<p>
|
||||
<b>Игрок упал вниз</b> (за карту) — вернуть на спавн. Проверяем
|
||||
высоту каждый кадр:
|
||||
</p>
|
||||
<Code>{`game.onTick(() => {
|
||||
if (game.player.position.y < -10) {
|
||||
game.player.respawn();
|
||||
game.ui.showText('Упал! Назад на старт.', 2);
|
||||
}
|
||||
});`}</Code>
|
||||
<p><b>Финиш</b> — дошёл до зоны, победа:</p>
|
||||
<ScriptKind kind="object" on="финишную плиту" />
|
||||
<Code>{`game.self.onTouch(() => {
|
||||
game.ui.showText('🏁 ПОБЕДА!', 4);
|
||||
game.sound.play('win');
|
||||
game.player.setInputBlocked(true); // заморозить управление
|
||||
});`}</Code>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'recipes-npc-enemy',
|
||||
title: 'S11. Враг, который идёт за игроком',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
<b>NPC/враг</b>, который преследует игрока и наносит урон.
|
||||
</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`const enemy = game.scene.spawnNpc('zombie', {
|
||||
x: 10, y: 0, z: 10,
|
||||
hp: 100, name: 'Зомби', speed: 3
|
||||
});
|
||||
enemy.follow('player'); // идти за игроком
|
||||
enemy.say('Хочу тебя поймать!', 3);
|
||||
|
||||
enemy.onDeath(() => {
|
||||
game.ui.showText('Враг повержен!', 2);
|
||||
game.fx.damageFloater(enemy.position, 0, { isHeal: true });
|
||||
});`}</Code>
|
||||
<p>Урон игроку, когда враг близко:</p>
|
||||
<Code>{`game.every(0.5, () => {
|
||||
const d = game.distance(enemy.position, game.player.position);
|
||||
if (d < 2) game.player.damage(10);
|
||||
});`}</Code>
|
||||
<Note>
|
||||
Облачка урона над всеми мобами одной строкой:
|
||||
<code> game.fx.autoMobFloaters(true)</code>.
|
||||
</Note>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'recipes-save',
|
||||
title: 'S12. Сохранение прогресса и лидерборд',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
<b>Лидерборд</b> (таблица очков справа) — объяви стат и
|
||||
прибавляй:
|
||||
</p>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`game.leaderstats.define('Монеты', { initial: 0 });
|
||||
// прибавить текущему игроку:
|
||||
game.leaderstats.me.add('Монеты', 1);`}</Code>
|
||||
<p>
|
||||
<b>Сохранение между сессиями</b> (прогресс не теряется после
|
||||
выхода):
|
||||
</p>
|
||||
<Code>{`// записать
|
||||
game.save.merge('progress', {
|
||||
patch: { level: 3 }, // обычные поля
|
||||
increment: { coins: 10 }, // атомарно прибавить
|
||||
max: { bestScore: 5000 } // запишется только если больше старого
|
||||
});
|
||||
|
||||
// прочитать при старте
|
||||
game.save.get('progress', (data) => {
|
||||
if (data) {
|
||||
game.ui.showText('С возвращением! Уровень ' + data.level, 3);
|
||||
}
|
||||
});`}</Code>
|
||||
<Try>
|
||||
Собери всё вместе: монетки шлют broadcast → глобальный скрипт
|
||||
считает в leaderstats → раз в N монет сохраняет через
|
||||
game.save. Получится игра с прогрессом как в настоящем Roblox.
|
||||
</Try>
|
||||
</>
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ════════════════════════════════════════════════════
|
||||
// РАЗДЕЛ — СОВМЕСТНОЕ РЕДАКТИРОВАНИЕ (Team Create)
|
||||
// ════════════════════════════════════════════════════
|
||||
{
|
||||
id: 'collab',
|
||||
icon: 'users',
|
||||
title: 'Вместе с друзьями',
|
||||
summary: 'Совместное редактирование игры в реальном времени: приглашай друзей, стройте сцену вдвоём, видьте курсоры и правки друг друга.',
|
||||
sections: [
|
||||
{
|
||||
id: 'collab-what',
|
||||
title: 'V1. Что такое совместное редактирование',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
<b>Совместное редактирование (Team Create)</b> — это когда
|
||||
одну игру в студии редактируют <b>несколько человек
|
||||
одновременно</b>. Ты строишь дом, друг в это же время
|
||||
ставит деревья — и каждый видит правки другого
|
||||
<b> вживую</b>, без перезагрузки страницы.
|
||||
</p>
|
||||
<p>Что синхронизируется в реальном времени:</p>
|
||||
<ul>
|
||||
<li><b>Блоки</b> — поставил/удалил блок, друг сразу видит;</li>
|
||||
<li><b>Примитивы</b> — добавил, подвинул, повернул, изменил
|
||||
цвет или размер;</li>
|
||||
<li><b>Модели</b> — добавил из Тулбокса или удалил;</li>
|
||||
<li><b>Курсоры друзей</b> — где сейчас «мышка» каждого
|
||||
соавтора (цветная точка с ником);</li>
|
||||
<li><b>Кто онлайн</b> — список соавторов с цветными
|
||||
аватарками вверху сцены.</li>
|
||||
</ul>
|
||||
<Shot src="collab-scene.png" wide
|
||||
caption="Сцена при совместном редактировании: вверху — кто онлайн (аватарки «У» и «М», всего 2), на сцене — курсор соавтора «УтреннийРозмарин4633» (оранжевая точка с ником) и блок, который он только что поставил." />
|
||||
<Note>
|
||||
Это как Google Документы, только для 3D-игр. Удобно делать
|
||||
игру в команде, помогать ученику или показывать, как что
|
||||
устроено — прямо в его проекте.
|
||||
</Note>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'collab-invite',
|
||||
title: 'V2. Как пригласить друга',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
Открой свою игру в студии и перейди на вкладку
|
||||
<kbd className="kbd">Игра</kbd> в верхней панели. Там, в
|
||||
группе <b>«Вместе»</b>, есть кнопка
|
||||
<kbd className="kbd">Пригласить</kbd>.
|
||||
</p>
|
||||
<Shot src="collab-button.png" wide
|
||||
caption="Вкладка «Игра» → группа «Вместе» → кнопка «Пригласить». Когда соавторы подключатся, на ней появится счётчик «Вместе (2)»." />
|
||||
<Step n={1}>
|
||||
Нажми <kbd className="kbd">Пригласить</kbd> — ссылка-приглашение
|
||||
автоматически скопируется в буфер обмена (появится
|
||||
уведомление).
|
||||
</Step>
|
||||
<Step n={2}>
|
||||
Отправь эту ссылку другу (в чат, мессенджер — как угодно).
|
||||
</Step>
|
||||
<Step n={3}>
|
||||
Друг открывает ссылку — и попадает в <b>ту же сцену</b>.
|
||||
Теперь вы редактируете вместе. На кнопке появится счётчик:
|
||||
<b> «Вместе (2)»</b>.
|
||||
</Step>
|
||||
<Note>
|
||||
Приглашать может только <b>автор игры</b>. Ссылка действует
|
||||
24 часа. Друг должен быть зарегистрирован на Рублоксе и
|
||||
войти в свой аккаунт.
|
||||
</Note>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'collab-how',
|
||||
title: 'V3. Как это работает и правила',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
<b>Блокировка объекта.</b> Пока один соавтор выделил объект
|
||||
и двигает его — этот объект <b>заблокирован</b> для других
|
||||
(никто другой не сможет его двигать одновременно). Так
|
||||
правки не конфликтуют. Как только выделение снято — объект
|
||||
снова свободен.
|
||||
</p>
|
||||
<p>
|
||||
<b>Кто сохраняет.</b> Игру в базу сохраняет <b>автор</b>
|
||||
(владелец проекта). Приглашённые друзья видят пометку
|
||||
«Совместное редактирование» вместо кнопок Сохранить и
|
||||
Опубликовать — это правильно: они помогают строить, а
|
||||
управляет игрой автор.
|
||||
</p>
|
||||
<p>
|
||||
<b>Цвета.</b> У каждого соавтора свой цвет — им подсвечены
|
||||
его курсор и аватарка, чтобы было понятно, кто что делает.
|
||||
</p>
|
||||
<Note>
|
||||
Если друг ненадолго потерял связь (вылетел интернет) — у
|
||||
него есть несколько секунд, чтобы переподключиться и
|
||||
продолжить с того же места.
|
||||
</Note>
|
||||
<p>
|
||||
<b>Совет:</b> договоритесь заранее, кто какую часть карты
|
||||
делает (например, один — здания, другой — ландшафт и
|
||||
декор) — так работать вместе быстрее и без накладок.
|
||||
</p>
|
||||
</>
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// ════════════════════════════════════════════════════
|
||||
// РАЗДЕЛ — КОНТЕКСТ ДЛЯ НЕЙРОНКИ (AI)
|
||||
// ════════════════════════════════════════════════════
|
||||
{
|
||||
id: 'ai-context',
|
||||
icon: 'lightbulb',
|
||||
title: 'Контекст для нейронки',
|
||||
summary: 'Готовый текст со всем API скриптов Рублокса. Скопируй его целиком, вставь в ChatGPT/нейросеть — и она будет писать тебе рабочие скрипты под твою задачу.',
|
||||
sections: [
|
||||
{
|
||||
id: 'ai-howto',
|
||||
title: 'AI1. Как писать скрипты с нейросетью',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
Хочешь, чтобы скрипт написала <b>нейросеть</b> (ChatGPT,
|
||||
DeepSeek, Claude и т.п.)? Проблема в том, что нейросеть <b>не
|
||||
знает</b> устройство Рублокса — придумает несуществующие
|
||||
команды. Решение простое:
|
||||
</p>
|
||||
<Step n={1}>
|
||||
Открой статью <b>«AI2. Контекст — скопируй в нейросеть»</b> ниже.
|
||||
</Step>
|
||||
<Step n={2}>
|
||||
<b>Выдели и скопируй весь текст</b> из серого блока (он
|
||||
описывает все команды Рублокса).
|
||||
</Step>
|
||||
<Step n={3}>
|
||||
Вставь его в нейросеть <b>первым сообщением</b>. Затем добавь
|
||||
свою задачу, например: «Напиши скрипт: при касании синего куба
|
||||
игрок прыгает высоко и играет звук».
|
||||
</Step>
|
||||
<Step n={4}>
|
||||
Нейросеть выдаст готовый код. Скопируй его в скрипт в студии
|
||||
(глобальный или на объекте — она подскажет куда).
|
||||
</Step>
|
||||
<Note>
|
||||
Если нейросеть всё равно ошиблась в команде — скинь ей текст
|
||||
ошибки из «Консоли» студии, она исправит. И всегда проверяй
|
||||
результат запуском игры.
|
||||
</Note>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'ai-context-text',
|
||||
title: 'AI2. Контекст — скопируй в нейросеть',
|
||||
body: (
|
||||
<>
|
||||
<p>
|
||||
<b>Выдели весь текст ниже и скопируй</b> (Ctrl+A внутри блока
|
||||
или мышью), затем вставь в нейросеть перед своим вопросом:
|
||||
</p>
|
||||
<Code>{AI_CONTEXT}</Code>
|
||||
</>
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
|
||||
@ -21,6 +21,14 @@ const F = { fill: 'currentColor', stroke: 'none' };
|
||||
|
||||
const ICONS = {
|
||||
// ── разделы вики ──────────────────────────────────────────
|
||||
users: () => (
|
||||
<>
|
||||
<circle cx="9" cy="8" r="3.2" {...S} />
|
||||
<path d="M3.5 19c0-3 2.5-5 5.5-5s5.5 2 5.5 5" {...S} />
|
||||
<circle cx="16.5" cy="9" r="2.4" {...S} />
|
||||
<path d="M15 14.2c2.6.2 4.7 2 4.7 4.8" {...S} />
|
||||
</>
|
||||
),
|
||||
rocket: () => (
|
||||
<>
|
||||
<path d="M12 3c3.4 1.7 5.4 5 5.4 9l-2.2 2.3H8.8L6.6 12C6.6 8 8.6 4.7 12 3Z" {...S} />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user