docs(37) + feat(g38): «Музыкальная игра»
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 + 'Слушай снова'
This commit is contained in:
parent
f0025f0dad
commit
0fcc5b85d0
@ -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
|
// buildGameProject в docsGamesBuilders.js использует generateFallbackLua
|
||||||
// (главный скрипт → показ подсказки + слушает FinishReached →
|
// (главный скрипт → показ подсказки + слушает FinishReached →
|
||||||
// победа+конфетти; скрипт на финиш-примитиве → шлёт FinishReached;
|
// победа+конфетти; скрипт на финиш-примитиве → шлёт FinishReached;
|
||||||
|
|||||||
@ -5243,7 +5243,7 @@ game.self.onInteract(() => {
|
|||||||
|
|
||||||
<h3 className="lessonH">Шаг 2. Главный скрипт</h3>
|
<h3 className="lessonH">Шаг 2. Главный скрипт</h3>
|
||||||
<ScriptKind kind="global" />
|
<ScriptKind kind="global" />
|
||||||
<Code>{`// === ИГРА «ПОЛОСА ПРЕПЯТСТВИЙ» — главный скрипт ===
|
<CodeBoth game="obstacle-course" script="g37_main">{`// === ИГРА «ПОЛОСА ПРЕПЯТСТВИЙ» — главный скрипт ===
|
||||||
|
|
||||||
let won = false;
|
let won = false;
|
||||||
|
|
||||||
@ -5285,7 +5285,7 @@ game.onMessage('finish', () => {
|
|||||||
const p = game.player.position;
|
const p = game.player.position;
|
||||||
game.scene.spawnParticles('confetti',
|
game.scene.spawnParticles('confetti',
|
||||||
{ x: p.x, y: p.y + 3, z: p.z }, { duration: 3, count: 3 });
|
{ x: p.x, y: p.y + 3, z: p.z }, { duration: 3, count: 3 });
|
||||||
});`}</Code>
|
});`}</CodeBoth>
|
||||||
<p>Разберём:</p>
|
<p>Разберём:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>game.after(0.2, ...)</code> — ждём чуть-чуть,
|
<li><code>game.after(0.2, ...)</code> — ждём чуть-чуть,
|
||||||
@ -5306,16 +5306,16 @@ game.onMessage('finish', () => {
|
|||||||
|
|
||||||
<h3 className="lessonH">Шаг 3. Скрипты шипа, чекпоинта и финиша</h3>
|
<h3 className="lessonH">Шаг 3. Скрипты шипа, чекпоинта и финиша</h3>
|
||||||
<ScriptKind kind="object" on="каждый красный шип" />
|
<ScriptKind kind="object" on="каждый красный шип" />
|
||||||
<Code>{`// === Скрипт шипа ===
|
<CodeBoth game="obstacle-course" script="g37_spike_1">{`// === Скрипт шипа ===
|
||||||
game.self.onTouch(() => {
|
game.self.onTouch(() => {
|
||||||
game.player.damage(25);
|
game.player.damage(25);
|
||||||
game.sound.play('hit');
|
game.sound.play('hit');
|
||||||
});`}</Code>
|
});`}</CodeBoth>
|
||||||
<ScriptKind kind="object" on="жёлтый чекпоинт" />
|
<ScriptKind kind="object" on="жёлтый чекпоинт" />
|
||||||
<Code>{`// === Скрипт чекпоинта ===
|
<CodeBoth game="obstacle-course" script="g37_cp">{`// === Скрипт чекпоинта ===
|
||||||
game.self.onTouch(() => {
|
game.self.onTouch(() => {
|
||||||
game.broadcast('checkpoint');
|
game.broadcast('checkpoint');
|
||||||
});`}</Code>
|
});`}</CodeBoth>
|
||||||
<ScriptKind kind="object" on="зелёный финиш" />
|
<ScriptKind kind="object" on="зелёный финиш" />
|
||||||
<Code>{`// === Скрипт финиша ===
|
<Code>{`// === Скрипт финиша ===
|
||||||
game.self.onTouch(() => {
|
game.self.onTouch(() => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user