Level 1 • Day 7 Final Exam

Weekly Review Quiz & Graduation Exam

Day 7 of 7-Day Foundation • Grand Finale

ยินดีด้วยครับ! คุณมาถึง Day 7
Weekly Review Quiz & Graduation Exam

คุณได้ผ่านการฝึกฝนเข้มข้นมาครบ 6 วัน ทั้งเรื่อง Composition vs Inheritance, Type Safety, Node Lifecycles, Scene Unique Nodes (%), Dynamic Spawning และ Pure Component Design วันนี้คือบทสรุปเพื่อประเมินความรู้และลงมือสร้างมินิเกมวัดผลจริง "Modular Cannon Defense" เพื่อรับวุฒิบัตร Architect Grade!

10m

1. Architectural Quiz

ทบทวน 8 ข้อสำคัญ

15m

2. Exam Project

สร้าง Cannon Defense

5m

3. Level 2 Preview

Physics & CharacterBody2D

D7

คีย์เวิร์ดแห่งชัยชนะ Level 1

"เขียนสถาปัตยกรรมที่ยืดหยุ่น: ตัดขาดการผูกติด ส่งสัญญาณขึ้น เรียกคำสั่งลง พิมพ์ Type ชัดเจนทุกบรรทัด"

8/8 Architecture Mastery
Pure Modular Composition
100% Type-Safe & Robust UI
Step 1 • 10 Minutes Assessment

1. Weekly Review Quiz (แบบทดสอบสถาปัตยกรรมและการแก้บัค 8 ข้อ)

ลองทดสอบตนเองกับ 8 สถานการณ์จำลองที่โปรแกรมเมอร์มักเจอใน Godot 4 ตอบคำถามในใจก่อนกดดูเฉลยเพื่อทดสอบความแม่นยำทางสถาปัตยกรรมครับ:

ข้อที่ 1 Day 2 & 3 • Lifecycle
สถานการณ์: นักพัฒนาเขียนโค้ด @onready var sprite = $Sprite2D แต่เรียกใช้ sprite.visible = false ภายในฟังก์ชัน _init() แล้วเกมค้าง เกิดจากสาเหตุใด?
กดดูเฉลยข้อ 1
เฉลย: เกิด Null Instance Error!

เพราะในขั้นตอน _init() วัตถุเพิ่งถูกจัดสรรในหน่วยความจำ ยังไม่ได้ถูกนำเข้าสู่ SceneTree จึงยังไม่มี Node ลูก ($Sprite2D) อยู่จริง ต้องเรียกใช้หลัง _ready() หรือในฟังก์ชันหลังจากเข้า Tree แล้วเท่านั้น

ข้อที่ 2 Day 3 • Execution Order
สถานการณ์: หากมีโครงสร้าง ParentNode -> ChildNode ฟังก์ชัน _ready() ของ Node ใดจะทำงานเสร็จสิ้นก่อนกัน?
กดดูเฉลยข้อ 2
เฉลย: ChildNode จะทำงานเสร็จก่อน!

เพราะ Godot ใช้ลำดับการทำ _ready() แบบ Bottom-Up (จากลูกขึ้นไปหาแม่) เพื่อให้มั่นใจว่าเมื่อ Node แม่ทำ _ready() Node ลูกทั้งหมดจะเตรียมพร้อมและมีข้อมูลสมบูรณ์แล้ว

ข้อที่ 3 Day 4 • Unique Scope (%)
สถานการณ์: หากเราตั้งชื่อ %ScoreLabel ใน HUD.tscn แล้วนำ HUD.tscn ไป Instance ใส่ใน MainGame.tscn สคริปต์ของ MainGame.gd จะสามารถเรียก %ScoreLabel ตรงๆ ได้หรือไม่?
กดดูเฉลยข้อ 3
เฉลย: ไม่ได้ครับ! (เกิด Null Error)

เพราะ Scene Unique Node (%) มีขอบเขตการใช้งาน (Scope) เฉพาะภายใน Scene เดียวกันเท่านั้น เพื่อรักษาหลัก Encapsulation สคริปต์ภายนอกต้องเข้าถึงผ่านฟังก์ชันของตัวแม่ เช่น $HUD.update_score() หรือส่งข้อมูลผ่าน Signal

ข้อที่ 4 Day 5 • preload vs load
สถานการณ์: ในเกมประเภท Bullet Hell ที่ต้องสร้างกระสุน 50 นัดต่อวินาที หากใช้ load("res://Bullet.tscn") ด้านในฟังก์ชันยิงกระสุน จะเกิดผลเสียอย่างไร?
กดดูเฉลยข้อ 4
เฉลย: เกมจะกระตุกอย่างรุนแรง (Runtime I/O Stutter)!

เนื่องจากเอนจินต้องอ่านและ Parse ไฟล์จากฮาร์ดดิสก์ใหม่ทุกครั้งที่ยิง ควรใช้ preload("res://Bullet.tscn") ที่คอมไพล์ไว้ล่วงหน้า หรือใช้ @export var bullet_scene: PackedScene

