From 0fcc5b85d04976d54ae696ea533baec25beffd44 Mon Sep 17 00:00:00 2001 From: min Date: Tue, 9 Jun 2026 22:35:40 +0300 Subject: [PATCH] =?UTF-8?q?docs(37)=20+=20feat(g38):=20=C2=AB=D0=9C=D1=83?= =?UTF-8?q?=D0=B7=D1=8B=D0=BA=D0=B0=D0=BB=D1=8C=D0=BD=D0=B0=D1=8F=20=D0=B8?= =?UTF-8?q?=D0=B3=D1=80=D0=B0=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit g37 docs: CodeBoth main+spike_1+cp+finish. g38 паритет: - SOUNDS [coin,jump,click,hit], SEQ [1,3,2,4,1] - task.delay 1 + i*0.8 → play sound + 'Нота N из 5' - После последней task.delay → canPress=true + 'Повтори!' - BindableEvent NotePressed(n) - 4 g38_tile_N: Heartbeat distance(3) → '[E] Сыграть ноту' E → tileSound + sparks + NotePressed:Fire(n) - Правильная → playerStep++, при #SEQ → win + confetti - Ошибка → playerStep=0 + lose + 'Слушай снова' --- src/community/docsGamesBuildersLua.js | 111 +++++++++++++++++++++++++- src/community/docsLessons.jsx | 12 +-- 2 files changed, 116 insertions(+), 7 deletions(-) diff --git a/src/community/docsGamesBuildersLua.js b/src/community/docsGamesBuildersLua.js index 2fcc493..916d94f 100644 --- a/src/community/docsGamesBuildersLua.js +++ b/src/community/docsGamesBuildersLua.js @@ -3402,7 +3402,116 @@ end)`; })(), // ═══════════════════════════════════════════════════════════════ - // ИГРЫ 38-50: явных Lua-версий пока нет. + // ИГРА 38 — «Музыкальная игра» + // ═══════════════════════════════════════════════════════════════ + 'music-game': (function() { + const TILES = [ + { snd: 'coin', color: '#e23b3b' }, + { snd: 'jump', color: '#facc15' }, + { snd: 'click', color: '#22c55e' }, + { snd: 'hit', color: '#3b82f6' }, + ]; + const overrides = { + g38_main: `-- === ИГРА «МУЗЫКАЛЬНАЯ ИГРА» — главный скрипт (Lua) === +${SNIPPET_BROADCAST} + +local SOUNDS = { "coin", "jump", "click", "hit" } +local SEQ = { 1, 3, 2, 4, 1 } +local playerStep = 0 +local won = false +local canPress = false + +__rbxl_show_text("Слушай мелодию, потом повтори!", 3) + +local winSound = Instance.new("Sound", workspace) +winSound.SoundId = "win"; winSound.Volume = 1 +local loseSound = Instance.new("Sound", workspace) +loseSound.SoundId = "lose"; loseSound.Volume = 0.7 + +-- Проигрываем мелодию: нота за нотой каждые 0.8 сек +for i, note in ipairs(SEQ) do + task.delay(1 + (i - 1) * 0.8, function() + local s = Instance.new("Sound", workspace) + s.SoundId = SOUNDS[note]; s.Volume = 0.8 + s:Play() + __rbxl_show_text("Нота " .. i .. " из " .. #SEQ, 0.7) + task.delay(0.6, function() s:Destroy() end) + end) +end + +-- После мелодии разрешаем игроку +task.delay(1 + #SEQ * 0.8 + 0.5, function() + canPress = true + __rbxl_show_text("Теперь повтори мелодию!", 3) +end) + +-- Плитки шлют NotePressed:Fire(n) +local pressEvent = getEvent("NotePressed") +pressEvent.Event:Connect(function(n) + if won or not canPress then return end + if n == SEQ[playerStep + 1] then + playerStep = playerStep + 1 + if playerStep >= #SEQ then + won = true + __rbxl_show_text("Победа! Мелодия повторена верно!", 5) + winSound:Play() + local px = __rbxl_player_x() + local py = __rbxl_player_y() + local pz = __rbxl_player_z() + __rbxl_spawn_particles("confetti", px, py + 3, pz, 3, 3) + end + else + playerStep = 0 + __rbxl_show_text("Ошибка! Слушай и пробуй снова.", 2) + loseSound:Play() + end +end)`, + }; + // 4 плитки — E проигрывает звук + sparks + NotePressed:Fire(n) + TILES.forEach((t, idx) => { + const n = idx + 1; + overrides['g38_tile_' + n] = `-- === Скрипт ноты-плитки ${n} (Lua) === +local UserInputService = game:GetService("UserInputService") +local ReplicatedStorage = game:GetService("ReplicatedStorage") +local RunService = game:GetService("RunService") +local part = script.Parent +local hintVisible = false + +local tileSound = Instance.new("Sound", part) +tileSound.SoundId = "${t.snd}"; tileSound.Volume = 0.8 + +RunService.Heartbeat:Connect(function() + local px = __rbxl_player_x() + local pz = __rbxl_player_z() + local dx = part.Position.X - px + local dz = part.Position.Z - pz + local dist = math.sqrt(dx*dx + dz*dz) + local near = dist <= 3 + if near ~= hintVisible then + hintVisible = near + if near then + __rbxl_hud_set("g38_tile_${n}_hint", "[E] Сыграть ноту", 50, 75, "#ffe44a", 20) + else + __rbxl_hud_set("g38_tile_${n}_hint", nil) + end + end +end) + +UserInputService.InputBegan:Connect(function(input, gp) + if gp then return end + if not hintVisible then return end + if input.KeyCode ~= Enum.KeyCode.E then return end + tileSound:Play() + __rbxl_spawn_particles("sparks", part.Position.X, part.Position.Y + 1, part.Position.Z, 0.4, 1) + local ev = ReplicatedStorage:FindFirstChild("NotePressed") + if ev then ev:Fire(${n}) end +end)`; + }); + return overrides; + })(), + + // ═══════════════════════════════════════════════════════════════ + // ИГРЫ 39-50: явных Lua-версий пока нет. // buildGameProject в docsGamesBuilders.js использует generateFallbackLua // (главный скрипт → показ подсказки + слушает FinishReached → // победа+конфетти; скрипт на финиш-примитиве → шлёт FinishReached; diff --git a/src/community/docsLessons.jsx b/src/community/docsLessons.jsx index e383220..e69d927 100644 --- a/src/community/docsLessons.jsx +++ b/src/community/docsLessons.jsx @@ -5243,7 +5243,7 @@ game.self.onInteract(() => {

Шаг 2. Главный скрипт

- {`// === ИГРА «ПОЛОСА ПРЕПЯТСТВИЙ» — главный скрипт === + {`// === ИГРА «ПОЛОСА ПРЕПЯТСТВИЙ» — главный скрипт === let won = false; @@ -5285,7 +5285,7 @@ game.onMessage('finish', () => { const p = game.player.position; game.scene.spawnParticles('confetti', { x: p.x, y: p.y + 3, z: p.z }, { duration: 3, count: 3 }); -});`} +});`}

Разберём: