feat(studio): +5 готовых механик из Вики (батут/ускорение/портал/исчезающая платформа/дверь)

Партия 1 из TOOLBOX_KITS_FROM_WIKI.md:
- Батут (пружина) — onTouch → setVy(20) подброс вверх.
- Лента ускорения — onTouch → x2 скорости на 3с.
- Портал-телепорт — пара порталов, onTouch → teleport ко второму.
- Исчезающая платформа — onTouch → через 1с пропадает, через 3с возвращается.
- Дверь по кнопке E — onInteract → дверь уезжает вниз/возвращается.

game.self расширен: setVisible(vis) / setCollide(can) (нужны для исчезающей
платформы). Все скрипты прошли синтаксис-проверку (new Function).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
min 2026-06-05 07:41:25 +03:00
parent 6b857636c3
commit cfc79f325f
2 changed files with 95 additions and 0 deletions

View File

@ -191,6 +191,89 @@ game.self.onInteract(() => {
game.after(3, () => game.ui.set('loot', '')); game.after(3, () => game.ui.set('loot', ''));
}, { text: 'Открыть сундук', key: 'f', distance: 4 });` }], }, { text: 'Открыть сундук', key: 'f', distance: 4 });` }],
}, },
// ===== Партия 1 из Вики (киты 13-17) =====
{
id: 'trampoline',
name: 'Батут (пружина)',
desc: 'Яркая платформа-батут — наступи на неё, и игрока подбросит высоко вверх. (Вики: «Прыжок-пружина»)',
icon: 'arrow-up', category: 'movement',
prims: [{ type: 'cylinder', x: 0, y: 0.3, z: 0, sx: 3, sy: 0.6, sz: 3, color: '#ff3c8e', material: 'neon', name: 'Батут' }],
scripts: [{ attachTo: 'on-target', code:
`// Батут: касание → подброс игрока вверх.
game.self.onTouch(() => {
game.player.setVy(20); // вертикальный импульс (как трамплин)
});` }],
},
{
id: 'speed-pad',
name: 'Лента ускорения',
desc: 'Жёлтая плита-ускоритель — наступи, и игрок бежит быстрее несколько секунд. (Вики: «бусты скорости»)',
icon: 'zap', category: 'movement',
prims: [{ type: 'cube', x: 0, y: 0.1, z: 0, sx: 3, sy: 0.2, sz: 5, color: '#ffd23a', material: 'neon', name: 'Лента ускорения', canCollide: false }],
scripts: [{ attachTo: 'on-target', code:
`// Лента ускорения: касание → x2 скорости на 3 секунды.
let boosting = false;
game.self.onTouch(() => {
if (boosting) return;
boosting = true;
game.player.setSpeed(2.0);
game.ui.set('boost', '⚡ Ускорение!', { x: 50, y: 80, anchor: 'bottom', color: '#ffd23a', size: 18 });
game.after(3, () => { game.player.setSpeed(1.0); game.ui.set('boost', ''); boosting = false; });
});` }],
},
{
id: 'teleport-portal',
name: 'Портал-телепорт',
desc: 'Два синих портала. Вошёл в портал — мгновенно переносишься ко второму. Поставь второй портал где нужно. (Вики: «секретный путь»)',
icon: 'sparkles', category: 'movement',
prims: [
{ type: 'cylinder', x: 0, y: 1.5, z: 0, sx: 0.4, sy: 3, sz: 3, color: '#4d6bff', material: 'neon', name: 'Портал A' },
{ type: 'cylinder', x: 8, y: 1.5, z: 0, sx: 0.4, sy: 3, sz: 3, color: '#4dffd6', material: 'neon', name: 'Портал B', canCollide: false },
],
scripts: [{ attachTo: 'on-target', code:
`// Портал A: касание → телепорт к порталу B (стоит правее на +8 по X).
// Передвинь «Портал B» куда нужно и поправь координаты ниже.
let cd = false;
game.self.onTouch(() => {
if (cd) return; cd = true;
const p = game.self.position;
game.player.teleport(p.x + 8, p.y + 1, p.z); // к месту портала B
game.after(1, () => { cd = false; });
});` }],
},
{
id: 'disappearing-platform',
name: 'Исчезающая платформа',
desc: 'Платформа пропадает под ногами через секунду после касания и возвращается через 3с. (Вики: «Не упади», «Падающий мост»)',
icon: 'square', category: 'world',
prims: [{ type: 'cube', x: 0, y: 0.25, z: 0, sx: 4, sy: 0.5, sz: 4, color: '#e06a3c', material: 'matte', name: 'Исчезающая платформа' }],
scripts: [{ attachTo: 'on-target', code:
`// Исчезающая платформа: наступил → через 1с пропадает, через 3с возвращается.
let busy = false;
game.self.onTouch(() => {
if (busy) return; busy = true;
game.after(1, () => { game.self.setVisible(false); game.self.setCollide(false); });
game.after(3, () => { game.self.setVisible(true); game.self.setCollide(true); busy = false; });
});` }],
},
{
id: 'door-button',
name: 'Дверь по кнопке E',
desc: 'Дверь + кнопка: подойди, нажми E — дверь уезжает в сторону и открывает проход. (Вики: «Кнопка-открывашка»)',
icon: 'door', category: 'world',
prims: [{ type: 'cube', x: 0, y: 2, z: 0, sx: 1, sy: 4, sz: 3, color: '#8a5a3c', material: 'matte', name: 'Дверь' }],
scripts: [{ attachTo: 'on-target', code:
`// Дверь по E: открыта/закрыта — уезжает вниз и возвращается.
let open = false;
const p0 = game.self.position; // закрытое положение
game.self.onInteract(() => {
open = !open;
if (open) game.self.move(p0.x, p0.y - 4.2, p0.z); // уехала вниз (открыта)
else game.self.move(p0.x, p0.y, p0.z); // вернулась (закрыта)
}, { text: open ? 'Закрыть' : 'Открыть', key: 'e', distance: 5 });` }],
},
]; ];
/** Найти кит по id. */ /** Найти кит по id. */

View File

@ -754,6 +754,18 @@ function _buildSelfApi() {
_send('scene.rotate', { kind: k, id, ref: (k && id != null) ? (k + ':' + id) : undefined, rotationY: r }); _send('scene.rotate', { kind: k, id, ref: (k && id != null) ? (k + ':' + id) : undefined, rotationY: r });
}, },
rotateY(ry) { this.rotate(ry); }, rotateY(ry) { this.rotate(ry); },
/** Показать/скрыть объект-носитель. */
setVisible(vis) {
const k = _target.kind;
const id = _target.id ?? _target.ref;
_send('scene.setVisible', { kind: k, id, ref: (k && id != null) ? (k + ':' + id) : undefined, visible: !!vis });
},
/** Включить/выключить столкновения объекта-носителя (проходимость). */
setCollide(can) {
const k = _target.kind;
const id = _target.id ?? _target.ref;
_send('scene.setCollide', { kind: k, id, ref: (k && id != null) ? (k + ':' + id) : undefined, canCollide: !!can });
},
delete() { delete() {
_send('self.delete', { target: _target }); _send('self.delete', { target: _target });
}, },