feat(lua-games): полный паритет для игры 9 «Светофор»

JS:
- showText 'Зелёный — беги! Красный — замри!'
- light=findOne('Светофор'), green/red/green циклически (3с/2.5с)
- setColor light на красный/зелёный + showText
- onTick: если красный и moved/dt>0.8 — respawn + lose sound
- onMessage 'win' → showText + win + confetti
- g9_finish: onTouch → broadcast 'win'

Lua (паритет):
- __rbxl_show_text для всех подсказок
- Heartbeat-таймер фазы (task.spawn не умеет yield) — переключает
  phase 'green'/'red' каждые GREEN_TIME/RED_TIME
- light=workspace:FindFirstChild('Светофор'), .Color = Color3.fromRGB
- Heartbeat: prevX/prevZ, при phase=red и moved/dt>0.8 → LoadCharacter
  + lose Sound + 'Двинулся на красный!'
- BindableEvent WinReached
- g9_finish: Touched → ev:Fire с fired-флагом
- При победе: win Sound + confetti
This commit is contained in:
min 2026-06-09 18:35:47 +03:00
parent 41e0f7b6a4
commit bec3c478e7

View File

@ -632,41 +632,89 @@ end)`,
// ═══════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════
'traffic-light': { 'traffic-light': {
g9_main: `-- === ИГРА «СВЕТОФОР» — главный скрипт (Lua) === g9_main: `-- === ИГРА «СВЕТОФОР» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local Players = game:GetService("Players") local Players = game:GetService("Players")
local RunService = game:GetService("RunService") local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
local won = false
local phase = "green" -- "green" (беги) или "red" (замри)
local phaseTimer = 0
local GREEN_TIME = 3
local RED_TIME = 2.5
local isGreen = true __rbxl_show_text("Зелёный — беги! Красный — замри!", 3)
print("ЗЕЛЁНЫЙ — беги!")
-- Каждые 3-5 сек переключаем свет local loseSound = Instance.new("Sound", workspace)
task.spawn(function() loseSound.SoundId = "lose"; loseSound.Volume = 1
while true do local winSound = Instance.new("Sound", workspace)
task.wait(math.random(3, 5)) winSound.SoundId = "win"; winSound.Volume = 1
isGreen = not isGreen
if isGreen then -- Находим светофор и сразу красим в зелёный
print("ЗЕЛЁНЫЙ — беги!") local light = workspace:FindFirstChild("Светофор")
else if light then light.Color = Color3.fromRGB(34, 221, 85) end
print("КРАСНЫЙ — стой!") __rbxl_show_text("ЗЕЛЁНЫЙ — беги!", 1.2)
-- Каждый кадр считаем таймер фазы и проверяем движение
local prevX, prevZ = nil, nil
RunService.Heartbeat:Connect(function(dt)
if won then return end
dt = dt or 0.016
-- Переключение фаз
phaseTimer = phaseTimer + dt
if phase == "green" and phaseTimer >= GREEN_TIME then
phaseTimer = 0
phase = "red"
if light then light.Color = Color3.fromRGB(226, 59, 59) end
__rbxl_show_text("КРАСНЫЙ — замри!", 1.2)
elseif phase == "red" and phaseTimer >= RED_TIME then
phaseTimer = 0
phase = "green"
if light then light.Color = Color3.fromRGB(34, 221, 85) end
__rbxl_show_text("ЗЕЛЁНЫЙ — беги!", 1.2)
end
-- Если красный и игрок шевелится респаун
local px = __rbxl_player_x()
local pz = __rbxl_player_z()
if prevX and phase == "red" then
local dx = px - prevX
local dz = pz - prevZ
local moved = math.sqrt(dx*dx + dz*dz)
if moved / dt > 0.8 then
player:LoadCharacter()
loseSound:Play()
__rbxl_show_text("Двинулся на красный! На старт.", 2)
end end
end end
prevX, prevZ = px, pz
end) end)
-- Следим за движением игрока во время красного -- Финиш-зона шлёт BindableEvent
local lastPos = {} local winEvent = getEvent("WinReached")
RunService.Heartbeat:Connect(function() winEvent.Event:Connect(function()
if isGreen then return end if won then return end
for _, player in ipairs(Players:GetPlayers()) do won = true
local char = player.Character winSound:Play()
local hrp = char and char:FindFirstChild("HumanoidRootPart") __rbxl_show_text("Победа! Ты дошёл до финиша!", 5)
if hrp then local px = __rbxl_player_x()
local prev = lastPos[player] local py = __rbxl_player_y()
if prev and (hrp.Position - prev).Magnitude > 0.5 then local pz = __rbxl_player_z()
print(player.Name .. " двигался на красный! Респаун") __rbxl_spawn_particles("confetti", px, py + 3, pz, 3, 3)
player:LoadCharacter() end)`,
end g9_finish: `-- === Скрипт финиша (Lua) ===
lastPos[player] = hrp.Position local ReplicatedStorage = game:GetService("ReplicatedStorage")
end local part = script.Parent
end local fired = false
part.Touched:Connect(function(hit)
if fired then return end
local h = hit.Parent and hit.Parent:FindFirstChild("Humanoid")
if not h then return end
fired = true
local ev = ReplicatedStorage:FindFirstChild("WinReached")
if ev then ev:Fire() end
end)`, end)`,
}, },