From f3b0cabdbd9cad9abf1d134e70b18afb75f2b17f Mon Sep 17 00:00:00 2001
From: min
Date: Tue, 9 Jun 2026 22:18:18 +0300
Subject: [PATCH] =?UTF-8?q?docs(32)=20+=20feat(g33):=20=C2=AB=D0=9F=D0=BB?=
=?UTF-8?q?=D0=B0=D1=82=D1=84=D0=BE=D1=80=D0=BC=D0=B5=D1=80=20=D1=81=20?=
=?UTF-8?q?=D0=B1=D0=BE=D1=81=D1=81=D0=BE=D0=BC=C2=BB?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
g32 docs: CodeBoth main+cp_1.
g33 паритет:
- Heartbeat: py<-3 → LoadCharacter + lose
- При pz>24 + py>5 (на арене) — spawnNpc 'БОСС' hp=120 speed=2
- task.delay npc.follow('player') + setLabel 'БОСС HP: 120'
- __rbxl_npc_on_click(bossRef, onBossHit):
dist<5 → bossHp -= 20 + npc.damage + setLabel + sparks + hit
- __rbxl_npc_on_death → clear_label + 'Победа!' + confetti + win
---
src/community/docsGamesBuildersLua.js | 86 ++++++++++++++++++++++++++-
src/community/docsLessons.jsx | 8 +--
2 files changed, 89 insertions(+), 5 deletions(-)
diff --git a/src/community/docsGamesBuildersLua.js b/src/community/docsGamesBuildersLua.js
index e5b666c..e478991 100644
--- a/src/community/docsGamesBuildersLua.js
+++ b/src/community/docsGamesBuildersLua.js
@@ -2940,7 +2940,91 @@ end)`;
})(),
// ═══════════════════════════════════════════════════════════════
- // ИГРЫ 33-50: явных Lua-версий пока нет.
+ // ИГРА 33 — «Платформер с боссом»
+ // ═══════════════════════════════════════════════════════════════
+ 'boss-platformer': {
+ g33_main: `-- === ИГРА «ПЛАТФОРМЕР С БОССОМ» — главный скрипт (Lua) ===
+${SNIPPET_BROADCAST}
+
+local Players = game:GetService("Players")
+local RunService = game:GetService("RunService")
+local player = Players.LocalPlayer
+
+local won = false
+local bossSpawned = false
+local bossHp = 120
+local MAX_HP = 120
+local bossRef = nil
+
+__rbxl_show_text("Пройди паркур до арены босса!", 3)
+
+local hitSound = Instance.new("Sound", workspace)
+hitSound.SoundId = "hit"; hitSound.Volume = 0.6
+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
+
+-- Клик по боссу (через __rbxl_npc_on_click при спавне)
+local function onBossHit()
+ if won then return end
+ local pp_x = __rbxl_player_x()
+ local pp_z = __rbxl_player_z()
+ local bp_x = __rbxl_npc_x(bossRef)
+ local bp_z = __rbxl_npc_z(bossRef)
+ local dx = pp_x - bp_x
+ local dz = pp_z - bp_z
+ local dist = math.sqrt(dx*dx + dz*dz)
+ if dist < 5 then
+ bossHp = bossHp - 20
+ if bossHp < 0 then bossHp = 0 end
+ __rbxl_npc_damage(bossRef, 20)
+ __rbxl_set_label(bossRef, "БОСС HP: " .. bossHp, "#ff3333", 2.5)
+ __rbxl_spawn_particles("sparks", bp_x, 2, bp_z, 0.4, 1)
+ hitSound:Play()
+ end
+end
+
+-- Heartbeat: респаун при падении + спавн босса при подходе к арене
+RunService.Heartbeat:Connect(function()
+ if won then return end
+ local py = __rbxl_player_y()
+ if py < -3 then
+ player:LoadCharacter()
+ loseSound:Play()
+ return
+ end
+ if not bossSpawned then
+ local pz = __rbxl_player_z()
+ if pz > 24 and py > 5 then
+ bossSpawned = true
+ bossRef = __rbxl_spawn_npc("character-b", 0, 7, 32, "БОСС", MAX_HP, 2)
+ task.delay(0.3, function()
+ __rbxl_npc_follow(bossRef, "player")
+ __rbxl_set_label(bossRef, "БОСС HP: " .. MAX_HP, "#ff3333", 2.5)
+ end)
+ __rbxl_show_text("БОСС! Кликай по нему!", 3)
+ -- Подписка на клик по боссу
+ __rbxl_npc_on_click(bossRef, onBossHit)
+ -- Подписка на смерть
+ __rbxl_npc_on_death(bossRef, function()
+ if won then return end
+ won = true
+ __rbxl_clear_label(bossRef)
+ __rbxl_show_text("Победа! Босс повержен!", 5)
+ winSound:Play()
+ local px = __rbxl_player_x()
+ local py2 = __rbxl_player_y()
+ local pz2 = __rbxl_player_z()
+ __rbxl_spawn_particles("confetti", px, py2 + 3, pz2, 3, 3)
+ end)
+ end
+ end
+end)`,
+ },
+
+ // ═══════════════════════════════════════════════════════════════
+ // ИГРЫ 34-50: явных Lua-версий пока нет.
// buildGameProject в docsGamesBuilders.js использует generateFallbackLua
// (главный скрипт → показ подсказки + слушает FinishReached →
// победа+конфетти; скрипт на финиш-примитиве → шлёт FinishReached;
diff --git a/src/community/docsLessons.jsx b/src/community/docsLessons.jsx
index 6437176..0172f8b 100644
--- a/src/community/docsLessons.jsx
+++ b/src/community/docsLessons.jsx
@@ -4509,7 +4509,7 @@ game.every(2, () => {
Шаг 2. Главный скрипт
- {`// === ИГРА «ГОНКА С КРУГАМИ» — главный скрипт ===
+ {`// === ИГРА «ГОНКА С КРУГАМИ» — главный скрипт ===
const LAPS = 2; // сколько кругов проехать
const CP_COUNT = 4; // чекпоинтов на круге
@@ -4552,7 +4552,7 @@ game.onMessage('checkpoint', (d) => {
game.ui.showText('Круг ' + lap + ' из ' + LAPS + '!', 2);
}
}
-});`}
+});`}
Главное здесь — порядок чекпоинтов:
game.onMessage('checkpoint', (d) => {'{...}'}) —
@@ -4584,10 +4584,10 @@ game.onMessage('checkpoint', (d) => {
номер. Вот скрипт первого чекпоинта:
- {`// === Скрипт чекпоинта 1 ===
+ {`// === Скрипт чекпоинта 1 ===
game.self.onTouch(() => {
game.broadcast('checkpoint', { num: 1 });
-});`}
+});`}
Чекпоинт шлёт сообщение
game.broadcast('checkpoint', {'{ num: 1 }'}):