feat: 50 игр на Lua + импорт Roblox для всех + поддержка Lua в плеере #39
@ -4343,13 +4343,114 @@ end)`,
|
|||||||
},
|
},
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════
|
||||||
// ИГРЫ 46-50: явных Lua-версий пока нет.
|
// ИГРА 47 — «Квест-побег»
|
||||||
// buildGameProject в docsGamesBuilders.js использует generateFallbackLua
|
// ═══════════════════════════════════════════════════════════════
|
||||||
// (главный скрипт → показ подсказки + слушает FinishReached →
|
'escape-quest': (function() {
|
||||||
// победа+конфетти; скрипт на финиш-примитиве → шлёт FinishReached;
|
const BTN_COUNT = 3;
|
||||||
// остальные target-скрипты → красят примитив на касание).
|
const overrides = {
|
||||||
// Это даёт «хоть что-то рабочее» в любой игре до того как напишем
|
g47_main: `-- === ИГРА «КВЕСТ-ПОБЕГ» — главный скрипт (Lua) ===
|
||||||
// полноценный Lua-скрипт. Когда дописываем игру — добавляем сюда явный override.
|
${SNIPPET_BROADCAST}
|
||||||
|
|
||||||
|
local TweenService = game:GetService("TweenService")
|
||||||
|
local TOTAL = ${BTN_COUNT}
|
||||||
|
local pressed = 0
|
||||||
|
local escaped = false
|
||||||
|
|
||||||
|
__rbxl_show_text("Найди и нажми 3 кнопки, чтобы выйти!", 4)
|
||||||
|
|
||||||
|
local clickSound = Instance.new("Sound", workspace)
|
||||||
|
clickSound.SoundId = "click"; clickSound.Volume = 0.6
|
||||||
|
local winSound = Instance.new("Sound", workspace)
|
||||||
|
winSound.SoundId = "win"; winSound.Volume = 1
|
||||||
|
|
||||||
|
local btnEvent = getEvent("ButtonPressed")
|
||||||
|
btnEvent.Event:Connect(function()
|
||||||
|
pressed = pressed + 1
|
||||||
|
clickSound:Play()
|
||||||
|
__rbxl_show_text("Кнопка " .. pressed .. " из " .. TOTAL, 1.5)
|
||||||
|
if pressed >= TOTAL then
|
||||||
|
local door = workspace:FindFirstChild("Дверь")
|
||||||
|
if door then
|
||||||
|
local dp = door.Position
|
||||||
|
local goal = { Position = Vector3.new(dp.X, dp.Y + 6, dp.Z) }
|
||||||
|
TweenService:Create(door, TweenInfo.new(1.2), goal):Play()
|
||||||
|
door.CanCollide = false
|
||||||
|
end
|
||||||
|
__rbxl_show_text("Все кнопки нажаты! Дверь открыта!", 3)
|
||||||
|
winSound:Play()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local escEvent = getEvent("Escape")
|
||||||
|
escEvent.Event:Connect(function()
|
||||||
|
if escaped then return end
|
||||||
|
escaped = 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)`,
|
||||||
|
g47_finish: `-- === Скрипт финиша (Lua) ===
|
||||||
|
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||||
|
local part = script.Parent
|
||||||
|
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("Escape")
|
||||||
|
if ev then ev:Fire() end
|
||||||
|
end)`,
|
||||||
|
};
|
||||||
|
for (let i = 1; i <= BTN_COUNT; i++) {
|
||||||
|
overrides['g47_btn_' + i] = `-- === Скрипт кнопки ${i} (Lua) ===
|
||||||
|
local UserInputService = game:GetService("UserInputService")
|
||||||
|
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||||
|
local RunService = game:GetService("RunService")
|
||||||
|
local part = script.Parent
|
||||||
|
local used = false
|
||||||
|
local hintVisible = false
|
||||||
|
|
||||||
|
RunService.Heartbeat:Connect(function()
|
||||||
|
if used then return end
|
||||||
|
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("g47_btn_${i}_hint", "[E] Нажать кнопку", 50, 75, "#ffe44a", 20)
|
||||||
|
else
|
||||||
|
__rbxl_hud_set("g47_btn_${i}_hint", nil)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
UserInputService.InputBegan:Connect(function(input, gp)
|
||||||
|
if gp then return end
|
||||||
|
if not hintVisible then return end
|
||||||
|
if used then return end
|
||||||
|
if input.KeyCode ~= Enum.KeyCode.E then return end
|
||||||
|
used = true
|
||||||
|
__rbxl_hud_set("g47_btn_${i}_hint", nil)
|
||||||
|
part.Color = Color3.fromRGB(34, 221, 85)
|
||||||
|
local ev = ReplicatedStorage:FindFirstChild("ButtonPressed")
|
||||||
|
if ev then ev:Fire() end
|
||||||
|
end)`;
|
||||||
|
}
|
||||||
|
return overrides;
|
||||||
|
})(),
|
||||||
|
|
||||||
|
// ═══════════════════════════════════════════════════════════════
|
||||||
|
// ИГРЫ 48-50: явных Lua-версий пока нет.
|
||||||
|
// buildGameProject в docsGamesBuilders.js использует generateFallbackLua.
|
||||||
'clicker': {
|
'clicker': {
|
||||||
g46_main: `-- === ИГРА «КЛИКЕР» — главный скрипт (Lua) ===
|
g46_main: `-- === ИГРА «КЛИКЕР» — главный скрипт (Lua) ===
|
||||||
${SNIPPET_BROADCAST}
|
${SNIPPET_BROADCAST}
|
||||||
|
|||||||
@ -6660,7 +6660,7 @@ game.every(1.8, () => {
|
|||||||
|
|
||||||
<h3 className="lessonH">Шаг 2. Главный скрипт</h3>
|
<h3 className="lessonH">Шаг 2. Главный скрипт</h3>
|
||||||
<ScriptKind kind="global" />
|
<ScriptKind kind="global" />
|
||||||
<Code>{`// === ИГРА «КЛИКЕР» — главный скрипт ===
|
<CodeBoth game="clicker" script="g46_main">{`// === ИГРА «КЛИКЕР» — главный скрипт ===
|
||||||
|
|
||||||
let points = 0; // очки
|
let points = 0; // очки
|
||||||
let perClick = 1; // очков за клик
|
let perClick = 1; // очков за клик
|
||||||
@ -6725,7 +6725,7 @@ game.onMessage('buyAuto', () => {
|
|||||||
game.ui.score = points;
|
game.ui.score = points;
|
||||||
game.sound.play('pickup');
|
game.sound.play('pickup');
|
||||||
game.ui.showText('Авто-доход: +' + autoIncome + ' в секунду', 2);
|
game.ui.showText('Авто-доход: +' + autoIncome + ' в секунду', 2);
|
||||||
});`}</Code>
|
});`}</CodeBoth>
|
||||||
<p>Разберём:</p>
|
<p>Разберём:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>points</code> — очки, <code>perClick</code> —
|
<li><code>points</code> — очки, <code>perClick</code> —
|
||||||
@ -6745,22 +6745,22 @@ game.onMessage('buyAuto', () => {
|
|||||||
|
|
||||||
<h3 className="lessonH">Шаг 3. Скрипты куба и кнопок</h3>
|
<h3 className="lessonH">Шаг 3. Скрипты куба и кнопок</h3>
|
||||||
<ScriptKind kind="object" on="жёлтый куб-кликер" />
|
<ScriptKind kind="object" on="жёлтый куб-кликер" />
|
||||||
<Code>{`// === Скрипт куба-кликера ===
|
<CodeBoth game="clicker" script="g46_cube">{`// === Скрипт куба-кликера ===
|
||||||
game.self.onClick(() => {
|
game.self.onClick(() => {
|
||||||
game.broadcast('click');
|
game.broadcast('click');
|
||||||
// куб слегка вспыхивает
|
// куб слегка вспыхивает
|
||||||
game.scene.spawnParticles('sparks', game.self.position, { duration: 0.3 });
|
game.scene.spawnParticles('sparks', game.self.position, { duration: 0.3 });
|
||||||
});`}</Code>
|
});`}</CodeBoth>
|
||||||
<ScriptKind kind="object" on="красную кнопку" />
|
<ScriptKind kind="object" on="красную кнопку" />
|
||||||
<Code>{`// === Скрипт улучшения «сила клика» (20 очков) ===
|
<CodeBoth game="clicker" script="g46_up1">{`// === Скрипт улучшения «сила клика» (20 очков) ===
|
||||||
game.self.onInteract(() => {
|
game.self.onInteract(() => {
|
||||||
game.broadcast('buyPower');
|
game.broadcast('buyPower');
|
||||||
}, { text: 'Купить +силу клика (20)', distance: 3 });`}</Code>
|
}, { text: 'Купить +силу клика (20)', distance: 3 });`}</CodeBoth>
|
||||||
<ScriptKind kind="object" on="синюю кнопку" />
|
<ScriptKind kind="object" on="синюю кнопку" />
|
||||||
<Code>{`// === Скрипт улучшения «авто-доход» (40 очков) ===
|
<CodeBoth game="clicker" script="g46_up2">{`// === Скрипт улучшения «авто-доход» (40 очков) ===
|
||||||
game.self.onInteract(() => {
|
game.self.onInteract(() => {
|
||||||
game.broadcast('buyAuto');
|
game.broadcast('buyAuto');
|
||||||
}, { text: 'Купить авто-доход (40)', distance: 3 });`}</Code>
|
}, { text: 'Купить авто-доход (40)', distance: 3 });`}</CodeBoth>
|
||||||
<Note>
|
<Note>
|
||||||
Главная идея кликера: сначала кликаешь руками, потом
|
Главная идея кликера: сначала кликаешь руками, потом
|
||||||
покупаешь улучшения — и игра «играет сама». Это экономика:
|
покупаешь улучшения — и игра «играет сама». Это экономика:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user