Spaces:
Sleeping
Sleeping
Upload 5 files
Browse files- src/pages/HomePage.tsx +174 -0
- src/pages/Lesson1Page.tsx +534 -0
- src/pages/Lesson2Page.tsx +731 -0
- src/pages/Lesson3Page.tsx +752 -0
- src/pages/Lesson4Page.tsx +707 -0
src/pages/HomePage.tsx
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { motion } from 'framer-motion';
|
| 2 |
+
|
| 3 |
+
export default function HomePage() {
|
| 4 |
+
return (
|
| 5 |
+
<div className="py-8">
|
| 6 |
+
<motion.div
|
| 7 |
+
initial={{ opacity: 0, y: 20 }}
|
| 8 |
+
animate={{ opacity: 1, y: 0 }}
|
| 9 |
+
transition={{ duration: 0.5 }}
|
| 10 |
+
className="text-center mb-12"
|
| 11 |
+
>
|
| 12 |
+
<h1 className="text-4xl md:text-5xl font-bold mb-4 bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
|
| 13 |
+
Roblox 基礎入門教學
|
| 14 |
+
</h1>
|
| 15 |
+
<p className="text-xl text-gray-600 max-w-3xl mx-auto">
|
| 16 |
+
從零開始學習 Roblox Studio 開發,打造屬於你的遊戲世界
|
| 17 |
+
</p>
|
| 18 |
+
</motion.div>
|
| 19 |
+
|
| 20 |
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-16">
|
| 21 |
+
<motion.div
|
| 22 |
+
initial={{ opacity: 0, x: -50 }}
|
| 23 |
+
animate={{ opacity: 1, x: 0 }}
|
| 24 |
+
transition={{ duration: 0.5, delay: 0.2 }}
|
| 25 |
+
className="bg-gradient-to-br from-blue-50 to-indigo-50 p-8 rounded-xl shadow-lg"
|
| 26 |
+
>
|
| 27 |
+
<h2 className="text-2xl font-bold text-blue-800 mb-4">為什麼學習 Roblox 開發?</h2>
|
| 28 |
+
<p className="text-gray-700 mb-4">
|
| 29 |
+
Roblox 是一個全球性的遊戲平台,擁有超過 2 億月活躍用戶,為創作者提供了展示創意和賺取收入的機會。
|
| 30 |
+
透過學習 Roblox Studio 開發,你可以:
|
| 31 |
+
</p>
|
| 32 |
+
<ul className="list-disc pl-5 space-y-2 text-gray-700">
|
| 33 |
+
<li>將創意轉化為互動體驗</li>
|
| 34 |
+
<li>學習程式設計、3D 建模和遊戲開發基礎</li>
|
| 35 |
+
<li>加入全球開發者社群</li>
|
| 36 |
+
<li>有機會透過作品獲得收入</li>
|
| 37 |
+
</ul>
|
| 38 |
+
</motion.div>
|
| 39 |
+
|
| 40 |
+
<motion.div
|
| 41 |
+
initial={{ opacity: 0, x: 50 }}
|
| 42 |
+
animate={{ opacity: 1, x: 0 }}
|
| 43 |
+
transition={{ duration: 0.5, delay: 0.4 }}
|
| 44 |
+
className="bg-gradient-to-br from-purple-50 to-pink-50 p-8 rounded-xl shadow-lg"
|
| 45 |
+
>
|
| 46 |
+
<h2 className="text-2xl font-bold text-purple-800 mb-4">課程特色</h2>
|
| 47 |
+
<p className="text-gray-700 mb-4">
|
| 48 |
+
我們的教學課程專為初學者設計,透過循序漸進的方式帶你掌握 Roblox 開發技能:
|
| 49 |
+
</p>
|
| 50 |
+
<ul className="list-disc pl-5 space-y-2 text-gray-700">
|
| 51 |
+
<li>實用範例與實作練習</li>
|
| 52 |
+
<li>清晰的步驟說明與圖片指引</li>
|
| 53 |
+
<li>從基礎到進階的學習路徑</li>
|
| 54 |
+
<li>完整的程式碼範例與解說</li>
|
| 55 |
+
<li>專注於創意與互動性</li>
|
| 56 |
+
</ul>
|
| 57 |
+
</motion.div>
|
| 58 |
+
</div>
|
| 59 |
+
|
| 60 |
+
<motion.h2
|
| 61 |
+
initial={{ opacity: 0, y: 20 }}
|
| 62 |
+
animate={{ opacity: 1, y: 0 }}
|
| 63 |
+
transition={{ duration: 0.5, delay: 0.6 }}
|
| 64 |
+
className="text-3xl font-bold text-center mb-8 text-gray-800"
|
| 65 |
+
>
|
| 66 |
+
課程內容
|
| 67 |
+
</motion.h2>
|
| 68 |
+
|
| 69 |
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
| 70 |
+
<motion.div
|
| 71 |
+
initial={{ opacity: 0, y: 20 }}
|
| 72 |
+
animate={{ opacity: 1, y: 0 }}
|
| 73 |
+
transition={{ duration: 0.5, delay: 0.7 }}
|
| 74 |
+
className="bg-white rounded-xl shadow-lg overflow-hidden hover:shadow-xl transition-shadow"
|
| 75 |
+
>
|
| 76 |
+
<div className="h-3 bg-blue-500"></div>
|
| 77 |
+
<div className="p-6">
|
| 78 |
+
<h3 className="text-xl font-bold text-gray-800 mb-2">第一課:基礎入門</h3>
|
| 79 |
+
<p className="text-gray-600 mb-4">
|
| 80 |
+
了解 Roblox 平台、基本操作與 Studio 環境熟悉,為後續開發打下基礎。
|
| 81 |
+
</p>
|
| 82 |
+
<a
|
| 83 |
+
href="/lesson1"
|
| 84 |
+
className="inline-block px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors"
|
| 85 |
+
>
|
| 86 |
+
開始學習
|
| 87 |
+
</a>
|
| 88 |
+
</div>
|
| 89 |
+
</motion.div>
|
| 90 |
+
|
| 91 |
+
<motion.div
|
| 92 |
+
initial={{ opacity: 0, y: 20 }}
|
| 93 |
+
animate={{ opacity: 1, y: 0 }}
|
| 94 |
+
transition={{ duration: 0.5, delay: 0.8 }}
|
| 95 |
+
className="bg-white rounded-xl shadow-lg overflow-hidden hover:shadow-xl transition-shadow"
|
| 96 |
+
>
|
| 97 |
+
<div className="h-3 bg-green-500"></div>
|
| 98 |
+
<div className="p-6">
|
| 99 |
+
<h3 className="text-xl font-bold text-gray-800 mb-2">第二課:賽車遊戲</h3>
|
| 100 |
+
<p className="text-gray-600 mb-4">
|
| 101 |
+
建構四輪車模型與 8 字形賽道,實現車輛控制與計分系統。
|
| 102 |
+
</p>
|
| 103 |
+
<a
|
| 104 |
+
href="/lesson2"
|
| 105 |
+
className="inline-block px-4 py-2 bg-green-500 text-white rounded-md hover:bg-green-600 transition-colors"
|
| 106 |
+
>
|
| 107 |
+
開始學習
|
| 108 |
+
</a>
|
| 109 |
+
</div>
|
| 110 |
+
</motion.div>
|
| 111 |
+
|
| 112 |
+
<motion.div
|
| 113 |
+
initial={{ opacity: 0, y: 20 }}
|
| 114 |
+
animate={{ opacity: 1, y: 0 }}
|
| 115 |
+
transition={{ duration: 0.5, delay: 0.9 }}
|
| 116 |
+
className="bg-white rounded-xl shadow-lg overflow-hidden hover:shadow-xl transition-shadow"
|
| 117 |
+
>
|
| 118 |
+
<div className="h-3 bg-purple-500"></div>
|
| 119 |
+
<div className="p-6">
|
| 120 |
+
<h3 className="text-xl font-bold text-gray-800 mb-2">第三課:互動機關</h3>
|
| 121 |
+
<p className="text-gray-600 mb-4">
|
| 122 |
+
設計機關門與數學題互動系統,學習進階互動機制與教育元素整合。
|
| 123 |
+
</p>
|
| 124 |
+
<a
|
| 125 |
+
href="/lesson3"
|
| 126 |
+
className="inline-block px-4 py-2 bg-purple-500 text-white rounded-md hover:bg-purple-600 transition-colors"
|
| 127 |
+
>
|
| 128 |
+
開始學習
|
| 129 |
+
</a>
|
| 130 |
+
</div>
|
| 131 |
+
</motion.div>
|
| 132 |
+
|
| 133 |
+
<motion.div
|
| 134 |
+
initial={{ opacity: 0, y: 20 }}
|
| 135 |
+
animate={{ opacity: 1, y: 0 }}
|
| 136 |
+
transition={{ duration: 0.5, delay: 1 }}
|
| 137 |
+
className="bg-white rounded-xl shadow-lg overflow-hidden hover:shadow-xl transition-shadow"
|
| 138 |
+
>
|
| 139 |
+
<div className="h-3 bg-pink-500"></div>
|
| 140 |
+
<div className="p-6">
|
| 141 |
+
<h3 className="text-xl font-bold text-gray-800 mb-2">第四課:視覺化設計</h3>
|
| 142 |
+
<p className="text-gray-600 mb-4">
|
| 143 |
+
使用立方體創建科技感立體投影圖像,探索視覺化程式設計的創意可能。
|
| 144 |
+
</p>
|
| 145 |
+
<a
|
| 146 |
+
href="/lesson4"
|
| 147 |
+
className="inline-block px-4 py-2 bg-pink-500 text-white rounded-md hover:bg-pink-600 transition-colors"
|
| 148 |
+
>
|
| 149 |
+
開始學習
|
| 150 |
+
</a>
|
| 151 |
+
</div>
|
| 152 |
+
</motion.div>
|
| 153 |
+
</div>
|
| 154 |
+
|
| 155 |
+
<motion.div
|
| 156 |
+
initial={{ opacity: 0, y: 20 }}
|
| 157 |
+
animate={{ opacity: 1, y: 0 }}
|
| 158 |
+
transition={{ duration: 0.5, delay: 1.1 }}
|
| 159 |
+
className="mt-16 bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl p-8 text-white text-center"
|
| 160 |
+
>
|
| 161 |
+
<h2 className="text-2xl font-bold mb-4">準備好開始你的 Roblox 開發之旅了嗎?</h2>
|
| 162 |
+
<p className="mb-6 max-w-2xl mx-auto">
|
| 163 |
+
從第一課開始,循序漸進地學習 Roblox Studio 開發技能,打造屬於你的遊戲世界!
|
| 164 |
+
</p>
|
| 165 |
+
<a
|
| 166 |
+
href="/lesson1"
|
| 167 |
+
className="inline-block px-6 py-3 bg-white text-blue-600 font-bold rounded-md hover:bg-gray-100 transition-colors"
|
| 168 |
+
>
|
| 169 |
+
立即開始學習
|
| 170 |
+
</a>
|
| 171 |
+
</motion.div>
|
| 172 |
+
</div>
|
| 173 |
+
);
|
| 174 |
+
}
|
src/pages/Lesson1Page.tsx
ADDED
|
@@ -0,0 +1,534 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useState } from 'react';
|
| 2 |
+
import { motion } from 'framer-motion';
|
| 3 |
+
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
| 4 |
+
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
| 5 |
+
|
| 6 |
+
export default function Lesson1Page() {
|
| 7 |
+
const [activeSection, setActiveSection] = useState('intro');
|
| 8 |
+
|
| 9 |
+
const scrollToSection = (sectionId: string) => {
|
| 10 |
+
setActiveSection(sectionId);
|
| 11 |
+
const element = document.getElementById(sectionId);
|
| 12 |
+
if (element) {
|
| 13 |
+
element.scrollIntoView({ behavior: 'smooth' });
|
| 14 |
+
}
|
| 15 |
+
};
|
| 16 |
+
|
| 17 |
+
return (
|
| 18 |
+
<div className="flex flex-col md:flex-row gap-6">
|
| 19 |
+
{/* Sidebar Navigation */}
|
| 20 |
+
<div className="md:w-1/4 lg:w-1/5">
|
| 21 |
+
<div className="bg-white rounded-xl shadow-md p-6 sticky top-24">
|
| 22 |
+
<h3 className="text-lg font-bold text-gray-800 mb-4">課程目錄</h3>
|
| 23 |
+
<nav className="space-y-2">
|
| 24 |
+
<button
|
| 25 |
+
onClick={() => scrollToSection('intro')}
|
| 26 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 27 |
+
activeSection === 'intro'
|
| 28 |
+
? 'bg-blue-100 text-blue-700'
|
| 29 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 30 |
+
}`}
|
| 31 |
+
>
|
| 32 |
+
課程目標
|
| 33 |
+
</button>
|
| 34 |
+
<button
|
| 35 |
+
onClick={() => scrollToSection('part1')}
|
| 36 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 37 |
+
activeSection === 'part1'
|
| 38 |
+
? 'bg-blue-100 text-blue-700'
|
| 39 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 40 |
+
}`}
|
| 41 |
+
>
|
| 42 |
+
Roblox 平台介紹
|
| 43 |
+
</button>
|
| 44 |
+
<button
|
| 45 |
+
onClick={() => scrollToSection('part2')}
|
| 46 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 47 |
+
activeSection === 'part2'
|
| 48 |
+
? 'bg-blue-100 text-blue-700'
|
| 49 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 50 |
+
}`}
|
| 51 |
+
>
|
| 52 |
+
Roblox 基本操作
|
| 53 |
+
</button>
|
| 54 |
+
<button
|
| 55 |
+
onClick={() => scrollToSection('part3')}
|
| 56 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 57 |
+
activeSection === 'part3'
|
| 58 |
+
? 'bg-blue-100 text-blue-700'
|
| 59 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 60 |
+
}`}
|
| 61 |
+
>
|
| 62 |
+
Roblox Studio 環境熟悉
|
| 63 |
+
</button>
|
| 64 |
+
<button
|
| 65 |
+
onClick={() => scrollToSection('summary')}
|
| 66 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 67 |
+
activeSection === 'summary'
|
| 68 |
+
? 'bg-blue-100 text-blue-700'
|
| 69 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 70 |
+
}`}
|
| 71 |
+
>
|
| 72 |
+
總結與練習
|
| 73 |
+
</button>
|
| 74 |
+
</nav>
|
| 75 |
+
</div>
|
| 76 |
+
</div>
|
| 77 |
+
|
| 78 |
+
{/* Main Content */}
|
| 79 |
+
<div className="md:w-3/4 lg:w-4/5">
|
| 80 |
+
<motion.div
|
| 81 |
+
initial={{ opacity: 0 }}
|
| 82 |
+
animate={{ opacity: 1 }}
|
| 83 |
+
transition={{ duration: 0.5 }}
|
| 84 |
+
>
|
| 85 |
+
<div className="bg-gradient-to-r from-blue-600 to-purple-600 rounded-xl p-8 mb-8 text-white">
|
| 86 |
+
<h1 className="text-3xl md:text-4xl font-bold mb-4">Roblox 基礎入門 - 第一課</h1>
|
| 87 |
+
<p className="text-lg opacity-90">
|
| 88 |
+
從零開始學習 Roblox,了解平台基礎與 Studio 開發環境
|
| 89 |
+
</p>
|
| 90 |
+
</div>
|
| 91 |
+
|
| 92 |
+
{/* Course Objectives */}
|
| 93 |
+
<section id="intro" className="mb-12 scroll-mt-24">
|
| 94 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">課程目標</h2>
|
| 95 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 96 |
+
<p className="text-gray-700 mb-4">
|
| 97 |
+
本課程旨在幫助初學者了解 Roblox 平台的基本概念,掌握基本操作,並熟悉 Roblox Studio 開發環境。通過本課程,學員將能夠:
|
| 98 |
+
</p>
|
| 99 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 100 |
+
<li>了解 Roblox 平台的基本概念與特色</li>
|
| 101 |
+
<li>掌握 Roblox 平台的基本操作方式</li>
|
| 102 |
+
<li>熟悉 Roblox Studio 開發環境的界面與功能</li>
|
| 103 |
+
<li>創建一個簡單的 Roblox 場景</li>
|
| 104 |
+
</ul>
|
| 105 |
+
</div>
|
| 106 |
+
</section>
|
| 107 |
+
|
| 108 |
+
{/* Part 1: Roblox Platform Introduction */}
|
| 109 |
+
<section id="part1" className="mb-12 scroll-mt-24">
|
| 110 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第一部分:Roblox 平台介紹</h2>
|
| 111 |
+
|
| 112 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 113 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">Roblox 是什麼?</h3>
|
| 114 |
+
<p className="text-gray-700 mb-4">
|
| 115 |
+
Roblox 是一個全球性平台,���天有成千上萬人在這裡的沉浸式使用者創作 3D 世界裡一起想像、創作及分享體驗。在 Roblox 中,您可以找到各種類型的體驗,這些多樣化的體驗充分展現了創作者們廣闊的想像力。
|
| 116 |
+
</p>
|
| 117 |
+
<p className="text-gray-700 mb-4">
|
| 118 |
+
Roblox 的獨特之處在於,平台上所有的體驗和大部分虛擬人偶道具都是由全球社群創作的。這意味著 Roblox 不僅是一個遊戲平台,更是一個創作平台,讓使用者可以自由發揮創意,創造屬於自己的虛擬世界。
|
| 119 |
+
</p>
|
| 120 |
+
<div className="my-6 flex justify-center">
|
| 121 |
+
<img
|
| 122 |
+
src="/roblox-platform.webp"
|
| 123 |
+
alt="Roblox 平台介紹"
|
| 124 |
+
className="rounded-lg shadow-md max-w-full h-auto"
|
| 125 |
+
/>
|
| 126 |
+
</div>
|
| 127 |
+
</div>
|
| 128 |
+
|
| 129 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 130 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">Roblox 的特色</h3>
|
| 131 |
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
| 132 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 133 |
+
<h4 className="font-bold text-blue-800 mb-2">創作與分享</h4>
|
| 134 |
+
<p className="text-gray-700">
|
| 135 |
+
Roblox 允許使用者創建自己的遊戲和體驗,並與全球數百萬玩家分享。
|
| 136 |
+
</p>
|
| 137 |
+
</div>
|
| 138 |
+
<div className="bg-purple-50 p-4 rounded-lg">
|
| 139 |
+
<h4 className="font-bold text-purple-800 mb-2">社交互動</h4>
|
| 140 |
+
<p className="text-gray-700">
|
| 141 |
+
使用者可以與朋友一起遊玩,參與各種社交活動,建立虛擬社區。
|
| 142 |
+
</p>
|
| 143 |
+
</div>
|
| 144 |
+
<div className="bg-green-50 p-4 rounded-lg">
|
| 145 |
+
<h4 className="font-bold text-green-800 mb-2">跨平台體驗</h4>
|
| 146 |
+
<p className="text-gray-700">
|
| 147 |
+
Roblox 支援多種設備,包括電腦、手機、平板和遊戲主機,讓使用者可以隨時隨地享受 Roblox 體驗。
|
| 148 |
+
</p>
|
| 149 |
+
</div>
|
| 150 |
+
<div className="bg-yellow-50 p-4 rounded-lg">
|
| 151 |
+
<h4 className="font-bold text-yellow-800 mb-2">虛擬經濟系統</h4>
|
| 152 |
+
<p className="text-gray-700">
|
| 153 |
+
Roblox 擁有自己的虛擬貨幣 Robux,使用者可以通過創作內容賺取 Robux,甚至將其兌換為真實貨幣。
|
| 154 |
+
</p>
|
| 155 |
+
</div>
|
| 156 |
+
<div className="bg-pink-50 p-4 rounded-lg md:col-span-2">
|
| 157 |
+
<h4 className="font-bold text-pink-800 mb-2">持續更新與發展</h4>
|
| 158 |
+
<p className="text-gray-700">
|
| 159 |
+
Roblox 平台不斷推出新功能和工具,為創作者提供更多可能性。
|
| 160 |
+
</p>
|
| 161 |
+
</div>
|
| 162 |
+
</div>
|
| 163 |
+
</div>
|
| 164 |
+
|
| 165 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 166 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">Roblox 的應用領域</h3>
|
| 167 |
+
<p className="text-gray-700 mb-4">
|
| 168 |
+
除了娛樂,Roblox 也被廣泛應用於教育領域。許多教育工作者利用 Roblox 教授編程、設計和創意思維等技能。通過在 Roblox 上開發,使用者可以培養問題解決、團隊合作和程式編寫等重要能力,同時也能發展數理工科(STEM)技能。
|
| 169 |
+
</p>
|
| 170 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 171 |
+
<h4 className="font-bold text-blue-800 mb-2">教育價值</h4>
|
| 172 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 173 |
+
<li>培養程式設計思維</li>
|
| 174 |
+
<li>發展 3D 建模與空間思考能力</li>
|
| 175 |
+
<li>鍛煉創意解決問題的能力</li>
|
| 176 |
+
<li>學習團隊協作與專案管理</li>
|
| 177 |
+
<li>理解基本經濟概念與市場運作</li>
|
| 178 |
+
</ul>
|
| 179 |
+
</div>
|
| 180 |
+
</div>
|
| 181 |
+
</section>
|
| 182 |
+
|
| 183 |
+
{/* Part 2: Roblox Basic Operations */}
|
| 184 |
+
<section id="part2" className="mb-12 scroll-mt-24">
|
| 185 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第二部分:Roblox 基本操作</h2>
|
| 186 |
+
|
| 187 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 188 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">註冊與登入</h3>
|
| 189 |
+
<p className="text-gray-700 mb-4">
|
| 190 |
+
要開始使用 Roblox,首先需要創建一個帳號。訪問 <a href="https://www.roblox.com" target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:underline">Roblox 官網</a>,點擊「註冊」按鈕,填寫相關信息即可完成註冊。註冊後,您可以使用您的用戶名和密碼登入 Roblox 平台。
|
| 191 |
+
</p>
|
| 192 |
+
<div className="bg-yellow-50 p-4 rounded-lg">
|
| 193 |
+
<h4 className="font-bold text-yellow-800 mb-2">註冊提示</h4>
|
| 194 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 195 |
+
<li>選擇一個容易記住但難以猜測的密碼</li>
|
| 196 |
+
<li>使用真實的出生日期(這會影響帳號的安全設置)</li>
|
| 197 |
+
<li>考慮啟用雙重驗證以增強帳號安全性</li>
|
| 198 |
+
</ul>
|
| 199 |
+
</div>
|
| 200 |
+
</div>
|
| 201 |
+
|
| 202 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 203 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">探索 Roblox 平台</h3>
|
| 204 |
+
<p className="text-gray-700 mb-4">
|
| 205 |
+
登入後,您將看到 Roblox 的主頁面,這裡展示了推薦的遊戲和體驗。您可以通過頂部的導航欄訪問不同的頁面:
|
| 206 |
+
</p>
|
| 207 |
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
|
| 208 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 209 |
+
<h4 className="font-bold text-blue-800 mb-2">首頁</h4>
|
| 210 |
+
<p className="text-gray-700">顯示推薦的遊戲和體驗</p>
|
| 211 |
+
</div>
|
| 212 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 213 |
+
<h4 className="font-bold text-blue-800 mb-2">發現</h4>
|
| 214 |
+
<p className="text-gray-700">瀏覽不同類別的遊戲和體驗</p>
|
| 215 |
+
</div>
|
| 216 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 217 |
+
<h4 className="font-bold text-blue-800 mb-2">市場</h4>
|
| 218 |
+
<p className="text-gray-700">購買虛擬物品,如服裝、配件等</p>
|
| 219 |
+
</div>
|
| 220 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 221 |
+
<h4 className="font-bold text-blue-800 mb-2">創建</h4>
|
| 222 |
+
<p className="text-gray-700">訪問 Roblox Studio 和創作相關資源</p>
|
| 223 |
+
</div>
|
| 224 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 225 |
+
<h4 className="font-bold text-blue-800 mb-2">Robux</h4>
|
| 226 |
+
<p className="text-gray-700">購買和管理虛擬貨幣</p>
|
| 227 |
+
</div>
|
| 228 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 229 |
+
<h4 className="font-bold text-blue-800 mb-2">個人資料</h4>
|
| 230 |
+
<p className="text-gray-700">查看和編輯個人信息</p>
|
| 231 |
+
</div>
|
| 232 |
+
</div>
|
| 233 |
+
</div>
|
| 234 |
+
|
| 235 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 236 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">遊玩體驗</h3>
|
| 237 |
+
<p className="text-gray-700 mb-4">
|
| 238 |
+
在 Roblox 中遊玩體驗非常簡單:
|
| 239 |
+
</p>
|
| 240 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 241 |
+
<li>在首頁或發現頁面找到您感興趣的體驗</li>
|
| 242 |
+
<li>點擊體驗卡片進入詳情頁</li>
|
| 243 |
+
<li>點擊「遊玩」按鈕開始體驗</li>
|
| 244 |
+
<li>等待體驗加載完成後,您就可以開始遊玩了</li>
|
| 245 |
+
</ol>
|
| 246 |
+
</div>
|
| 247 |
+
|
| 248 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 249 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">基本控制</h3>
|
| 250 |
+
<p className="text-gray-700 mb-4">
|
| 251 |
+
在大多數 Roblox 體驗中,基本控制方式如下:
|
| 252 |
+
</p>
|
| 253 |
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
| 254 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 255 |
+
<h4 className="font-bold text-gray-800 mb-2">移動</h4>
|
| 256 |
+
<p className="text-gray-700">使用 W, A, S, D 鍵或方向鍵控制角色移動</p>
|
| 257 |
+
</div>
|
| 258 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 259 |
+
<h4 className="font-bold text-gray-800 mb-2">跳躍</h4>
|
| 260 |
+
<p className="text-gray-700">按空格鍵</p>
|
| 261 |
+
</div>
|
| 262 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 263 |
+
<h4 className="font-bold text-gray-800 mb-2">視角控制</h4>
|
| 264 |
+
<p className="text-gray-700">移動滑鼠來改變視角</p>
|
| 265 |
+
</div>
|
| 266 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 267 |
+
<h4 className="font-bold text-gray-800 mb-2">互動</h4>
|
| 268 |
+
<p className="text-gray-700">點擊滑鼠左鍵或按 E 鍵與物體互動(具體按鍵可能因體驗而異)</p>
|
| 269 |
+
</div>
|
| 270 |
+
</div>
|
| 271 |
+
</div>
|
| 272 |
+
|
| 273 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 274 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">社交功能</h3>
|
| 275 |
+
<p className="text-gray-700 mb-4">
|
| 276 |
+
Roblox 提供了豐富的社交功能,讓使用者可以與朋友互動:
|
| 277 |
+
</p>
|
| 278 |
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
| 279 |
+
<div className="bg-purple-50 p-4 rounded-lg">
|
| 280 |
+
<h4 className="font-bold text-purple-800 mb-2">添加好友</h4>
|
| 281 |
+
<p className="text-gray-700">訪問其他使用者的個人資料頁面,點擊「添加好友」按鈕</p>
|
| 282 |
+
</div>
|
| 283 |
+
<div className="bg-purple-50 p-4 rounded-lg">
|
| 284 |
+
<h4 className="font-bold text-purple-800 mb-2">聊天</h4>
|
| 285 |
+
<p className="text-gray-700">通過聊天功能與好友交流</p>
|
| 286 |
+
</div>
|
| 287 |
+
<div className="bg-purple-50 p-4 rounded-lg">
|
| 288 |
+
<h4 className="font-bold text-purple-800 mb-2">組隊</h4>
|
| 289 |
+
<p className="text-gray-700">邀請好友一起遊玩體驗</p>
|
| 290 |
+
</div>
|
| 291 |
+
<div className="bg-purple-50 p-4 rounded-lg">
|
| 292 |
+
<h4 className="font-bold text-purple-800 mb-2">加入群組</h4>
|
| 293 |
+
<p className="text-gray-700">參與社區活動,結識志同道合的玩家</p>
|
| 294 |
+
</div>
|
| 295 |
+
</div>
|
| 296 |
+
</div>
|
| 297 |
+
</section>
|
| 298 |
+
|
| 299 |
+
{/* Part 3: Roblox Studio Environment */}
|
| 300 |
+
<section id="part3" className="mb-12 scroll-mt-24">
|
| 301 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第三部分:Roblox Studio 環境熟悉</h2>
|
| 302 |
+
|
| 303 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 304 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">什麼是 Roblox Studio?</h3>
|
| 305 |
+
<p className="text-gray-700 mb-4">
|
| 306 |
+
Roblox Studio 是 Roblox 的官方開發工具,它允許創作者設計、構建和發布自己的 Roblox 體驗。無論您是初學者還是有經驗的開發者,Roblox Studio 都提供了豐富的工具和資源,幫助您實現創意。
|
| 307 |
+
</p>
|
| 308 |
+
<div className="my-6 flex justify-center">
|
| 309 |
+
<img
|
| 310 |
+
src="/roblox-studio.webp"
|
| 311 |
+
alt="Roblox Studio 介紹"
|
| 312 |
+
className="rounded-lg shadow-md max-w-full h-auto"
|
| 313 |
+
/>
|
| 314 |
+
</div>
|
| 315 |
+
</div>
|
| 316 |
+
|
| 317 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 318 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">安裝 Roblox Studio</h3>
|
| 319 |
+
<p className="text-gray-700 mb-4">
|
| 320 |
+
要開始使用 Roblox Studio,請按照以下步驟操作:
|
| 321 |
+
</p>
|
| 322 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 323 |
+
<li>訪問 <a href="https://www.roblox.com/create" target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:underline">Roblox 創建頁面</a></li>
|
| 324 |
+
<li>點擊「開始創建」按鈕</li>
|
| 325 |
+
<li>如果您尚未安裝 Roblox Studio,系統會提示您下載並安裝</li>
|
| 326 |
+
<li>安裝完成後,使用您的 Roblox 帳號登入 Studio</li>
|
| 327 |
+
</ol>
|
| 328 |
+
</div>
|
| 329 |
+
|
| 330 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 331 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">Roblox Studio 界面概覽</h3>
|
| 332 |
+
<p className="text-gray-700 mb-4">
|
| 333 |
+
首次打開 Roblox Studio 時,您會看到一個起始頁面,提供了多種模板供您選擇。選擇一個模板後,您將進入 Studio 的主界面,主要包括以下部分:
|
| 334 |
+
</p>
|
| 335 |
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
|
| 336 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 337 |
+
<h4 className="font-bold text-gray-800 mb-2">菜單欄</h4>
|
| 338 |
+
<p className="text-gray-700">位於頂部,包含文件、編輯、視圖等選項</p>
|
| 339 |
+
</div>
|
| 340 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 341 |
+
<h4 className="font-bold text-gray-800 mb-2">工具欄</h4>
|
| 342 |
+
<p className="text-gray-700">包含常用工具按鈕,如選擇、移動、縮放等</p>
|
| 343 |
+
</div>
|
| 344 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 345 |
+
<h4 className="font-bold text-gray-800 mb-2">資源管理器</h4>
|
| 346 |
+
<p className="text-gray-700">顯示場景中的所有物體和組件</p>
|
| 347 |
+
</div>
|
| 348 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 349 |
+
<h4 className="font-bold text-gray-800 mb-2">屬性面板</h4>
|
| 350 |
+
<p className="text-gray-700">顯示選中物體的屬性和設置</p>
|
| 351 |
+
</div>
|
| 352 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 353 |
+
<h4 className="font-bold text-gray-800 mb-2">工作區</h4>
|
| 354 |
+
<p className="text-gray-700">主要的 3D 編輯區域,您可以在這裡構建和編輯場景</p>
|
| 355 |
+
</div>
|
| 356 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 357 |
+
<h4 className="font-bold text-gray-800 mb-2">輸出窗口</h4>
|
| 358 |
+
<p className="text-gray-700">顯示腳本執行結果和錯誤信息</p>
|
| 359 |
+
</div>
|
| 360 |
+
</div>
|
| 361 |
+
</div>
|
| 362 |
+
|
| 363 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 364 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">基本工具使用</h3>
|
| 365 |
+
<p className="text-gray-700 mb-4">
|
| 366 |
+
Roblox Studio 提供了多種工具,幫助您創建和編輯場景:
|
| 367 |
+
</p>
|
| 368 |
+
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
|
| 369 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 370 |
+
<h4 className="font-bold text-blue-800 mb-2">選擇工具</h4>
|
| 371 |
+
<p className="text-gray-700">用於選擇場景中的物體</p>
|
| 372 |
+
</div>
|
| 373 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 374 |
+
<h4 className="font-bold text-blue-800 mb-2">移動工具</h4>
|
| 375 |
+
<p className="text-gray-700">用於移動物體的位置</p>
|
| 376 |
+
</div>
|
| 377 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 378 |
+
<h4 className="font-bold text-blue-800 mb-2">旋轉工具</h4>
|
| 379 |
+
<p className="text-gray-700">用於旋轉物體</p>
|
| 380 |
+
</div>
|
| 381 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 382 |
+
<h4 className="font-bold text-blue-800 mb-2">縮放工具</h4>
|
| 383 |
+
<p className="text-gray-700">用於調整物體的大小</p>
|
| 384 |
+
</div>
|
| 385 |
+
<div className="bg-blue-50 p-4 rounded-lg md:col-span-2">
|
| 386 |
+
<h4 className="font-bold text-blue-800 mb-2">部件工具</h4>
|
| 387 |
+
<p className="text-gray-700">用於創建基本形狀,如方塊、球體等</p>
|
| 388 |
+
</div>
|
| 389 |
+
</div>
|
| 390 |
+
</div>
|
| 391 |
+
|
| 392 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 393 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">創建簡單場景</h3>
|
| 394 |
+
<p className="text-gray-700 mb-4">
|
| 395 |
+
讓我們通過創建一個簡單的場景來熟悉 Roblox Studio 的基本操作:
|
| 396 |
+
</p>
|
| 397 |
+
<div className="space-y-4">
|
| 398 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 399 |
+
<h4 className="font-bold text-gray-800 mb-2">1. 創建新項目</h4>
|
| 400 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 401 |
+
<li>打開 Roblox Studio</li>
|
| 402 |
+
<li>選擇「基礎模板」創建新項目</li>
|
| 403 |
+
</ul>
|
| 404 |
+
</div>
|
| 405 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 406 |
+
<h4 className="font-bold text-gray-800 mb-2">2. 添加地形</h4>
|
| 407 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 408 |
+
<li>點擊「模型」選項卡</li>
|
| 409 |
+
<li>選擇「地形編輯器」</li>
|
| 410 |
+
<li>使用地形工具創建基本地形</li>
|
| 411 |
+
</ul>
|
| 412 |
+
</div>
|
| 413 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 414 |
+
<h4 className="font-bold text-gray-800 mb-2">3. 添加物體</h4>
|
| 415 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 416 |
+
<li>在工具欄中選擇「部件」工具</li>
|
| 417 |
+
<li>點擊工作區創建一個方塊</li>
|
| 418 |
+
<li>使用移動、旋轉和縮放工具調整方塊的位置和大小</li>
|
| 419 |
+
</ul>
|
| 420 |
+
</div>
|
| 421 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 422 |
+
<h4 className="font-bold text-gray-800 mb-2">4. 設置屬性</h4>
|
| 423 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 424 |
+
<li>在資源管理器中選擇創建的方塊</li>
|
| 425 |
+
<li>在屬性面板中修改顏色、材質等屬性</li>
|
| 426 |
+
</ul>
|
| 427 |
+
</div>
|
| 428 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 429 |
+
<h4 className="font-bold text-gray-800 mb-2">5. 測試場景</h4>
|
| 430 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 431 |
+
<li>點擊「播放」按鈕測試場景</li>
|
| 432 |
+
<li>使用 WASD 鍵和空格鍵控制角色移動和跳躍</li>
|
| 433 |
+
</ul>
|
| 434 |
+
</div>
|
| 435 |
+
<div className="bg-gray-50 p-4 rounded-lg">
|
| 436 |
+
<h4 className="font-bold text-gray-800 mb-2">6. 保存項目</h4>
|
| 437 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 438 |
+
<li>點擊「文件」{'>'}「保存」</li>
|
| 439 |
+
<li>輸入項目名稱並保存</li>
|
| 440 |
+
</ul>
|
| 441 |
+
</div>
|
| 442 |
+
</div>
|
| 443 |
+
</div>
|
| 444 |
+
|
| 445 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 446 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">發布體驗</h3>
|
| 447 |
+
<p className="text-gray-700 mb-4">
|
| 448 |
+
完成場景創建後,您可以將其發布到 Roblox 平台,與其他玩家分享:
|
| 449 |
+
</p>
|
| 450 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700">
|
| 451 |
+
<li>點擊「文件」{'>'}「發布到 Roblox」</li>
|
| 452 |
+
<li>設置體驗名稱、描述和縮略圖</li>
|
| 453 |
+
<li>選擇發布選項(公開或私人)</li>
|
| 454 |
+
<li>點擊「發布」按鈕</li>
|
| 455 |
+
</ol>
|
| 456 |
+
</div>
|
| 457 |
+
</section>
|
| 458 |
+
|
| 459 |
+
{/* Summary and Practice */}
|
| 460 |
+
<section id="summary" className="mb-12 scroll-mt-24">
|
| 461 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">總結</h2>
|
| 462 |
+
|
| 463 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 464 |
+
<p className="text-gray-700 mb-4">
|
| 465 |
+
在本課程中,我們介紹了 Roblox 平台的基本概念,學習了 Roblox 的基本操作方式,並熟悉了 Roblox Studio 開發環境。通過這些基礎知識,您已經具備了開始 Roblox 創作之旅的能力。
|
| 466 |
+
</p>
|
| 467 |
+
<p className="text-gray-700 mb-4">
|
| 468 |
+
在接下來的課程中,我們將深入探討 Roblox Studio 的更多功能,學習如何創建更複雜的場景,添加互動元素,以及使用 Lua 腳本為體驗添加邏輯和功能。
|
| 469 |
+
</p>
|
| 470 |
+
</div>
|
| 471 |
+
|
| 472 |
+
<div className="bg-gradient-to-r from-blue-50 to-purple-50 rounded-xl shadow-md p-6 mb-6">
|
| 473 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">練習任務</h3>
|
| 474 |
+
<p className="text-gray-700 mb-4">
|
| 475 |
+
為了鞏固所學知識,請嘗試完成以下任務:
|
| 476 |
+
</p>
|
| 477 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700">
|
| 478 |
+
<li>創建一個 Roblox 帳號並探索平台</li>
|
| 479 |
+
<li>遊玩至少三個不同類型的 Roblox 體驗</li>
|
| 480 |
+
<li>安裝 Roblox Studio 並熟悉界面</li>
|
| 481 |
+
<li>使用基礎模板創建一個簡單的場景,包含地形和至少三個不同的物體</li>
|
| 482 |
+
<li>測試您創建的場景並保存項目</li>
|
| 483 |
+
</ol>
|
| 484 |
+
</div>
|
| 485 |
+
|
| 486 |
+
<div className="bg-gradient-to-r from-green-50 to-blue-50 rounded-xl shadow-md p-6">
|
| 487 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">資源推薦</h3>
|
| 488 |
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
| 489 |
+
<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">
|
| 490 |
+
<h4 className="font-bold text-blue-800 mb-2">Roblox 開發者文檔</h4>
|
| 491 |
+
<p className="text-gray-700">官方開發文檔,包含詳細的 API 參考和教程</p>
|
| 492 |
+
</a>
|
| 493 |
+
<a href="https://education.roblox.com/" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
|
| 494 |
+
<h4 className="font-bold text-blue-800 mb-2">Roblox 教育資源</h4>
|
| 495 |
+
<p className="text-gray-700">專為教育者和學生設計的學習資源</p>
|
| 496 |
+
</a>
|
| 497 |
+
<a href="https://devforum.roblox.com/" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
|
| 498 |
+
<h4 className="font-bold text-blue-800 mb-2">Roblox 開發者論壇</h4>
|
| 499 |
+
<p className="text-gray-700">與其他開發者交流,獲取幫助和分享經驗</p>
|
| 500 |
+
</a>
|
| 501 |
+
<a href="https://www.youtube.com/channel/UCjiPEaapiHbJMoAdi_L8fNA" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
|
| 502 |
+
<h4 className="font-bold text-blue-800 mb-2">Roblox 開發者 YouTube 頻道</h4>
|
| 503 |
+
<p className="text-gray-700">官方視頻教程和開發者更新</p>
|
| 504 |
+
</a>
|
| 505 |
+
</div>
|
| 506 |
+
</div>
|
| 507 |
+
</section>
|
| 508 |
+
|
| 509 |
+
{/* Navigation Buttons */}
|
| 510 |
+
<div className="flex justify-between mt-12">
|
| 511 |
+
<a
|
| 512 |
+
href="/"
|
| 513 |
+
className="px-6 py-3 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition-colors flex items-center"
|
| 514 |
+
>
|
| 515 |
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
|
| 516 |
+
<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" />
|
| 517 |
+
</svg>
|
| 518 |
+
返回首頁
|
| 519 |
+
</a>
|
| 520 |
+
<a
|
| 521 |
+
href="/lesson2"
|
| 522 |
+
className="px-6 py-3 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors flex items-center"
|
| 523 |
+
>
|
| 524 |
+
下一課:賽車遊戲
|
| 525 |
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 ml-2" viewBox="0 0 20 20" fill="currentColor">
|
| 526 |
+
<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" />
|
| 527 |
+
</svg>
|
| 528 |
+
</a>
|
| 529 |
+
</div>
|
| 530 |
+
</motion.div>
|
| 531 |
+
</div>
|
| 532 |
+
</div>
|
| 533 |
+
);
|
| 534 |
+
}
|
src/pages/Lesson2Page.tsx
ADDED
|
@@ -0,0 +1,731 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useState } from 'react';
|
| 2 |
+
import { motion } from 'framer-motion';
|
| 3 |
+
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
| 4 |
+
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
| 5 |
+
|
| 6 |
+
const carControllerScript = `
|
| 7 |
+
-- 車輛控制腳本
|
| 8 |
+
-- 常數設定
|
| 9 |
+
local FORWARD_FORCE = 15000 -- 前進力量
|
| 10 |
+
local REVERSE_FORCE = 8000 -- 後退力量
|
| 11 |
+
local TURN_SPEED = 2.5 -- 轉向速度
|
| 12 |
+
local MAX_SPEED = 60 -- 最大速度 (studs/秒)
|
| 13 |
+
local BRAKE_FORCE = 10000 -- 剎車力量
|
| 14 |
+
|
| 15 |
+
-- 獲取車輛模型及其組件
|
| 16 |
+
local car = script.Parent
|
| 17 |
+
local body = car:WaitForChild("Body") -- 車身主體
|
| 18 |
+
local frontLeftWheel = car:WaitForChild("FrontLeftWheel")
|
| 19 |
+
local frontRightWheel = car:WaitForChild("FrontRightWheel")
|
| 20 |
+
local rearLeftWheel = car:WaitForChild("RearLeftWheel")
|
| 21 |
+
local rearRightWheel = car:WaitForChild("RearRightWheel")
|
| 22 |
+
|
| 23 |
+
-- 獲取車輪連接點
|
| 24 |
+
local flHinge = car:WaitForChild("FLHinge")
|
| 25 |
+
local frHinge = car:WaitForChild("FRHinge")
|
| 26 |
+
local rlHinge = car:WaitForChild("RLHinge")
|
| 27 |
+
local rrHinge = car:WaitForChild("RRHinge")
|
| 28 |
+
|
| 29 |
+
-- 設置車輛控制
|
| 30 |
+
local vehicleSeat = car:WaitForChild("VehicleSeat")
|
| 31 |
+
|
| 32 |
+
-- 當玩家進入車輛時
|
| 33 |
+
vehicleSeat.Changed:Connect(function(property)
|
| 34 |
+
if property == "Occupant" then
|
| 35 |
+
local player = vehicleSeat.Occupant
|
| 36 |
+
if player then
|
| 37 |
+
-- 玩家進入車輛
|
| 38 |
+
print("玩家進入車輛")
|
| 39 |
+
else
|
| 40 |
+
-- 玩家離開車輛
|
| 41 |
+
print("玩家離開車輛")
|
| 42 |
+
end
|
| 43 |
+
end
|
| 44 |
+
end)
|
| 45 |
+
|
| 46 |
+
-- 主要控制循環
|
| 47 |
+
game:GetService("RunService").Heartbeat:Connect(function(deltaTime)
|
| 48 |
+
if not vehicleSeat.Occupant then return end
|
| 49 |
+
|
| 50 |
+
local throttle = vehicleSeat.ThrottleFloat -- -1 到 1 之間的值
|
| 51 |
+
local steer = vehicleSeat.SteerFloat -- -1 到 1 之間的值
|
| 52 |
+
|
| 53 |
+
-- 計算車輛當前速度
|
| 54 |
+
local velocity = body.Velocity
|
| 55 |
+
local speed = velocity.Magnitude
|
| 56 |
+
|
| 57 |
+
-- 應用前進/後退力量
|
| 58 |
+
local forceVector = body.CFrame.LookVector
|
| 59 |
+
local force = Vector3.new(0, 0, 0)
|
| 60 |
+
|
| 61 |
+
if throttle > 0 then
|
| 62 |
+
-- 前進
|
| 63 |
+
force = forceVector * FORWARD_FORCE * throttle
|
| 64 |
+
elseif throttle < 0 then
|
| 65 |
+
-- 後退
|
| 66 |
+
force = forceVector * -REVERSE_FORCE * math.abs(throttle)
|
| 67 |
+
end
|
| 68 |
+
|
| 69 |
+
-- 限制最大速度
|
| 70 |
+
if speed > MAX_SPEED and throttle > 0 then
|
| 71 |
+
force = Vector3.new(0, 0, 0)
|
| 72 |
+
end
|
| 73 |
+
|
| 74 |
+
-- 應用轉向
|
| 75 |
+
local turnAngle = steer * TURN_SPEED * deltaTime
|
| 76 |
+
if math.abs(throttle) > 0.1 then -- 只有在移動時才轉向
|
| 77 |
+
body.CFrame = body.CFrame * CFrame.Angles(0, turnAngle, 0)
|
| 78 |
+
end
|
| 79 |
+
|
| 80 |
+
-- 應用力量到車身
|
| 81 |
+
body:ApplyForce(force)
|
| 82 |
+
|
| 83 |
+
-- 旋轉車輪
|
| 84 |
+
local wheelRotationSpeed = speed * 0.5
|
| 85 |
+
if throttle > 0 then
|
| 86 |
+
-- 前進時車輪正向旋轉
|
| 87 |
+
flHinge.AngularVelocity = wheelRotationSpeed
|
| 88 |
+
frHinge.AngularVelocity = wheelRotationSpeed
|
| 89 |
+
rlHinge.AngularVelocity = wheelRotationSpeed
|
| 90 |
+
rrHinge.AngularVelocity = wheelRotationSpeed
|
| 91 |
+
elseif throttle < 0 then
|
| 92 |
+
-- 後退時車輪反向旋轉
|
| 93 |
+
flHinge.AngularVelocity = -wheelRotationSpeed
|
| 94 |
+
frHinge.AngularVelocity = -wheelRotationSpeed
|
| 95 |
+
rlHinge.AngularVelocity = -wheelRotationSpeed
|
| 96 |
+
rrHinge.AngularVelocity = -wheelRotationSpeed
|
| 97 |
+
else
|
| 98 |
+
-- 停止時車輪不旋轉
|
| 99 |
+
flHinge.AngularVelocity = 0
|
| 100 |
+
frHinge.AngularVelocity = 0
|
| 101 |
+
rlHinge.AngularVelocity = 0
|
| 102 |
+
rrHinge.AngularVelocity = 0
|
| 103 |
+
end
|
| 104 |
+
|
| 105 |
+
-- 轉向前輪
|
| 106 |
+
frontLeftWheel.CFrame = frontLeftWheel.CFrame * CFrame.Angles(0, steer * 0.5, 0)
|
| 107 |
+
frontRightWheel.CFrame = frontRightWheel.CFrame * CFrame.Angles(0, steer * 0.5, 0)
|
| 108 |
+
end)
|
| 109 |
+
|
| 110 |
+
-- 設置攝影機
|
| 111 |
+
local function setupCamera(player)
|
| 112 |
+
local character = player.Character or player.CharacterAdded:Wait()
|
| 113 |
+
local humanoid = character:WaitForChild("Humanoid")
|
| 114 |
+
|
| 115 |
+
-- 設置第三人稱攝影機
|
| 116 |
+
humanoid.CameraOffset = Vector3.new(0, 2, 0)
|
| 117 |
+
end
|
| 118 |
+
|
| 119 |
+
vehicleSeat.Changed:Connect(function(property)
|
| 120 |
+
if property == "Occupant" and vehicleSeat.Occupant then
|
| 121 |
+
local player = game.Players:GetPlayerFromCharacter(vehicleSeat.Occupant.Parent)
|
| 122 |
+
if player then
|
| 123 |
+
setupCamera(player)
|
| 124 |
+
end
|
| 125 |
+
end
|
| 126 |
+
end)
|
| 127 |
+
`;
|
| 128 |
+
|
| 129 |
+
const scoringSystemScript = `
|
| 130 |
+
-- 計分系統腳本
|
| 131 |
+
-- 常數設定
|
| 132 |
+
local CHECKPOINTS_TO_COMPLETE = 8 -- 完成一圈所需的檢查點數量
|
| 133 |
+
local FINISH_MESSAGE = "恭喜完成比賽!"
|
| 134 |
+
|
| 135 |
+
-- 服務引用
|
| 136 |
+
local Players = game:GetService("Players")
|
| 137 |
+
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
| 138 |
+
|
| 139 |
+
-- 創建遠端事件用於更新UI
|
| 140 |
+
local checkpointEvent = Instance.new("RemoteEvent")
|
| 141 |
+
checkpointEvent.Name = "CheckpointEvent"
|
| 142 |
+
checkpointEvent.Parent = ReplicatedStorage
|
| 143 |
+
|
| 144 |
+
-- 玩家數據儲存
|
| 145 |
+
local playerData = {}
|
| 146 |
+
|
| 147 |
+
-- 初始化玩家數據
|
| 148 |
+
local function initPlayerData(player)
|
| 149 |
+
playerData[player.UserId] = {
|
| 150 |
+
checkpointsPassed = 0,
|
| 151 |
+
lastCheckpoint = 0,
|
| 152 |
+
raceCompleted = false,
|
| 153 |
+
startTime = 0,
|
| 154 |
+
finishTime = 0
|
| 155 |
+
}
|
| 156 |
+
end
|
| 157 |
+
|
| 158 |
+
-- 當玩家加入遊戲時
|
| 159 |
+
Players.PlayerAdded:Connect(function(player)
|
| 160 |
+
initPlayerData(player)
|
| 161 |
+
|
| 162 |
+
-- 創建計分UI
|
| 163 |
+
local scoreGui = Instance.new("ScreenGui")
|
| 164 |
+
scoreGui.Name = "RaceScoreGui"
|
| 165 |
+
|
| 166 |
+
local frame = Instance.new("Frame")
|
| 167 |
+
frame.Size = UDim2.new(0, 200, 0, 100)
|
| 168 |
+
frame.Position = UDim2.new(0.85, -100, 0, 10)
|
| 169 |
+
frame.BackgroundTransparency = 0.5
|
| 170 |
+
frame.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
|
| 171 |
+
frame.Parent = scoreGui
|
| 172 |
+
|
| 173 |
+
local checkpointLabel = Instance.new("TextLabel")
|
| 174 |
+
checkpointLabel.Name = "CheckpointLabel"
|
| 175 |
+
checkpointLabel.Size = UDim2.new(1, 0, 0.5, 0)
|
| 176 |
+
checkpointLabel.Text = "檢查點: 0/" .. CHECKPOINTS_TO_COMPLETE
|
| 177 |
+
checkpointLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
|
| 178 |
+
checkpointLabel.BackgroundTransparency = 1
|
| 179 |
+
checkpointLabel.Parent = frame
|
| 180 |
+
|
| 181 |
+
local timeLabel = Instance.new("TextLabel")
|
| 182 |
+
timeLabel.Name = "TimeLabel"
|
| 183 |
+
timeLabel.Size = UDim2.new(1, 0, 0.5, 0)
|
| 184 |
+
timeLabel.Position = UDim2.new(0, 0, 0.5, 0)
|
| 185 |
+
timeLabel.Text = "時間: 0.00"
|
| 186 |
+
timeLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
|
| 187 |
+
timeLabel.BackgroundTransparency = 1
|
| 188 |
+
timeLabel.Parent = frame
|
| 189 |
+
|
| 190 |
+
scoreGui.Parent = player.PlayerGui
|
| 191 |
+
|
| 192 |
+
-- 當玩家角色加入時
|
| 193 |
+
player.CharacterAdded:Connect(function(character)
|
| 194 |
+
-- 重置玩家數據
|
| 195 |
+
initPlayerData(player)
|
| 196 |
+
|
| 197 |
+
-- 更新UI
|
| 198 |
+
checkpointEvent:FireClient(player, "reset", 0, CHECKPOINTS_TO_COMPLETE)
|
| 199 |
+
end)
|
| 200 |
+
end)
|
| 201 |
+
|
| 202 |
+
-- 當玩家離開遊戲時
|
| 203 |
+
Players.PlayerRemoving:Connect(function(player)
|
| 204 |
+
playerData[player.UserId] = nil
|
| 205 |
+
end)
|
| 206 |
+
|
| 207 |
+
-- 設置檢查點觸發器
|
| 208 |
+
local function setupCheckpoint(checkpoint, checkpointNumber)
|
| 209 |
+
checkpoint.Touched:Connect(function(hit)
|
| 210 |
+
local character = hit.Parent
|
| 211 |
+
local player = Players:GetPlayerFromCharacter(character)
|
| 212 |
+
|
| 213 |
+
if player and not playerData[player.UserId].raceCompleted then
|
| 214 |
+
local data = playerData[player.UserId]
|
| 215 |
+
|
| 216 |
+
-- 確保檢查點按順序通過
|
| 217 |
+
if checkpointNumber == (data.lastCheckpoint % CHECKPOINTS_TO_COMPLETE) + 1 then
|
| 218 |
+
data.checkpointsPassed = data.checkpointsPassed + 1
|
| 219 |
+
data.lastCheckpoint = checkpointNumber
|
| 220 |
+
|
| 221 |
+
-- 如果是第一個檢查點且剛開始比賽,記錄開始時間
|
| 222 |
+
if checkpointNumber == 1 and data.startTime == 0 then
|
| 223 |
+
data.startTime = tick()
|
| 224 |
+
end
|
| 225 |
+
|
| 226 |
+
-- 更新UI
|
| 227 |
+
checkpointEvent:FireClient(player, "update", data.checkpointsPassed, CHECKPOINTS_TO_COMPLETE)
|
| 228 |
+
|
| 229 |
+
-- 檢查是否完成比賽 (完成一圈8字形)
|
| 230 |
+
if data.checkpointsPassed >= CHECKPOINTS_TO_COMPLETE then
|
| 231 |
+
data.raceCompleted = true
|
| 232 |
+
data.finishTime = tick() - data.startTime
|
| 233 |
+
|
| 234 |
+
-- 通知玩家完成比賽
|
| 235 |
+
checkpointEvent:FireClient(player, "complete", data.finishTime)
|
| 236 |
+
|
| 237 |
+
-- 顯示完成訊息
|
| 238 |
+
game.StarterGui:SetCore("ChatMakeSystemMessage", {
|
| 239 |
+
Text = FINISH_MESSAGE .. "\\n完成時間: " .. string.format("%.2f", data.finishTime) .. " 秒",
|
| 240 |
+
Color = Color3.fromRGB(0, 255, 0),
|
| 241 |
+
Font = Enum.Font.SourceSansBold
|
| 242 |
+
})
|
| 243 |
+
end
|
| 244 |
+
end
|
| 245 |
+
end
|
| 246 |
+
end)
|
| 247 |
+
end
|
| 248 |
+
|
| 249 |
+
-- 尋找並設置所有檢查點
|
| 250 |
+
local function setupAllCheckpoints()
|
| 251 |
+
local checkpoints = workspace:FindFirstChild("Checkpoints")
|
| 252 |
+
if checkpoints then
|
| 253 |
+
for i, checkpoint in ipairs(checkpoints:GetChildren()) do
|
| 254 |
+
if checkpoint:IsA("BasePart") and checkpoint.Name:match("Checkpoint%d+") then
|
| 255 |
+
local number = tonumber(checkpoint.Name:match("%d+"))
|
| 256 |
+
if number then
|
| 257 |
+
setupCheckpoint(checkpoint, number)
|
| 258 |
+
end
|
| 259 |
+
end
|
| 260 |
+
end
|
| 261 |
+
else
|
| 262 |
+
warn("找不到檢查點資料夾!請確保在工作區中有一個名為 'Checkpoints' 的資料夾,其中包含命名為 'Checkpoint1', 'Checkpoint2' 等的檢查點。")
|
| 263 |
+
end
|
| 264 |
+
end
|
| 265 |
+
|
| 266 |
+
-- 設置客戶端UI更新
|
| 267 |
+
local function setupClientUI()
|
| 268 |
+
local clientScript = Instance.new("LocalScript")
|
| 269 |
+
clientScript.Name = "RaceUIUpdater"
|
| 270 |
+
|
| 271 |
+
clientScript.Source = [[
|
| 272 |
+
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
| 273 |
+
local checkpointEvent = ReplicatedStorage:WaitForChild("CheckpointEvent")
|
| 274 |
+
local player = game.Players.LocalPlayer
|
| 275 |
+
local scoreGui = player.PlayerGui:WaitForChild("RaceScoreGui")
|
| 276 |
+
local frame = scoreGui:WaitForChild("Frame")
|
| 277 |
+
local checkpointLabel = frame:WaitForChild("CheckpointLabel")
|
| 278 |
+
local timeLabel = frame:WaitForChild("TimeLabel")
|
| 279 |
+
|
| 280 |
+
local startTime = 0
|
| 281 |
+
local isRacing = false
|
| 282 |
+
|
| 283 |
+
-- 更新時間顯示
|
| 284 |
+
game:GetService("RunService").RenderStepped:Connect(function()
|
| 285 |
+
if isRacing and startTime > 0 then
|
| 286 |
+
local currentTime = tick() - startTime
|
| 287 |
+
timeLabel.Text = "時間: " .. string.format("%.2f", currentTime)
|
| 288 |
+
end
|
| 289 |
+
end)
|
| 290 |
+
|
| 291 |
+
-- 處理檢查點事件
|
| 292 |
+
checkpointEvent.OnClientEvent:Connect(function(action, value, total)
|
| 293 |
+
if action == "update" then
|
| 294 |
+
checkpointLabel.Text = "檢查點: " .. value .. "/" .. total
|
| 295 |
+
|
| 296 |
+
-- 如果是第一個檢查點,開始計時
|
| 297 |
+
if value == 1 and not isRacing then
|
| 298 |
+
startTime = tick()
|
| 299 |
+
isRacing = true
|
| 300 |
+
end
|
| 301 |
+
elseif action == "complete" then
|
| 302 |
+
isRacing = false
|
| 303 |
+
timeLabel.Text = "完成時間: " .. string.format("%.2f", value)
|
| 304 |
+
checkpointLabel.TextColor3 = Color3.fromRGB(0, 255, 0)
|
| 305 |
+
timeLabel.TextColor3 = Color3.fromRGB(0, 255, 0)
|
| 306 |
+
elseif action == "reset" then
|
| 307 |
+
isRacing = false
|
| 308 |
+
startTime = 0
|
| 309 |
+
checkpointLabel.Text = "檢查點: 0/" .. total
|
| 310 |
+
timeLabel.Text = "時間: 0.00"
|
| 311 |
+
checkpointLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
|
| 312 |
+
timeLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
|
| 313 |
+
end
|
| 314 |
+
end)
|
| 315 |
+
]]
|
| 316 |
+
|
| 317 |
+
clientScript.Parent = ReplicatedStorage
|
| 318 |
+
end
|
| 319 |
+
|
| 320 |
+
-- 初始化
|
| 321 |
+
setupAllCheckpoints()
|
| 322 |
+
setupClientUI()
|
| 323 |
+
|
| 324 |
+
print("賽車計分系統已初始化!")
|
| 325 |
+
`;
|
| 326 |
+
|
| 327 |
+
export default function Lesson2Page() {
|
| 328 |
+
const [activeSection, setActiveSection] = useState('intro');
|
| 329 |
+
|
| 330 |
+
const scrollToSection = (sectionId: string) => {
|
| 331 |
+
setActiveSection(sectionId);
|
| 332 |
+
const element = document.getElementById(sectionId);
|
| 333 |
+
if (element) {
|
| 334 |
+
element.scrollIntoView({ behavior: 'smooth' });
|
| 335 |
+
}
|
| 336 |
+
};
|
| 337 |
+
|
| 338 |
+
return (
|
| 339 |
+
<div className="flex flex-col md:flex-row gap-6">
|
| 340 |
+
{/* Sidebar Navigation */}
|
| 341 |
+
<div className="md:w-1/4 lg:w-1/5">
|
| 342 |
+
<div className="bg-white rounded-xl shadow-md p-6 sticky top-24">
|
| 343 |
+
<h3 className="text-lg font-bold text-gray-800 mb-4">課程目錄</h3>
|
| 344 |
+
<nav className="space-y-2">
|
| 345 |
+
<button
|
| 346 |
+
onClick={() => scrollToSection('intro')}
|
| 347 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 348 |
+
activeSection === 'intro'
|
| 349 |
+
? 'bg-green-100 text-green-700'
|
| 350 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 351 |
+
}`}
|
| 352 |
+
>
|
| 353 |
+
課程簡介
|
| 354 |
+
</button>
|
| 355 |
+
<button
|
| 356 |
+
onClick={() => scrollToSection('part1')}
|
| 357 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 358 |
+
activeSection === 'part1'
|
| 359 |
+
? 'bg-green-100 text-green-700'
|
| 360 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 361 |
+
}`}
|
| 362 |
+
>
|
| 363 |
+
賽車模型建構
|
| 364 |
+
</button>
|
| 365 |
+
<button
|
| 366 |
+
onClick={() => scrollToSection('part2')}
|
| 367 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 368 |
+
activeSection === 'part2'
|
| 369 |
+
? 'bg-green-100 text-green-700'
|
| 370 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 371 |
+
}`}
|
| 372 |
+
>
|
| 373 |
+
8字形賽道設計
|
| 374 |
+
</button>
|
| 375 |
+
<button
|
| 376 |
+
onClick={() => scrollToSection('part3')}
|
| 377 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 378 |
+
activeSection === 'part3'
|
| 379 |
+
? 'bg-green-100 text-green-700'
|
| 380 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 381 |
+
}`}
|
| 382 |
+
>
|
| 383 |
+
車輛控制系統
|
| 384 |
+
</button>
|
| 385 |
+
<button
|
| 386 |
+
onClick={() => scrollToSection('part4')}
|
| 387 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 388 |
+
activeSection === 'part4'
|
| 389 |
+
? 'bg-green-100 text-green-700'
|
| 390 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 391 |
+
}`}
|
| 392 |
+
>
|
| 393 |
+
計分系統
|
| 394 |
+
</button>
|
| 395 |
+
<button
|
| 396 |
+
onClick={() => scrollToSection('part5')}
|
| 397 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 398 |
+
activeSection === 'part5'
|
| 399 |
+
? 'bg-green-100 text-green-700'
|
| 400 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 401 |
+
}`}
|
| 402 |
+
>
|
| 403 |
+
完善與匯出
|
| 404 |
+
</button>
|
| 405 |
+
<button
|
| 406 |
+
onClick={() => scrollToSection('summary')}
|
| 407 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 408 |
+
activeSection === 'summary'
|
| 409 |
+
? 'bg-green-100 text-green-700'
|
| 410 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 411 |
+
}`}
|
| 412 |
+
>
|
| 413 |
+
總結與挑戰
|
| 414 |
+
</button>
|
| 415 |
+
</nav>
|
| 416 |
+
</div>
|
| 417 |
+
</div>
|
| 418 |
+
|
| 419 |
+
{/* Main Content */}
|
| 420 |
+
<div className="md:w-3/4 lg:w-4/5">
|
| 421 |
+
<motion.div
|
| 422 |
+
initial={{ opacity: 0 }}
|
| 423 |
+
animate={{ opacity: 1 }}
|
| 424 |
+
transition={{ duration: 0.5 }}
|
| 425 |
+
>
|
| 426 |
+
<div className="bg-gradient-to-r from-green-600 to-teal-600 rounded-xl p-8 mb-8 text-white">
|
| 427 |
+
<h1 className="text-3xl md:text-4xl font-bold mb-4">Roblox 基礎入門第二課 - 創造我的世界:賽車遊戲學習</h1>
|
| 428 |
+
<p className="text-lg opacity-90">
|
| 429 |
+
學習建構賽車模型、設計賽道、編寫控制腳本與計分系統
|
| 430 |
+
</p>
|
| 431 |
+
</div>
|
| 432 |
+
|
| 433 |
+
{/* Course Introduction */}
|
| 434 |
+
<section id="intro" className="mb-12 scroll-mt-24">
|
| 435 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">課程簡介</h2>
|
| 436 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 437 |
+
<p className="text-gray-700 mb-4">
|
| 438 |
+
本課程將帶領學習者建構一個完整的賽車遊戲,包含四輪車模型、8字形賽道、車輛控制系統與計分機制。通過實際操作,學習者將掌握 Roblox Studio 中的模型建構、程式控制與遊戲機制設計等核心技能。
|
| 439 |
+
</p>
|
| 440 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">課程目標</h3>
|
| 441 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 442 |
+
<li>在 Roblox Studio 中建構可操作的四輪車模型</li>
|
| 443 |
+
<li>設計並實現 8 字形賽道與檢查點系統</li>
|
| 444 |
+
<li>編寫車輛控制腳本,實現前進、後退、左右轉向功能</li>
|
| 445 |
+
<li>設計計分機制,追蹤賽車完成圈數並判定比賽完成</li>
|
| 446 |
+
</ul>
|
| 447 |
+
<h3 className="text-xl font-bold text-green-700 mt-6 mb-3">前置準備</h3>
|
| 448 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 449 |
+
<li>已安裝最新版本的 Roblox Studio</li>
|
| 450 |
+
<li>具備 Roblox Studio 基本操作能力(第一課內容)</li>
|
| 451 |
+
<li>了解基本的 Lua 程式語法</li>
|
| 452 |
+
</ul>
|
| 453 |
+
</div>
|
| 454 |
+
</section>
|
| 455 |
+
|
| 456 |
+
{/* Part 1: Car Model Construction */}
|
| 457 |
+
<section id="part1" className="mb-12 scroll-mt-24">
|
| 458 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第一部分:賽車模型建構</h2>
|
| 459 |
+
|
| 460 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 461 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 1:創建新專案</h3>
|
| 462 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700">
|
| 463 |
+
<li>打開 Roblox Studio</li>
|
| 464 |
+
<li>選擇「基礎模板」創建新專案</li>
|
| 465 |
+
<li>保存專案,命名為「RaceCarGame」</li>
|
| 466 |
+
</ol>
|
| 467 |
+
</div>
|
| 468 |
+
|
| 469 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 470 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 2:建立車身基本結構</h3>
|
| 471 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 472 |
+
<li>在工作區中插入一個方塊部件(Part)</li>
|
| 473 |
+
<li>調整車身尺寸與位置:Size: 6, 2, 10 (寬, 高, 長), Position: 0, 3, 0 (X, Y, Z), 命名為「Body」</li>
|
| 474 |
+
<li>設置車身外觀:選擇喜歡的顏色, Material: SmoothPlastic, Anchored: false</li>
|
| 475 |
+
<li>設置物理屬性:CanCollide: true, Massless: false, CustomPhysicalProperties: true (Density: 1, Friction: 0.3, Elasticity: 0.2)</li>
|
| 476 |
+
</ol>
|
| 477 |
+
</div>
|
| 478 |
+
|
| 479 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 480 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 3:創建車輪</h3>
|
| 481 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 482 |
+
<li>創建前左輪:插入圓柱體(Cylinder), Size: 2, 0.5, 2, Position: -3, 2, 3.5, Orientation: 0, 0, 90, 命名為「FrontLeftWheel」</li>
|
| 483 |
+
<li>創建前右輪:複製前左輪, Position: 3, 2, 3.5, 命名為「FrontRightWheel」</li>
|
| 484 |
+
<li>創建後左輪:複製前左輪, Position: -3, 2, -3.5, 命名為「RearLeftWheel」</li>
|
| 485 |
+
<li>創建後右輪:複製前左輪, Position: 3, 2, -3.5, 命名為「RearRightWheel」</li>
|
| 486 |
+
<li>設置車輪外觀:Color: 黑色, Material: Rubber, CanCollide: true</li>
|
| 487 |
+
</ol>
|
| 488 |
+
</div>
|
| 489 |
+
|
| 490 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 491 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 4:連接車輪與車身</h3>
|
| 492 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 493 |
+
<li>創建前左輪連接點:使用 HingeConstraint, Attachment0 連接 Body, Attachment1 連接 FrontLeftWheel, 命名為「FLHinge」</li>
|
| 494 |
+
<li>設置前左輪連接點屬性:ActuatorType: Motor, AngularVelocity: 0, MotorMaxTorque: 1000</li>
|
| 495 |
+
<li>重複上述步驟,為其他三個車輪創建連接點 (FRHinge, RLHinge, RRHinge)</li>
|
| 496 |
+
</ol>
|
| 497 |
+
</div>
|
| 498 |
+
|
| 499 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 500 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 5:添加車身細節</h3>
|
| 501 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700 mb-4">
|
| 502 |
+
<li>創建擋風玻璃:使用方塊部件, 設置大小、位置、顏色(淺藍)、透明度(0.5)、材質(Glass)</li>
|
| 503 |
+
<li>創建前燈:使用兩個小方塊部件, 放置在車身前部, 設置顏色(黃/白), 可選添加 PointLight</li>
|
| 504 |
+
<li>創建後燈:使用兩個小方塊部件, 放置在車身後部, 設置顏色(紅)</li>
|
| 505 |
+
<li>創建座椅與方向盤:使用方塊和圓環部件</li>
|
| 506 |
+
</ul>
|
| 507 |
+
</div>
|
| 508 |
+
|
| 509 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 510 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 6:添加駕駛座</h3>
|
| 511 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 512 |
+
<li>插入 VehicleSeat:放置在車身上方中央, 命名為「VehicleSeat」</li>
|
| 513 |
+
<li>設置 VehicleSeat 屬性:MaxSpeed: 60, Torque: 200, TurnSpeed: 2.5</li>
|
| 514 |
+
<li>將所有部件組織到一個模型中:選中所有部件, 右鍵「Group」, 命名為「RaceCar」</li>
|
| 515 |
+
</ol>
|
| 516 |
+
</div>
|
| 517 |
+
</section>
|
| 518 |
+
|
| 519 |
+
{/* Part 2: Figure-8 Track Design */}
|
| 520 |
+
<section id="part2" className="mb-12 scroll-mt-24">
|
| 521 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第二部分:8字形賽道設計</h2>
|
| 522 |
+
|
| 523 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 524 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 1:規劃賽道布局</h3>
|
| 525 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 526 |
+
<li>創建賽道基礎平面:插入大型方塊部件, Size: 100, 1, 100, Position: 0, 0, 0, Color: 綠色, Material: Grass, Anchored: true</li>
|
| 527 |
+
<li>規劃 8 字形賽道路徑:在基礎平面上方繪製, 確保寬度足夠(12-15 studs), 彎道半徑適當</li>
|
| 528 |
+
</ol>
|
| 529 |
+
</div>
|
| 530 |
+
|
| 531 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 532 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 2:建構賽道</h3>
|
| 533 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 534 |
+
<li>創建賽道部件:使用多個方塊部件組合成 8 字形, 設置大小、位置、顏色(灰色)、材質(Concrete)、Anchored: true</li>
|
| 535 |
+
<li>使用 Union 工具合併賽道部件...賽道部件, 點擊「Model」{'>'}「Union」, 命名為「Track...</li>
|
| 536 |
+
</ol>
|
| 537 |
+
</div>
|
| 538 |
+
|
| 539 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 540 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 3:添加賽道邊界</h3>
|
| 541 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 542 |
+
<li>創建護欄:沿賽道外圍放置方塊部件, 設置大小、顏色(紅白相間)、材質(SmoothPlastic)、Anchored: true</li>
|
| 543 |
+
<li>調整彎道處的護欄:使用多個小段護欄拼接, 確保護欄緊貼賽道邊緣</li>
|
| 544 |
+
</ol>
|
| 545 |
+
</div>
|
| 546 |
+
|
| 547 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 548 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 4:創建檢查點系統</h3>
|
| 549 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 550 |
+
<li>創建檢查點資料夾:在工作區創建 Folder, 命名為「Checkpoints」</li>
|
| 551 |
+
<li>創建檢查點觸發器:在關鍵位置插入方塊部件, Size: 賽道寬度, 5, 1, Transparency: 0.8, CanCollide: false, 命名為「Checkpoint1」、「Checkpoint2」等, 按順序排列</li>
|
| 552 |
+
<li>創建起點/終點線:在賽道上創建明顯的起點/終點線, 與第一個檢查點重合</li>
|
| 553 |
+
</ol>
|
| 554 |
+
</div>
|
| 555 |
+
</section>
|
| 556 |
+
|
| 557 |
+
{/* Part 3: Vehicle Control System */}
|
| 558 |
+
<section id="part3" className="mb-12 scroll-mt-24">
|
| 559 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第三部分:車輛控制系統</h2>
|
| 560 |
+
|
| 561 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 562 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 1:創建車輛控制腳本</h3>
|
| 563 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 564 |
+
<li>在 RaceCar 模型中添加腳本, 命名為「CarController」</li>
|
| 565 |
+
<li>編寫車輛控制腳本(見下方代碼)</li>
|
| 566 |
+
<li>保存腳本</li>
|
| 567 |
+
</ol>
|
| 568 |
+
<SyntaxHighlighter language="lua" style={vscDarkPlus} className="rounded-lg">
|
| 569 |
+
{carControllerScript}
|
| 570 |
+
</SyntaxHighlighter>
|
| 571 |
+
</div>
|
| 572 |
+
|
| 573 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 574 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 2:測試車輛控制</h3>
|
| 575 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 576 |
+
<li>點擊「Play」按鈕進入測試模式</li>
|
| 577 |
+
<li>使用 W/A/S/D 或方向鍵駕駛車輛</li>
|
| 578 |
+
<li>測試加速、轉向和剎車功能</li>
|
| 579 |
+
<li>點擊「Stop」按鈕退出測試模式</li>
|
| 580 |
+
</ol>
|
| 581 |
+
</div>
|
| 582 |
+
|
| 583 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 584 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 3:調整車輛控制參數</h3>
|
| 585 |
+
<p className="text-gray-700 mb-4">
|
| 586 |
+
根據測試結果調整 CarController 腳本中的參數:
|
| 587 |
+
</p>
|
| 588 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 589 |
+
<li>FORWARD_FORCE, REVERSE_FORCE, MAX_SPEED:調整速度與力量</li>
|
| 590 |
+
<li>TURN_SPEED:調整轉向靈敏度</li>
|
| 591 |
+
<li>物理屬性:調整車身和車輪的 Density, Friction, Elasticity</li>
|
| 592 |
+
</ul>
|
| 593 |
+
</div>
|
| 594 |
+
</section>
|
| 595 |
+
|
| 596 |
+
{/* Part 4: Scoring System */}
|
| 597 |
+
<section id="part4" className="mb-12 scroll-mt-24">
|
| 598 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第四部分:計分系統</h2>
|
| 599 |
+
|
| 600 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 601 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 1:創建計分系統腳本</h3>
|
| 602 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 603 |
+
<li>在 ServerScriptService 中添加腳本, 命名為「ScoringSystem」</li>
|
| 604 |
+
<li>編寫計分系統腳本(見下方代碼)</li>
|
| 605 |
+
<li>保存腳本</li>
|
| 606 |
+
</ol>
|
| 607 |
+
<SyntaxHighlighter language="lua" style={vscDarkPlus} className="rounded-lg">
|
| 608 |
+
{scoringSystemScript}
|
| 609 |
+
</SyntaxHighlighter>
|
| 610 |
+
</div>
|
| 611 |
+
|
| 612 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 613 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 2:測試計分系統</h3>
|
| 614 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 615 |
+
<li>確保所有檢查點已正確設置在 Checkpoints 資料夾中</li>
|
| 616 |
+
<li>點擊「Play」按鈕進入測試模式</li>
|
| 617 |
+
<li>駕駛車輛通過檢查點</li>
|
| 618 |
+
<li>觀察計分 UI 是否正確更新(檢查點數量和時間)</li>
|
| 619 |
+
<li>完成一圈 8 字形賽道,確認比賽完成提示是否顯示</li>
|
| 620 |
+
<li>點擊「Stop」按鈕退出測試模式</li>
|
| 621 |
+
</ol>
|
| 622 |
+
</div>
|
| 623 |
+
</section>
|
| 624 |
+
|
| 625 |
+
{/* Part 5: Refinement and Export */}
|
| 626 |
+
<section id="part5" className="mb-12 scroll-mt-24">
|
| 627 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第五部分:完善與匯出</h2>
|
| 628 |
+
|
| 629 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 630 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 1:完善遊戲細節</h3>
|
| 631 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 632 |
+
<li>添加遊戲說明 GUI:包含控制說明和遊戲目標</li>
|
| 633 |
+
<li>添加環境裝飾:樹木、建築、天空盒等</li>
|
| 634 |
+
<li>添加音效:車輛引擎聲、比賽開始/完成音效</li>
|
| 635 |
+
</ul>
|
| 636 |
+
</div>
|
| 637 |
+
|
| 638 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 639 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 2:最終測試與調整</h3>
|
| 640 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 641 |
+
<li>進行全面測試:車輛控制、檢查點、計分、性能</li>
|
| 642 |
+
<li>根據測試結果進行調整:優化物理、調整檢查點、修復問題</li>
|
| 643 |
+
</ul>
|
| 644 |
+
</div>
|
| 645 |
+
|
| 646 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 647 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">步驟 3:匯出專案</h3>
|
| 648 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700">
|
| 649 |
+
<li>保存專案:File {'>'}Save</li>
|
| 650 |
+
<li>發布到 Roblox:File {'>'}Publish to Roblox</li>
|
| 651 |
+
<li>匯出模型(可選):選中 RaceCar 模型, File {'>'}Export Selection</li>
|
| 652 |
+
</ol>
|
| 653 |
+
</div>
|
| 654 |
+
</section>
|
| 655 |
+
|
| 656 |
+
{/* Summary and Challenge */}
|
| 657 |
+
<section id="summary" className="mb-12 scroll-mt-24">
|
| 658 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">總結</h2>
|
| 659 |
+
|
| 660 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 661 |
+
<p className="text-gray-700 mb-4">
|
| 662 |
+
在本課程中,我們成功建構了一個完整的賽車遊戲,包含四輪車模型、8字形賽道、車輛控制系統與計分機制。通過這個項目,學習者掌握了 Roblox Studio 中的模型建構、程式控制與遊戲機制設計等核心技能。
|
| 663 |
+
</p>
|
| 664 |
+
<p className="text-gray-700 mb-4">
|
| 665 |
+
這些技能可以應用於更複雜的遊戲開發項目,例如多人賽車遊戲、障礙賽車場、開放世界駕駛遊戲、車輛模擬器等。
|
| 666 |
+
</p>
|
| 667 |
+
</div>
|
| 668 |
+
|
| 669 |
+
<div className="bg-gradient-to-r from-green-50 to-teal-50 rounded-xl shadow-md p-6 mb-6">
|
| 670 |
+
<h3 className="text-xl font-bold text-green-700 mb-3">進階挑戰</h3>
|
| 671 |
+
<p className="text-gray-700 mb-4">
|
| 672 |
+
想要進一步提升您的賽車遊戲?嘗試以下挑戰:
|
| 673 |
+
</p>
|
| 674 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 675 |
+
<li>添加多人競賽功能</li>
|
| 676 |
+
<li>實現車輛損壞系統</li>
|
| 677 |
+
<li>添加不同類型的車輛</li>
|
| 678 |
+
<li>創建更複雜的賽道,包含坡道、跳台等</li>
|
| 679 |
+
<li>添加道具系統(如加速、護盾等)</li>
|
| 680 |
+
</ul>
|
| 681 |
+
</div>
|
| 682 |
+
|
| 683 |
+
<div className="bg-gradient-to-r from-blue-50 to-green-50 rounded-xl shadow-md p-6">
|
| 684 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">資源推薦</h3>
|
| 685 |
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
| 686 |
+
<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">
|
| 687 |
+
<h4 className="font-bold text-blue-800 mb-2">Roblox 開發者文檔</h4>
|
| 688 |
+
<p className="text-gray-700">官方開發文檔,包含詳細的 API 參考和教程</p>
|
| 689 |
+
</a>
|
| 690 |
+
<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">
|
| 691 |
+
<h4 className="font-bold text-blue-800 mb-2">Roblox 車輛系統教程</h4>
|
| 692 |
+
<p className="text-gray-700">官方關於車輛系統的詳細教程</p>
|
| 693 |
+
</a>
|
| 694 |
+
<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">
|
| 695 |
+
<h4 className="font-bold text-blue-800 mb-2">Lua 程式設計指南</h4>
|
| 696 |
+
<p className="text-gray-700">學習 Lua 語言的官方手冊</p>
|
| 697 |
+
</a>
|
| 698 |
+
<a href="https://devforum.roblox.com/" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
|
| 699 |
+
<h4 className="font-bold text-blue-800 mb-2">Roblox 開發者論壇</h4>
|
| 700 |
+
<p className="text-gray-700">與其他開發者交流,獲取幫助和分享經驗</p>
|
| 701 |
+
</a>
|
| 702 |
+
</div>
|
| 703 |
+
</div>
|
| 704 |
+
</section>
|
| 705 |
+
|
| 706 |
+
{/* Navigation Buttons */}
|
| 707 |
+
<div className="flex justify-between mt-12">
|
| 708 |
+
<a
|
| 709 |
+
href="/lesson1"
|
| 710 |
+
className="px-6 py-3 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition-colors flex items-center"
|
| 711 |
+
>
|
| 712 |
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
|
| 713 |
+
<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" />
|
| 714 |
+
</svg>
|
| 715 |
+
上一課:基礎入門
|
| 716 |
+
</a>
|
| 717 |
+
<a
|
| 718 |
+
href="/lesson3"
|
| 719 |
+
className="px-6 py-3 bg-green-600 text-white rounded-md hover:bg-green-700 transition-colors flex items-center"
|
| 720 |
+
>
|
| 721 |
+
下一課:互動機關
|
| 722 |
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 ml-2" viewBox="0 0 20 20" fill="currentColor">
|
| 723 |
+
<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" />
|
| 724 |
+
</svg>
|
| 725 |
+
</a>
|
| 726 |
+
</div>
|
| 727 |
+
</motion.div>
|
| 728 |
+
</div>
|
| 729 |
+
</div>
|
| 730 |
+
);
|
| 731 |
+
}
|
src/pages/Lesson3Page.tsx
ADDED
|
@@ -0,0 +1,752 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useState } from 'react';
|
| 2 |
+
import { motion } from 'framer-motion';
|
| 3 |
+
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
| 4 |
+
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
| 5 |
+
|
| 6 |
+
const buttonInteractionScript = `
|
| 7 |
+
-- 按鈕互動腳本
|
| 8 |
+
-- 獲取按鈕模型及其組件
|
| 9 |
+
local button = script.Parent
|
| 10 |
+
local buttonTop = button:WaitForChild("ButtonTop") -- 按鈕頂部可互動部分
|
| 11 |
+
local door = workspace:WaitForChild("Door") -- 門模型
|
| 12 |
+
local doorPanel = door:WaitForChild("DoorPanel") -- 門板
|
| 13 |
+
|
| 14 |
+
-- 按鈕狀態變數
|
| 15 |
+
local isPressed = false
|
| 16 |
+
local cooldownTime = 1 -- 按鈕冷卻時間(秒)
|
| 17 |
+
local isCooldown = false
|
| 18 |
+
|
| 19 |
+
-- 按鈕視覺效果設置
|
| 20 |
+
local defaultColor = Color3.fromRGB(255, 0, 0) -- 紅色
|
| 21 |
+
local pressedColor = Color3.fromRGB(0, 255, 0) -- 綠色
|
| 22 |
+
local defaultPosition = buttonTop.Position
|
| 23 |
+
local pressedPosition = defaultPosition - Vector3.new(0, 0.2, 0) -- 按下時下降0.2個單位
|
| 24 |
+
|
| 25 |
+
-- 門的狀態變數
|
| 26 |
+
local doorTransparency = 0.8 -- 透明狀態的透明度值
|
| 27 |
+
local doorTransitionTime = 1 -- 門變透明的過渡時間(秒)
|
| 28 |
+
local doorOpenTime = 30 -- 門保持透明的時間(秒)
|
| 29 |
+
|
| 30 |
+
-- 按鈕按下效果函數
|
| 31 |
+
local function pressButton()
|
| 32 |
+
if isCooldown then return end
|
| 33 |
+
|
| 34 |
+
-- 設置冷卻狀態
|
| 35 |
+
isCooldown = true
|
| 36 |
+
isPressed = true
|
| 37 |
+
|
| 38 |
+
-- 播放按鈕按下音效(可選)
|
| 39 |
+
local sound = Instance.new("Sound")
|
| 40 |
+
sound.SoundId = "rbxassetid://142376088" -- 按鈕音效ID
|
| 41 |
+
sound.Volume = 0.5
|
| 42 |
+
sound.Parent = button
|
| 43 |
+
sound:Play()
|
| 44 |
+
|
| 45 |
+
-- 按鈕視覺效果
|
| 46 |
+
buttonTop.Color = pressedColor
|
| 47 |
+
buttonTop.Position = pressedPosition
|
| 48 |
+
|
| 49 |
+
-- 觸發門變透明
|
| 50 |
+
makeDoorTransparent()
|
| 51 |
+
|
| 52 |
+
-- 按鈕恢復
|
| 53 |
+
wait(cooldownTime)
|
| 54 |
+
buttonTop.Color = defaultColor
|
| 55 |
+
buttonTop.Position = defaultPosition
|
| 56 |
+
isPressed = false
|
| 57 |
+
isCooldown = false
|
| 58 |
+
end
|
| 59 |
+
|
| 60 |
+
-- 使門變透明的函數
|
| 61 |
+
function makeDoorTransparent()
|
| 62 |
+
-- 創建過渡效果
|
| 63 |
+
local startTime = tick()
|
| 64 |
+
local initialTransparency = doorPanel.Transparency
|
| 65 |
+
|
| 66 |
+
-- 漸變透明度
|
| 67 |
+
while tick() - startTime < doorTransitionTime do
|
| 68 |
+
local alpha = (tick() - startTime) / doorTransitionTime
|
| 69 |
+
doorPanel.Transparency = initialTransparency * (1 - alpha) + doorTransparency * alpha
|
| 70 |
+
wait()
|
| 71 |
+
end
|
| 72 |
+
|
| 73 |
+
-- 確保最終透明度正確
|
| 74 |
+
doorPanel.Transparency = doorTransparency
|
| 75 |
+
|
| 76 |
+
-- 門變為可穿透(但仍然可見)
|
| 77 |
+
doorPanel.CanCollide = false
|
| 78 |
+
|
| 79 |
+
-- 添加發光效果(可選)
|
| 80 |
+
local highlight = Instance.new("Highlight")
|
| 81 |
+
highlight.FillColor = Color3.fromRGB(0, 200, 255)
|
| 82 |
+
highlight.OutlineColor = Color3.fromRGB(0, 100, 255)
|
| 83 |
+
highlight.FillTransparency = 0.5
|
| 84 |
+
highlight.Parent = doorPanel
|
| 85 |
+
|
| 86 |
+
-- 設置計時器,讓門在一段時間後恢復
|
| 87 |
+
wait(doorOpenTime)
|
| 88 |
+
|
| 89 |
+
-- 如果沒有被數學題系統覆蓋,則恢復門的狀態
|
| 90 |
+
if doorPanel.Transparency == doorTransparency then
|
| 91 |
+
-- 漸變回不透明
|
| 92 |
+
startTime = tick()
|
| 93 |
+
while tick() - startTime < doorTransitionTime do
|
| 94 |
+
local alpha = (tick() - startTime) / doorTransitionTime
|
| 95 |
+
doorPanel.Transparency = doorTransparency * (1 - alpha) + initialTransparency * alpha
|
| 96 |
+
wait()
|
| 97 |
+
end
|
| 98 |
+
|
| 99 |
+
-- 恢復門的碰撞
|
| 100 |
+
doorPanel.Transparency = initialTransparency
|
| 101 |
+
doorPanel.CanCollide = true
|
| 102 |
+
|
| 103 |
+
-- 移除發光效果
|
| 104 |
+
if highlight and highlight.Parent then
|
| 105 |
+
highlight:Destroy()
|
| 106 |
+
end
|
| 107 |
+
end
|
| 108 |
+
end
|
| 109 |
+
|
| 110 |
+
-- 設置按鈕觸發
|
| 111 |
+
buttonTop.Touched:Connect(function(hit)
|
| 112 |
+
-- 檢查是否是玩家角色的一部分
|
| 113 |
+
local humanoid = hit.Parent:FindFirstChild("Humanoid")
|
| 114 |
+
if humanoid and not isPressed then
|
| 115 |
+
pressButton()
|
| 116 |
+
end
|
| 117 |
+
end)
|
| 118 |
+
|
| 119 |
+
print("按鈕互動腳本已加載!")
|
| 120 |
+
`;
|
| 121 |
+
|
| 122 |
+
const doorMathInteractionScript = `
|
| 123 |
+
-- 透明門與數學題互動腳本
|
| 124 |
+
-- 獲取門板及相關組件
|
| 125 |
+
local doorPanel = script.Parent
|
| 126 |
+
local door = doorPanel.Parent
|
| 127 |
+
|
| 128 |
+
-- 數學題相關變數
|
| 129 |
+
local mathProblemActive = false
|
| 130 |
+
local currentAnswer = 0
|
| 131 |
+
local currentProblem = ""
|
| 132 |
+
|
| 133 |
+
-- 服務引用
|
| 134 |
+
local Players = game:GetService("Players")
|
| 135 |
+
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
| 136 |
+
|
| 137 |
+
-- 創建遠端事件用於UI更新
|
| 138 |
+
local mathProblemEvent = Instance.new("RemoteEvent")
|
| 139 |
+
mathProblemEvent.Name = "MathProblemEvent"
|
| 140 |
+
mathProblemEvent.Parent = ReplicatedStorage
|
| 141 |
+
|
| 142 |
+
-- 生成二位數乘法題目
|
| 143 |
+
local function generateMathProblem()
|
| 144 |
+
-- 生成兩個10-99之間的隨機數
|
| 145 |
+
local num1 = math.random(10, 99)
|
| 146 |
+
local num2 = math.random(10, 99)
|
| 147 |
+
|
| 148 |
+
-- 計算答案
|
| 149 |
+
local answer = num1 * num2
|
| 150 |
+
|
| 151 |
+
-- 創建題目字串
|
| 152 |
+
local problem = num1 .. " × " .. num2 .. " = ?"
|
| 153 |
+
|
| 154 |
+
return problem, answer
|
| 155 |
+
end
|
| 156 |
+
|
| 157 |
+
-- 創建數學題UI
|
| 158 |
+
local function createMathProblemUI(player)
|
| 159 |
+
-- 創建ScreenGui
|
| 160 |
+
local mathGui = Instance.new("ScreenGui")
|
| 161 |
+
mathGui.Name = "MathProblemGui"
|
| 162 |
+
|
| 163 |
+
-- 創建主框架
|
| 164 |
+
local frame = Instance.new("Frame")
|
| 165 |
+
frame.Size = UDim2.new(0, 300, 0, 200)
|
| 166 |
+
frame.Position = UDim2.new(0.5, -150, 0.5, -100)
|
| 167 |
+
frame.BackgroundColor3 = Color3.fromRGB(50, 50, 50)
|
| 168 |
+
frame.BorderSizePixel = 2
|
| 169 |
+
frame.BorderColor3 = Color3.fromRGB(255, 255, 255)
|
| 170 |
+
frame.Parent = mathGui
|
| 171 |
+
|
| 172 |
+
-- 創建標題
|
| 173 |
+
local titleLabel = Instance.new("TextLabel")
|
| 174 |
+
titleLabel.Size = UDim2.new(1, 0, 0.2, 0)
|
| 175 |
+
titleLabel.Position = UDim2.new(0, 0, 0, 0)
|
| 176 |
+
titleLabel.BackgroundTransparency = 1
|
| 177 |
+
titleLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
|
| 178 |
+
titleLabel.TextSize = 24
|
| 179 |
+
titleLabel.Font = Enum.Font.SourceSansBold
|
| 180 |
+
titleLabel.Text = "解答數學題以通過門"
|
| 181 |
+
titleLabel.Parent = frame
|
| 182 |
+
|
| 183 |
+
-- 創建問題標籤
|
| 184 |
+
local problemLabel = Instance.new("TextLabel")
|
| 185 |
+
problemLabel.Size = UDim2.new(1, 0, 0.3, 0)
|
| 186 |
+
problemLabel.Position = UDim2.new(0, 0, 0.2, 0)
|
| 187 |
+
problemLabel.BackgroundTransparency = 1
|
| 188 |
+
problemLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
|
| 189 |
+
problemLabel.TextSize = 36
|
| 190 |
+
problemLabel.Font = Enum.Font.SourceSansBold
|
| 191 |
+
problemLabel.Name = "ProblemLabel"
|
| 192 |
+
problemLabel.Text = currentProblem
|
| 193 |
+
problemLabel.Parent = frame
|
| 194 |
+
|
| 195 |
+
-- 創建答案輸入框
|
| 196 |
+
local answerBox = Instance.new("TextBox")
|
| 197 |
+
answerBox.Size = UDim2.new(0.6, 0, 0.2, 0)
|
| 198 |
+
answerBox.Position = UDim2.new(0.2, 0, 0.5, 0)
|
| 199 |
+
answerBox.BackgroundColor3 = Color3.fromRGB(255, 255, 255)
|
| 200 |
+
answerBox.TextColor3 = Color3.fromRGB(0, 0, 0)
|
| 201 |
+
answerBox.TextSize = 24
|
| 202 |
+
answerBox.Font = Enum.Font.SourceSans
|
| 203 |
+
answerBox.PlaceholderText = "輸入答案..."
|
| 204 |
+
answerBox.Text = ""
|
| 205 |
+
answerBox.Name = "AnswerBox"
|
| 206 |
+
answerBox.ClearTextOnFocus = true
|
| 207 |
+
answerBox.Parent = frame
|
| 208 |
+
|
| 209 |
+
-- 創建提交按鈕
|
| 210 |
+
local submitButton = Instance.new("TextButton")
|
| 211 |
+
submitButton.Size = UDim2.new(0.4, 0, 0.15, 0)
|
| 212 |
+
submitButton.Position = UDim2.new(0.3, 0, 0.75, 0)
|
| 213 |
+
submitButton.BackgroundColor3 = Color3.fromRGB(0, 150, 255)
|
| 214 |
+
submitButton.TextColor3 = Color3.fromRGB(255, 255, 255)
|
| 215 |
+
submitButton.TextSize = 20
|
| 216 |
+
submitButton.Font = Enum.Font.SourceSansBold
|
| 217 |
+
submitButton.Text = "提交答案"
|
| 218 |
+
submitButton.Name = "SubmitButton"
|
| 219 |
+
submitButton.Parent = frame
|
| 220 |
+
|
| 221 |
+
-- 創建結果標籤
|
| 222 |
+
local resultLabel = Instance.new("TextLabel")
|
| 223 |
+
resultLabel.Size = UDim2.new(1, 0, 0.1, 0)
|
| 224 |
+
resultLabel.Position = UDim2.new(0, 0, 0.9, 0)
|
| 225 |
+
resultLabel.BackgroundTransparency = 1
|
| 226 |
+
resultLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
|
| 227 |
+
resultLabel.TextSize = 18
|
| 228 |
+
resultLabel.Font = Enum.Font.SourceSans
|
| 229 |
+
resultLabel.Name = "ResultLabel"
|
| 230 |
+
resultLabel.Text = ""
|
| 231 |
+
resultLabel.Parent = frame
|
| 232 |
+
|
| 233 |
+
-- 將UI添加到玩家的PlayerGui
|
| 234 |
+
mathGui.Parent = player.PlayerGui
|
| 235 |
+
|
| 236 |
+
-- 創建本地腳本處理UI交互
|
| 237 |
+
local localScript = Instance.new("LocalScript")
|
| 238 |
+
localScript.Parent = mathGui
|
| 239 |
+
|
| 240 |
+
localScript.Source = [[
|
| 241 |
+
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
| 242 |
+
local mathProblemEvent = ReplicatedStorage:WaitForChild("MathProblemEvent")
|
| 243 |
+
local player = game.Players.LocalPlayer
|
| 244 |
+
local gui = script.Parent
|
| 245 |
+
local frame = gui:WaitForChild("Frame")
|
| 246 |
+
local submitButton = frame:WaitForChild("SubmitButton")
|
| 247 |
+
local answerBox = frame:WaitForChild("AnswerBox")
|
| 248 |
+
local resultLabel = frame:WaitForChild("ResultLabel")
|
| 249 |
+
|
| 250 |
+
-- 提交答案
|
| 251 |
+
local function submitAnswer()
|
| 252 |
+
local answer = tonumber(answerBox.Text)
|
| 253 |
+
if answer then
|
| 254 |
+
mathProblemEvent:FireServer(answer)
|
| 255 |
+
else
|
| 256 |
+
resultLabel.Text = "請輸入有效的數字!"
|
| 257 |
+
resultLabel.TextColor3 = Color3.fromRGB(255, 100, 100)
|
| 258 |
+
end
|
| 259 |
+
end
|
| 260 |
+
|
| 261 |
+
-- 連接提交按鈕
|
| 262 |
+
submitButton.MouseButton1Click:Connect(submitAnswer)
|
| 263 |
+
|
| 264 |
+
-- 按Enter鍵也可提交
|
| 265 |
+
answerBox.FocusLost:Connect(function(enterPressed)
|
| 266 |
+
if enterPressed then
|
| 267 |
+
submitAnswer()
|
| 268 |
+
end
|
| 269 |
+
end)
|
| 270 |
+
|
| 271 |
+
-- 處理服務器回應
|
| 272 |
+
mathProblemEvent.OnClientEvent:Connect(function(action, message)
|
| 273 |
+
if action == "result" then
|
| 274 |
+
resultLabel.Text = message
|
| 275 |
+
if message:find("正確") then
|
| 276 |
+
resultLabel.TextColor3 = Color3.fromRGB(100, 255, 100)
|
| 277 |
+
-- 答對後關閉UI
|
| 278 |
+
wait(1.5)
|
| 279 |
+
gui:Destroy()
|
| 280 |
+
else
|
| 281 |
+
resultLabel.TextColor3 = Color3.fromRGB(255, 100, 100)
|
| 282 |
+
-- 清空輸入框
|
| 283 |
+
answerBox.Text = ""
|
| 284 |
+
end
|
| 285 |
+
elseif action == "close" then
|
| 286 |
+
-- 關閉UI
|
| 287 |
+
gui:Destroy()
|
| 288 |
+
end
|
| 289 |
+
end)
|
| 290 |
+
]]
|
| 291 |
+
|
| 292 |
+
return mathGui
|
| 293 |
+
end
|
| 294 |
+
|
| 295 |
+
-- 處理玩家碰觸透明門
|
| 296 |
+
doorPanel.Touched:Connect(function(hit)
|
| 297 |
+
-- ��保門是透明狀態
|
| 298 |
+
if doorPanel.Transparency < 0.5 then return end
|
| 299 |
+
|
| 300 |
+
-- 檢查是否是玩家角色的一部分
|
| 301 |
+
local character = hit.Parent
|
| 302 |
+
local player = Players:GetPlayerFromCharacter(character)
|
| 303 |
+
|
| 304 |
+
if player and not mathProblemActive then
|
| 305 |
+
-- 防止多次觸發
|
| 306 |
+
mathProblemActive = true
|
| 307 |
+
|
| 308 |
+
-- 生成數學題
|
| 309 |
+
currentProblem, currentAnswer = generateMathProblem()
|
| 310 |
+
|
| 311 |
+
-- 創建並顯示數學題UI
|
| 312 |
+
createMathProblemUI(player)
|
| 313 |
+
|
| 314 |
+
-- 發送題目到客戶端
|
| 315 |
+
mathProblemEvent:FireClient(player, "problem", currentProblem)
|
| 316 |
+
end
|
| 317 |
+
end)
|
| 318 |
+
|
| 319 |
+
-- 處理玩家答題
|
| 320 |
+
mathProblemEvent.OnServerEvent:Connect(function(player, answer)
|
| 321 |
+
if answer == currentAnswer then
|
| 322 |
+
-- 答案正確
|
| 323 |
+
mathProblemEvent:FireClient(player, "result", "正確!門已開啟。")
|
| 324 |
+
|
| 325 |
+
-- 允許玩家通過門
|
| 326 |
+
local character = player.Character
|
| 327 |
+
if character then
|
| 328 |
+
-- 創建一個臨時的無碰撞區域,只對這個玩家有效
|
| 329 |
+
local noCollisionPart = Instance.new("Part")
|
| 330 |
+
noCollisionPart.Size = doorPanel.Size
|
| 331 |
+
noCollisionPart.CFrame = doorPanel.CFrame
|
| 332 |
+
noCollisionPart.Transparency = 1
|
| 333 |
+
noCollisionPart.CanCollide = false
|
| 334 |
+
noCollisionPart.Anchored = true
|
| 335 |
+
noCollisionPart.Parent = workspace
|
| 336 |
+
|
| 337 |
+
-- 設置門完全透明(對這個玩家)
|
| 338 |
+
local tempHighlight = Instance.new("Highlight")
|
| 339 |
+
tempHighlight.FillColor = Color3.fromRGB(0, 255, 100)
|
| 340 |
+
tempHighlight.OutlineColor = Color3.fromRGB(0, 200, 50)
|
| 341 |
+
tempHighlight.FillTransparency = 0.7
|
| 342 |
+
tempHighlight.Parent = doorPanel
|
| 343 |
+
|
| 344 |
+
-- 5秒後恢復
|
| 345 |
+
wait(5)
|
| 346 |
+
if noCollisionPart and noCollisionPart.Parent then
|
| 347 |
+
noCollisionPart:Destroy()
|
| 348 |
+
end
|
| 349 |
+
if tempHighlight and tempHighlight.Parent then
|
| 350 |
+
tempHighlight:Destroy()
|
| 351 |
+
end
|
| 352 |
+
end
|
| 353 |
+
else
|
| 354 |
+
-- 答案錯誤
|
| 355 |
+
mathProblemEvent:FireClient(player, "result", "錯誤!請再試一次。")
|
| 356 |
+
end
|
| 357 |
+
|
| 358 |
+
-- 重置狀態,允許再次觸發
|
| 359 |
+
wait(2)
|
| 360 |
+
mathProblemActive = false
|
| 361 |
+
end)
|
| 362 |
+
|
| 363 |
+
print("透明門與數學題互動腳本已加載!")
|
| 364 |
+
`;
|
| 365 |
+
|
| 366 |
+
export default function Lesson3Page() {
|
| 367 |
+
const [activeSection, setActiveSection] = useState('intro');
|
| 368 |
+
|
| 369 |
+
const scrollToSection = (sectionId: string) => {
|
| 370 |
+
setActiveSection(sectionId);
|
| 371 |
+
const element = document.getElementById(sectionId);
|
| 372 |
+
if (element) {
|
| 373 |
+
element.scrollIntoView({ behavior: 'smooth' });
|
| 374 |
+
}
|
| 375 |
+
};
|
| 376 |
+
|
| 377 |
+
return (
|
| 378 |
+
<div className="flex flex-col md:flex-row gap-6">
|
| 379 |
+
{/* Sidebar Navigation */}
|
| 380 |
+
<div className="md:w-1/4 lg:w-1/5">
|
| 381 |
+
<div className="bg-white rounded-xl shadow-md p-6 sticky top-24">
|
| 382 |
+
<h3 className="text-lg font-bold text-gray-800 mb-4">課程目錄</h3>
|
| 383 |
+
<nav className="space-y-2">
|
| 384 |
+
<button
|
| 385 |
+
onClick={() => scrollToSection('intro')}
|
| 386 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 387 |
+
activeSection === 'intro'
|
| 388 |
+
? 'bg-purple-100 text-purple-700'
|
| 389 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 390 |
+
}`}
|
| 391 |
+
>
|
| 392 |
+
課程簡介
|
| 393 |
+
</button>
|
| 394 |
+
<button
|
| 395 |
+
onClick={() => scrollToSection('part1')}
|
| 396 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 397 |
+
activeSection === 'part1'
|
| 398 |
+
? 'bg-purple-100 text-purple-700'
|
| 399 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 400 |
+
}`}
|
| 401 |
+
>
|
| 402 |
+
機關門模型建構
|
| 403 |
+
</button>
|
| 404 |
+
<button
|
| 405 |
+
onClick={() => scrollToSection('part2')}
|
| 406 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 407 |
+
activeSection === 'part2'
|
| 408 |
+
? 'bg-purple-100 text-purple-700'
|
| 409 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 410 |
+
}`}
|
| 411 |
+
>
|
| 412 |
+
按鈕互動機制
|
| 413 |
+
</button>
|
| 414 |
+
<button
|
| 415 |
+
onClick={() => scrollToSection('part3')}
|
| 416 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 417 |
+
activeSection === 'part3'
|
| 418 |
+
? 'bg-purple-100 text-purple-700'
|
| 419 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 420 |
+
}`}
|
| 421 |
+
>
|
| 422 |
+
數學題互動系統
|
| 423 |
+
</button>
|
| 424 |
+
<button
|
| 425 |
+
onClick={() => scrollToSection('part4')}
|
| 426 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 427 |
+
activeSection === 'part4'
|
| 428 |
+
? 'bg-purple-100 text-purple-700'
|
| 429 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 430 |
+
}`}
|
| 431 |
+
>
|
| 432 |
+
優化與擴展
|
| 433 |
+
</button>
|
| 434 |
+
<button
|
| 435 |
+
onClick={() => scrollToSection('part5')}
|
| 436 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 437 |
+
activeSection === 'part5'
|
| 438 |
+
? 'bg-purple-100 text-purple-700'
|
| 439 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 440 |
+
}`}
|
| 441 |
+
>
|
| 442 |
+
匯出與分享
|
| 443 |
+
</button>
|
| 444 |
+
<button
|
| 445 |
+
onClick={() => scrollToSection('summary')}
|
| 446 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 447 |
+
activeSection === 'summary'
|
| 448 |
+
? 'bg-purple-100 text-purple-700'
|
| 449 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 450 |
+
}`}
|
| 451 |
+
>
|
| 452 |
+
總結與挑戰
|
| 453 |
+
</button>
|
| 454 |
+
</nav>
|
| 455 |
+
</div>
|
| 456 |
+
</div>
|
| 457 |
+
|
| 458 |
+
{/* Main Content */}
|
| 459 |
+
<div className="md:w-3/4 lg:w-4/5">
|
| 460 |
+
<motion.div
|
| 461 |
+
initial={{ opacity: 0 }}
|
| 462 |
+
animate={{ opacity: 1 }}
|
| 463 |
+
transition={{ duration: 0.5 }}
|
| 464 |
+
>
|
| 465 |
+
<div className="bg-gradient-to-r from-purple-600 to-indigo-600 rounded-xl p-8 mb-8 text-white">
|
| 466 |
+
<h1 className="text-3xl md:text-4xl font-bold mb-4">Roblox 基礎入門第三課 - 遊戲互動學習:機關門與數學題互動</h1>
|
| 467 |
+
<p className="text-lg opacity-90">
|
| 468 |
+
學習建構互動機關門、按鈕觸發、透明效果與數學題答題系統
|
| 469 |
+
</p>
|
| 470 |
+
</div>
|
| 471 |
+
|
| 472 |
+
{/* Course Introduction */}
|
| 473 |
+
<section id="intro" className="mb-12 scroll-mt-24">
|
| 474 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">課程簡介</h2>
|
| 475 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 476 |
+
<p className="text-gray-700 mb-4">
|
| 477 |
+
本課程將帶領學習者建構一個互動機關門系統,包含按鈕觸發、透明門效果與數學題答題機制。通過實際操作,學習者將掌握 Roblox Studio 中的互動機制設計、UI 創建與程式控制等進階技能。
|
| 478 |
+
</p>
|
| 479 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">課程目標</h3>
|
| 480 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 481 |
+
<li>在 Roblox Studio 中建構互動機關門模型</li>
|
| 482 |
+
<li>設計並實現按鈕觸發機制</li>
|
| 483 |
+
<li>編寫透明門效果控制腳本</li>
|
| 484 |
+
<li>設計數學題生成與答題系統</li>
|
| 485 |
+
</ul>
|
| 486 |
+
<h3 className="text-xl font-bold text-purple-700 mt-6 mb-3">前置準備</h3>
|
| 487 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 488 |
+
<li>已安裝最新版本的 Roblox Studio</li>
|
| 489 |
+
<li>具備 Roblox Studio 基本操作能力(第一課內容)</li>
|
| 490 |
+
<li>了解基本的 Lua 程式語法(第二課內容)</li>
|
| 491 |
+
</ul>
|
| 492 |
+
</div>
|
| 493 |
+
</section>
|
| 494 |
+
|
| 495 |
+
{/* Part 1: Door Model Construction */}
|
| 496 |
+
<section id="part1" className="mb-12 scroll-mt-24">
|
| 497 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第一部分:機關門模型建構</h2>
|
| 498 |
+
|
| 499 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 500 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 1:創建新專案</h3>
|
| 501 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700">
|
| 502 |
+
<li>打開 Roblox Studio</li>
|
| 503 |
+
<li>選擇「基礎模板」創建新專案</li>
|
| 504 |
+
<li>保存專案,命名為「InteractiveDoorGame」</li>
|
| 505 |
+
</ol>
|
| 506 |
+
</div>
|
| 507 |
+
|
| 508 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 509 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 2:建立門框架</h3>
|
| 510 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 511 |
+
<li>在工作區中插入一個方塊部件(Part)</li>
|
| 512 |
+
<li>調整門框尺寸與位置:Size: 6, 8, 0.5 (寬, 高, 厚), Position: 0, 4, 0 (X, Y, Z), 命名為「DoorFrame」</li>
|
| 513 |
+
<li>設置門框外觀:Color: 深棕色, Material: Wood, Anchored: true</li>
|
| 514 |
+
</ol>
|
| 515 |
+
</div>
|
| 516 |
+
|
| 517 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 518 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 3:創建門板</h3>
|
| 519 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 520 |
+
<li>插入一個方塊部件作為門板</li>
|
| 521 |
+
<li>設置屬性:Size: 5, 7, 0.3, Position: 調整至門框內, 命名為「DoorPanel」</li>
|
| 522 |
+
<li>設置門板外觀:Color: 淺棕色, Material: Wood, Anchored: true, CanCollide: true</li>
|
| 523 |
+
</ol>
|
| 524 |
+
</div>
|
| 525 |
+
|
| 526 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 527 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 4:添加門把手</h3>
|
| 528 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 529 |
+
<li>插入一個圓柱體(Cylinder)作為門把手</li>
|
| 530 |
+
<li>設置屬性:Size: 0.3, 0.3, 0.8, Position: 調整至門板側面, Orientation: 水平, 命名為「DoorHandle」</li>
|
| 531 |
+
<li>設置門把手外觀:Color: 金色/銀色, Material: Metal, Anchored: true</li>
|
| 532 |
+
</ol>
|
| 533 |
+
</div>
|
| 534 |
+
|
| 535 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 536 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 5:創建按鈕</h3>
|
| 537 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 538 |
+
<li>創建按鈕基座:插入方塊部件, Size: 1, 1, 0.5, Position: 門旁牆壁, 命名為「ButtonBase」</li>
|
| 539 |
+
<li>創建按鈕頂部:插入方塊部件, Size: 0.8, 0.8, 0.3, Position: 基座前方, Color: 紅色, Material: Neon, 命名為「ButtonTop」</li>
|
| 540 |
+
<li>設置按鈕外觀:基座顏色深灰, 確保按鈕突出</li>
|
| 541 |
+
</ol>
|
| 542 |
+
</div>
|
| 543 |
+
|
| 544 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 545 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 6:組織模型結構</h3>
|
| 546 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 547 |
+
<li>組織門模型:選中門框、門板、門把手, 右鍵「Group」, 命名為「Door」</li>
|
| 548 |
+
<li>組織按鈕模型:選中按鈕基座、按鈕頂部, 右鍵「Group」, 命名為「Button」</li>
|
| 549 |
+
</ol>
|
| 550 |
+
</div>
|
| 551 |
+
</section>
|
| 552 |
+
|
| 553 |
+
{/* Part 2: Button Interaction Mechanism */}
|
| 554 |
+
<section id="part2" className="mb-12 scroll-mt-24">
|
| 555 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第二部分:按鈕互動機制設計</h2>
|
| 556 |
+
|
| 557 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 558 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 1:創建按鈕互動腳本</h3>
|
| 559 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 560 |
+
<li>在 Button 模型中添加腳本, 命名為「ButtonScript」</li>
|
| 561 |
+
<li>編寫按鈕互動腳本(見下方代碼)</li>
|
| 562 |
+
<li>保存腳本</li>
|
| 563 |
+
</ol>
|
| 564 |
+
<SyntaxHighlighter language="lua" style={vscDarkPlus} className="rounded-lg">
|
| 565 |
+
{buttonInteractionScript}
|
| 566 |
+
</SyntaxHighlighter>
|
| 567 |
+
</div>
|
| 568 |
+
|
| 569 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 570 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 2:測試按鈕互動</h3>
|
| 571 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 572 |
+
<li>點擊「Play」按鈕進入測試模式</li>
|
| 573 |
+
<li>控制角色接觸按鈕</li>
|
| 574 |
+
<li>觀察按鈕按下效果與門變透明的過程</li>
|
| 575 |
+
<li>點擊「Stop」按鈕退出測試模式</li>
|
| 576 |
+
</ol>
|
| 577 |
+
</div>
|
| 578 |
+
|
| 579 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 580 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 3:調整按鈕互動參數</h3>
|
| 581 |
+
<p className="text-gray-700 mb-4">
|
| 582 |
+
根據測試結果調整 ButtonScript 腳本中的參數:
|
| 583 |
+
</p>
|
| 584 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 585 |
+
<li>cooldownTime:調整按鈕冷卻時間</li>
|
| 586 |
+
<li>doorTransparency:調整門的透明度</li>
|
| 587 |
+
<li>doorTransitionTime:調整門變透明的過渡時間</li>
|
| 588 |
+
<li>doorOpenTime:調整門保持透明的時間</li>
|
| 589 |
+
</ul>
|
| 590 |
+
</div>
|
| 591 |
+
</section>
|
| 592 |
+
|
| 593 |
+
{/* Part 3: Transparent Door & Math Problem Interaction */}
|
| 594 |
+
<section id="part3" className="mb-12 scroll-mt-24">
|
| 595 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第三部分:透明門與數學題互動系統</h2>
|
| 596 |
+
|
| 597 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 598 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 1:創建透明門互動腳本</h3>
|
| 599 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 600 |
+
<li>在 DoorPanel 中添加腳本, 命名為「DoorMathScript」</li>
|
| 601 |
+
<li>編寫透明門與數學題互動腳本(見下方代碼)</li>
|
| 602 |
+
<li>保存腳本</li>
|
| 603 |
+
</ol>
|
| 604 |
+
<SyntaxHighlighter language="lua" style={vscDarkPlus} className="rounded-lg">
|
| 605 |
+
{doorMathInteractionScript}
|
| 606 |
+
</SyntaxHighlighter>
|
| 607 |
+
</div>
|
| 608 |
+
|
| 609 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 610 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 2:設置 ReplicatedStorage</h3>
|
| 611 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 612 |
+
<li>確保 ReplicatedStorage 中有正確的遠端事件</li>
|
| 613 |
+
<li>如果腳本沒有自動創建,手動創建一個 RemoteEvent</li>
|
| 614 |
+
<li>命名為「MathProblemEvent」</li>
|
| 615 |
+
<li>放置在 ReplicatedStorage 中</li>
|
| 616 |
+
</ol>
|
| 617 |
+
</div>
|
| 618 |
+
|
| 619 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 620 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 3:測試數學題互動</h3>
|
| 621 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 622 |
+
<li>點擊「Play」按鈕進入測試模式</li>
|
| 623 |
+
<li>按下按鈕使門變透明</li>
|
| 624 |
+
<li>接觸透明門觸發數學題 UI</li>
|
| 625 |
+
<li>測試答題功能:輸入正確/錯誤答案,觀察結果</li>
|
| 626 |
+
<li>確認答對後門可以穿透</li>
|
| 627 |
+
<li>點擊「Stop」按鈕退出測試模式</li>
|
| 628 |
+
</ol>
|
| 629 |
+
</div>
|
| 630 |
+
</section>
|
| 631 |
+
|
| 632 |
+
{/* Part 4: Optimization and Expansion */}
|
| 633 |
+
<section id="part4" className="mb-12 scroll-mt-24">
|
| 634 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第四部分:優化與擴展</h2>
|
| 635 |
+
|
| 636 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 637 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 1:添加視覺效果</h3>
|
| 638 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 639 |
+
<li>按鈕按下效果:粒子效果、光源</li>
|
| 640 |
+
<li>門變透明效果:過渡動畫、粒子效果</li>
|
| 641 |
+
<li>答題成功效果:成功音效、視覺反饋</li>
|
| 642 |
+
</ul>
|
| 643 |
+
</div>
|
| 644 |
+
|
| 645 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 646 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 2:擴展功能</h3>
|
| 647 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 648 |
+
<li>調整數學題難度:修改 generateMathProblem 函數,添加難度選項</li>
|
| 649 |
+
<li>添加計時功能:設置答題時間限制,添加倒計時顯示</li>
|
| 650 |
+
<li>添加積分系統:記錄答題正確率,顯示積分排行榜</li>
|
| 651 |
+
</ul>
|
| 652 |
+
</div>
|
| 653 |
+
</section>
|
| 654 |
+
|
| 655 |
+
{/* Part 5: Export and Share */}
|
| 656 |
+
<section id="part5" className="mb-12 scroll-mt-24">
|
| 657 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第五部分:匯出與分享</h2>
|
| 658 |
+
|
| 659 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 660 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 1:最終測試與調整</h3>
|
| 661 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 662 |
+
<li>進行全面測試:按鈕、透明門、數學題、性能</li>
|
| 663 |
+
<li>根據測試結果進行調整:優化腳本、修復問題</li>
|
| 664 |
+
</ul>
|
| 665 |
+
</div>
|
| 666 |
+
|
| 667 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 668 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">步驟 2:匯出專案</h3>
|
| 669 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700">
|
| 670 |
+
<li>保存專案:File {'>'}Save</li>
|
| 671 |
+
<li>發布到 Roblox:File {'>'}Publish to Roblox</li>
|
| 672 |
+
<li>匯出模型(可選):選中 Door 和 Button 模型, File {'>'}Export Selection</li>
|
| 673 |
+
</ol>
|
| 674 |
+
</div>
|
| 675 |
+
</section>
|
| 676 |
+
|
| 677 |
+
{/* Summary and Challenge */}
|
| 678 |
+
<section id="summary" className="mb-12 scroll-mt-24">
|
| 679 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">總結</h2>
|
| 680 |
+
|
| 681 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 682 |
+
<p className="text-gray-700 mb-4">
|
| 683 |
+
在本課程中,我們成功建構了一個互動機關門系統,包含按鈕觸發、透明門效果與數學題答題機制。通過這個項目,學習者掌握了 Roblox Studio 中的互動機制設計、UI 創建與程式控制等進階技能。
|
| 684 |
+
</p>
|
| 685 |
+
<p className="text-gray-700 mb-4">
|
| 686 |
+
這些技能可以應用於更複雜的遊戲開發項目,例如解謎遊戲、教育類遊戲、互動式學習環境、技能挑戰系統等。
|
| 687 |
+
</p>
|
| 688 |
+
</div>
|
| 689 |
+
|
| 690 |
+
<div className="bg-gradient-to-r from-purple-50 to-indigo-50 rounded-xl shadow-md p-6 mb-6">
|
| 691 |
+
<h3 className="text-xl font-bold text-purple-700 mb-3">進階挑戰</h3>
|
| 692 |
+
<p className="text-gray-700 mb-4">
|
| 693 |
+
想要進一步提升您的互動機關系統?嘗試以下挑戰:
|
| 694 |
+
</p>
|
| 695 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 696 |
+
<li>添加多種類型的數學題(加減乘除、方程式等)</li>
|
| 697 |
+
<li>實現難度漸進系統</li>
|
| 698 |
+
<li>添加多人競賽模式</li>
|
| 699 |
+
<li>創建更複雜的機關系統,如需要多個按鈕同時按下</li>
|
| 700 |
+
<li>添加視覺化教學提示系統</li>
|
| 701 |
+
</ul>
|
| 702 |
+
</div>
|
| 703 |
+
|
| 704 |
+
<div className="bg-gradient-to-r from-blue-50 to-purple-50 rounded-xl shadow-md p-6">
|
| 705 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">資源推薦</h3>
|
| 706 |
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
| 707 |
+
<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">
|
| 708 |
+
<h4 className="font-bold text-blue-800 mb-2">Roblox 開發者文檔</h4>
|
| 709 |
+
<p className="text-gray-700">官方開發文檔,包含詳細的 API 參考和教程</p>
|
| 710 |
+
</a>
|
| 711 |
+
<a href="https://developer.roblox.com/en-us/articles/ui-design" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
|
| 712 |
+
<h4 className="font-bold text-blue-800 mb-2">Roblox UI 設計指南</h4>
|
| 713 |
+
<p className="text-gray-700">官方關於 UI 設計的最佳實踐和指南</p>
|
| 714 |
+
</a>
|
| 715 |
+
<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">
|
| 716 |
+
<h4 className="font-bold text-blue-800 mb-2">Lua 程式設計指南</h4>
|
| 717 |
+
<p className="text-gray-700">學習 Lua 語言的官方手冊</p>
|
| 718 |
+
</a>
|
| 719 |
+
<a href="https://devforum.roblox.com/" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
|
| 720 |
+
<h4 className="font-bold text-blue-800 mb-2">Roblox 開發者論壇</h4>
|
| 721 |
+
<p className="text-gray-700">與其他開發者交流,獲取幫助和分享經驗</p>
|
| 722 |
+
</a>
|
| 723 |
+
</div>
|
| 724 |
+
</div>
|
| 725 |
+
</section>
|
| 726 |
+
|
| 727 |
+
{/* Navigation Buttons */}
|
| 728 |
+
<div className="flex justify-between mt-12">
|
| 729 |
+
<a
|
| 730 |
+
href="/lesson2"
|
| 731 |
+
className="px-6 py-3 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition-colors flex items-center"
|
| 732 |
+
>
|
| 733 |
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
|
| 734 |
+
<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" />
|
| 735 |
+
</svg>
|
| 736 |
+
上一課:賽車遊戲
|
| 737 |
+
</a>
|
| 738 |
+
<a
|
| 739 |
+
href="/lesson4"
|
| 740 |
+
className="px-6 py-3 bg-purple-600 text-white rounded-md hover:bg-purple-700 transition-colors flex items-center"
|
| 741 |
+
>
|
| 742 |
+
下一課:視覺化設計
|
| 743 |
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 ml-2" viewBox="0 0 20 20" fill="currentColor">
|
| 744 |
+
<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" />
|
| 745 |
+
</svg>
|
| 746 |
+
</a>
|
| 747 |
+
</div>
|
| 748 |
+
</motion.div>
|
| 749 |
+
</div>
|
| 750 |
+
</div>
|
| 751 |
+
);
|
| 752 |
+
}
|
src/pages/Lesson4Page.tsx
ADDED
|
@@ -0,0 +1,707 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { useState } from 'react';
|
| 2 |
+
import { motion } from 'framer-motion';
|
| 3 |
+
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
| 4 |
+
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
| 5 |
+
|
| 6 |
+
const cubeGeneratorScript = `
|
| 7 |
+
-- 立方體生成函數
|
| 8 |
+
local function createCube(position, size, color, transparency)
|
| 9 |
+
local cube = Instance.new("Part")
|
| 10 |
+
cube.Size = Vector3.new(size, size, size)
|
| 11 |
+
cube.Position = position
|
| 12 |
+
cube.Anchored = true
|
| 13 |
+
cube.CanCollide = false
|
| 14 |
+
cube.Material = Enum.Material.Neon
|
| 15 |
+
cube.Color = color or Color3.fromRGB(0, 170, 255)
|
| 16 |
+
cube.Transparency = transparency or 0.5
|
| 17 |
+
cube.Parent = workspace
|
| 18 |
+
|
| 19 |
+
-- 添加發光效果
|
| 20 |
+
local light = Instance.new("PointLight")
|
| 21 |
+
light.Range = size * 2
|
| 22 |
+
light.Brightness = 0.5
|
| 23 |
+
light.Color = color or Color3.fromRGB(0, 170, 255)
|
| 24 |
+
light.Parent = cube
|
| 25 |
+
|
| 26 |
+
return cube
|
| 27 |
+
end
|
| 28 |
+
|
| 29 |
+
-- 創建立方體網格陣列
|
| 30 |
+
local function createCubeGrid(centerPosition, gridSize, cubeSize, spacing)
|
| 31 |
+
local model = Instance.new("Model")
|
| 32 |
+
model.Name = "CubeGrid"
|
| 33 |
+
model.Parent = workspace
|
| 34 |
+
|
| 35 |
+
for x = -gridSize/2, gridSize/2 do
|
| 36 |
+
for y = -gridSize/2, gridSize/2 do
|
| 37 |
+
for z = -gridSize/2, gridSize/2 do
|
| 38 |
+
-- 計算位置
|
| 39 |
+
local position = centerPosition + Vector3.new(
|
| 40 |
+
x * (cubeSize + spacing),
|
| 41 |
+
y * (cubeSize + spacing),
|
| 42 |
+
z * (cubeSize + spacing)
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
-- 根據位置計算顏色(漸變效果)
|
| 46 |
+
local color = Color3.fromHSV(
|
| 47 |
+
(x + gridSize/2) / gridSize,
|
| 48 |
+
(y + gridSize/2) / gridSize,
|
| 49 |
+
(z + gridSize/2) / gridSize
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
-- 創建立方體
|
| 53 |
+
local cube = createCube(position, cubeSize, color, 0.5)
|
| 54 |
+
cube.Parent = model
|
| 55 |
+
end
|
| 56 |
+
end
|
| 57 |
+
end
|
| 58 |
+
|
| 59 |
+
return model
|
| 60 |
+
end
|
| 61 |
+
`;
|
| 62 |
+
|
| 63 |
+
const dnaStructureScript = `
|
| 64 |
+
-- 創建DNA雙螺旋結構
|
| 65 |
+
local function createDNAStructure(centerPosition, height, radius, turns)
|
| 66 |
+
local model = Instance.new("Model")
|
| 67 |
+
model.Name = "DNAStructure"
|
| 68 |
+
model.Parent = workspace
|
| 69 |
+
|
| 70 |
+
local pointsPerTurn = 20 -- 每圈點數
|
| 71 |
+
local totalPoints = turns * pointsPerTurn -- 總點數
|
| 72 |
+
|
| 73 |
+
-- 創建兩條螺旋骨架
|
| 74 |
+
for i = 0, totalPoints do
|
| 75 |
+
local angle = (i / pointsPerTurn) * math.pi * 2
|
| 76 |
+
local y = (i / totalPoints) * height
|
| 77 |
+
|
| 78 |
+
-- 第一條螺旋
|
| 79 |
+
local x1 = math.cos(angle) * radius
|
| 80 |
+
local z1 = math.sin(angle) * radius
|
| 81 |
+
local position1 = centerPosition + Vector3.new(x1, y, z1)
|
| 82 |
+
local cube1 = createCube(position1, 0.4, Color3.fromRGB(0, 200, 255), 0.3)
|
| 83 |
+
cube1.Parent = model
|
| 84 |
+
|
| 85 |
+
-- 第二條螺旋 (相位差180度)
|
| 86 |
+
local x2 = math.cos(angle + math.pi) * radius
|
| 87 |
+
local z2 = math.sin(angle + math.pi) * radius
|
| 88 |
+
local position2 = centerPosition + Vector3.new(x2, y, z2)
|
| 89 |
+
local cube2 = createCube(position2, 0.4, Color3.fromRGB(0, 255, 200), 0.3)
|
| 90 |
+
cube2.Parent = model
|
| 91 |
+
|
| 92 |
+
-- 每隔幾個點添加連接橫桿
|
| 93 |
+
if i % 4 == 0 then
|
| 94 |
+
-- 創建連接兩條螺旋的橫桿
|
| 95 |
+
local connector = Instance.new("Part")
|
| 96 |
+
connector.Size = Vector3.new(radius * 2, 0.2, 0.2)
|
| 97 |
+
connector.CFrame = CFrame.new(
|
| 98 |
+
centerPosition + Vector3.new((x1 + x2) / 2, y, (z1 + z2) / 2),
|
| 99 |
+
centerPosition + Vector3.new(x2, y, z2)
|
| 100 |
+
)
|
| 101 |
+
connector.Anchored = true
|
| 102 |
+
connector.CanCollide = false
|
| 103 |
+
connector.Material = Enum.Material.Neon
|
| 104 |
+
connector.Color = Color3.fromRGB(255, 255, 255)
|
| 105 |
+
connector.Transparency = 0.7
|
| 106 |
+
connector.Parent = model
|
| 107 |
+
end
|
| 108 |
+
end
|
| 109 |
+
|
| 110 |
+
return model
|
| 111 |
+
end
|
| 112 |
+
`;
|
| 113 |
+
|
| 114 |
+
const holographicProjectionScript = `
|
| 115 |
+
-- 服務引用
|
| 116 |
+
local RunService = game:GetService("RunService")
|
| 117 |
+
local TweenService = game:GetService("TweenService")
|
| 118 |
+
|
| 119 |
+
-- 常數設定
|
| 120 |
+
local GRID_SIZE = 20 -- 網格大小
|
| 121 |
+
local BASE_COLOR = Color3.fromRGB(0, 100, 150) -- 基本顏色(藍色)
|
| 122 |
+
|
| 123 |
+
-- 創建容器模型
|
| 124 |
+
local hologramModel = Instance.new("Model")
|
| 125 |
+
hologramModel.Name = "HologramModel"
|
| 126 |
+
hologramModel.Parent = workspace
|
| 127 |
+
|
| 128 |
+
-- 創建投影平台
|
| 129 |
+
local function createProjectionBase()
|
| 130 |
+
local base = Instance.new("Part")
|
| 131 |
+
base.Name = "ProjectionBase"
|
| 132 |
+
base.Size = Vector3.new(GRID_SIZE * 1.5, 0.5, GRID_SIZE * 1.5)
|
| 133 |
+
base.Position = Vector3.new(0, 0, 0)
|
| 134 |
+
base.Anchored = true
|
| 135 |
+
base.CanCollide = true
|
| 136 |
+
base.Material = Enum.Material.Neon
|
| 137 |
+
base.Color = BASE_COLOR
|
| 138 |
+
base.Transparency = 0.2
|
| 139 |
+
base.Parent = hologramModel
|
| 140 |
+
|
| 141 |
+
-- 添加投影光環
|
| 142 |
+
local ring = Instance.new("Part")
|
| 143 |
+
ring.Name = "ProjectionRing"
|
| 144 |
+
ring.Shape = Enum.PartType.Cylinder
|
| 145 |
+
ring.Size = Vector3.new(0.2, base.Size.X * 1.1, base.Size.Z * 1.1)
|
| 146 |
+
ring.CFrame = base.CFrame * CFrame.Angles(0, 0, math.rad(90))
|
| 147 |
+
ring.Anchored = true
|
| 148 |
+
ring.CanCollide = false
|
| 149 |
+
ring.Material = Enum.Material.Neon
|
| 150 |
+
ring.Color = Color3.fromRGB(0, 200, 255)
|
| 151 |
+
ring.Transparency = 0.5
|
| 152 |
+
ring.Parent = hologramModel
|
| 153 |
+
|
| 154 |
+
return base
|
| 155 |
+
end
|
| 156 |
+
|
| 157 |
+
-- 添加投影光束
|
| 158 |
+
local function createProjectionBeam(base)
|
| 159 |
+
-- 創建光束起點
|
| 160 |
+
local attachment1 = Instance.new("Attachment")
|
| 161 |
+
attachment1.Position = Vector3.new(0, -2, 0)
|
| 162 |
+
attachment1.Parent = base
|
| 163 |
+
|
| 164 |
+
-- 創建光束終點
|
| 165 |
+
local attachment2 = Instance.new("Attachment")
|
| 166 |
+
attachment2.Position = Vector3.new(0, 15, 0)
|
| 167 |
+
attachment2.Parent = base
|
| 168 |
+
|
| 169 |
+
-- 創建光束
|
| 170 |
+
local beam = Instance.new("Beam")
|
| 171 |
+
beam.Attachment0 = attachment1
|
| 172 |
+
beam.Attachment1 = attachment2
|
| 173 |
+
beam.Width0 = 5
|
| 174 |
+
beam.Width1 = 2
|
| 175 |
+
beam.FaceCamera = true
|
| 176 |
+
beam.LightEmission = 1
|
| 177 |
+
beam.LightInfluence = 0
|
| 178 |
+
beam.Transparency = NumberSequence.new({
|
| 179 |
+
NumberSequenceKeypoint.new(0, 0.7),
|
| 180 |
+
NumberSequenceKeypoint.new(1, 0.9)
|
| 181 |
+
})
|
| 182 |
+
beam.Color = ColorSequence.new(Color3.fromRGB(0, 200, 255))
|
| 183 |
+
beam.Parent = base
|
| 184 |
+
|
| 185 |
+
return beam
|
| 186 |
+
end
|
| 187 |
+
`;
|
| 188 |
+
|
| 189 |
+
export default function Lesson4Page() {
|
| 190 |
+
const [activeSection, setActiveSection] = useState('intro');
|
| 191 |
+
|
| 192 |
+
const scrollToSection = (sectionId: string) => {
|
| 193 |
+
setActiveSection(sectionId);
|
| 194 |
+
const element = document.getElementById(sectionId);
|
| 195 |
+
if (element) {
|
| 196 |
+
element.scrollIntoView({ behavior: 'smooth' });
|
| 197 |
+
}
|
| 198 |
+
};
|
| 199 |
+
|
| 200 |
+
return (
|
| 201 |
+
<div className="flex flex-col md:flex-row gap-6">
|
| 202 |
+
{/* Sidebar Navigation */}
|
| 203 |
+
<div className="md:w-1/4 lg:w-1/5">
|
| 204 |
+
<div className="bg-white rounded-xl shadow-md p-6 sticky top-24">
|
| 205 |
+
<h3 className="text-lg font-bold text-gray-800 mb-4">課程目錄</h3>
|
| 206 |
+
<nav className="space-y-2">
|
| 207 |
+
<button
|
| 208 |
+
onClick={() => scrollToSection('intro')}
|
| 209 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 210 |
+
activeSection === 'intro'
|
| 211 |
+
? 'bg-blue-100 text-blue-700'
|
| 212 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 213 |
+
}`}
|
| 214 |
+
>
|
| 215 |
+
課程簡介
|
| 216 |
+
</button>
|
| 217 |
+
<button
|
| 218 |
+
onClick={() => scrollToSection('part1')}
|
| 219 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 220 |
+
activeSection === 'part1'
|
| 221 |
+
? 'bg-blue-100 text-blue-700'
|
| 222 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 223 |
+
}`}
|
| 224 |
+
>
|
| 225 |
+
科技感圖像設計概念
|
| 226 |
+
</button>
|
| 227 |
+
<button
|
| 228 |
+
onClick={() => scrollToSection('part2')}
|
| 229 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 230 |
+
activeSection === 'part2'
|
| 231 |
+
? 'bg-blue-100 text-blue-700'
|
| 232 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 233 |
+
}`}
|
| 234 |
+
>
|
| 235 |
+
立方體模型建構
|
| 236 |
+
</button>
|
| 237 |
+
<button
|
| 238 |
+
onClick={() => scrollToSection('part3')}
|
| 239 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 240 |
+
activeSection === 'part3'
|
| 241 |
+
? 'bg-blue-100 text-blue-700'
|
| 242 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 243 |
+
}`}
|
| 244 |
+
>
|
| 245 |
+
科技感圖像實例
|
| 246 |
+
</button>
|
| 247 |
+
<button
|
| 248 |
+
onClick={() => scrollToSection('part4')}
|
| 249 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 250 |
+
activeSection === 'part4'
|
| 251 |
+
? 'bg-blue-100 text-blue-700'
|
| 252 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 253 |
+
}`}
|
| 254 |
+
>
|
| 255 |
+
立體投影效果實現
|
| 256 |
+
</button>
|
| 257 |
+
<button
|
| 258 |
+
onClick={() => scrollToSection('part5')}
|
| 259 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 260 |
+
activeSection === 'part5'
|
| 261 |
+
? 'bg-blue-100 text-blue-700'
|
| 262 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 263 |
+
}`}
|
| 264 |
+
>
|
| 265 |
+
互動控制與優化
|
| 266 |
+
</button>
|
| 267 |
+
<button
|
| 268 |
+
onClick={() => scrollToSection('summary')}
|
| 269 |
+
className={`w-full text-left px-3 py-2 rounded-md text-sm font-medium transition-colors ${
|
| 270 |
+
activeSection === 'summary'
|
| 271 |
+
? 'bg-blue-100 text-blue-700'
|
| 272 |
+
: 'text-gray-600 hover:bg-gray-100'
|
| 273 |
+
}`}
|
| 274 |
+
>
|
| 275 |
+
總結與進階挑戰
|
| 276 |
+
</button>
|
| 277 |
+
</nav>
|
| 278 |
+
</div>
|
| 279 |
+
</div>
|
| 280 |
+
|
| 281 |
+
{/* Main Content */}
|
| 282 |
+
<div className="md:w-3/4 lg:w-4/5">
|
| 283 |
+
<motion.div
|
| 284 |
+
initial={{ opacity: 0 }}
|
| 285 |
+
animate={{ opacity: 1 }}
|
| 286 |
+
transition={{ duration: 0.5 }}
|
| 287 |
+
>
|
| 288 |
+
<div className="bg-gradient-to-r from-blue-600 to-cyan-500 rounded-xl p-8 mb-8 text-white">
|
| 289 |
+
<h1 className="text-3xl md:text-4xl font-bold mb-4">Roblox 基礎入門第四課 - 視覺化程式設計:科技感立體投影圖像</h1>
|
| 290 |
+
<p className="text-lg opacity-90">
|
| 291 |
+
探索程式與視覺藝術的完美結合,使用立方體 Part 創建令人驚嘆的科技感立體投影
|
| 292 |
+
</p>
|
| 293 |
+
</div>
|
| 294 |
+
|
| 295 |
+
{/* Course Introduction */}
|
| 296 |
+
<section id="intro" className="mb-12 scroll-mt-24">
|
| 297 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">課程簡介</h2>
|
| 298 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 299 |
+
<p className="text-gray-700 mb-4">
|
| 300 |
+
本課程將帶領學習者探索 Roblox 中的視覺化程式設計,通過使用立方體 Part 創建科技感的立體投影圖像,展現程式與視覺藝術的完美結合。學習者將掌握如何使用程式化方法生成複雜的視覺效果,並實現互動式的立體投影展示。
|
| 301 |
+
</p>
|
| 302 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">課程目標</h3>
|
| 303 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 304 |
+
<li>在 Roblox Studio 中使用立方體 Part 創建複雜的科技感圖像</li>
|
| 305 |
+
<li>設計並實現立體投影效果</li>
|
| 306 |
+
<li>編寫程式控制圖像的動態變化與互動</li>
|
| 307 |
+
<li>掌握粒子效果與光源運用技巧</li>
|
| 308 |
+
</ul>
|
| 309 |
+
<h3 className="text-xl font-bold text-blue-700 mt-6 mb-3">前置準備</h3>
|
| 310 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 311 |
+
<li>已安裝最新版本的 Roblox Studio</li>
|
| 312 |
+
<li>具備 Roblox Studio 基本操作能力(第一課內容)</li>
|
| 313 |
+
<li>了解基本的 Lua 程式語法(第二課與第三課內容)</li>
|
| 314 |
+
<li>對視覺設計有基本興趣</li>
|
| 315 |
+
</ul>
|
| 316 |
+
</div>
|
| 317 |
+
</section>
|
| 318 |
+
|
| 319 |
+
{/* Part 1: Design Concepts */}
|
| 320 |
+
<section id="part1" className="mb-12 scroll-mt-24">
|
| 321 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第一部分:科技感圖像設計概念</h2>
|
| 322 |
+
|
| 323 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 324 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 1:了解科技感設計元素</h3>
|
| 325 |
+
<p className="text-gray-700 mb-4">
|
| 326 |
+
科技感設計通常包含以下元素:
|
| 327 |
+
</p>
|
| 328 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700 mb-4">
|
| 329 |
+
<li><strong>幾何形狀與線條</strong>:使用簡潔的幾何形狀、直線和網格</li>
|
| 330 |
+
<li><strong>色彩選擇</strong>:藍色、青色等冷色調,高對比度</li>
|
| 331 |
+
<li><strong>光影效果</strong>:發光、半透明、光束</li>
|
| 332 |
+
<li><strong>動態變化</strong>:脈衝、旋轉、懸浮效果</li>
|
| 333 |
+
</ul>
|
| 334 |
+
<p className="text-gray-700 mb-4">
|
| 335 |
+
在 Roblox 中,我們可以通過以下方式實現這些元素:
|
| 336 |
+
</p>
|
| 337 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 338 |
+
<li>使用立方體 Part 創建基本形狀</li>
|
| 339 |
+
<li>調整材質、顏色和透明度</li>
|
| 340 |
+
<li>添加光源和粒子效果</li>
|
| 341 |
+
<li>使用腳本控制動態變化</li>
|
| 342 |
+
</ul>
|
| 343 |
+
</div>
|
| 344 |
+
|
| 345 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 346 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 2:規劃立方體陣列設計</h3>
|
| 347 |
+
<p className="text-gray-700 mb-4">
|
| 348 |
+
立方體陣列是創建複雜科技感圖像的基礎,主要設計思路包括:
|
| 349 |
+
</p>
|
| 350 |
+
<div className="space-y-4">
|
| 351 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 352 |
+
<h4 className="font-bold text-blue-800 mb-2">點陣圖像原理</h4>
|
| 353 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 354 |
+
<li>將三維空間劃分為網格</li>
|
| 355 |
+
<li>每個網格點放置一個立方體</li>
|
| 356 |
+
<li>通過控制立方體的存在、大小、顏色等屬性形成圖像</li>
|
| 357 |
+
</ul>
|
| 358 |
+
</div>
|
| 359 |
+
|
| 360 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 361 |
+
<h4 className="font-bold text-blue-800 mb-2">模塊化設計</h4>
|
| 362 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 363 |
+
<li>將複雜圖像分解為簡單模塊</li>
|
| 364 |
+
<li>使用函數生成不同的模塊</li>
|
| 365 |
+
<li>組合模塊形成完整圖像</li>
|
| 366 |
+
</ul>
|
| 367 |
+
</div>
|
| 368 |
+
|
| 369 |
+
<div className="bg-blue-50 p-4 rounded-lg">
|
| 370 |
+
<h4 className="font-bold text-blue-800 mb-2">數據驅動設計</h4>
|
| 371 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 372 |
+
<li>使用數學函數生成立方體位置</li>
|
| 373 |
+
<li>使用參數控制整體效果</li>
|
| 374 |
+
<li>實現動態變化和互動</li>
|
| 375 |
+
</ul>
|
| 376 |
+
</div>
|
| 377 |
+
</div>
|
| 378 |
+
</div>
|
| 379 |
+
|
| 380 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 381 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 3:創建新專案</h3>
|
| 382 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700">
|
| 383 |
+
<li>打開 Roblox Studio</li>
|
| 384 |
+
<li>選擇「基礎模板」創建新專案</li>
|
| 385 |
+
<li>保存專案,命名為「HolographicProjection」</li>
|
| 386 |
+
</ol>
|
| 387 |
+
</div>
|
| 388 |
+
</section>
|
| 389 |
+
|
| 390 |
+
{/* Part 2: Cube Model Construction */}
|
| 391 |
+
<section id="part2" className="mb-12 scroll-mt-24">
|
| 392 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第二部分:立方體模型建構</h2>
|
| 393 |
+
|
| 394 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 395 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 1:創建基本立方體</h3>
|
| 396 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 397 |
+
<li>在工作區中插入一個方塊部件(Part)</li>
|
| 398 |
+
<li>調整立方體屬性:
|
| 399 |
+
<ul className="list-disc pl-6 mt-2 space-y-1">
|
| 400 |
+
<li>Size: 0.5, 0.5, 0.5 (寬, 高, 長)</li>
|
| 401 |
+
<li>Color: 設置為藍色 (0, 170, 255)</li>
|
| 402 |
+
<li>Material: Neon</li>
|
| 403 |
+
<li>Transparency: 0.5</li>
|
| 404 |
+
<li>Anchored: true</li>
|
| 405 |
+
<li>CanCollide: false</li>
|
| 406 |
+
</ul>
|
| 407 |
+
</li>
|
| 408 |
+
<li>添加發光效果:
|
| 409 |
+
<ul className="list-disc pl-6 mt-2 space-y-1">
|
| 410 |
+
<li>在立方體中添加 PointLight</li>
|
| 411 |
+
<li>Range: 1</li>
|
| 412 |
+
<li>Brightness: 0.5</li>
|
| 413 |
+
<li>Color: 與立方體相同顏色</li>
|
| 414 |
+
</ul>
|
| 415 |
+
</li>
|
| 416 |
+
</ol>
|
| 417 |
+
</div>
|
| 418 |
+
|
| 419 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 420 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 2:創建立方體生成函數</h3>
|
| 421 |
+
<p className="text-gray-700 mb-4">
|
| 422 |
+
為了更有效地創建多個立方體,我們需要編寫一個函數來生成它們:
|
| 423 |
+
</p>
|
| 424 |
+
<ol className="list-decimal pl-6 space-y-2 text-gray-700 mb-4">
|
| 425 |
+
<li>在 ServerScriptService 中添加腳本,命名為「CubeGenerator」</li>
|
| 426 |
+
<li>編寫立方體生成函數</li>
|
| 427 |
+
<li>測試立方體生成</li>
|
| 428 |
+
</ol>
|
| 429 |
+
<SyntaxHighlighter language="lua" style={vscDarkPlus} className="rounded-lg">
|
| 430 |
+
{cubeGeneratorScript}
|
| 431 |
+
</SyntaxHighlighter>
|
| 432 |
+
</div>
|
| 433 |
+
|
| 434 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 435 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 3:創建立方體陣列</h3>
|
| 436 |
+
<p className="text-gray-700 mb-4">
|
| 437 |
+
使用迴圈創建立方體陣列,形成基本的三維網格結構:
|
| 438 |
+
</p>
|
| 439 |
+
<div className="bg-gray-100 p-4 rounded-lg mb-4">
|
| 440 |
+
<p className="text-gray-700 font-mono">
|
| 441 |
+
-- 創建一個 5x5x5 的立方體網格<br/>
|
| 442 |
+
local grid = createCubeGrid(Vector3.new(0, 10, 0), 5, 0.5, 0.2)
|
| 443 |
+
</p>
|
| 444 |
+
</div>
|
| 445 |
+
<p className="text-gray-700">
|
| 446 |
+
這段代碼將在空間中創建一個 5x5x5 的立方體網格,每個立方體大小為 0.5,間距為 0.2,中心位置在 (0, 10, 0)。
|
| 447 |
+
</p>
|
| 448 |
+
</div>
|
| 449 |
+
</section>
|
| 450 |
+
|
| 451 |
+
{/* Part 3: Tech Image Examples */}
|
| 452 |
+
<section id="part3" className="mb-12 scroll-mt-24">
|
| 453 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第三部分:科技感圖像實例</h2>
|
| 454 |
+
|
| 455 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 456 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 1:創建 DNA 雙螺旋結構</h3>
|
| 457 |
+
<p className="text-gray-700 mb-4">
|
| 458 |
+
DNA 雙螺旋是一個很好的科技感圖像範例,我們可以使用立方體來構建它:
|
| 459 |
+
</p>
|
| 460 |
+
<SyntaxHighlighter language="lua" style={vscDarkPlus} className="rounded-lg mb-4">
|
| 461 |
+
{dnaStructureScript}
|
| 462 |
+
</SyntaxHighlighter>
|
| 463 |
+
<div className="bg-gray-100 p-4 rounded-lg">
|
| 464 |
+
<p className="text-gray-700 font-mono">
|
| 465 |
+
-- 創��一個 DNA 雙螺旋結構<br/>
|
| 466 |
+
local dna = createDNAStructure(Vector3.new(0, 5, 0), 15, 3, 3)
|
| 467 |
+
</p>
|
| 468 |
+
</div>
|
| 469 |
+
</div>
|
| 470 |
+
|
| 471 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 472 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 2:創建全息投影地球</h3>
|
| 473 |
+
<p className="text-gray-700 mb-4">
|
| 474 |
+
全息地球是另一個很酷的科技感圖像,使用立方體點陣模擬球體:
|
| 475 |
+
</p>
|
| 476 |
+
<div className="bg-blue-50 p-4 rounded-lg mb-4">
|
| 477 |
+
<h4 className="font-bold text-blue-800 mb-2">全息地球實現原理</h4>
|
| 478 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 479 |
+
<li>使用球面坐標系(緯度、經度)計算立方體位置</li>
|
| 480 |
+
<li>根據隨機值決定是陸地還是海洋,設置不同顏色</li>
|
| 481 |
+
<li>添加經緯線網格增強科技感</li>
|
| 482 |
+
</ul>
|
| 483 |
+
</div>
|
| 484 |
+
<p className="text-gray-700">
|
| 485 |
+
實現代碼會創建一個由小立方體組成的球體,模擬地球表面,並添加經緯線網格增強科技感。
|
| 486 |
+
</p>
|
| 487 |
+
</div>
|
| 488 |
+
|
| 489 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 490 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 3:創建 3D 數據可視化圖表</h3>
|
| 491 |
+
<p className="text-gray-700 mb-4">
|
| 492 |
+
數據可視化是科技感圖像的重要應用:
|
| 493 |
+
</p>
|
| 494 |
+
<div className="bg-blue-50 p-4 rounded-lg mb-4">
|
| 495 |
+
<h4 className="font-bold text-blue-800 mb-2">3D 數據圖表實現要點</h4>
|
| 496 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 497 |
+
<li>創建 X、Y、Z 三個坐標軸</li>
|
| 498 |
+
<li>根據數據值生成不同高度的柱體</li>
|
| 499 |
+
<li>使用顏色漸變表示數據值大小</li>
|
| 500 |
+
</ul>
|
| 501 |
+
</div>
|
| 502 |
+
<p className="text-gray-700">
|
| 503 |
+
實現代碼會創建一個三維座標系,並在其中生成數據柱體,柱體高度和顏色根據數據值變化。
|
| 504 |
+
</p>
|
| 505 |
+
</div>
|
| 506 |
+
</section>
|
| 507 |
+
|
| 508 |
+
{/* Part 4: Holographic Projection */}
|
| 509 |
+
<section id="part4" className="mb-12 scroll-mt-24">
|
| 510 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第四部分:立體投影效果實現</h2>
|
| 511 |
+
|
| 512 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 513 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 1:創建投影平台</h3>
|
| 514 |
+
<p className="text-gray-700 mb-4">
|
| 515 |
+
投影平台是立體投影效果的基礎:
|
| 516 |
+
</p>
|
| 517 |
+
<SyntaxHighlighter language="lua" style={vscDarkPlus} className="rounded-lg">
|
| 518 |
+
{holographicProjectionScript}
|
| 519 |
+
</SyntaxHighlighter>
|
| 520 |
+
</div>
|
| 521 |
+
|
| 522 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 523 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 2:添加投影光效</h3>
|
| 524 |
+
<p className="text-gray-700 mb-4">
|
| 525 |
+
為了增強立體投影效果,我們需要添加光效:
|
| 526 |
+
</p>
|
| 527 |
+
<div className="bg-blue-50 p-4 rounded-lg mb-4">
|
| 528 |
+
<h4 className="font-bold text-blue-800 mb-2">投影光效關鍵元素</h4>
|
| 529 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 530 |
+
<li>光束效果:使用 Beam 物件創建從底部向上的光束</li>
|
| 531 |
+
<li>環繞粒子:使用 ParticleEmitter 創建環繞投影的粒子效果</li>
|
| 532 |
+
<li>脈衝光環:使用 TweenService 創建平台邊緣的脈衝光環</li>
|
| 533 |
+
</ul>
|
| 534 |
+
</div>
|
| 535 |
+
<p className="text-gray-700">
|
| 536 |
+
這些視覺效果結合起來,能夠創造出逼真的科幻全息投影感。
|
| 537 |
+
</p>
|
| 538 |
+
</div>
|
| 539 |
+
|
| 540 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 541 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 3:實現投影切換效果</h3>
|
| 542 |
+
<p className="text-gray-700 mb-4">
|
| 543 |
+
為了展示不同的科技感圖像,我們需要實現投影切換功能:
|
| 544 |
+
</p>
|
| 545 |
+
<div className="bg-blue-50 p-4 rounded-lg mb-4">
|
| 546 |
+
<h4 className="font-bold text-blue-800 mb-2">投影切換實現方法</h4>
|
| 547 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 548 |
+
<li>創建切換按鈕,添加點擊事件</li>
|
| 549 |
+
<li>設置模型顯示/隱藏邏輯</li>
|
| 550 |
+
<li>添加切換時的視覺效果(如淡入淡出、粒子爆發等)</li>
|
| 551 |
+
</ul>
|
| 552 |
+
</div>
|
| 553 |
+
<p className="text-gray-700">
|
| 554 |
+
通過這種方式,玩家可以輕鬆切換不同的科技感圖像,增強互動體驗。
|
| 555 |
+
</p>
|
| 556 |
+
</div>
|
| 557 |
+
</section>
|
| 558 |
+
|
| 559 |
+
{/* Part 5: Interactive Control */}
|
| 560 |
+
<section id="part5" className="mb-12 scroll-mt-24">
|
| 561 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">第五部分:互動控制與優化</h2>
|
| 562 |
+
|
| 563 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 564 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 1:添加旋轉控制</h3>
|
| 565 |
+
<p className="text-gray-700 mb-4">
|
| 566 |
+
為了讓玩家能夠從不同角度觀察投影模型,我們可以添加旋轉控制:
|
| 567 |
+
</p>
|
| 568 |
+
<div className="bg-gray-100 p-4 rounded-lg mb-4">
|
| 569 |
+
<p className="text-gray-700 font-mono">
|
| 570 |
+
-- 添加旋轉功能<br/>
|
| 571 |
+
RunService.Heartbeat:Connect(function(deltaTime)<br/>
|
| 572 |
+
-- 緩慢旋轉當前顯示的模型<br/>
|
| 573 |
+
if displays[currentDisplay].Parent == hologramModel then<br/>
|
| 574 |
+
displays[currentDisplay]:SetPrimaryPartCFrame(<br/>
|
| 575 |
+
displays[currentDisplay].PrimaryPart.CFrame * CFrame.Angles(0, deltaTime * 0.5, 0)<br/>
|
| 576 |
+
)<br/>
|
| 577 |
+
end<br/>
|
| 578 |
+
end)
|
| 579 |
+
</p>
|
| 580 |
+
</div>
|
| 581 |
+
<p className="text-gray-700">
|
| 582 |
+
這段代碼會使當前顯示的模型緩慢旋轉,讓玩家可以看到模型的各個角度。
|
| 583 |
+
</p>
|
| 584 |
+
</div>
|
| 585 |
+
|
| 586 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 587 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 2:添加縮放控制</h3>
|
| 588 |
+
<p className="text-gray-700 mb-4">
|
| 589 |
+
添加縮放控制可以讓玩家更詳細地觀察模型:
|
| 590 |
+
</p>
|
| 591 |
+
<div className="bg-blue-50 p-4 rounded-lg mb-4">
|
| 592 |
+
<h4 className="font-bold text-blue-800 mb-2">縮放控制實現方法</h4>
|
| 593 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 594 |
+
<li>創建縮放按鈕(放大/縮小)</li>
|
| 595 |
+
<li>使用 TweenService 平滑過渡縮放效果</li>
|
| 596 |
+
<li>設置縮放限制,防止模型過大或過小</li>
|
| 597 |
+
</ul>
|
| 598 |
+
</div>
|
| 599 |
+
<p className="text-gray-700">
|
| 600 |
+
通過縮放控制,玩家可以放大查看模型細節,或縮小查看整體效果。
|
| 601 |
+
</p>
|
| 602 |
+
</div>
|
| 603 |
+
|
| 604 |
+
<div className="bg-white rounded-xl shadow-md p-6">
|
| 605 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">步驟 3:優化性能</h3>
|
| 606 |
+
<p className="text-gray-700 mb-4">
|
| 607 |
+
由於我們使用了大量立方體,需要注意性能優化:
|
| 608 |
+
</p>
|
| 609 |
+
<div className="bg-blue-50 p-4 rounded-lg mb-4">
|
| 610 |
+
<h4 className="font-bold text-blue-800 mb-2">性能優化技巧</h4>
|
| 611 |
+
<ul className="list-disc pl-6 space-y-1 text-gray-700">
|
| 612 |
+
<li>使用 LOD(細節層次):根據距離調整立方體數量</li>
|
| 613 |
+
<li>對象池技術:重用立方體而非創建新的</li>
|
| 614 |
+
<li>視錐體剔除:只渲染視野內的立方體</li>
|
| 615 |
+
<li>減少光源數量:合理控制發光效果</li>
|
| 616 |
+
</ul>
|
| 617 |
+
</div>
|
| 618 |
+
<p className="text-gray-700">
|
| 619 |
+
通過這些優化技巧,可以在保持視覺效果的同時提高遊戲性能。
|
| 620 |
+
</p>
|
| 621 |
+
</div>
|
| 622 |
+
</section>
|
| 623 |
+
|
| 624 |
+
{/* Summary and Challenge */}
|
| 625 |
+
<section id="summary" className="mb-12 scroll-mt-24">
|
| 626 |
+
<h2 className="text-2xl font-bold text-gray-800 mb-4">總結與進階挑戰</h2>
|
| 627 |
+
|
| 628 |
+
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
|
| 629 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">課程總結</h3>
|
| 630 |
+
<p className="text-gray-700 mb-4">
|
| 631 |
+
在本課程中,我們學習了如何在 Roblox Studio 中使用立方體 Part 創建科技感的立體投影圖像。我們掌握了以下關鍵技能:
|
| 632 |
+
</p>
|
| 633 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 634 |
+
<li>使用程式化方法生成複雜的立方體陣列</li>
|
| 635 |
+
<li>創建 DNA 雙螺旋、全息地球等科技感圖像</li>
|
| 636 |
+
<li>實現立體投影效果,包括投影平台、光束和粒子效果</li>
|
| 637 |
+
<li>添加互動控制,如切換顯示、旋轉和縮放</li>
|
| 638 |
+
<li>優化性能,確保流暢運行</li>
|
| 639 |
+
</ul>
|
| 640 |
+
<p className="text-gray-700 mt-4">
|
| 641 |
+
這些技能可以應用於各種 Roblox 遊戲和體驗,如科幻遊戲、教育應用、數據可視化等。
|
| 642 |
+
</p>
|
| 643 |
+
</div>
|
| 644 |
+
|
| 645 |
+
<div className="bg-gradient-to-r from-blue-50 to-cyan-50 rounded-xl shadow-md p-6 mb-6">
|
| 646 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">進階挑戰</h3>
|
| 647 |
+
<p className="text-gray-700 mb-4">
|
| 648 |
+
想要進一步提升您的視覺化程式設計技能?嘗試以下挑戰:
|
| 649 |
+
</p>
|
| 650 |
+
<ul className="list-disc pl-6 space-y-2 text-gray-700">
|
| 651 |
+
<li>創建更複雜的科技感圖像,如太陽系模型、分子結構等</li>
|
| 652 |
+
<li>添加聲音效果,增強沉浸感</li>
|
| 653 |
+
<li>實現手勢控制,讓玩家可以用手勢旋轉和縮放模型</li>
|
| 654 |
+
<li>添加數據連接功能,實時顯示外部數據源的信息</li>
|
| 655 |
+
<li>創建可編程界面,讓玩家自定義立方體陣列</li>
|
| 656 |
+
</ul>
|
| 657 |
+
</div>
|
| 658 |
+
|
| 659 |
+
<div className="bg-gradient-to-r from-cyan-50 to-blue-50 rounded-xl shadow-md p-6">
|
| 660 |
+
<h3 className="text-xl font-bold text-blue-700 mb-3">資源推薦</h3>
|
| 661 |
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
| 662 |
+
<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">
|
| 663 |
+
<h4 className="font-bold text-blue-800 mb-2">Roblox 開發者文檔</h4>
|
| 664 |
+
<p className="text-gray-700">官方開發文檔,包含詳細的 API 參考和教程</p>
|
| 665 |
+
</a>
|
| 666 |
+
<a href="https://developer.roblox.com/en-us/articles/Particle-Emitters" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
|
| 667 |
+
<h4 className="font-bold text-blue-800 mb-2">粒子效果指南</h4>
|
| 668 |
+
<p className="text-gray-700">學習如何創建和自定義粒子效果</p>
|
| 669 |
+
</a>
|
| 670 |
+
<a href="https://devforum.roblox.com/c/resources/visualization/55" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
|
| 671 |
+
<h4 className="font-bold text-blue-800 mb-2">視覺化資源</h4>
|
| 672 |
+
<p className="text-gray-700">Roblox 開發者論壇中的視覺化資源和討論</p>
|
| 673 |
+
</a>
|
| 674 |
+
<a href="https://www.youtube.com/results?search_query=roblox+studio+hologram+effect" target="_blank" rel="noopener noreferrer" className="bg-white p-4 rounded-lg shadow hover:shadow-md transition-shadow">
|
| 675 |
+
<h4 className="font-bold text-blue-800 mb-2">全息效果教學</h4>
|
| 676 |
+
<p className="text-gray-700">YouTube 上的全息效果教學視頻</p>
|
| 677 |
+
</a>
|
| 678 |
+
</div>
|
| 679 |
+
</div>
|
| 680 |
+
</section>
|
| 681 |
+
|
| 682 |
+
{/* Navigation Buttons */}
|
| 683 |
+
<div className="flex justify-between mt-12">
|
| 684 |
+
<a
|
| 685 |
+
href="/lesson3"
|
| 686 |
+
className="px-6 py-3 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition-colors flex items-center"
|
| 687 |
+
>
|
| 688 |
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 mr-2" viewBox="0 0 20 20" fill="currentColor">
|
| 689 |
+
<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" />
|
| 690 |
+
</svg>
|
| 691 |
+
上一課:機關門與數學題
|
| 692 |
+
</a>
|
| 693 |
+
<a
|
| 694 |
+
href="/"
|
| 695 |
+
className="px-6 py-3 bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors flex items-center"
|
| 696 |
+
>
|
| 697 |
+
返回首頁
|
| 698 |
+
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 ml-2" viewBox="0 0 20 20" fill="currentColor">
|
| 699 |
+
<path d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z" />
|
| 700 |
+
</svg>
|
| 701 |
+
</a>
|
| 702 |
+
</div>
|
| 703 |
+
</motion.div>
|
| 704 |
+
</div>
|
| 705 |
+
</div>
|
| 706 |
+
);
|
| 707 |
+
}
|