feat: 50 игр на Lua + импорт Roblox для всех + поддержка Lua в плеере #39
@ -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;
|
||||
|
||||
@ -4509,7 +4509,7 @@ game.every(2, () => {
|
||||
|
||||
<h3 className="lessonH">Шаг 2. Главный скрипт</h3>
|
||||
<ScriptKind kind="global" />
|
||||
<Code>{`// === ИГРА «ГОНКА С КРУГАМИ» — главный скрипт ===
|
||||
<CodeBoth game="lap-race" script="g32_main">{`// === ИГРА «ГОНКА С КРУГАМИ» — главный скрипт ===
|
||||
|
||||
const LAPS = 2; // сколько кругов проехать
|
||||
const CP_COUNT = 4; // чекпоинтов на круге
|
||||
@ -4552,7 +4552,7 @@ game.onMessage('checkpoint', (d) => {
|
||||
game.ui.showText('Круг ' + lap + ' из ' + LAPS + '!', 2);
|
||||
}
|
||||
}
|
||||
});`}</Code>
|
||||
});`}</CodeBoth>
|
||||
<p>Главное здесь — порядок чекпоинтов:</p>
|
||||
<ul>
|
||||
<li><code>game.onMessage('checkpoint', (d) => {'{...}'})</code> —
|
||||
@ -4584,10 +4584,10 @@ game.onMessage('checkpoint', (d) => {
|
||||
номер. Вот скрипт первого чекпоинта:
|
||||
</p>
|
||||
<ScriptKind kind="object" on="Чекпоинт_1" />
|
||||
<Code>{`// === Скрипт чекпоинта 1 ===
|
||||
<CodeBoth game="lap-race" script="g32_cp_1">{`// === Скрипт чекпоинта 1 ===
|
||||
game.self.onTouch(() => {
|
||||
game.broadcast('checkpoint', { num: 1 });
|
||||
});`}</Code>
|
||||
});`}</CodeBoth>
|
||||
<p>
|
||||
Чекпоинт шлёт сообщение
|
||||
<code> game.broadcast('checkpoint', {'{ num: 1 }'})</code>:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user