DockerRoblox / src /pages /Lesson2Page.tsx
Joey889's picture
Upload 5 files
b666577 verified
import { useState } from 'react';
import { motion } from 'framer-motion';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
const carControllerScript = `
-- 車輛控制腳本
-- 常數設定
local FORWARD_FORCE = 15000 -- 前進力量
local REVERSE_FORCE = 8000 -- 後退力量
local TURN_SPEED = 2.5 -- 轉向速度
local MAX_SPEED = 60 -- 最大速度 (studs/秒)
local BRAKE_FORCE = 10000 -- 剎車力量
-- 獲取車輛模型及其組件
local car = script.Parent
local body = car:WaitForChild("Body") -- 車身主體
local frontLeftWheel = car:WaitForChild("FrontLeftWheel")
local frontRightWheel = car:WaitForChild("FrontRightWheel")
local rearLeftWheel = car:WaitForChild("RearLeftWheel")
local rearRightWheel = car:WaitForChild("RearRightWheel")
-- 獲取車輪連接點
local flHinge = car:WaitForChild("FLHinge")
local frHinge = car:WaitForChild("FRHinge")
local rlHinge = car:WaitForChild("RLHinge")
local rrHinge = car:WaitForChild("RRHinge")
-- 設置車輛控制
local vehicleSeat = car:WaitForChild("VehicleSeat")
-- 當玩家進入車輛時
vehicleSeat.Changed:Connect(function(property)
if property == "Occupant" then
local player = vehicleSeat.Occupant
if player then
-- 玩家進入車輛
print("玩家進入車輛")
else
-- 玩家離開車輛
print("玩家離開車輛")
end
end
end)
-- 主要控制循環
game:GetService("RunService").Heartbeat:Connect(function(deltaTime)
if not vehicleSeat.Occupant then return end
local throttle = vehicleSeat.ThrottleFloat -- -1 到 1 之間的值
local steer = vehicleSeat.SteerFloat -- -1 到 1 之間的值
-- 計算車輛當前速度
local velocity = body.Velocity
local speed = velocity.Magnitude
-- 應用前進/後退力量
local forceVector = body.CFrame.LookVector
local force = Vector3.new(0, 0, 0)
if throttle > 0 then
-- 前進
force = forceVector * FORWARD_FORCE * throttle
elseif throttle < 0 then
-- 後退
force = forceVector * -REVERSE_FORCE * math.abs(throttle)
end
-- 限制最大速度
if speed > MAX_SPEED and throttle > 0 then
force = Vector3.new(0, 0, 0)
end
-- 應用轉向
local turnAngle = steer * TURN_SPEED * deltaTime
if math.abs(throttle) > 0.1 then -- 只有在移動時才轉向
body.CFrame = body.CFrame * CFrame.Angles(0, turnAngle, 0)
end
-- 應用力量到車身
body:ApplyForce(force)
-- 旋轉車輪
local wheelRotationSpeed = speed * 0.5
if throttle > 0 then
-- 前進時車輪正向旋轉
flHinge.AngularVelocity = wheelRotationSpeed
frHinge.AngularVelocity = wheelRotationSpeed
rlHinge.AngularVelocity = wheelRotationSpeed
rrHinge.AngularVelocity = wheelRotationSpeed
elseif throttle < 0 then
-- 後退時車輪反向旋轉
flHinge.AngularVelocity = -wheelRotationSpeed
frHinge.AngularVelocity = -wheelRotationSpeed
rlHinge.AngularVelocity = -wheelRotationSpeed
rrHinge.AngularVelocity = -wheelRotationSpeed
else
-- 停止時車輪不旋轉
flHinge.AngularVelocity = 0
frHinge.AngularVelocity = 0
rlHinge.AngularVelocity = 0
rrHinge.AngularVelocity = 0
end
-- 轉向前輪
frontLeftWheel.CFrame = frontLeftWheel.CFrame * CFrame.Angles(0, steer * 0.5, 0)
frontRightWheel.CFrame = frontRightWheel.CFrame * CFrame.Angles(0, steer * 0.5, 0)
end)
-- 設置攝影機
local function setupCamera(player)
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
-- 設置第三人稱攝影機
humanoid.CameraOffset = Vector3.new(0, 2, 0)
end
vehicleSeat.Changed:Connect(function(property)
if property == "Occupant" and vehicleSeat.Occupant then
local player = game.Players:GetPlayerFromCharacter(vehicleSeat.Occupant.Parent)
if player then
setupCamera(player)
end
end
end)
`;
const scoringSystemScript = `
-- 計分系統腳本
-- 常數設定
local CHECKPOINTS_TO_COMPLETE = 8 -- 完成一圈所需的檢查點數量
local FINISH_MESSAGE = "恭喜完成比賽!"
-- 服務引用
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- 創建遠端事件用於更新UI
local checkpointEvent = Instance.new("RemoteEvent")
checkpointEvent.Name = "CheckpointEvent"
checkpointEvent.Parent = ReplicatedStorage
-- 玩家數據儲存
local playerData = {}
-- 初始化玩家數據
local function initPlayerData(player)
playerData[player.UserId] = {
checkpointsPassed = 0,
lastCheckpoint = 0,
raceCompleted = false,
startTime = 0,
finishTime = 0
}
end
-- 當玩家加入遊戲時
Players.PlayerAdded:Connect(function(player)
initPlayerData(player)
-- 創建計分UI
local scoreGui = Instance.new("ScreenGui")
scoreGui.Name = "RaceScoreGui"
local frame = Instance.new("Frame")
frame.Size = UDim2.new(0, 200, 0, 100)
frame.Position = UDim2.new(0.85, -100, 0, 10)
frame.BackgroundTransparency = 0.5
frame.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
frame.Parent = scoreGui
local checkpointLabel = Instance.new("TextLabel")
checkpointLabel.Name = "CheckpointLabel"
checkpointLabel.Size = UDim2.new(1, 0, 0.5, 0)
checkpointLabel.Text = "檢查點: 0/" .. CHECKPOINTS_TO_COMPLETE
checkpointLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
checkpointLabel.BackgroundTransparency = 1
checkpointLabel.Parent = frame
local timeLabel = Instance.new("TextLabel")
timeLabel.Name = "TimeLabel"
timeLabel.Size = UDim2.new(1, 0, 0.5, 0)
timeLabel.Position = UDim2.new(0, 0, 0.5, 0)
timeLabel.Text = "時間: 0.00"
timeLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
timeLabel.BackgroundTransparency = 1
timeLabel.Parent = frame
scoreGui.Parent = player.PlayerGui
-- 當玩家角色加入時
player.CharacterAdded:Connect(function(character)
-- 重置玩家數據
initPlayerData(player)
-- 更新UI
checkpointEvent:FireClient(player, "reset", 0, CHECKPOINTS_TO_COMPLETE)
end)
end)
-- 當玩家離開遊戲時
Players.PlayerRemoving:Connect(function(player)
playerData[player.UserId] = nil
end)
-- 設置檢查點觸發器
local function setupCheckpoint(checkpoint, checkpointNumber)
checkpoint.Touched:Connect(function(hit)
local character = hit.Parent
local player = Players:GetPlayerFromCharacter(character)
if player and not playerData[player.UserId].raceCompleted then
local data = playerData[player.UserId]
-- 確保檢查點按順序通過
if checkpointNumber == (data.lastCheckpoint % CHECKPOINTS_TO_COMPLETE) + 1 then
data.checkpointsPassed = data.checkpointsPassed + 1
data.lastCheckpoint = checkpointNumber
-- 如果是第一個檢查點且剛開始比賽,記錄開始時間
if checkpointNumber == 1 and data.startTime == 0 then
data.startTime = tick()
end
-- 更新UI
checkpointEvent:FireClient(player, "update", data.checkpointsPassed, CHECKPOINTS_TO_COMPLETE)
-- 檢查是否完成比賽 (完成一圈8字形)
if data.checkpointsPassed >= CHECKPOINTS_TO_COMPLETE then
data.raceCompleted = true
data.finishTime = tick() - data.startTime
-- 通知玩家完成比賽
checkpointEvent:FireClient(player, "complete", data.finishTime)
-- 顯示完成訊息
game.StarterGui:SetCore("ChatMakeSystemMessage", {
Text = FINISH_MESSAGE .. "\\n完成時間: " .. string.format("%.2f", data.finishTime) .. " 秒",
Color = Color3.fromRGB(0, 255, 0),
Font = Enum.Font.SourceSansBold
})
end
end
end
end)
end
-- 尋找並設置所有檢查點
local function setupAllCheckpoints()
local checkpoints = workspace:FindFirstChild("Checkpoints")
if checkpoints then
for i, checkpoint in ipairs(checkpoints:GetChildren()) do
if checkpoint:IsA("BasePart") and checkpoint.Name:match("Checkpoint%d+") then
local number = tonumber(checkpoint.Name:match("%d+"))
if number then
setupCheckpoint(checkpoint, number)
end
end
end
else
warn("找不到檢查點資料夾!請確保在工作區中有一個名為 'Checkpoints' 的資料夾,其中包含命名為 'Checkpoint1', 'Checkpoint2' 等的檢查點。")
end
end
-- 設置客戶端UI更新
local function setupClientUI()
local clientScript = Instance.new("LocalScript")
clientScript.Name = "RaceUIUpdater"
clientScript.Source = [[
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local checkpointEvent = ReplicatedStorage:WaitForChild("CheckpointEvent")
local player = game.Players.LocalPlayer
local scoreGui = player.PlayerGui:WaitForChild("RaceScoreGui")
local frame = scoreGui:WaitForChild("Frame")
local checkpointLabel = frame:WaitForChild("CheckpointLabel")
local timeLabel = frame:WaitForChild("TimeLabel")
local startTime = 0
local isRacing = false
-- 更新時間顯示
game:GetService("RunService").RenderStepped:Connect(function()
if isRacing and startTime > 0 then
local currentTime = tick() - startTime
timeLabel.Text = "時間: " .. string.format("%.2f", currentTime)
end
end)
-- 處理檢查點事件
checkpointEvent.OnClientEvent:Connect(function(action, value, total)
if action == "update" then
checkpointLabel.Text = "檢查點: " .. value .. "/" .. total
-- 如果是第一個檢查點,開始計時
if value == 1 and not isRacing then
startTime = tick()
isRacing = true
end
elseif action == "complete" then
isRacing = false
timeLabel.Text = "完成時間: " .. string.format("%.2f", value)
checkpointLabel.TextColor3 = Color3.fromRGB(0, 255, 0)
timeLabel.TextColor3 = Color3.fromRGB(0, 255, 0)
elseif action == "reset" then
isRacing = false
startTime = 0
checkpointLabel.Text = "檢查點: 0/" .. total
timeLabel.Text = "時間: 0.00"
checkpointLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
timeLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
end
end)
]]
clientScript.Parent = ReplicatedStorage
end
-- 初始化
setupAllCheckpoints()
setupClientUI()
print("賽車計分系統已初始化!")
`;
export default function Lesson2Page() {
const [activeSection, setActiveSection] = useState('intro');
const scrollToSection = (sectionId: string) => {
setActiveSection(sectionId);
const element = document.getElementById(sectionId);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
};
return (
<div className="flex flex-col md:flex-row gap-6">
{/* Sidebar Navigation */}
<div className="md:w-1/4 lg:w-1/5">
<div className="bg-white rounded-xl shadow-md p-6 sticky top-24">
<h3 className="text-lg font-bold text-gray-800 mb-4">課程目錄</h3>
<nav className="space-y-2">
<button
onClick={() => scrollToSection('intro')}
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
activeSection === 'intro'
? 'bg-green-100 text-green-700'
: 'text-gray-600 hover:bg-gray-100'
}`}
>
課程簡介
</button>
<button
onClick={() => scrollToSection('part1')}
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
activeSection === 'part1'
? 'bg-green-100 text-green-700'
: 'text-gray-600 hover:bg-gray-100'
}`}
>
賽車模型建構
</button>
<button
onClick={() => scrollToSection('part2')}
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
activeSection === 'part2'
? 'bg-green-100 text-green-700'
: 'text-gray-600 hover:bg-gray-100'
}`}
>
8字形賽道設計
</button>
<button
onClick={() => scrollToSection('part3')}
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
activeSection === 'part3'
? 'bg-green-100 text-green-700'
: 'text-gray-600 hover:bg-gray-100'
}`}
>
車輛控制系統
</button>
<button
onClick={() => scrollToSection('part4')}
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
activeSection === 'part4'
? 'bg-green-100 text-green-700'
: 'text-gray-600 hover:bg-gray-100'
}`}
>
計分系統
</button>
<button
onClick={() => scrollToSection('part5')}
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
activeSection === 'part5'
? 'bg-green-100 text-green-700'
: 'text-gray-600 hover:bg-gray-100'
}`}
>
完善與匯出
</button>
<button
onClick={() => scrollToSection('summary')}
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
activeSection === 'summary'
? 'bg-green-100 text-green-700'
: 'text-gray-600 hover:bg-gray-100'
}`}
>
總結與挑戰
</button>
</nav>
</div>
</div>
{/* Main Content */}
<div className="md:w-3/4 lg:w-4/5">
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5 }}
>
<div className="bg-gradient-to-r from-green-600 to-teal-600 rounded-xl p-8 mb-8 text-white">
<h1 className="text-3xl md:text-4xl font-bold mb-4">Roblox 基礎入門第二課 - 創造我的世界:賽車遊戲學習</h1>
<p className="text-lg opacity-90">
學習建構賽車模型、設計賽道、編寫控制腳本與計分系統
</p>
</div>
{/* Course Introduction */}
<section id="intro" className="mb-12 scroll-mt-24">
<h2 className="text-2xl font-bold text-gray-800 mb-4">課程簡介</h2>
<div className="bg-white rounded-xl shadow-md p-6">
<p className="text-gray-700 mb-4">
本課程將帶領學習者建構一個完整的賽車遊戲,包含四輪車模型、8字形賽道、車輛控制系統與計分機制。通過實際操作,學習者將掌握 Roblox Studio 中的模型建構、程式控制與遊戲機制設計等核心技能。
</p>
<h3 className="text-xl font-bold text-green-700 mb-3">課程目標</h3>
<ul className="list-disc pl-6 space-y-2 text-gray-700">
<li>在 Roblox Studio 中建構可操作的四輪車模型</li>
<li>設計並實現 8 字形賽道與檢查點系統</li>
<li>編寫車輛控制腳本,實現前進、後退、左右轉向功能</li>
<li>設計計分機制,追蹤賽車完成圈數並判定比賽完成</li>
</ul>
<h3 className="text-xl font-bold text-green-700 mt-6 mb-3">前置準備</h3>
<ul className="list-disc pl-6 space-y-2 text-gray-700">
<li>已安裝最新版本的 Roblox Studio</li>
<li>具備 Roblox Studio 基本操作能力(第一課內容)</li>
<li>了解基本的 Lua 程式語法</li>
</ul>
</div>
</section>
{/* Part 1: Car Model Construction */}
<section id="part1" className="mb-12 scroll-mt-24">
<h2 className="text-2xl font-bold text-gray-800 mb-4">第一部分:賽車模型建構</h2>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 1:創建新專案</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700">
<li>打開 Roblox Studio</li>
<li>選擇「基礎模板」創建新專案</li>
<li>保存專案,命名為「RaceCarGame」</li>
</ol>
</div>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 2:建立車身基本結構</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>在工作區中插入一個方塊部件(Part)</li>
<li>調整車身尺寸與位置:Size: 6, 2, 10 (寬, 高, 長), Position: 0, 3, 0 (X, Y, Z), 命名為「Body」</li>
<li>設置車身外觀:選擇喜歡的顏色, Material: SmoothPlastic, Anchored: false</li>
<li>設置物理屬性:CanCollide: true, Massless: false, CustomPhysicalProperties: true (Density: 1, Friction: 0.3, Elasticity: 0.2)</li>
</ol>
</div>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 3:創建車輪</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>創建前左輪:插入圓柱體(Cylinder), Size: 2, 0.5, 2, Position: -3, 2, 3.5, Orientation: 0, 0, 90, 命名為「FrontLeftWheel」</li>
<li>創建前右輪:複製前左輪, Position: 3, 2, 3.5, 命名為「FrontRightWheel」</li>
<li>創建後左輪:複製前左輪, Position: -3, 2, -3.5, 命名為「RearLeftWheel」</li>
<li>創建後右輪:複製前左輪, Position: 3, 2, -3.5, 命名為「RearRightWheel」</li>
<li>設置車輪外觀:Color: 黑色, Material: Rubber, CanCollide: true</li>
</ol>
</div>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 4:連接車輪與車身</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>創建前左輪連接點:使用 HingeConstraint, Attachment0 連接 Body, Attachment1 連接 FrontLeftWheel, 命名為「FLHinge」</li>
<li>設置前左輪連接點屬性:ActuatorType: Motor, AngularVelocity: 0, MotorMaxTorque: 1000</li>
<li>重複上述步驟,為其他三個車輪創建連接點 (FRHinge, RLHinge, RRHinge)</li>
</ol>
</div>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 5:添加車身細節</h3>
<ul className="list-disc pl-6 space-y-2 text-gray-700 mb-4">
<li>創建擋風玻璃:使用方塊部件, 設置大小、位置、顏色(淺藍)、透明度(0.5)、材質(Glass)</li>
<li>創建前燈:使用兩個小方塊部件, 放置在車身前部, 設置顏色(黃/白), 可選添加 PointLight</li>
<li>創建後燈:使用兩個小方塊部件, 放置在車身後部, 設置顏色(紅)</li>
<li>創建座椅與方向盤:使用方塊和圓環部件</li>
</ul>
</div>
<div className="bg-white rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 6:添加駕駛座</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>插入 VehicleSeat:放置在車身上方中央, 命名為「VehicleSeat」</li>
<li>設置 VehicleSeat 屬性:MaxSpeed: 60, Torque: 200, TurnSpeed: 2.5</li>
<li>將所有部件組織到一個模型中:選中所有部件, 右鍵「Group」, 命名為「RaceCar」</li>
</ol>
</div>
</section>
{/* Part 2: Figure-8 Track Design */}
<section id="part2" className="mb-12 scroll-mt-24">
<h2 className="text-2xl font-bold text-gray-800 mb-4">第二部分:8字形賽道設計</h2>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 1:規劃賽道布局</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>創建賽道基礎平面:插入大型方塊部件, Size: 100, 1, 100, Position: 0, 0, 0, Color: 綠色, Material: Grass, Anchored: true</li>
<li>規劃 8 字形賽道路徑:在基礎平面上方繪製, 確保寬度足夠(12-15 studs), 彎道半徑適當</li>
</ol>
</div>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 2:建構賽道</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>創建賽道部件:使用多個方塊部件組合成 8 字形, 設置大小、位置、顏色(灰色)、材質(Concrete)、Anchored: true</li>
<li>使用 Union 工具合併賽道部件...賽道部件, 點擊「Model」{'>'}「Union」, 命名為「Track...</li>
</ol>
</div>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 3:添加賽道邊界</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>創建護欄:沿賽道外圍放置方塊部件, 設置大小、顏色(紅白相間)、材質(SmoothPlastic)、Anchored: true</li>
<li>調整彎道處的護欄:使用多個小段護欄拼接, 確保護欄緊貼賽道邊緣</li>
</ol>
</div>
<div className="bg-white rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 4:創建檢查點系統</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>創建檢查點資料夾:在工作區創建 Folder, 命名為「Checkpoints」</li>
<li>創建檢查點觸發器:在關鍵位置插入方塊部件, Size: 賽道寬度, 5, 1, Transparency: 0.8, CanCollide: false, 命名為「Checkpoint1」、「Checkpoint2」等, 按順序排列</li>
<li>創建起點/終點線:在賽道上創建明顯的起點/終點線, 與第一個檢查點重合</li>
</ol>
</div>
</section>
{/* Part 3: Vehicle Control System */}
<section id="part3" className="mb-12 scroll-mt-24">
<h2 className="text-2xl font-bold text-gray-800 mb-4">第三部分:車輛控制系統</h2>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 1:創建車輛控制腳本</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>在 RaceCar 模型中添加腳本, 命名為「CarController」</li>
<li>編寫車輛控制腳本(見下方代碼)</li>
<li>保存腳本</li>
</ol>
<SyntaxHighlighter language="lua" style={vscDarkPlus} className="rounded-lg">
{carControllerScript}
</SyntaxHighlighter>
</div>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 2:測試車輛控制</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>點擊「Play」按鈕進入測試模式</li>
<li>使用 W/A/S/D 或方向鍵駕駛車輛</li>
<li>測試加速、轉向和剎車功能</li>
<li>點擊「Stop」按鈕退出測試模式</li>
</ol>
</div>
<div className="bg-white rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 3:調整車輛控制參數</h3>
<p className="text-gray-700 mb-4">
根據測試結果調整 CarController 腳本中的參數:
</p>
<ul className="list-disc pl-6 space-y-2 text-gray-700">
<li>FORWARD_FORCE, REVERSE_FORCE, MAX_SPEED:調整速度與力量</li>
<li>TURN_SPEED:調整轉向靈敏度</li>
<li>物理屬性:調整車身和車輪的 Density, Friction, Elasticity</li>
</ul>
</div>
</section>
{/* Part 4: Scoring System */}
<section id="part4" className="mb-12 scroll-mt-24">
<h2 className="text-2xl font-bold text-gray-800 mb-4">第四部分:計分系統</h2>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 1:創建計分系統腳本</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>在 ServerScriptService 中添加腳本, 命名為「ScoringSystem」</li>
<li>編寫計分系統腳本(見下方代碼)</li>
<li>保存腳本</li>
</ol>
<SyntaxHighlighter language="lua" style={vscDarkPlus} className="rounded-lg">
{scoringSystemScript}
</SyntaxHighlighter>
</div>
<div className="bg-white rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 2:測試計分系統</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
<li>確保所有檢查點已正確設置在 Checkpoints 資料夾中</li>
<li>點擊「Play」按鈕進入測試模式</li>
<li>駕駛車輛通過檢查點</li>
<li>觀察計分 UI 是否正確更新(檢查點數量和時間)</li>
<li>完成一圈 8 字形賽道,確認比賽完成提示是否顯示</li>
<li>點擊「Stop」按鈕退出測試模式</li>
</ol>
</div>
</section>
{/* Part 5: Refinement and Export */}
<section id="part5" className="mb-12 scroll-mt-24">
<h2 className="text-2xl font-bold text-gray-800 mb-4">第五部分:完善與匯出</h2>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 1:完善遊戲細節</h3>
<ul className="list-disc pl-6 space-y-2 text-gray-700">
<li>添加遊戲說明 GUI:包含控制說明和遊戲目標</li>
<li>添加環境裝飾:樹木、建築、天空盒等</li>
<li>添加音效:車輛引擎聲、比賽開始/完成音效</li>
</ul>
</div>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 2:最終測試與調整</h3>
<ul className="list-disc pl-6 space-y-2 text-gray-700">
<li>進行全面測試:車輛控制、檢查點、計分、性能</li>
<li>根據測試結果進行調整:優化物理、調整檢查點、修復問題</li>
</ul>
</div>
<div className="bg-white rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 3:匯出專案</h3>
<ol className="list-decimal pl-6 space-y-2 text-gray-700">
<li>保存專案:File {'>'}Save</li>
<li>發布到 Roblox:File {'>'}Publish to Roblox</li>
<li>匯出模型(可選):選中 RaceCar 模型, File {'>'}Export Selection</li>
</ol>
</div>
</section>
{/* Summary and Challenge */}
<section id="summary" className="mb-12 scroll-mt-24">
<h2 className="text-2xl font-bold text-gray-800 mb-4">總結</h2>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<p className="text-gray-700 mb-4">
在本課程中,我們成功建構了一個完整的賽車遊戲,包含四輪車模型、8字形賽道、車輛控制系統與計分機制。通過這個項目,學習者掌握了 Roblox Studio 中的模型建構、程式控制與遊戲機制設計等核心技能。
</p>
<p className="text-gray-700 mb-4">
這些技能可以應用於更複雜的遊戲開發項目,例如多人賽車遊戲、障礙賽車場、開放世界駕駛遊戲、車輛模擬器等。
</p>
</div>
<div className="bg-gradient-to-r from-green-50 to-teal-50 rounded-xl shadow-md p-6 mb-6">
<h3 className="text-xl font-bold text-green-700 mb-3">進階挑戰</h3>
<p className="text-gray-700 mb-4">
想要進一步提升您的賽車遊戲?嘗試以下挑戰:
</p>
<ul className="list-disc pl-6 space-y-2 text-gray-700">
<li>添加多人競賽功能</li>
<li>實現車輛損壞系統</li>
<li>添加不同類型的車輛</li>
<li>創建更複雜的賽道,包含坡道、跳台等</li>
<li>添加道具系統(如加速、護盾等)</li>
</ul>
</div>
<div className="bg-gradient-to-r from-blue-50 to-green-50 rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-blue-700 mb-3">資源推薦</h3>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<a href="https://create.roblox.com/docs" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
<h4 className="font-bold text-blue-800 mb-2">Roblox 開發者文檔</h4>
<p className="text-gray-700">官方開發文檔,包含詳細的 API 參考和教程</p>
</a>
<a href="https://developer.roblox.com/en-us/articles/vehicles" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
<h4 className="font-bold text-blue-800 mb-2">Roblox 車輛系統教程</h4>
<p className="text-gray-700">官方關於車輛系統的詳細教程</p>
</a>
<a href="https://www.lua.org/manual/5.1/" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
<h4 className="font-bold text-blue-800 mb-2">Lua 程式設計指南</h4>
<p className="text-gray-700">學習 Lua 語言的官方手冊</p>
</a>
<a href="https://devforum.roblox.com/" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
<h4 className="font-bold text-blue-800 mb-2">Roblox 開發者論壇</h4>
<p className="text-gray-700">與其他開發者交流,獲取幫助和分享經驗</p>
</a>
</div>
</div>
</section>
{/* Navigation Buttons */}
<div className="flex justify-between mt-12">
<a
href="/lesson1"
className="px-6 py-3 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition-colors flex items-center"
>
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M9.707 14.707a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 1.414L7.414 9H15a1 1 0 110 2H7.414l2.293 2.293a1 1 0 010 1.414z" clipRule="evenodd" />
</svg>
上一課:基礎入門
</a>
<a
href="/lesson3"
className="px-6 py-3 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors flex items-center"
>
下一課:互動機關
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 ml-2" viewBox="0 0 20 20" fill="currentColor">
<path fillRule="evenodd" d="M10.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L12.586 11H5a1 1 0 110-2h7.586l-2.293-2.293a1 1 0 010-1.414z" clipRule="evenodd" />
</svg>
</a>
</div>
</motion.div>
</div>
</div>
);
}