ข้อที่ 5 Day 5 • Memory Cleanup
สถานการณ์: ทำไมเราถึงควรใช้ queue_free() แทนการใช้ free() กับ Node ที่อยู่ใน SceneTree?
กดดูเฉลยข้อ 5
เฉลย: ป้องกัน Dangling Pointer Crash!

queue_free() จะรอให้รอบการประมวลผลของ Frame ปัจจุบันทำงานเสร็จสิ้นก่อนจึงค่อยลบ Node ออกจาก RAM อย่างปลอดภัย ป้องกันปัญหาที่สคริปต์อื่นหรือระบบฟิสิกส์กำลังพยายามอ้างอิง Node นั้นอยู่ในเฟรมเดียวกัน

ข้อที่ 6 Day 4 • Fragile Pathing
สถานการณ์: โค้ด $UI/MarginContainer/VBoxContainer/Panel/Label.text = "HP" มีจุดอ่อนอย่างไรในเชิง Game Architecture?
กดดูเฉลยข้อ 6
เฉลย: เป็น Brittle Node Path ที่เปราะบางอย่างยิ่ง!

หากฝ่าย UI ปรับเปลี่ยนโครงสร้างเพียงชั้นเดียว (เช่น แทรก HBoxContainer หรือเปลี่ยน Panel) พาทจะหลุดและเกมจะแครชทันที ควรแก้ไขโดยใช้ Scene Unique Node (%Label) หรือสร้างฟังก์ชันอัปเดตจากตัวแม่ลงมา

ข้อที่ 7 Day 1 • Delta Math
สถานการณ์: หากเราเขียนโค้ด position.x += speed * delta ใน _process() ข้อดีของการคูณ delta คืออะไร?
กดดูเฉลยข้อ 7
เฉลย: Frame-rate Independence!

ทำให้ความเร็วในการเคลื่อนที่ของวัตถุเท่ากันในทุกเครื่องคอมพิวเตอร์อย่างคงที่ ไม่ว่าเครื่องนั้นจะรันเกมที่ 30 FPS, 60 FPS หรือจอ 144 FPS ก็ตาม

ข้อที่ 8 Day 6 • Call Down, Signal Up
สถานการณ์: เมื่อ HealthComponent มีค่า HP ลดลงจนเหลือ 0 มันควรสั่ง get_tree().change_scene_to_file() เพื่อเปลี่ยนเป็นหน้า Game Over โดยตรงหรือไม่?
กดดูเฉลยข้อ 8
เฉลย: ไม่ควรทำเด็ดขาด! (ทำลาย Reusability)

เพราะจะทำให้ HealthComponent ไม่สามารถนำไปใช้กับวัตถุอื่นๆ (เช่น ศัตรู หรือ กล่องไม้พังได้) ได้อีก ควรปล่อยสัญญาณ died ออกไปแทน แล้วให้ Node แม่หรือ Level Manager เป็นผู้จัดการตัดสินใจเปลี่ยนฉากตามบริบทของตนเอง

Step 2 • Hands-on Project Exam

2. Level 1 Graduation Exam: "Modular Cannon Defense"

Architecture Capstone Project

โจทย์โปรเจกต์มินิเกม (Mini-Game Specification):

สร้างเกมป้องกันป้อมปืน 2D ที่ประกอบด้วยป้อมปืนยิงเป้าหมาย โดยต้องประยุกต์ใช้ความรู้ทั้งหมดจาก Day 1 ถึง Day 6 อย่างเคร่งครัด เน้นการแบ่งโมดูลแบบ Pure Composition และ Type Safety 100%

1
1. Turret System

ป้อมปืนหมุนตามตำแหน่งเมาส์ (look_at) และยิงกระสุนออกจากปากกระบอก (Marker2D) เมื่อคลิกเมาส์ซ้าย มี Cooldown Timer

2
2. Bullet System

กระสุนถูกเสกจาก PackedScene บินไปข้างหน้าตาม transform.x และลบตนเองอัตโนมัติด้วย queue_free() เมื่อครบ 3 วินาที

3
3. Target Dummy System

เป้าหมายใช้ HealthComponent เมื่อถูกกระสุนชนจะลด HP และลบตนเองออกจากเกมพร้อมส่ง Signal แจ้งเตือนเมื่อ HP เหลือ 0

4
4. UI HUD System

แสดงคะแนนปัจจุบัน โดยใช้อ้างอิงแบบ Scene Unique Node (%ScoreLabel) อัปเดตผ่าน Signal เมื่อเป้าหมายถูกทำลาย

โครงสร้าง Node Tree ที่กำหนดสำหรับ MainGame.tscn Pure Composition Architecture
MainGame (Node2D) [สคริปต์ MainGame.gd - ตัวประสานงานหลัก]
├── Turret (Node2D)
│ └── Muzzle (Marker2D) [แนบ TurretMuzzle.gd พร้อม export bullet_scene]
├── TargetDummy (Node2D)
│ ├── Sprite2D [รูปเป้าหมาย]
│ ├── Area2D (Hurtbox) [CollisionShape2D ตรวจจับกระสุนชน]
│ └── HealthComponent (Node) [แนบ HealthComponent.gd ที่ทำใน Day 6]
└── CanvasLayer (UI)
    └── HUD (Control)
        └── MarginContainer
            └── Label (%ScoreLabel) [เปิด Access as Unique Name]
