docs(34) + feat(g35): «Прятки от NPC»

g34 docs: CodeBoth main+plant_1.

g35 паритет:
- SURVIVE=40c, NPC 'Искатель' speed=3 follow('player')
- __rbxl_timer_set каждый кадр
- dist<1.7 → LoadCharacter + 'Найден!' + lose (с throttle 2с)
- time>=40 → npc.stop + 'Победа!' + confetti + win
This commit is contained in:
min 2026-06-09 22:25:20 +03:00
parent 3e572e1136
commit 92a9ef220d
2 changed files with 71 additions and 5 deletions

View File

@ -3125,7 +3125,73 @@ end)`;
})(),
// ═══════════════════════════════════════════════════════════════
// ИГРЫ 35-50: явных Lua-версий пока нет.
// ИГРА 35 — «Прятки от NPC»
// ═══════════════════════════════════════════════════════════════
'hide-from-npc': {
g35_main: `-- === ИГРА «ПРЯТКИ ОТ NPC» — главный скрипт (Lua) ===
${SNIPPET_BROADCAST}
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local player = Players.LocalPlayer
local SURVIVE = 40
local time = 0
local won = false
local lastCaughtTime = 0
__rbxl_timer_set(0)
__rbxl_show_text("Прячься за стенами 40 секунд!", 4)
local loseSound = Instance.new("Sound", workspace)
loseSound.SoundId = "lose"; loseSound.Volume = 0.7
local winSound = Instance.new("Sound", workspace)
winSound.SoundId = "win"; winSound.Volume = 1
-- NPC-искатель ходит за игроком
local seekerRef = __rbxl_spawn_npc("character-b", 0, 1, 10, "Искатель", 100, 3)
task.delay(0.3, function()
__rbxl_npc_follow(seekerRef, "player")
end)
RunService.Heartbeat:Connect(function(dt)
if won then return end
time = time + dt
__rbxl_timer_set(time)
-- Поймал респаун
local px = __rbxl_player_x()
local pz = __rbxl_player_z()
local ex = __rbxl_npc_x(seekerRef)
local ez = __rbxl_npc_z(seekerRef)
if not (ex == 0 and ez == 0) then
local dx = px - ex
local dz = pz - ez
local dist = math.sqrt(dx*dx + dz*dz)
if dist < 1.7 then
local now = tick()
if now - lastCaughtTime > 2 then
lastCaughtTime = now
player:LoadCharacter()
__rbxl_show_text("Найден! Прячься снова!", 1.5)
loseSound:Play()
end
end
end
-- Продержался 40 секунд победа
if time >= SURVIVE then
won = true
__rbxl_npc_stop(seekerRef)
__rbxl_show_text("Победа! Ты прятался 40 секунд!", 5)
winSound:Play()
__rbxl_spawn_particles("confetti", px, 1, pz, 3, 3)
end
end)`,
},
// ═══════════════════════════════════════════════════════════════
// ИГРЫ 36-50: явных Lua-версий пока нет.
// buildGameProject в docsGamesBuilders.js использует generateFallbackLua
// (главный скрипт → показ подсказки + слушает FinishReached →
// победа+конфетти; скрипт на финиш-примитиве → шлёт FinishReached;

View File

@ -4811,7 +4811,7 @@ game.onTick(() => {
<h3 className="lessonH">Шаг 2. Главный скрипт</h3>
<ScriptKind kind="global" />
<Code>{`// === ИГРА «СБОР УРОЖАЯ» — главный скрипт ===
<CodeBoth game="harvest" script="g34_main">{`// === ИГРА «СБОР УРОЖАЯ» — главный скрипт ===
let harvested = 0;
const GOAL = 6;
@ -4831,7 +4831,7 @@ game.onMessage('harvested', () => {
game.scene.spawnParticles('confetti',
{ x: p.x, y: p.y + 3, z: p.z }, { duration: 3, count: 3 });
}
});`}</Code>
});`}</CodeBoth>
<p>
Главный скрипт считает собранные растения и проверяет
победу. Каждое растение работает в своей «песочнице»,
@ -4845,7 +4845,7 @@ game.onMessage('harvested', () => {
<h3 className="lessonH">Шаг 3. Скрипт растения</h3>
<p>Этот скрипт вешается на <b>каждое</b> растение.</p>
<ScriptKind kind="object" on="каждое растение" />
<Code>{`// === Скрипт растения ===
<CodeBoth game="harvest" script="g34_plant_1">{`// === Скрипт растения ===
let ripe = false; // растение выросло (спелое)?
let picked = false;
@ -4870,7 +4870,7 @@ game.self.onInteract(() => {
picked = true;
game.self.delete();
game.broadcast('harvested');
}, { text: 'Собрать', distance: 3 });`}</Code>
}, { text: 'Собрать', distance: 3 });`}</CodeBoth>
<p>Разберём:</p>
<ul>
<li><code>game.tween(ref, {'{ sx, sy, sz, y }'}, опции)</code>