เคล็ดลับสถาปัตยกรรมระดับ Architect:

จำกฎ "Call Down, Signal Up" ให้แม่นยำครับ: เมื่อกระสุนชนเป้าหมาย ให้ Area2D ของเป้าหมายเรียก health_component.take_damage(25) ลงไป และเมื่อ HP หมด HealthComponent จะส่ง Signal died ขึ้นมาบอก TargetDummy ให้ทำลายตัวเองและบอก MainGame ให้เพิ่มคะแนนบน %ScoreLabel โดยไม่มีการเรียกข้าม Scene Tree ให้ผิดหลักการแม้แต่จุดเดียว!

Step 3 • Grading Criteria

3. เกณฑ์การประเมินผลระดับ Architect (Evaluation Rubric)

ใช้เกณฑ์การประเมินนี้ในการตรวจเช็คโค้ดของตนเอง เพื่อตรวจสอบว่าคุณภาพงานอยู่ในระดับมืออาชีพแล้วหรือยัง:

หัวข้อประเมิน (Criteria) 1 คะแนน (ต้องปรับปรุง) 3 คะแนน (ผ่านเกณฑ์) 5 คะแนน (ระดับ Architecture Grade) 🏆
Node Composition
เขียนโค้ดทุกอย่างรวมไว้ในสคริปต์เดียวที่ Root Node (Monolithic script) แยก Scene แต่ยังมี NodePath ผูกติดกันแน่น เช่น get_parent().get_node(...) ใช้ Pure Component (HealthComponent) แยกอิสระ 100% ไร้เงาของ Parent นำไป Reuse กับวัตถุใดก็ได้ทันที
GDScript Type Safety
ไม่ระบุ Static Type เลย หรือใช้ var ลอยๆ ทั้งหมด ไม่มี Type Hinting ระบุ Type เฉพาะตัวแประดับ Class แต่ฟังก์ชันและ Parameter ไม่มี Type และไม่มี Return Type ใช้ Strict Static Typing 100% (: Type, -> void), มี @export_range, และ @onready ครบถ้วน
Signal & Event Flow
เรียกฟังก์ชันข้าม Scene ตรงๆ โดยไม่ใช้ Signal ทำให้เกิดการผูกมัดแน่น (Tight Coupling) ใช้ Signal แต่ยังมีการอ้างอิง Hardcoded Path ข้าม Scene เพื่อ Connect Signal ปฏิบัติตามหลัก "Call Down, Signal Up" 100% และใช้ Scene Unique Nodes (%) จัดการ UI อย่างแข็งแกร่ง
Lifecycle & Memory
เรียก Node ใน _init() หรือใช้ free() ตรงๆ จนเกมแครช รันผ่านแต่เรียก load() ในลูปยิง หรือค้นหา Node ซ้ำๆ ใน _process() แคช Node ใน _ready(), ใช้ queue_free() ป้องกัน Memory Leak และใช้ PackedScene ถูกต้อง
เมื่อสร้างโปรเจกต์เสร็จและผ่านเกณฑ์ระดับ 5 คะแนน คุณคือ Godot 4 Foundation Architect อย่างเป็นทางการ! Grade: 20/20 Pts
Level 1 Complete • Graduation

4. สรุปความสำเร็จ และก้าวต่อไปสู่ LEVEL 2!

LEVEL 1 GRADUATION CERTIFIED

ขอแสดงความยินดีด้วยครับ! คุณจบหลักสูตร 7-Day Foundation แล้ว 🎉

ตลอด 7 วันที่ผ่านมา คุณไม่ได้เพียงแค่เรียนรู้การเขียนโค้ด Godot 4 แต่คุณได้ปลูกฝัง "สถาปัตยกรรมระดับซีเนียร์ (Architect Mindset)" ตั้งแต่วันแรก ทั้งการออกแบบระบบแบบ Component-Based, การจัดการ Scene Tree, การเขียนโค้ดที่ทนทานต่อการ Refactor ด้วย Unique Nodes และการจัดการหน่วยความจำที่ปลอดภัย

Day 8: Physics Bodies 2D

เจาะลึกความต่างของ StaticBody2D, RigidBody2D, Area2D และ CharacterBody2D

Day 9: Player Controller

สร้างระบบควบคุมตัวละครระดับ Production พร้อม Coyote Time, Jump Buffering และ Inertia

Day 10: Hitbox & Hurtbox

ระบบต่อสู้และการรับความเสียหายแยก Collision Layers vs. Masks อย่างเป็นระบบ

เมื่อสร้างโปรเจกต์ Modular Cannon Defense เรียบร้อยแล้ว สามารถส่งโค้ดมาพูดคุยหรือรีวิวได้ตลอดเวลาครับ!

คัดลอกข้อมูลเรียบร้อยแล้ว!