diff --git a/games/unreal/tutorial/QUICKSTART-CODE-FIRST.md b/games/unreal/tutorial/QUICKSTART-CODE-FIRST.md
new file mode 100644
index 0000000..a14dc5f
--- /dev/null
+++ b/games/unreal/tutorial/QUICKSTART-CODE-FIRST.md
@@ -0,0 +1,344 @@
+# Quick Start: Code-First Unreal Tutorial
+
+**Problem Solved:** The Blueprint tutorial requires extensive manual UI work (60+ clicks to define 12 variables). The code-first approach lets you **copy-paste entire code blocks** instead.
+
+---
+
+## ⚡ 3-Minute Quick Start
+
+### 1. Choose Your Path
+
+- **New Project?** → Start with [Part 1 (C++): Project Setup](part-1-cpp-project-setup.md)
+- **Already have Blueprint project?** → See [Migration Guide](#migrating-from-blueprint-to-c) below
+- **Just need reference code?** → See existing implementations in `Source/MCPGameProject/`
+
+### 2. Create C++ Project (New Projects Only)
+
+If starting fresh:
+
+```
+Unreal Engine → New Project → Games → Blank
+✅ Project Type: C++ (NOT Blueprint!)
+Name: BulletHellGame
+```
+
+If you already have a Blueprint project, skip to [Migration Guide](#migrating-from-blueprint-to-c) below.
+
+### 3. Copy-Paste the Classes
+
+Instead of clicking through UI 60+ times, just copy these ready-to-use files:
+
+**STGPawn.h** (Player) - [Get from Appendix D](appendix-d-cpp-reference.md#stgpawnh-complete-file)
+```cpp
+// All 12 player variables in one copy-paste:
+UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+float MoveSpeed = 750.0f;
+
+UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+FVector2D BoundsMin = FVector2D(-850.0f, -450.0f);
+
+UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+FVector2D BoundsMax = FVector2D(850.0f, 450.0f);
+
+// ... (9 more variables, all with defaults)
+```
+
+**STGProjectile.h** (Bullets) - [Get from Appendix D](appendix-d-cpp-reference.md#stgprojectileh-complete-file)
+
+**STGEnemy.h** (Enemies) - [Get from Appendix D](appendix-d-cpp-reference.md#stgenemyh-complete-file)
+
+**STGGameMode.h** (Game Rules) - [Get from Appendix D](appendix-d-cpp-reference.md#stggamemodeh-complete-file)
+
+### 4. Compile
+
+- Click **Compile** in Unreal Editor (or build in IDE)
+- Wait 30-60 seconds
+- Done! All variables are now available in editor
+
+### 5. Create Minimal Blueprints
+
+Create Blueprint children **only** for visual assets:
+
+1. `BP_Player` inherits from `STGPawn` → Assign ship mesh/material
+2. `BP_Bullet` inherits from `STGProjectile` → Assign sphere mesh/color
+3. `BP_Enemy` inherits from `STGEnemy` → Assign enemy mesh/material
+
+**No need to define variables!** They all come from C++.
+
+---
+
+## 📊 Time Savings
+
+| Task | Blueprint Approach | Code-First | Time Saved |
+|------|-------------------|------------|------------|
+| Define player variables (×12) | 15 minutes | 2 minutes | ⚡ 13 min |
+| Define enemy variables (×15) | 20 minutes | 2 minutes | ⚡ 18 min |
+| Create enemy variants (×4) | 35 minutes | 8 minutes | ⚡ 27 min |
+| Implement firing logic | 30 minutes | 10 minutes | ⚡ 20 min |
+| **Complete game** | **6-8 hours** | **2-3 hours** | **⚡ 4-5 hours** |
+
+---
+
+## 🎯 Key Benefits
+
+### ✅ Copy-Paste Variables
+
+**Blueprint:**
+```
+Click + → Type "MoveSpeed" → Select type "Float" → Compile → Set value "750.0"
+Click + → Type "BoundsMin" → Select type "Vector2D" → Compile → Set value...
+... (repeat 10 more times, ~15 minutes total)
+```
+
+**Code:**
+```cpp
+// Copy this entire block in 10 seconds:
+UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+float MoveSpeed = 750.0f;
+
+UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+FVector2D BoundsMin = FVector2D(-850.0f, -450.0f);
+
+UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+FVector2D BoundsMax = FVector2D(850.0f, 450.0f);
+```
+
+### ✅ Version Control
+
+**Blueprint:** Binary files, impossible to review changes
+
+```diff
+Binary files differ
+```
+
+**Code:** Readable diffs, easy code review
+
+```diff
++ float MoveSpeed = 850.0f; // Increased for better feel
+- float MoveSpeed = 750.0f;
+```
+
+### ✅ Batch Modifications
+
+**Blueprint:** Open each file, find variable, change value, save (2 min per file)
+
+**Code:** Find/replace across all files (5 seconds)
+
+```
+Find: MaxHealth = 12;
+Replace: MaxHealth = 24;
+Replace All → Done!
+```
+
+---
+
+## 🔗 Full Documentation Links
+
+1. **[Code-First Tutorial](code-first-approach.md)** - Complete step-by-step guide
+2. **[Appendix D: C++ Reference](appendix-d-cpp-reference.md)** - Copy-paste ready code
+3. **[Blueprint vs Code Comparison](blueprint-vs-code-comparison.md)** - Detailed time analysis
+4. **[Main Tutorial Index](README.md)** - Access both approaches
+
+---
+
+## 💡 Recommended Workflow
+
+### For This Bullet Hell Game:
+
+1. ✅ **Use C++ for ALL game logic and variables**
+ - Player stats, movement, firing
+ - Enemy behavior, health, spawning
+ - Game rules, timers, scoring
+
+2. ✅ **Use Blueprints ONLY for visual assets**
+ - Assign meshes and materials
+ - Set particle effects
+ - Configure sound effects
+
+### Result:
+
+- 🚀 **3x faster development** (2-3 hours vs 6-8 hours)
+- 📝 **Maintainable code** (version control, refactoring)
+- 🎨 **Easy visual tweaks** (designers can change colors/meshes)
+
+---
+
+## 🔄 Migrating from Blueprint to C++
+
+**Already started with the Blueprint tutorial?** Here's how to move to C++ without losing your work.
+
+### Option 1: Add C++ to Existing Blueprint Project (Recommended)
+
+This approach keeps your existing Blueprints and adds C++ support.
+
+#### Step 1: Add C++ Support to Project
+
+1. In Unreal Editor: **Tools → New C++ Class**
+2. Choose any parent (e.g., "Actor") → Next
+3. Name it anything (e.g., `Dummy`) → Create Class
+4. **This triggers C++ project generation!**
+ - Visual Studio/Rider opens
+ - `Source/` folder is created
+ - Project compiles (~2-5 minutes first time)
+
+5. After compilation, you'll have:
+ ```
+ YourProject/
+ ├── Source/ ← NEW! C++ folder created
+ ├── Content/ ← Your existing Blueprints (unchanged)
+ └── YourProject.uproject
+ ```
+
+#### Step 2: Create C++ Classes
+
+Now follow the C++ tutorial parts to create classes:
+
+1. **Tools → New C++ Class** → Pawn → `STGPawn`
+2. Copy-paste code from [Part 2 (C++)](part-2-cpp-create-player.md)
+3. Compile
+4. Repeat for bullets, enemies, etc.
+
+#### Step 3: Reparent Existing Blueprints
+
+Instead of creating new BP_Player, **reparent your existing one**:
+
+1. Open your existing `BP_Player` Blueprint
+2. **File → Reparent Blueprint** (top menu)
+3. In the dialog, click "All Classes" dropdown
+4. Search for `STGPawn` (your C++ class)
+5. Select it → Reparent
+
+**What happens:**
+- ✅ BP_Player now inherits from STGPawn (C++)
+- ✅ All C++ variables appear in Blueprint
+- ✅ Your existing visual assets (meshes, materials) are preserved
+- ✅ Old Blueprint variables become redundant (you can delete them)
+
+#### Step 4: Clean Up Duplicate Variables
+
+1. In BP_Player, look at "Variables" panel
+2. You'll see duplicates:
+ - `MoveSpeed` (from Blueprint - old)
+ - `MoveSpeed` (from STGPawn - new, with C++ icon)
+3. **Delete the old Blueprint variables** - keep only C++ ones
+4. Compile and Save
+
+#### Step 5: Migrate Logic (If Needed)
+
+If you had Blueprint nodes for logic:
+
+**Option A:** Keep Blueprint nodes for now (hybrid approach)
+- Blueprints can call C++ functions
+- Gradually move logic to C++ over time
+
+**Option B:** Move everything to C++ immediately
+- Copy Blueprint logic to C++ functions
+- Delete Blueprint nodes
+- Use Blueprints only for visual assets
+
+### Option 2: Fresh Start (Faster but Loses Visual Setup)
+
+If you haven't done much visual work:
+
+1. Create new C++ project
+2. Follow C++ tutorial from [Part 1](part-1-cpp-project-setup.md)
+3. Manually recreate any visual assets from old project
+
+**When to use:** If you're still early in the Blueprint tutorial (Parts 1-3).
+
+---
+
+### Migration Example: BP_Player → STGPawn
+
+**Before (Blueprint only):**
+```
+BP_Player (Blueprint)
+├── Components (added manually in editor)
+│ ├── ShipMesh
+│ ├── Camera
+│ └── Hitbox
+├── Variables (defined one-by-one in UI)
+│ ├── MoveSpeed = 750.0
+│ ├── BoundsMin = (-850, -450)
+│ └── ... (10 more)
+└── Event Graph (Blueprint nodes for logic)
+```
+
+**After (Reparented to C++):**
+```
+BP_Player (Blueprint, inherits from STGPawn C++)
+├── Parent Class: STGPawn ← NEW!
+├── Components (inherited from C++)
+│ ├── ShipMesh (from STGPawn)
+│ ├── Camera (from STGPawn)
+│ └── Hitbox (from STGPawn)
+├── Variables (inherited from C++)
+│ ├── MoveSpeed = 750.0 (from STGPawn)
+│ ├── BoundsMin = (-850, -450) (from STGPawn)
+│ └── ... (all from C++)
+└── Visual Assets Only (meshes, materials)
+ └── ShipMesh → Assign cone mesh
+```
+
+**Benefits:**
+- ✅ Variables now in version control (C++ files)
+- ✅ Can modify via IDE (autocomplete, refactoring)
+- ✅ Type-safe (compiler checks)
+- ✅ Blueprint kept for visual assets only
+
+---
+
+### Common Migration Pitfalls
+
+**Problem:** "I reparented but variables duplicated!"
+- **Solution:** Delete the old Blueprint variables manually. Keep only C++ ones (they have a C++ icon next to them).
+
+**Problem:** "Compilation errors after adding C++ support"
+- **Solution:** Make sure Visual Studio has "Desktop Development with C++" workload installed. Check Output Log for specific errors.
+
+**Problem:** "My Blueprint logic stopped working after reparenting"
+- **Solution:** Check that function names match. C++ functions must be marked `UFUNCTION(BlueprintCallable)` to be called from Blueprints.
+
+**Problem:** "Hot reload isn't working"
+- **Solution:** Close Unreal Editor before compiling C++ changes. Reopen after compilation. Hot reload is unreliable.
+
+---
+
+## ❓ FAQ
+
+**Q: I'm new to C++, should I use Blueprint instead?**
+
+A: The code-first tutorial is actually **easier for beginners** because:
+- You copy-paste working code (less chance for errors)
+- No complex node wiring (easier to understand flow)
+- Clear error messages from compiler
+- Better for learning (code is more transferable to other engines)
+
+**Q: Can I mix C++ and Blueprints?**
+
+A: Yes! That's the recommended approach:
+- C++ base classes with all logic
+- Blueprint children that inherit from C++
+- Use Blueprints only for visual asset assignments
+
+**Q: What if I already started with Blueprints?**
+
+A: See the [Migration Guide](#migrating-from-blueprint-to-c) above! You can reparent existing Blueprints to C++ classes.
+
+**Q: Do I need to know Unreal's C++ API?**
+
+A: No! The tutorial provides **complete, working code** you can copy-paste. You'll learn the API as you read the code.
+
+---
+
+## 🚀 Get Started Now
+
+**New Project:** [→ Start with Part 1 (C++)](part-1-cpp-project-setup.md)
+
+**Existing Blueprint Project:** [→ See Migration Guide](#migrating-from-blueprint-to-c)
+
+Build the complete bullet-hell game in 2-3 hours with copy-paste ready code!
+
+---
+
+[Back to Main Index](README.md)
diff --git a/games/unreal/tutorial/README.md b/games/unreal/tutorial/README.md
index f115669..beb316b 100644
--- a/games/unreal/tutorial/README.md
+++ b/games/unreal/tutorial/README.md
@@ -14,6 +14,53 @@ This tutorial recreates the Unity "magisterka_1" bullet-hell shooter in Unreal E
---
+## 🆕 Two Approaches Available
+
+This tutorial offers **two ways** to implement the game:
+
+### 1. **Code-First Approach (RECOMMENDED)** ⚡
+
+**→ [🚀 QUICK START: 3-Minute Code-First Guide](QUICKSTART-CODE-FIRST.md)** ⭐
+
+**→ Start the C++ Tutorial:**
+- [Part 1 (C++): Project Setup](part-1-cpp-project-setup.md)
+- [Part 2 (C++): Create Player](part-2-cpp-create-player.md)
+- [Part 3 (C++): Create Bullet](part-3-cpp-create-bullet.md)
+- [Parts 4-9 (C++) Summary](part-4-9-cpp-summary.md)
+
+- ✅ **90% faster** - copy-paste variable blocks instead of clicking UI
+- ✅ **Version control friendly** - readable Git diffs, not binary files
+- ✅ **Easier to replicate** - copy entire class files between projects
+- ✅ **Better for teams** - code review, refactoring tools, find/replace
+- ✅ **Type-safe** - compiler catches errors at compile time
+
+**Best for:** Anyone comfortable with C++ or wanting to learn modern game development workflows.
+
+### 2. **Blueprint-Heavy Approach** 🎨
+
+**→ [Start the Blueprint Tutorial](#table-of-contents)** (see below)
+
+- ✅ **Visual node editing** - see logic flow graphically
+- ✅ **Instant iteration** - no compile time for Blueprint changes
+- ✅ **Designer-friendly** - non-programmers can modify behavior
+
+**Best for:** Complete Unreal beginners, visual learners, or rapid prototyping.
+
+### Comparison
+
+| Task | Code-First (C++) | Blueprint |
+|------|-----------------|-----------|
+| Define 12+ variables | 2 minutes (copy-paste) | 15 minutes (clicking) |
+| Version control | ✅ Readable diffs | ❌ Binary files |
+| Refactoring | ✅ IDE tools | ❌ Manual |
+| Full game time | ~2-3 hours | ~6-8 hours |
+
+**💡 Pro Tip:** You can combine both! Use C++ for logic/variables, Blueprints for visual assets.
+
+**📖 Migrating from Blueprint?** See [Migration Guide in Quickstart](QUICKSTART-CODE-FIRST.md#migrating-from-blueprint-to-c)
+
+---
+
## Table of Contents
### Part 1: Project Setup
@@ -86,7 +133,7 @@ This tutorial recreates the Unity "magisterka_1" bullet-hell shooter in Unreal E
### Appendices
-- [Appendix A: Complete Variable Reference](appendix-a-variables.md)
+- [Appendix A: Complete Variable Reference](appendix-a-variables.md) (Blueprint)
- [Appendix B: Troubleshooting](appendix-b-troubleshooting.md)
- [Appendix C: Unity to Unreal Conversion Notes](appendix-c-unity-conversion.md)
@@ -94,6 +141,24 @@ This tutorial recreates the Unity "magisterka_1" bullet-hell shooter in Unreal E
## Quick Start
+### For Code-First Approach (Recommended)
+
+1. Read [3-Minute Quickstart](QUICKSTART-CODE-FIRST.md)
+2. Follow the C++ tutorial parts:
+ - [Part 1 (C++): Project Setup](part-1-cpp-project-setup.md)
+ - [Part 2 (C++): Create Player](part-2-cpp-create-player.md)
+ - [Part 3 (C++): Create Bullet](part-3-cpp-create-bullet.md)
+ - [Part 4 (C++): Create Enemy](part-4-cpp-create-enemy.md)
+ - [Part 5 (C++): Create Spawner](part-5-cpp-create-spawner.md)
+ - [Part 6 (C++): Create Game Director](part-6-cpp-create-game-director.md)
+ - [Part 7 (C++): Create UI](part-7-cpp-create-ui.md)
+ - [Part 8 (C++): Create Game Mode](part-8-cpp-create-game-mode.md)
+ - [Part 9 (C++): Final Setup](part-9-cpp-final-setup.md)
+3. **Complete the game in 2-3 hours** instead of 6-8 hours!
+4. **Already have Blueprint project?** See [Migration Guide](QUICKSTART-CODE-FIRST.md#migrating-from-blueprint-to-c)
+
+### For Blueprint Approach
+
1. Start with [Part 1: Project Setup](part-1-project-setup.md)
2. Follow each part in order
3. Test frequently using the "EXPECTED RESULT" sections
diff --git a/games/unreal/tutorial/part-1-cpp-project-setup.md b/games/unreal/tutorial/part-1-cpp-project-setup.md
new file mode 100644
index 0000000..38ed727
--- /dev/null
+++ b/games/unreal/tutorial/part-1-cpp-project-setup.md
@@ -0,0 +1,267 @@
+# Part 1 (C++): Project Setup
+
+[← Back to Index](README.md) | [Next: Part 2 (C++) - Create the Player →](part-2-cpp-create-player.md)
+
+---
+
+## Overview
+
+This is the **C++ version** of Part 1. Unlike the Blueprint tutorial which creates a Blueprint-only project, we'll create a **C++ project** from the start. This enables:
+
+- ✅ Copy-paste variable definitions instead of clicking UI
+- ✅ Version control friendly (readable diffs)
+- ✅ Faster development (define 12 variables in 30 seconds vs 15 minutes)
+
+---
+
+## Step 1.1: Create New C++ Project
+
+1. Open Epic Games Launcher
+2. Click "Unreal Engine" tab on the left sidebar
+3. Click yellow "Launch" button next to your UE5 version
+4. Wait for Unreal Engine to open (this may take 1-2 minutes)
+
+5. In the "Unreal Project Browser" window that appears:
+ - At the top, select "Games" category (should be selected by default)
+ - Click "Blank" template (empty square icon)
+
+6. On the right side panel, configure:
+ - **Project Defaults:** **C++** ⚠️ (NOT Blueprint!)
+ - **Target Platform:** Desktop
+ - **Quality Preset:** Scalable (faster compile times, easier iteration)
+ - **Starter Content:** UNCHECKED (reduces project size and avoids unnecessary assets for this bullet-hell game)
+ - **Raytracing:** UNCHECKED
+
+7. At the bottom:
+ - Choose folder location where you want to save
+ - Name the project: `BulletHellGame`
+
+8. Click "Create" button (bottom right, yellow)
+
+### What Happens Next
+
+Unreal will:
+1. Generate C++ project files (~30 seconds)
+2. **Open your IDE** (Visual Studio Code will launch if configured)
+3. **Automatically start compiling** the initial project (2-5 minutes, first time only)
+ - You'll see a terminal/console window showing compilation progress
+ - On Linux: Uses clang++ or g++ to compile C++ files
+ - Progress shown as: "Compiling C++ source files...", "Linking...", etc.
+4. Open Unreal Editor once compilation completes
+
+> **⚠️ IMPORTANT:** Do NOT close the IDE or compilation window! Wait for compilation to finish. You'll see "Build succeeded" or similar message when done.
+
+### Expected Result
+
+After compilation completes:
+
+**Unreal Editor viewport shows:**
+- Empty 3D viewport in the center with grid floor
+- Main toolbar at the top (File, Edit, Window, etc.)
+- Outliner panel on the right showing "Untitled" level actors
+- Details panel on the right side (currently empty)
+- Content Drawer button at bottom (click it or press `Ctrl+Space` to open)
+
+**VS Code (your IDE) shows:**
+- BulletHellGame project folder open
+- Left sidebar with file explorer showing `Source/` folder
+- `STGPawn.h` and `STGPawn.cpp` or similar auto-generated files
+
+**What you should see in Unreal Editor:**
+- A flat grid representing the game world (top-down view by default in new projects)
+- No errors in the Output Log
+- The word "Ready" or compilation success message in bottom-right corner
+
+> **NOTE:** If you see a 3D perspective view instead of top-down, don't worry - we'll fix that in Step 1.3.
+
+### Troubleshooting
+
+
+IDE didn't open? (Visual Studio Code on Linux/Arch)
+
+On Arch Linux with VS Code:
+- Install VS Code if not present: `sudo pacman -S code`
+- Install Unreal Engine extension for VS Code
+- In Unreal Editor: `Edit → Editor Preferences → Source Code`
+- Set "Source Code Editor" to "Visual Studio Code"
+- Right-click the `.uproject` file in file manager → "Generate VSCode project files"
+- Open the project folder in VS Code
+
+
+
+
+Compilation failed? (Linux/Arch)
+
+On Arch Linux:
+- Ensure you have the required build tools:
+ - `sudo pacman -S base-devel clang lld`
+- Check the Output Log (Window → Developer Tools → Output Log) for specific errors
+- If missing libraries, install them via pacman
+- Try regenerating project files: Right-click `.uproject` → "Generate VSCode project files"
+
+
+
+---
+
+## Step 1.2: Verify C++ Project Structure
+
+Before continuing, verify the C++ files were created:
+
+1. In your file explorer, navigate to your project folder
+2. You should see:
+
+```
+BulletHellGame/
+├── BulletHellGame.uproject # Project file
+├── Source/ # ⭐ C++ source code (this is new!)
+│ └── BulletHellGame/
+│ ├── BulletHellGame.h
+│ ├── BulletHellGame.cpp
+│ ├── BulletHellGame.Build.cs # Build configuration
+│ └── BulletHellGameGameMode.h/cpp # Auto-generated
+├── Content/ # Assets and Blueprints
+├── Config/ # Project settings
+├── Binaries/ # Compiled code (gitignore this)
+├── Intermediate/ # Build artifacts (gitignore this)
+└── BulletHellGame.sln # Visual Studio solution (if using VS)
+```
+
+The `Source/` folder is what makes this a C++ project! This is where we'll add our game classes.
+
+### Expected Result
+
+**In File Explorer (your Linux file manager):**
+```
+BulletHellGame/
+├── BulletHellGame.uproject # Double-click to open project
+├── Source/ # ✅ C++ source code folder
+│ └── BulletHellGame/
+│ ├── BulletHellGame.h
+│ ├── BulletHellGame.cpp
+│ └── BulletHellGame.Build.cs
+├── Content/ # Assets and Blueprints
+├── Config/ # Project configuration
+├── Binaries/ # Compiled game (gitignore this)
+└── Intermediate/ # Build files (gitignore this)
+```
+
+**Verify the Source folder exists** - this confirms C++ is enabled!
+
+---
+
+## Step 1.3: Set Up 2D Game View
+
+Same as Blueprint tutorial:
+
+1. In the main viewport, look at the top-left corner
+2. Click the dropdown that says "Perspective"
+3. Select "Top" from the dropdown menu (`Alt + J`)
+
+### Expected Result
+
+**Viewport changes:**
+- Camera now looks straight down at the grid
+- You see the game world from a bird's-eye view (perfect for bullet-hell)
+- Grid appears as horizontal lines (X and Y axes visible)
+- Objects will appear flat when placed in this view
+
+**Visual confirmation:**
+- Top-left corner now shows "Top" instead of "Perspective"
+- The viewport manipulation gizmo (3D arrows) now shows only X and Y axes prominently
+
+---
+
+## Step 1.4: Create Folder Structure
+
+1. Open Content Browser (or Content Drawer with `Ctrl+Space`)
+2. You should see "Content" folder on the left panel
+
+3. Right-click on "Content" folder → **New Folder**
+ - Name it: `Blueprints` (we'll use these for visual-only children)
+
+4. Right-click on "Content" folder → **New Folder**
+ - Name it: `Materials`
+
+5. Right-click on "Content" folder → **New Folder**
+ - Name it: `Sprites` (for 2D textures)
+
+6. Right-click on "Content" folder → **New Folder**
+ - Name it: `UI`
+
+### Expected Result
+
+Content Browser shows 4 folders:
+
+```
+Content/
+├── Blueprints/ (For Blueprint children that inherit from C++)
+├── Materials/
+├── Sprites/
+└── UI/
+```
+
+**AND** you should also see:
+
+```
+C++ Classes/
+└── BulletHellGame/
+ └── BulletHellGameGameMode (Auto-generated C++ class)
+```
+
+This "C++ Classes" folder shows all C++ classes in the project.
+
+---
+
+## Step 1.5: Configure .gitignore (Recommended)
+
+If using version control, create `.gitignore` in your project root:
+
+```gitignore
+# Unreal Engine
+Binaries/
+DerivedDataCache/
+Intermediate/
+Saved/
+
+# IDE
+*.sln
+*.suo
+*.opensdf
+*.sdf
+*.VC.db
+*.VC.opendb
+.vs/
+.vscode/
+.idea/
+
+# Build artifacts
+Build/
+Releases/
+```
+
+This prevents committing large binary files and build artifacts.
+
+---
+
+## Comparison: C++ vs Blueprint Project
+
+| Aspect | Blueprint Project | C++ Project |
+|--------|------------------|-------------|
+| Project creation time | ~30 seconds | ~5 minutes (first time) |
+| Source/ folder | ❌ No | ✅ Yes |
+| IDE integration | ❌ No | ✅ Yes |
+| Can add C++ classes | ❌ Requires migration | ✅ Ready to go |
+| Compile time | None (Blueprints) | 30-60 sec per change |
+| Hot reload | Instant | Limited support |
+
+**Key Difference:** C++ project has the `Source/` folder from the start. Blueprint projects require manual migration to add C++ support later.
+
+---
+
+## What's Next?
+
+In Part 2, we'll create the player ship as a **C++ class** instead of a Blueprint. You'll see how defining 12 variables takes 30 seconds with copy-paste instead of 15 minutes with UI clicks.
+
+---
+
+[← Back to Index](README.md) | [Next: Part 2 (C++) - Create the Player →](part-2-cpp-create-player.md)
diff --git a/games/unreal/tutorial/part-2-cpp-create-player.md b/games/unreal/tutorial/part-2-cpp-create-player.md
new file mode 100644
index 0000000..64061b9
--- /dev/null
+++ b/games/unreal/tutorial/part-2-cpp-create-player.md
@@ -0,0 +1,509 @@
+# Part 2 (C++): Create the Player
+
+[← Previous: Part 1 (C++) - Project Setup](part-1-cpp-project-setup.md) | [Back to Index](README.md) | [Next: Part 3 (C++) - Create the Bullet →](part-3-cpp-create-bullet.md)
+
+---
+
+## Overview
+
+In this part, we'll create the player ship as a **C++ class** called `ASTGPawn`.
+
+**Time comparison:**
+- Blueprint approach (Part 2): ~60 minutes (12 variables via UI + Blueprint nodes)
+- C++ approach (this part): ~15 minutes (copy-paste code)
+
+---
+
+## Step 2.1: Create STGPawn C++ Class
+
+### In Unreal Editor:
+
+1. Go to **Tools → New C++ Class** (top menu bar)
+2. In the "Choose Parent Class" window:
+ - Click **"Pawn"** (NOT Character - we want simple 2D control)
+ - Click **"Next"**
+
+3. In the "Name Your New Actor" window:
+ - **Name:** `STGPawn`
+ - **Path:** Should be `Source/BulletHellGame/` (default)
+ - Click **"Create Class"**
+
+### What Happens Next:
+
+1. Unreal generates `STGPawn.h` and `STGPawn.cpp`
+2. Your IDE opens with the new files
+3. Project compiles automatically (~30-60 seconds)
+4. Unreal Editor refreshes
+
+> **💡 TIP:** If compilation fails, check the Output Log in Unreal Editor
+
+---
+
+## Step 2.2: Define Player Variables in STGPawn.h
+
+Now comes the magic! Instead of clicking UI 60+ times, we'll **copy-paste** all variables at once.
+
+### Open STGPawn.h in your IDE
+
+Find the class definition (should look like this):
+
+```cpp
+UCLASS()
+class BULLETHELLGAME_API ASTGPawn : public APawn
+{
+ GENERATED_BODY()
+
+public:
+ ASTGPawn();
+
+protected:
+ virtual void BeginPlay() override;
+
+public:
+ virtual void Tick(float DeltaTime) override;
+ virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
+};
+```
+
+### Replace the entire class with this:
+
+```cpp
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/Pawn.h"
+#include "STGPawn.generated.h"
+
+// Forward declarations
+class UCameraComponent;
+class USpringArmComponent;
+class UStaticMeshComponent;
+class UBoxComponent;
+
+UCLASS()
+class BULLETHELLGAME_API ASTGPawn : public APawn
+{
+ GENERATED_BODY()
+
+public:
+ ASTGPawn();
+
+protected:
+ virtual void BeginPlay() override;
+
+public:
+ virtual void Tick(float DeltaTime) override;
+ virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
+
+ // ===== COMPONENTS =====
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
+ UStaticMeshComponent* ShipMesh;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
+ USpringArmComponent* SpringArm;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
+ UCameraComponent* Camera;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
+ UBoxComponent* Hitbox;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
+ UStaticMeshComponent* HitboxIndicator;
+
+ // ===== MOVEMENT & BOUNDARIES =====
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float MoveSpeed = 750.0f;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ FVector2D BoundsMin = FVector2D(-850.0f, -450.0f);
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ FVector2D BoundsMax = FVector2D(850.0f, 450.0f);
+
+ // ===== FIRING =====
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float FireInterval = 0.08f;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float BulletSpeed = 2200.0f;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ int32 VolleySize = 3;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float VolleySpread = 12.0f;
+
+ // ===== LIVES & SCORE =====
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ int32 MaxLives = 3;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stats")
+ int32 CurrentLives = 3;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stats")
+ int32 Score = 0;
+
+ // ===== SPECIAL ABILITY =====
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stats")
+ bool bSpecialUsed = false;
+
+ // ===== INPUT FUNCTIONS =====
+ void MoveForward(float Value);
+ void MoveRight(float Value);
+ void StartFire();
+ void StopFire();
+ void UseSpecial();
+
+ // ===== GAME LOGIC =====
+ void FireShot();
+ void TakeHit(int32 Damage);
+ void HandleDeath();
+ void AddScore(int32 Points);
+
+private:
+ FTimerHandle TimerHandle_Fire;
+ bool bIsFiring = false;
+ FVector MovementInput;
+ float FireTimer = 0.0f;
+};
+```
+
+### What Just Happened?
+
+You just defined **12 gameplay variables + 5 components** with default values in ~30 seconds (copy-paste time)!
+
+In the Blueprint tutorial, this would require:
+- 12 variables × 5 clicks each = 60 clicks
+- ~15 minutes of manual work
+- High chance of typos
+
+**Time saved: 14.5 minutes** ⚡
+
+---
+
+## Step 2.3: Implement STGPawn Constructor
+
+### Open STGPawn.cpp in your IDE
+
+Replace the file content with:
+
+```cpp
+#include "STGPawn.h"
+#include "GameFramework/SpringArmComponent.h"
+#include "Camera/CameraComponent.h"
+#include "Components/StaticMeshComponent.h"
+#include "Components/BoxComponent.h"
+
+ASTGPawn::ASTGPawn()
+{
+ PrimaryActorTick.bCanEverTick = true;
+
+ // Root component
+ RootComponent = CreateDefaultSubobject(TEXT("Root"));
+
+ // Ship mesh - cone shape pointing upward
+ ShipMesh = CreateDefaultSubobject(TEXT("ShipMesh"));
+ ShipMesh->SetupAttachment(RootComponent);
+ ShipMesh->SetCollisionProfileName("NoCollision");
+
+ // Load cone mesh from engine
+ static ConstructorHelpers::FObjectFinder ConeMesh(TEXT("/Engine/BasicShapes/Cone"));
+ if (ConeMesh.Succeeded())
+ {
+ ShipMesh->SetStaticMesh(ConeMesh.Object);
+ ShipMesh->SetRelativeScale3D(FVector(0.5f, 0.5f, 0.7f));
+ ShipMesh->SetRelativeRotation(FRotator(90.f, 0.f, 0.f)); // Point forward
+ }
+
+ // Hitbox - small for bullet-hell precision
+ Hitbox = CreateDefaultSubobject(TEXT("Hitbox"));
+ Hitbox->SetupAttachment(RootComponent);
+ Hitbox->SetBoxExtent(FVector(25.f, 25.f, 10.f));
+ Hitbox->SetCollisionProfileName("OverlapAllDynamic");
+ Hitbox->SetGenerateOverlapEvents(true);
+
+ // Visual hitbox indicator (small sphere)
+ HitboxIndicator = CreateDefaultSubobject(TEXT("HitboxIndicator"));
+ HitboxIndicator->SetupAttachment(RootComponent);
+ HitboxIndicator->SetCollisionEnabled(ECollisionEnabled::NoCollision);
+
+ static ConstructorHelpers::FObjectFinder SphereMesh(TEXT("/Engine/BasicShapes/Sphere"));
+ if (SphereMesh.Succeeded())
+ {
+ HitboxIndicator->SetStaticMesh(SphereMesh.Object);
+ HitboxIndicator->SetRelativeScale3D(FVector(0.05f, 0.05f, 0.05f));
+ }
+
+ // Camera setup for top-down view
+ SpringArm = CreateDefaultSubobject(TEXT("SpringArm"));
+ SpringArm->SetupAttachment(RootComponent);
+ SpringArm->SetRelativeRotation(FRotator(-90.f, 0.f, 0.f)); // Top-down
+ SpringArm->TargetArmLength = 1200.f;
+ SpringArm->bDoCollisionTest = false;
+ SpringArm->bInheritPitch = false;
+ SpringArm->bInheritRoll = false;
+ SpringArm->bInheritYaw = false;
+
+ Camera = CreateDefaultSubobject(TEXT("Camera"));
+ Camera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
+}
+
+void ASTGPawn::BeginPlay()
+{
+ Super::BeginPlay();
+ CurrentLives = MaxLives;
+}
+
+void ASTGPawn::Tick(float DeltaTime)
+{
+ Super::Tick(DeltaTime);
+
+ // Movement with bounds clamping
+ if (!MovementInput.IsZero())
+ {
+ FVector NewLocation = GetActorLocation();
+ FVector Normalized = MovementInput.GetSafeNormal();
+ NewLocation += Normalized * MoveSpeed * DeltaTime;
+
+ // Clamp to bounds
+ NewLocation.X = FMath::Clamp(NewLocation.X, BoundsMin.X, BoundsMax.X);
+ NewLocation.Y = FMath::Clamp(NewLocation.Y, BoundsMin.Y, BoundsMax.Y);
+
+ SetActorLocation(NewLocation);
+ }
+
+ // Auto-fire when holding fire button
+ if (bIsFiring)
+ {
+ FireTimer -= DeltaTime;
+ if (FireTimer <= 0.0f)
+ {
+ FireShot();
+ FireTimer = FireInterval;
+ }
+ }
+}
+
+void ASTGPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
+{
+ Super::SetupPlayerInputComponent(PlayerInputComponent);
+
+ // Bind movement axes
+ PlayerInputComponent->BindAxis("MoveForward", this, &ASTGPawn::MoveForward);
+ PlayerInputComponent->BindAxis("MoveRight", this, &ASTGPawn::MoveRight);
+
+ // Bind actions
+ PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &ASTGPawn::StartFire);
+ PlayerInputComponent->BindAction("Fire", IE_Released, this, &ASTGPawn::StopFire);
+ PlayerInputComponent->BindAction("Special", IE_Pressed, this, &ASTGPawn::UseSpecial);
+}
+
+void ASTGPawn::MoveForward(float Value)
+{
+ MovementInput.X = Value;
+}
+
+void ASTGPawn::MoveRight(float Value)
+{
+ MovementInput.Y = Value;
+}
+
+void ASTGPawn::StartFire()
+{
+ bIsFiring = true;
+ FireTimer = 0.0f; // Fire immediately
+}
+
+void ASTGPawn::StopFire()
+{
+ bIsFiring = false;
+}
+
+void ASTGPawn::FireShot()
+{
+ // Will implement in Part 3 when we create bullets
+ UE_LOG(LogTemp, Warning, TEXT("FIRE!"));
+}
+
+void ASTGPawn::UseSpecial()
+{
+ if (!bSpecialUsed)
+ {
+ bSpecialUsed = true;
+ UE_LOG(LogTemp, Warning, TEXT("SPECIAL ABILITY ACTIVATED!"));
+ // Will implement enemy/bullet destruction in Part 4
+ }
+}
+
+void ASTGPawn::TakeHit(int32 Damage)
+{
+ CurrentLives = FMath::Clamp(CurrentLives - Damage, 0, MaxLives);
+
+ if (CurrentLives <= 0)
+ {
+ HandleDeath();
+ }
+}
+
+void ASTGPawn::HandleDeath()
+{
+ SetActorHiddenInGame(true);
+ // Will notify GameMode in Part 6
+}
+
+void ASTGPawn::AddScore(int32 Points)
+{
+ Score += Points;
+}
+```
+
+---
+
+## Step 2.4: Compile the Code
+
+### In Unreal Editor:
+
+1. Click **"Compile"** button (bottom right, or `Ctrl+Alt+F11`)
+2. Wait for compilation (~30-60 seconds)
+3. Check for errors in Output Log
+
+OR
+
+### In your IDE:
+
+1. Build the project (`Ctrl+Shift+B` in Visual Studio, or `Ctrl+F9` in Rider)
+2. Wait for build to finish
+3. Unreal Editor will hot-reload automatically
+
+### Expected Result:
+
+- ✅ Compilation succeeds
+- ✅ "C++ Classes" folder in Content Browser now shows `STGPawn`
+- ✅ You can right-click STGPawn → "Create Blueprint Class based on STGPawn"
+
+---
+
+## Step 2.5: Configure Input Mappings
+
+This step is the same as Blueprint tutorial - we need to configure keyboard inputs in Project Settings.
+
+1. **Edit → Project Settings**
+2. **Engine → Input**
+3. **Axis Mappings** → Click "+" to add:
+ - `MoveForward`: W = 1.0, S = -1.0
+ - `MoveRight`: D = 1.0, A = -1.0
+4. **Action Mappings** → Click "+" to add:
+ - `Fire`: Space Bar, Left Mouse Button
+ - `Special`: X, Right Mouse Button
+5. Close Project Settings
+
+---
+
+## Step 2.6: Create Blueprint Child (for Visual Assets)
+
+Now we create a **minimal Blueprint** that inherits from our C++ class. This Blueprint is ONLY for visual assets!
+
+1. In Content Browser, navigate to `Content → Blueprints`
+2. Right-click → **Blueprint Class**
+3. In "Pick Parent Class" window:
+ - Click "All Classes" dropdown at top
+ - Search for `STGPawn`
+ - Select it
+ - Click "Select"
+4. Name it: `BP_Player`
+5. Double-click to open
+
+### In the Blueprint Editor:
+
+**Components (Left Panel):**
+- You'll see all components we created in C++ (ShipMesh, Hitbox, Camera, etc.)
+- NO NEED to add them manually - they're already there from C++!
+
+**Variables (My Blueprint Panel):**
+- You'll see all 12 variables we defined in C++ (MoveSpeed, BoundsMin, etc.)
+- NO NEED to create them - they're already there from C++!
+- You can see their default values (750.0, etc.) - all from C++!
+
+**What to do in Blueprint:**
+- NOTHING for now! All logic is in C++
+- In Part 9, we'll assign visual meshes/materials here
+
+### Compile and Save BP_Player
+
+---
+
+## Step 2.7: Test the Player
+
+1. Drag `BP_Player` from Content Browser into the level viewport
+2. Position it near the center (coordinates around X=0, Y=0, Z=0)
+3. Press **Play** (`Alt+P`)
+
+### Expected Result
+
+**In Play Mode Window:**
+- You see the cone/cube player ship from above (top-down view)
+- Ship is positioned at center of screen
+- Background is the default gray/blue Unreal grid
+- Camera follows the player from above
+
+**When pressing WASD keys:**
+- **W** - Ship moves upward on screen (toward top)
+- **S** - Ship moves downward on screen (toward bottom)
+- **A** - Ship moves left
+- **D** - Ship moves right
+- Movement stops immediately when you release keys (no sliding)
+- Ship stops at screen edges (cannot move outside bounds)
+
+**When pressing Z or Space:**
+- You see "FIRE!" message appear in top-left corner of screen (yellow text)
+- Message appears repeatedly while holding the button
+- No bullets yet (we'll add those after creating bullet class)
+
+**When pressing X:**
+- "SPECIAL ABILITY ACTIVATED!" appears once in top-left corner
+- Pressing X again does nothing (ability used up)
+
+**Visual Check:**
+- Ship model is visible (cone or cube shape)
+- Ship rotates/faces the direction of movement
+- No errors in Output Log
+- Frame rate counter shows stable FPS (if enabled)
+
+**To exit Play mode:** Press `Esc` or click the "Stop" button in the toolbar
+
+---
+
+## Comparison: What We Just Did
+
+### Blueprint Approach (Part 2):
+
+1. Create BP_Player Blueprint ✅
+2. Add 5 components manually (clicking, dragging)
+3. Add 12 variables one-by-one (click +, type name, select type, compile, set value) × 12 = **15 minutes**
+4. Create Blueprint nodes for movement logic (~30 nodes, connecting wires)
+5. Create Blueprint nodes for firing logic (~20 nodes)
+6. Configure input in Project Settings
+7. **Total: ~60 minutes**
+
+### C++ Approach (This Part):
+
+1. Create STGPawn C++ class ✅
+2. Copy-paste header file with all variables **30 seconds**
+3. Copy-paste implementation file
+4. Compile
+5. Create BP_Player (inherits everything from C++)
+6. Configure input in Project Settings
+7. **Total: ~15 minutes**
+
+**Time saved: 45 minutes** ⚡⚡⚡
+
+---
+
+## What's Next?
+
+In Part 3, we'll create the bullet class in C++. You'll see how defining bullet behavior in code is much cleaner than Blueprint nodes.
+
+---
+
+[← Previous: Part 1 (C++) - Project Setup](part-1-cpp-project-setup.md) | [Back to Index](README.md) | [Next: Part 3 (C++) - Create the Bullet →](part-3-cpp-create-bullet.md)
diff --git a/games/unreal/tutorial/part-3-cpp-create-bullet.md b/games/unreal/tutorial/part-3-cpp-create-bullet.md
new file mode 100644
index 0000000..0593a78
--- /dev/null
+++ b/games/unreal/tutorial/part-3-cpp-create-bullet.md
@@ -0,0 +1,317 @@
+# Part 3 (C++): Create the Bullet
+
+[← Previous: Part 2 (C++) - Create the Player](part-2-cpp-create-player.md) | [Back to Index](README.md) | [Next: Part 4 (C++) - Create the Enemy →](part-4-cpp-create-enemy.md)
+
+---
+
+## Overview
+
+Create the bullet/projectile class in C++. Again, we'll copy-paste all variables instead of clicking UI.
+
+**Time comparison:**
+- Blueprint: ~30 minutes (5 variables + Blueprint nodes)
+- C++ (this part): ~10 minutes (copy-paste code)
+
+---
+
+## Step 3.1: Create STGProjectile C++ Class
+
+1. **Tools → New C++ Class**
+2. Choose **"Actor"** as parent class → Next
+3. Name: `STGProjectile` → Create Class
+4. Wait for compilation
+
+---
+
+## Step 3.2: Copy-Paste STGProjectile.h
+
+Replace the entire header file with:
+
+```cpp
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/Actor.h"
+#include "STGProjectile.generated.h"
+
+class USphereComponent;
+class UProjectileMovementComponent;
+class UStaticMeshComponent;
+
+UCLASS()
+class BULLETHELLGAME_API ASTGProjectile : public AActor
+{
+ GENERATED_BODY()
+
+public:
+ ASTGProjectile();
+
+protected:
+ virtual void BeginPlay() override;
+
+public:
+ virtual void Tick(float DeltaTime) override;
+
+ // ===== COMPONENTS =====
+ UPROPERTY(VisibleDefaultsOnly, Category=Projectile)
+ USphereComponent* CollisionComp;
+
+ UPROPERTY(VisibleDefaultsOnly, Category=Projectile)
+ UStaticMeshComponent* MeshComp;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Movement)
+ UProjectileMovementComponent* ProjectileMovement;
+
+ // ===== VARIABLES (all with defaults!) =====
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay")
+ bool bIsPlayerBullet = false;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay")
+ float Damage = 1.0f;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay")
+ FLinearColor BulletColor = FLinearColor::Green;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Gameplay")
+ float Lifetime = 4.0f;
+
+ // ===== FUNCTIONS =====
+ UFUNCTION()
+ void OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
+ UPrimitiveComponent* OtherComp, int32 OtherBodyIndex,
+ bool bFromSweep, const FHitResult& SweepResult);
+
+ void SetBulletColor(FLinearColor InColor);
+ void SetSpeed(float InSpeed);
+
+private:
+ UMaterialInstanceDynamic* DynamicMaterial;
+};
+```
+
+**What just happened:** 5 bullet variables defined with defaults in 10 seconds!
+
+---
+
+## Step 3.3: Copy-Paste STGProjectile.cpp
+
+Replace the implementation file with:
+
+```cpp
+#include "STGProjectile.h"
+#include "Components/SphereComponent.h"
+#include "Components/StaticMeshComponent.h"
+#include "GameFramework/ProjectileMovementComponent.h"
+#include "STGEnemy.h" // Will create in Part 4
+#include "STGPawn.h"
+
+ASTGProjectile::ASTGProjectile()
+{
+ PrimaryActorTick.bCanEverTick = true;
+
+ // Collision sphere
+ CollisionComp = CreateDefaultSubobject(TEXT("SphereComp"));
+ CollisionComp->InitSphereRadius(5.0f);
+ CollisionComp->SetCollisionProfileName("OverlapAllDynamic");
+ CollisionComp->OnComponentBeginOverlap.AddDynamic(this, &ASTGProjectile::OnOverlapBegin);
+ RootComponent = CollisionComp;
+
+ // Visual mesh
+ MeshComp = CreateDefaultSubobject(TEXT("MeshComp"));
+ MeshComp->SetupAttachment(CollisionComp);
+ MeshComp->SetCollisionEnabled(ECollisionEnabled::NoCollision);
+
+ static ConstructorHelpers::FObjectFinder SphereMesh(TEXT("/Engine/BasicShapes/Sphere"));
+ if (SphereMesh.Succeeded())
+ {
+ MeshComp->SetStaticMesh(SphereMesh.Object);
+ MeshComp->SetRelativeScale3D(FVector(0.1f, 0.1f, 0.1f));
+ }
+
+ // Projectile movement
+ ProjectileMovement = CreateDefaultSubobject(TEXT("ProjectileComp"));
+ ProjectileMovement->UpdatedComponent = CollisionComp;
+ ProjectileMovement->InitialSpeed = 1200.f;
+ ProjectileMovement->MaxSpeed = 1200.f;
+ ProjectileMovement->bRotationFollowsVelocity = true;
+ ProjectileMovement->bShouldBounce = false;
+
+ // Auto-destroy after lifetime
+ InitialLifeSpan = Lifetime;
+}
+
+void ASTGProjectile::BeginPlay()
+{
+ Super::BeginPlay();
+
+ // Create dynamic material for bullet color
+ if (MeshComp)
+ {
+ DynamicMaterial = MeshComp->CreateAndSetMaterialInstanceDynamic(0);
+ if (DynamicMaterial)
+ {
+ DynamicMaterial->SetVectorParameterValue(TEXT("BaseColor"), BulletColor);
+ DynamicMaterial->SetVectorParameterValue(TEXT("EmissiveColor"), BulletColor * 3.0f);
+ }
+ }
+}
+
+void ASTGProjectile::Tick(float DeltaTime)
+{
+ Super::Tick(DeltaTime);
+}
+
+void ASTGProjectile::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
+ UPrimitiveComponent* OtherComp, int32 OtherBodyIndex,
+ bool bFromSweep, const FHitResult& SweepResult)
+{
+ if (OtherActor && OtherActor != this)
+ {
+ if (bIsPlayerBullet)
+ {
+ // Player bullet hits enemy (will implement in Part 4)
+ // ASTGEnemy* Enemy = Cast(OtherActor);
+ // if (Enemy) { Enemy->HandleDamage(Damage); Destroy(); }
+ }
+ else
+ {
+ // Enemy bullet hits player
+ ASTGPawn* Player = Cast(OtherActor);
+ if (Player)
+ {
+ Player->TakeHit(1);
+ Destroy();
+ }
+ }
+ }
+}
+
+void ASTGProjectile::SetBulletColor(FLinearColor InColor)
+{
+ BulletColor = InColor;
+ if (DynamicMaterial)
+ {
+ DynamicMaterial->SetVectorParameterValue(TEXT("BaseColor"), BulletColor);
+ DynamicMaterial->SetVectorParameterValue(TEXT("EmissiveColor"), BulletColor * 3.0f);
+ }
+}
+
+void ASTGProjectile::SetSpeed(float InSpeed)
+{
+ if (ProjectileMovement)
+ {
+ ProjectileMovement->InitialSpeed = InSpeed;
+ ProjectileMovement->MaxSpeed = InSpeed;
+ }
+}
+```
+
+---
+
+## Step 3.4: Compile
+
+1. Click **Compile** in Unreal Editor
+2. Wait for compilation
+3. Check for errors
+
+---
+
+## Step 3.5: Update Player Firing Logic
+
+Now that we have bullets, let's make the player actually spawn them!
+
+### Open STGPawn.cpp
+
+Find the `FireShot()` function and replace it with:
+
+```cpp
+void ASTGPawn::FireShot()
+{
+ // Spawn volley of bullets
+ for (int32 i = 0; i < VolleySize; i++)
+ {
+ FVector SpawnLocation = GetActorLocation() + FVector(0.f, 0.f, 50.f);
+ FRotator SpawnRotation = FRotator(90.f, 0.f, 0.f);
+
+ // Spread calculation
+ float Angle = VolleySpread * (i - (VolleySize - 1) / 2.0f);
+ SpawnRotation.Yaw += Angle;
+
+ // Spawn bullet
+ UWorld* World = GetWorld();
+ if (World)
+ {
+ ASTGProjectile* Bullet = World->SpawnActor(
+ ASTGProjectile::StaticClass(),
+ SpawnLocation,
+ SpawnRotation
+ );
+
+ if (Bullet)
+ {
+ Bullet->bIsPlayerBullet = true;
+ Bullet->SetSpeed(BulletSpeed);
+ Bullet->SetBulletColor(FLinearColor::Green);
+ }
+ }
+ }
+}
+```
+
+### Add include at top of STGPawn.cpp:
+
+```cpp
+#include "STGProjectile.h" // Add this line
+```
+
+### Compile again!
+
+---
+
+## Step 3.6: Test Bullet Firing
+
+1. Press **Play** (`Alt+P`)
+2. Move with WASD
+3. Press Z or Space to fire
+4. You should see green spheres shooting upward!
+
+### Expected Result:
+
+- ✅ Player fires 3 bullets in a spread pattern
+- ✅ Bullets are green
+- ✅ Bullets auto-destroy after 4 seconds
+- ✅ Can hold Z to auto-fire
+
+---
+
+## Comparison Summary
+
+### Blueprint Approach:
+
+- Create BP_Bullet Blueprint
+- Add 5 variables manually (×5 clicks each = 25 clicks)
+- Create Blueprint nodes for movement (~15 nodes)
+- Create Blueprint nodes for collision (~10 nodes)
+- Update BP_Player firing logic (~15 more nodes)
+- **Total: ~30 minutes**
+
+### C++ Approach:
+
+- Create STGProjectile class
+- Copy-paste header (5 variables with defaults)
+- Copy-paste implementation
+- Update one function in STGPawn
+- Compile twice
+- **Total: ~10 minutes**
+
+**Time saved: 20 minutes** ⚡
+
+---
+
+## What's Next?
+
+In Part 4, we'll create enemies with C++. You'll see how easy it is to copy enemy patterns!
+
+---
+
+[← Previous: Part 2 (C++) - Create the Player](part-2-cpp-create-player.md) | [Back to Index](README.md) | [Next: Part 4 (C++) - Create the Enemy →](part-4-cpp-create-enemy.md)
diff --git a/games/unreal/tutorial/part-4-cpp-create-enemy.md b/games/unreal/tutorial/part-4-cpp-create-enemy.md
new file mode 100644
index 0000000..a120e82
--- /dev/null
+++ b/games/unreal/tutorial/part-4-cpp-create-enemy.md
@@ -0,0 +1,548 @@
+# Part 4 (C++): Create the Enemy
+
+[← Previous: Part 3 (C++) - Create the Bullet](part-3-cpp-create-bullet.md) | [Back to Index](README.md) | [Next: Part 5 (C++) - Create Enemy Spawner →](part-5-cpp-create-spawner.md)
+
+---
+
+## Overview
+
+Create enemy ships in C++. Again, we'll copy-paste all 15 enemy variables instead of clicking UI 75+ times.
+
+**Time comparison:**
+- Blueprint approach (Part 4): ~90 minutes (16 variables + complex Blueprint nodes)
+- C++ approach (this part): ~25 minutes (copy-paste code)
+
+---
+
+## Step 4.1: Create STGEnemy C++ Class
+
+### In Unreal Editor:
+
+1. Go to **Tools → New C++ Class** (top menu bar)
+2. In the "Choose Parent Class" window:
+ - Click **"Actor"** (enemies are independent game objects)
+ - Click **"Next"**
+
+3. In the "Name Your New Actor" window:
+ - **Name:** `STGEnemy`
+ - **Path:** Should be `Source/BulletHellGame/` (default)
+ - Click **"Create Class"**
+
+### What Happens Next:
+
+1. Unreal generates `STGEnemy.h` and `STGEnemy.cpp`
+2. VS Code opens with the new files
+3. Project compiles automatically (~30-60 seconds)
+4. Unreal Editor refreshes
+
+---
+
+## Step 4.2: Define Enemy Variables in STGEnemy.h
+
+**This is where the magic happens!** Instead of clicking UI 75+ times (16 variables × ~5 clicks each), we'll **copy-paste** all variables at once.
+
+### Open STGEnemy.h in VS Code
+
+Replace the entire file content with:
+
+```cpp
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/Actor.h"
+#include "STGEnemy.generated.h"
+
+class UStaticMeshComponent;
+class UBoxComponent;
+
+UCLASS()
+class BULLETHELLGAME_API ASTGEnemy : public AActor
+{
+ GENERATED_BODY()
+
+public:
+ ASTGEnemy();
+
+protected:
+ virtual void BeginPlay() override;
+
+public:
+ virtual void Tick(float DeltaTime) override;
+
+ // ===== COMPONENTS =====
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
+ UStaticMeshComponent* MeshComp;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
+ UBoxComponent* CollisionComp;
+
+ // ===== HEALTH & SCORE (copy-paste all 15 variables!) =====
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ int32 MaxHealth = 12;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Stats")
+ int32 CurrentHealth = 12;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ int32 ScoreValue = 50;
+
+ // ===== MOVEMENT =====
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float VerticalSpeed = 220.0f;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float HorizontalAmplitude = 250.0f;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float HorizontalFrequency = 1.8f;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float DespawnY = -750.0f;
+
+ // ===== FIRING =====
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float FireInterval = 0.35f;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ int32 BulletsPerBurst = 20;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float BurstSpread = 360.0f;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float EnemyBulletSpeed = 1000.0f;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Stats")
+ float EnemyBulletLifetime = 6.0f;
+
+ // ===== FUNCTIONS =====
+ void Fire();
+ void HandleDamage(float DamageAmount);
+
+ UFUNCTION()
+ void OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
+ UPrimitiveComponent* OtherComp, int32 OtherBodyIndex,
+ bool bFromSweep, const FHitResult& SweepResult);
+
+private:
+ FTimerHandle TimerHandle_Fire;
+ float BaseX = 0.0f;
+ float WaveSeed = 0.0f;
+ float ElapsedTime = 0.0f;
+};
+```
+
+### What Just Happened?
+
+You just defined **15 gameplay variables + 2 components** with default values in ~30 seconds!
+
+In the Blueprint tutorial, this would require:
+- 16 variables × 5 clicks each = **80 clicks**
+- **~20 minutes** of manual work
+- High chance of typos or wrong types
+
+**Time saved: 19.5 minutes** ⚡
+
+---
+
+## Step 4.3: Implement STGEnemy Logic
+
+### Open STGEnemy.cpp in VS Code
+
+Replace the file content with:
+
+```cpp
+#include "STGEnemy.h"
+#include "Components/StaticMeshComponent.h"
+#include "Components/BoxComponent.h"
+#include "Kismet/GameplayStatics.h"
+#include "STGProjectile.h"
+#include "STGPawn.h"
+
+ASTGEnemy::ASTGEnemy()
+{
+ PrimaryActorTick.bCanEverTick = true;
+
+ // Root component
+ RootComponent = CreateDefaultSubobject(TEXT("Root"));
+
+ // Mesh component
+ MeshComp = CreateDefaultSubobject(TEXT("MeshComp"));
+ MeshComp->SetupAttachment(RootComponent);
+ MeshComp->SetCollisionProfileName("NoCollision");
+
+ // Load cube mesh
+ static ConstructorHelpers::FObjectFinder CubeMesh(TEXT("/Engine/BasicShapes/Cube"));
+ if (CubeMesh.Succeeded())
+ {
+ MeshComp->SetStaticMesh(CubeMesh.Object);
+ MeshComp->SetRelativeScale3D(FVector(0.6f, 0.6f, 0.1f));
+ }
+
+ // Collision component
+ CollisionComp = CreateDefaultSubobject(TEXT("CollisionComp"));
+ CollisionComp->SetupAttachment(RootComponent);
+ CollisionComp->SetBoxExtent(FVector(30.f, 30.f, 10.f));
+ CollisionComp->SetCollisionProfileName("OverlapAllDynamic");
+ CollisionComp->SetGenerateOverlapEvents(true);
+ CollisionComp->OnComponentBeginOverlap.AddDynamic(this, &ASTGEnemy::OnOverlapBegin);
+}
+
+void ASTGEnemy::BeginPlay()
+{
+ Super::BeginPlay();
+
+ CurrentHealth = MaxHealth;
+ BaseX = GetActorLocation().X;
+ WaveSeed = FMath::FRand() * 1000.0f;
+ ElapsedTime = 0.0f;
+
+ // Start firing timer
+ GetWorldTimerManager().SetTimer(TimerHandle_Fire, this, &ASTGEnemy::Fire,
+ FireInterval, true, FireInterval);
+}
+
+void ASTGEnemy::Tick(float DeltaTime)
+{
+ Super::Tick(DeltaTime);
+
+ ElapsedTime += DeltaTime;
+
+ // Sinusoidal movement (wave pattern)
+ FVector NewLocation = GetActorLocation();
+
+ // Move downward
+ NewLocation.X -= VerticalSpeed * DeltaTime;
+
+ // Horizontal sine wave
+ float HorizontalOffset = HorizontalAmplitude * FMath::Sin(
+ HorizontalFrequency * (ElapsedTime + WaveSeed)
+ );
+ NewLocation.Y = BaseX + HorizontalOffset;
+
+ SetActorLocation(NewLocation);
+
+ // Check if enemy should despawn (moved off screen)
+ if (NewLocation.X < DespawnY)
+ {
+ Destroy();
+ }
+}
+
+void ASTGEnemy::Fire()
+{
+ // Fire radial burst of bullets
+ for (int32 i = 0; i < BulletsPerBurst; i++)
+ {
+ // Calculate angle for this bullet in the burst
+ float AngleDeg = (BurstSpread / BulletsPerBurst) * i;
+ float AngleRad = FMath::DegreesToRadians(AngleDeg);
+
+ // Calculate direction vector
+ FVector Direction = FVector(
+ FMath::Cos(AngleRad),
+ FMath::Sin(AngleRad),
+ 0.0f
+ );
+
+ // Spawn location slightly below enemy
+ FVector SpawnLocation = GetActorLocation() + FVector(0.f, 0.f, -30.f);
+
+ // Spawn bullet
+ ASTGProjectile* Bullet = GetWorld()->SpawnActor(
+ ASTGProjectile::StaticClass(),
+ SpawnLocation,
+ Direction.Rotation()
+ );
+
+ if (Bullet)
+ {
+ Bullet->bIsPlayerBullet = false;
+ Bullet->SetSpeed(EnemyBulletSpeed);
+ Bullet->SetBulletColor(FLinearColor::Red);
+ Bullet->Lifetime = EnemyBulletLifetime;
+ }
+ }
+}
+
+void ASTGEnemy::HandleDamage(float DamageAmount)
+{
+ CurrentHealth -= DamageAmount;
+
+ if (CurrentHealth <= 0)
+ {
+ // Award score to player
+ ASTGPawn* Player = Cast(UGameplayStatics::GetPlayerPawn(GetWorld(), 0));
+ if (Player)
+ {
+ Player->AddScore(ScoreValue);
+ }
+
+ // Destroy enemy
+ Destroy();
+ }
+}
+
+void ASTGEnemy::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
+ UPrimitiveComponent* OtherComp, int32 OtherBodyIndex,
+ bool bFromSweep, const FHitResult& SweepResult)
+{
+ // Enemy collides with player - damage player
+ if (OtherActor && OtherActor != this)
+ {
+ ASTGPawn* Player = Cast(OtherActor);
+ if (Player)
+ {
+ Player->TakeHit(1);
+ Destroy(); // Enemy dies on collision with player
+ }
+ }
+}
+```
+
+---
+
+## Step 4.4: Update Bullet Collision Logic
+
+Now that enemies exist, we can complete the bullet collision logic.
+
+### Open STGProjectile.cpp
+
+Find the `OnOverlapBegin` function and update the player bullet section:
+
+```cpp
+void ASTGProjectile::OnOverlapBegin(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
+ UPrimitiveComponent* OtherComp, int32 OtherBodyIndex,
+ bool bFromSweep, const FHitResult& SweepResult)
+{
+ if (OtherActor && OtherActor != this)
+ {
+ if (bIsPlayerBullet)
+ {
+ // Player bullet hits enemy
+ ASTGEnemy* Enemy = Cast(OtherActor);
+ if (Enemy)
+ {
+ Enemy->HandleDamage(Damage);
+ Destroy();
+ }
+ }
+ else
+ {
+ // Enemy bullet hits player
+ ASTGPawn* Player = Cast(OtherActor);
+ if (Player)
+ {
+ Player->TakeHit(1);
+ Destroy();
+ }
+ }
+ }
+}
+```
+
+### Add include at top of STGProjectile.cpp:
+
+```cpp
+#include "STGEnemy.h" // Add this line
+```
+
+---
+
+## Step 4.5: Compile the Code
+
+### In Unreal Editor:
+
+1. Click **"Compile"** button (bottom right)
+2. Wait for compilation (~30-60 seconds)
+3. Check for errors in Output Log
+
+OR
+
+### In VS Code:
+
+1. Open terminal in VS Code (`Ctrl+` `)
+2. Run build command (project-specific)
+3. Wait for build to finish
+
+### Expected Result:
+
+- ✅ Compilation succeeds
+- ✅ "C++ Classes" folder in Content Browser shows `STGEnemy`
+- ✅ No errors in Output Log
+
+---
+
+## Step 4.6: Create Blueprint Child
+
+Create a **minimal Blueprint** that inherits from STGEnemy. This Blueprint is ONLY for visual assets!
+
+1. In Content Browser, navigate to `Content → Blueprints`
+2. Right-click → **Blueprint Class**
+3. In "Pick Parent Class" window:
+ - Click "All Classes" dropdown
+ - Search for `STGEnemy`
+ - Select it
+ - Click "Select"
+4. Name it: `BP_Enemy`
+5. Double-click to open
+
+### In the Blueprint Editor:
+
+**Components (Left Panel):**
+- You'll see `MeshComp` and `CollisionComp` from C++
+- NO NEED to add them manually!
+
+**Variables (My Blueprint Panel):**
+- You'll see all 15 variables from C++ (MaxHealth, VerticalSpeed, etc.)
+- NO NEED to create them!
+- All default values are already set from C++!
+
+**What to do:**
+- NOTHING for now! All logic is in C++
+- Compile and Save
+
+---
+
+## Step 4.7: Test Enemy Spawning
+
+1. Drag `BP_Enemy` from Content Browser into the level
+2. Position it above the player (Y = 0, X = 500 or so)
+3. Press **Play** (`Alt+P`)
+
+### Expected Result
+
+**In Play Mode Window:**
+
+**Enemy behavior:**
+- ✅ Enemy appears above player
+- ✅ Enemy moves downward smoothly
+- ✅ Enemy moves in sine wave pattern (left-right oscillation)
+- ✅ Enemy fires red bullet bursts in circular pattern
+- ✅ Bullets spread out in all directions (360-degree burst)
+
+**Player vs Enemy:**
+- ✅ Player bullets (green) destroy enemy when they hit
+- ✅ Enemy bullets (red) damage player when they hit
+- ✅ Player takes damage and loses life when hit
+- ✅ Touching enemy directly damages player and destroys enemy
+
+**Visual confirmation:**
+- Enemy is a cube/box shape (red-ish by default)
+- Enemy fires 20 red bullets in a circular burst every 0.35 seconds
+- Player can shoot enemy with green bullets
+- Score increases when enemy is destroyed (check Output Log or will see in UI later)
+
+**To test collision:**
+- Fly player into enemy - both should take damage
+- Let enemy bullets hit player - player should take damage
+- Shoot enemy with player bullets - enemy health should decrease
+
+**Despawning:**
+- After ~10 seconds, enemy moves off bottom of screen and disappears (auto-destroy)
+
+---
+
+## Step 4.8: Update Player Special Ability
+
+Now that enemies exist, we can complete the special ability to destroy all enemies on screen.
+
+### Open STGPawn.cpp
+
+Find the `UseSpecial()` function and replace it with:
+
+```cpp
+void ASTGPawn::UseSpecial()
+{
+ if (!bSpecialUsed)
+ {
+ bSpecialUsed = true;
+
+ // Destroy all enemies on screen
+ TArray FoundEnemies;
+ UGameplayStatics::GetAllActorsOfClass(GetWorld(), ASTGEnemy::StaticClass(), FoundEnemies);
+ for (AActor* Enemy : FoundEnemies)
+ {
+ Enemy->Destroy();
+ }
+
+ // Destroy all enemy bullets (not player bullets)
+ TArray FoundBullets;
+ UGameplayStatics::GetAllActorsOfClass(GetWorld(), ASTGProjectile::StaticClass(), FoundBullets);
+ for (AActor* Bullet : FoundBullets)
+ {
+ ASTGProjectile* Projectile = Cast(Bullet);
+ if (Projectile && !Projectile->bIsPlayerBullet)
+ {
+ Projectile->Destroy();
+ }
+ }
+
+ UE_LOG(LogTemp, Warning, TEXT("SPECIAL ABILITY - Screen Cleared!"));
+ }
+}
+```
+
+### Add include at top of STGPawn.cpp:
+
+```cpp
+#include "STGEnemy.h" // Add this line
+```
+
+### Compile again!
+
+---
+
+## Step 4.9: Test Special Ability
+
+1. Place several `BP_Enemy` instances in the level (or duplicate the existing one)
+2. Press **Play**
+3. Let enemies spawn and fire bullets
+4. Press **X** to activate special ability
+
+### Expected Result in Play Mode:
+
+- ✅ All enemies disappear instantly when X is pressed
+- ✅ All red enemy bullets disappear instantly
+- ✅ Player's green bullets remain (not destroyed)
+- ✅ Message "SPECIAL ABILITY - Screen Cleared!" appears in Output Log
+- ✅ Pressing X again does nothing (ability can only be used once per game)
+
+---
+
+## Comparison Summary
+
+### Blueprint Approach (Part 4):
+
+1. Create BP_Enemy Blueprint ✅
+2. Add 2 components manually
+3. Add 16 variables one-by-one = **~20 minutes of clicking**
+4. Create Blueprint nodes for movement (~40 nodes with sine wave math)
+5. Create Blueprint nodes for firing (~30 nodes for radial burst)
+6. Create Blueprint nodes for collision detection
+7. Create Blueprint nodes for health/damage system
+8. Update BP_Player special ability nodes
+9. **Total: ~90 minutes**
+
+### C++ Approach (This Part):
+
+1. Create STGEnemy C++ class ✅
+2. Copy-paste header file with 15 variables **30 seconds**
+3. Copy-paste implementation file with all logic
+4. Update bullet collision (5 lines)
+5. Update player special ability (10 lines)
+6. Compile
+7. Create BP_Enemy (inherits everything from C++)
+8. **Total: ~25 minutes**
+
+**Time saved: 65 minutes** ⚡⚡⚡
+
+---
+
+## What's Next?
+
+In Part 5, we'll create the enemy spawner in C++. You'll see how easy it is to manage spawn rates and difficulty curves with code!
+
+---
+
+[← Previous: Part 3 (C++) - Create the Bullet](part-3-cpp-create-bullet.md) | [Back to Index](README.md) | [Next: Part 5 (C++) - Create Enemy Spawner →](part-5-cpp-create-spawner.md)
diff --git a/games/unreal/tutorial/part-5-cpp-create-spawner.md b/games/unreal/tutorial/part-5-cpp-create-spawner.md
new file mode 100644
index 0000000..8f8f1ef
--- /dev/null
+++ b/games/unreal/tutorial/part-5-cpp-create-spawner.md
@@ -0,0 +1,247 @@
+# Part 5 (C++): Create Enemy Spawner
+
+[← Previous: Part 4 (C++) - Create the Enemy](part-4-cpp-create-enemy.md) | [Back to Index](README.md) | [Next: Part 6 (C++) - Create Game Director →](part-6-cpp-create-game-director.md)
+
+---
+
+## Overview
+
+Create an enemy spawner that gradually increases difficulty over time. Copy-paste variables instead of manual UI configuration.
+
+**Time comparison:**
+- Blueprint: ~40 minutes (variables + curve setup + Blueprint nodes)
+- C++ (this part): ~10 minutes (copy-paste code)
+
+---
+
+## Step 5.1: Create STGEnemySpawner C++ Class
+
+1. **Tools → New C++ Class** → Actor → Name: `STGEnemySpawner`
+2. Wait for compilation
+
+---
+
+## Step 5.2: Define Spawner Variables
+
+### Open STGEnemySpawner.h in VS Code
+
+Replace content with:
+
+```cpp
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/Actor.h"
+#include "STGEnemySpawner.generated.h"
+
+UCLASS()
+class BULLETHELLGAME_API ASTGEnemySpawner : public AActor
+{
+ GENERATED_BODY()
+
+public:
+ ASTGEnemySpawner();
+
+protected:
+ virtual void BeginPlay() override;
+
+public:
+ virtual void Tick(float DeltaTime) override;
+
+ // ===== SPAWNING VARIABLES =====
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawning")
+ float SpawnAreaHalfWidth = 900.0f;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawning")
+ float GameDuration = 300.0f; // 5 minutes
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawning")
+ int32 MaxSimultaneousEnemies = 120;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawning")
+ float BaseSpawnInterval = 2.0f;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Spawning")
+ float ElapsedTime = 0.0f;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Spawning")
+ bool bSpawningActive = true;
+
+private:
+ float SpawnTimer = 0.0f;
+ float CurrentSpawnInterval = 2.0f;
+
+ void SpawnEnemy();
+ float CalculateSpawnInterval();
+ FVector GetRandomSpawnLocation();
+};
+```
+
+---
+
+## Step 5.3: Implement Spawner Logic
+
+### Open STGEnemySpawner.cpp
+
+Replace with:
+
+```cpp
+#include "STGEnemySpawner.h"
+#include "STGEnemy.h"
+#include "Kismet/GameplayStatics.h"
+
+ASTGEnemySpawner::ASTGEnemySpawner()
+{
+ PrimaryActorTick.bCanEverTick = true;
+}
+
+void ASTGEnemySpawner::BeginPlay()
+{
+ Super::BeginPlay();
+
+ ElapsedTime = 0.0f;
+ SpawnTimer = 0.0f;
+ CurrentSpawnInterval = BaseSpawnInterval;
+}
+
+void ASTGEnemySpawner::Tick(float DeltaTime)
+{
+ Super::Tick(DeltaTime);
+
+ if (!bSpawningActive)
+ return;
+
+ ElapsedTime += DeltaTime;
+
+ // Stop spawning after game duration
+ if (ElapsedTime >= GameDuration)
+ {
+ bSpawningActive = false;
+ return;
+ }
+
+ // Update spawn interval based on difficulty curve
+ CurrentSpawnInterval = CalculateSpawnInterval();
+
+ // Spawn timer
+ SpawnTimer -= DeltaTime;
+ if (SpawnTimer <= 0.0f)
+ {
+ // Check enemy count
+ TArray FoundEnemies;
+ UGameplayStatics::GetAllActorsOfClass(GetWorld(), ASTGEnemy::StaticClass(), FoundEnemies);
+
+ if (FoundEnemies.Num() < MaxSimultaneousEnemies)
+ {
+ SpawnEnemy();
+ }
+
+ SpawnTimer = CurrentSpawnInterval;
+ }
+}
+
+void ASTGEnemySpawner::SpawnEnemy()
+{
+ FVector SpawnLocation = GetRandomSpawnLocation();
+ FRotator SpawnRotation = FRotator::ZeroRotator;
+
+ ASTGEnemy* NewEnemy = GetWorld()->SpawnActor(
+ ASTGEnemy::StaticClass(),
+ SpawnLocation,
+ SpawnRotation
+ );
+}
+
+float ASTGEnemySpawner::CalculateSpawnInterval()
+{
+ // Difficulty curve: spawn faster as time progresses
+ float GameProgress = ElapsedTime / GameDuration; // 0.0 to 1.0
+
+ // Start at BaseSpawnInterval, reduce to 0.5 seconds at end
+ float MinInterval = 0.5f;
+ float Interval = FMath::Lerp(BaseSpawnInterval, MinInterval, GameProgress);
+
+ return FMath::Max(Interval, MinInterval);
+}
+
+FVector ASTGEnemySpawner::GetRandomSpawnLocation()
+{
+ // Spawn at top of screen, random X position
+ FVector SpawnLoc = GetActorLocation();
+ SpawnLoc.Y = FMath::FRandRange(-SpawnAreaHalfWidth, SpawnAreaHalfWidth);
+ SpawnLoc.X = 800.0f; // Top of play area
+ SpawnLoc.Z = 0.0f;
+
+ return SpawnLoc;
+}
+```
+
+---
+
+## Step 5.4: Compile
+
+1. Click **Compile** in Unreal Editor
+2. Wait for compilation
+3. Check for errors
+
+---
+
+## Step 5.5: Place Spawner in Level
+
+1. From Content Browser "C++ Classes" folder, find `STGEnemySpawner`
+2. Can either:
+ - **Option A**: Drag directly into level (no Blueprint needed!)
+ - **Option B**: Create `BP_EnemySpawner` Blueprint child for tweaking values in editor
+
+3. Position spawner at origin (0, 0, 0) or anywhere - location doesn't matter for spawning
+
+---
+
+## Step 5.6: Test Spawning
+
+1. Remove any manually-placed enemies from level
+2. Make sure spawner is placed
+3. Press **Play**
+
+### Expected Result in Play Mode:
+
+**Spawning behavior:**
+- ✅ Enemies spawn at top of screen every ~2 seconds initially
+- ✅ Spawn rate gradually increases (gets faster over time)
+- ✅ Enemies spawn at random horizontal positions
+- ✅ Maximum of 120 enemies on screen at once
+- ✅ After 5 minutes (300 seconds), spawning stops
+
+**Visual confirmation:**
+- Enemies appear from top edge of screen
+- Each spawns at a different Y position (left-right spread)
+- As time passes, enemies spawn more frequently
+- Game becomes progressively harder
+
+**Performance:**
+- Even with many enemies, game maintains 60 FPS
+- No lag or stuttering when many enemies/bullets on screen
+
+---
+
+## Comparison Summary
+
+### Blueprint: ~40 minutes
+- Create spawner Blueprint
+- Add 6 variables manually
+- Create spawn rate curve asset
+- Complex Blueprint nodes for curve sampling
+- Random position calculation nodes
+- Enemy counting logic
+
+### C++: ~10 minutes
+- Create C++ class
+- Copy-paste variables and logic
+- Compile
+- Place in level
+
+**Time saved: 30 minutes** ⚡
+
+---
+
+[← Previous: Part 4 (C++) - Create the Enemy](part-4-cpp-create-enemy.md) | [Back to Index](README.md) | [Next: Part 6 (C++) - Create Game Director →](part-6-cpp-create-game-director.md)
diff --git a/games/unreal/tutorial/part-6-cpp-create-game-director.md b/games/unreal/tutorial/part-6-cpp-create-game-director.md
new file mode 100644
index 0000000..56f0e91
--- /dev/null
+++ b/games/unreal/tutorial/part-6-cpp-create-game-director.md
@@ -0,0 +1,167 @@
+# Part 6 (C++): Create Game Director
+
+[← Previous: Part 5 (C++) - Create Enemy Spawner](part-5-cpp-create-spawner.md) | [Back to Index](README.md) | [Next: Part 7 (C++) - Create UI →](part-7-cpp-create-ui.md)
+
+---
+
+## Overview
+
+Create a Game Director to manage the game timer, victory/defeat conditions, and overall game state.
+
+**Time:** ~10 minutes
+
+---
+
+## Step 6.1: Create STGGameDirector C++ Class
+
+1. **Tools → New C++ Class** → Actor → Name: `STGGameDirector`
+2. Wait for compilation
+
+---
+
+## Step 6.2: Define Game Director Variables
+
+### STGGameDirector.h:
+
+```cpp
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/Actor.h"
+#include "STGGameDirector.generated.h"
+
+UCLASS()
+class BULLETHELLGAME_API ASTGGameDirector : public AActor
+{
+ GENERATED_BODY()
+
+public:
+ ASTGGameDirector();
+
+protected:
+ virtual void BeginPlay() override;
+
+public:
+ virtual void Tick(float DeltaTime) override;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Game")
+ float GameDuration = 300.0f;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Game")
+ float ElapsedTime = 0.0f;
+
+ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Game")
+ bool bGameActive = true;
+
+ void OnPlayerDied();
+ void OnVictory();
+ void OnGameOver();
+};
+```
+
+---
+
+## Step 6.3: Implement Game Director
+
+### STGGameDirector.cpp:
+
+```cpp
+#include "STGGameDirector.h"
+#include "Kismet/GameplayStatics.h"
+
+ASTGGameDirector::ASTGGameDirector()
+{
+ PrimaryActorTick.bCanEverTick = true;
+}
+
+void ASTGGameDirector::BeginPlay()
+{
+ Super::BeginPlay();
+ ElapsedTime = 0.0f;
+ bGameActive = true;
+}
+
+void ASTGGameDirector::Tick(float DeltaTime)
+{
+ Super::Tick(DeltaTime);
+
+ if (!bGameActive)
+ return;
+
+ ElapsedTime += DeltaTime;
+
+ // Check for victory (survived full duration)
+ if (ElapsedTime >= GameDuration)
+ {
+ OnVictory();
+ }
+}
+
+void ASTGGameDirector::OnPlayerDied()
+{
+ OnGameOver();
+}
+
+void ASTGGameDirector::OnVictory()
+{
+ bGameActive = false;
+ UE_LOG(LogTemp, Warning, TEXT("VICTORY! You survived %f seconds!"), ElapsedTime);
+
+ // Pause game
+ UGameplayStatics::SetGamePaused(GetWorld(), true);
+}
+
+void ASTGGameDirector::OnGameOver()
+{
+ bGameActive = false;
+ UE_LOG(LogTemp, Warning, TEXT("GAME OVER! Survived %f seconds"), ElapsedTime);
+
+ // Pause game
+ UGameplayStatics::SetGamePaused(GetWorld(), true);
+}
+```
+
+---
+
+## Step 6.4: Update Player Death to Notify Director
+
+### In STGPawn.cpp, update HandleDeath():
+
+```cpp
+void ASTGPawn::HandleDeath()
+{
+ SetActorHiddenInGame(true);
+
+ // Find and notify Game Director
+ TArray FoundDirectors;
+ UGameplayStatics::GetAllActorsOfClass(GetWorld(), ASTGGameDirector::StaticClass(), FoundDirectors);
+ if (FoundDirectors.Num() > 0)
+ {
+ ASTGGameDirector* Director = Cast(FoundDirectors[0]);
+ if (Director)
+ {
+ Director->OnPlayerDied();
+ }
+ }
+}
+```
+
+Add include: `#include "STGGameDirector.h"`
+
+---
+
+## Step 6.5: Place Director in Level and Test
+
+1. Drag `STGGameDirector` from C++ Classes into level
+2. Press Play
+3. Wait 5 minutes OR let player die
+
+### Expected Result:
+
+- ✅ Timer counts up from 0
+- ✅ After 300 seconds: "VICTORY!" message, game pauses
+- ✅ If player dies: "GAME OVER!" message, game pauses
+
+---
+
+[← Previous: Part 5 (C++) - Create Enemy Spawner](part-5-cpp-create-spawner.md) | [Back to Index](README.md) | [Next: Part 7 (C++) - Create UI →](part-7-cpp-create-ui.md)
diff --git a/games/unreal/tutorial/part-7-cpp-create-ui.md b/games/unreal/tutorial/part-7-cpp-create-ui.md
new file mode 100644
index 0000000..415d5c2
--- /dev/null
+++ b/games/unreal/tutorial/part-7-cpp-create-ui.md
@@ -0,0 +1,209 @@
+# Part 7 (C++): Create UI
+
+[← Previous: Part 6 (C++) - Create Game Director](part-6-cpp-create-game-director.md) | [Back to Index](README.md) | [Next: Part 8 (C++) - Create Game Mode →](part-8-cpp-create-game-mode.md)
+
+---
+
+## Overview
+
+For UI, we use **Widget Blueprints** for visual layout (drag-and-drop is better for UI design), but bind to C++ properties for data.
+
+**Time:** ~15 minutes
+
+---
+
+## Step 7.1: Create Widget Blueprint
+
+1. Content Browser → UI folder
+2. Right-click → **User Interface → Widget Blueprint**
+3. Name: `WBP_HUD`
+4. Double-click to open Widget Designer
+
+---
+
+## Step 7.2: Design HUD Layout
+
+In Widget Designer:
+
+1. **Add Text blocks** (from Palette → Common):
+ - `txt_Score` - Display score
+ - `txt_Lives` - Display lives
+ - `txt_Timer` - Display time remaining
+
+2. **Position them** (top-left corner):
+ - Score: Top-left (0, 0)
+ - Lives: Below score (0, 30)
+ - Timer: Below lives (0, 60)
+
+3. **Style text:**
+ - Font Size: 24
+ - Color: White
+ - Set default text: "Score: 0", "Lives: 3", "Time: 300"
+
+4. **Compile and Save**
+
+---
+
+## Step 7.3: Create HUD Manager C++ Class
+
+We'll create a simple C++ class to update the UI.
+
+### Create STGHUDManager.h:
+
+```cpp
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/Actor.h"
+#include "STGHUDManager.generated.h"
+
+UCLASS()
+class BULLETHELLGAME_API ASTGHUDManager : public AActor
+{
+ GENERATED_BODY()
+
+public:
+ ASTGHUDManager();
+
+protected:
+ virtual void BeginPlay() override;
+
+public:
+ virtual void Tick(float DeltaTime) override;
+
+ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "UI")
+ TSubclassOf HUDWidgetClass;
+
+ UFUNCTION(BlueprintCallable, Category = "UI")
+ void UpdateScore(int32 NewScore);
+
+ UFUNCTION(BlueprintCallable, Category = "UI")
+ void UpdateLives(int32 NewLives);
+
+ UFUNCTION(BlueprintCallable, Category = "UI")
+ void UpdateTimer(float TimeRemaining);
+
+private:
+ class UUserWidget* HUDWidget;
+};
+```
+
+### STGHUDManager.cpp:
+
+```cpp
+#include "STGHUDManager.h"
+#include "Blueprint/UserWidget.h"
+#include "Components/TextBlock.h"
+
+ASTGHUDManager::ASTGHUDManager()
+{
+ PrimaryActorTick.bCanEverTick = true;
+}
+
+void ASTGHUDManager::BeginPlay()
+{
+ Super::BeginPlay();
+
+ if (HUDWidgetClass)
+ {
+ HUDWidget = CreateWidget(GetWorld(), HUDWidgetClass);
+ if (HUDWidget)
+ {
+ HUDWidget->AddToViewport();
+ }
+ }
+}
+
+void ASTGHUDManager::Tick(float DeltaTime)
+{
+ Super::Tick(DeltaTime);
+}
+
+void ASTGHUDManager::UpdateScore(int32 NewScore)
+{
+ if (HUDWidget)
+ {
+ UTextBlock* ScoreText = Cast(HUDWidget->GetWidgetFromName(TEXT("txt_Score")));
+ if (ScoreText)
+ {
+ ScoreText->SetText(FText::Format(FText::FromString("Score: {0}"), NewScore));
+ }
+ }
+}
+
+void ASTGHUDManager::UpdateLives(int32 NewLives)
+{
+ if (HUDWidget)
+ {
+ UTextBlock* LivesText = Cast(HUDWidget->GetWidgetFromName(TEXT("txt_Lives")));
+ if (LivesText)
+ {
+ LivesText->SetText(FText::Format(FText::FromString("Lives: {0}"), NewLives));
+ }
+ }
+}
+
+void ASTGHUDManager::UpdateTimer(float TimeRemaining)
+{
+ if (HUDWidget)
+ {
+ UTextBlock* TimerText = Cast(HUDWidget->GetWidgetFromName(TEXT("txt_Timer")));
+ if (TimerText)
+ {
+ int32 Seconds = FMath::CeilToInt(TimeRemaining);
+ TimerText->SetText(FText::Format(FText::FromString("Time: {0}s"), Seconds));
+ }
+ }
+}
+```
+
+---
+
+## Step 7.4: Integrate HUD with Game
+
+1. Place `STGHUDManager` in level
+2. Select it, in Details panel:
+ - Set **HUD Widget Class** → `WBP_HUD`
+
+3. Update `STGGameDirector` to update timer:
+
+```cpp
+void ASTGGameDirector::Tick(float DeltaTime)
+{
+ // ... existing code ...
+
+ // Update HUD
+ TArray FoundManagers;
+ UGameplayStatics::GetAllActorsOfClass(GetWorld(), ASTGHUDManager::StaticClass(), FoundManagers);
+ if (FoundManagers.Num() > 0)
+ {
+ ASTGHUDManager* HUDMgr = Cast(FoundManagers[0]);
+ if (HUDMgr)
+ {
+ HUDMgr->UpdateTimer(GameDuration - ElapsedTime);
+ }
+ }
+}
+```
+
+4. Update `STGPawn` to update score/lives when they change
+
+---
+
+## Step 7.5: Test UI
+
+Press Play
+
+### Expected Result:
+
+**In Play Mode:**
+- ✅ UI appears in top-left corner
+- ✅ "Score: 0", "Lives: 3", "Time: 300" displayed
+- ✅ Timer counts down from 300
+- ✅ Score increases when enemies are destroyed
+- ✅ Lives decrease when player is hit
+- ✅ Text is readable (white on dark background)
+
+---
+
+[← Previous: Part 6 (C++) - Create Game Director](part-6-cpp-create-game-director.md) | [Back to Index](README.md) | [Next: Part 8 (C++) - Create Game Mode →](part-8-cpp-create-game-mode.md)
diff --git a/games/unreal/tutorial/part-8-cpp-create-game-mode.md b/games/unreal/tutorial/part-8-cpp-create-game-mode.md
new file mode 100644
index 0000000..d67919f
--- /dev/null
+++ b/games/unreal/tutorial/part-8-cpp-create-game-mode.md
@@ -0,0 +1,96 @@
+# Part 8 (C++): Create Game Mode
+
+[← Previous: Part 7 (C++) - Create UI](part-7-cpp-create-ui.md) | [Back to Index](README.md) | [Next: Part 9 (C++) - Final Setup →](part-9-cpp-final-setup.md)
+
+---
+
+## Overview
+
+Create a custom Game Mode to set the default pawn class and manage game rules.
+
+**Time:** ~5 minutes
+
+---
+
+## Step 8.1: Create STGGameMode C++ Class
+
+1. **Tools → New C++ Class**
+2. Choose **"Game Mode Base"** as parent
+3. Name: `STGGameMode`
+4. Create Class
+
+---
+
+## Step 8.2: Define Game Mode
+
+### STGGameMode.h:
+
+```cpp
+#pragma once
+
+#include "CoreMinimal.h"
+#include "GameFramework/GameModeBase.h"
+#include "STGGameMode.generated.h"
+
+UCLASS()
+class BULLETHELLGAME_API ASTGGameMode : public AGameModeBase
+{
+ GENERATED_BODY()
+
+public:
+ ASTGGameMode();
+};
+```
+
+### STGGameMode.cpp:
+
+```cpp
+#include "STGGameMode.h"
+#include "STGPawn.h"
+
+ASTGGameMode::ASTGGameMode()
+{
+ // Set default pawn class to our player
+ DefaultPawnClass = ASTGPawn::StaticClass();
+
+ // Disable auto-possess (we'll handle spawning ourselves)
+ bStartPlayersAsSpectators = false;
+}
+```
+
+---
+
+## Step 8.3: Set Game Mode in Project Settings
+
+1. **Edit → Project Settings**
+2. **Project → Maps & Modes**
+3. Under "Default Modes":
+ - **Default GameMode** → Select `STGGameMode`
+4. Close Project Settings
+
+---
+
+## Step 8.4: Test
+
+Create a new level or use existing one:
+
+1. **File → New Level** → Empty Level
+2. Save as `BulletHellLevel`
+3. Add:
+ - Player Start (from Place Actors panel)
+ - STGEnemySpawner
+ - STGGameDirector
+ - STGHUDManager
+ - Directional Light (for visibility)
+
+4. Press Play
+
+### Expected Result:
+
+- ✅ Player automatically spawns at Player Start location
+- ✅ No need to manually drag BP_Player into level
+- ✅ All game systems work together
+
+---
+
+[← Previous: Part 7 (C++) - Create UI](part-7-cpp-create-ui.md) | [Back to Index](README.md) | [Next: Part 9 (C++) - Final Setup →](part-9-cpp-final-setup.md)
diff --git a/games/unreal/tutorial/part-9-cpp-final-setup.md b/games/unreal/tutorial/part-9-cpp-final-setup.md
new file mode 100644
index 0000000..b09c5c0
--- /dev/null
+++ b/games/unreal/tutorial/part-9-cpp-final-setup.md
@@ -0,0 +1,160 @@
+# Part 9 (C++): Final Setup
+
+[← Previous: Part 8 (C++) - Create Game Mode](part-8-cpp-create-game-mode.md) | [Back to Index](README.md)
+
+---
+
+## Overview
+
+Polish the game with visual assets, materials, and final tweaks.
+
+**Time:** ~15 minutes
+
+---
+
+## Step 9.1: Assign Better Visuals to Blueprints
+
+Now we use Blueprints for what they're good at: assigning visual assets!
+
+### BP_Player:
+
+1. Open `BP_Player`
+2. Select `ShipMesh` component
+3. In Details:
+ - **Static Mesh** → Keep Cone or choose a spaceship model
+ - **Material** → Create or assign a green emissive material
+4. Compile and Save
+
+### BP_Enemy:
+
+1. Open `BP_Enemy`
+2. Select `MeshComp` component
+3. In Details:
+ - **Static Mesh** → Keep Cube or choose enemy model
+ - **Material** → Create or assign a red emissive material
+4. Compile and Save
+
+### BP_Bullet (if you created one):
+
+1. Same process - assign materials for player (green) vs enemy (red) bullets
+
+---
+
+## Step 9.2: Create Background
+
+1. In level, add **Plane** (from Place Actors → Basic → Plane)
+2. Scale it large (Scale: 50, 50, 1)
+3. Position below player (Z: -100)
+4. Assign dark material (black or dark blue)
+5. This provides contrast for bullets and enemies
+
+---
+
+## Step 9.3: Adjust Camera
+
+If camera needs adjustment:
+
+1. Select BP_Player in level
+2. Find `SpringArm` component
+3. Adjust:
+ - **Target Arm Length** - Higher = further away camera
+ - **Socket Offset** - Adjust view position
+
+---
+
+## Step 9.4: Final Testing
+
+Press Play and verify:
+
+**Gameplay:**
+- ✅ Player moves smoothly with WASD
+- ✅ Player fires green bullets in spread pattern
+- ✅ Enemies spawn from top
+- ✅ Enemies move in sine wave pattern
+- ✅ Enemies fire red bullet bursts
+- ✅ Collision detection works (bullets hit enemies, enemies hit player)
+- ✅ Score increases when enemies destroyed
+- ✅ Lives decrease when hit
+- ✅ Special ability clears screen (X key)
+- ✅ Timer counts down
+- ✅ Victory after 300 seconds
+- ✅ Game over if lives reach 0
+
+**Visual Polish:**
+- ✅ Player and enemies have distinct colors
+- ✅ Bullets are visible and distinguishable
+- ✅ UI is readable
+- ✅ Background provides good contrast
+
+**Performance:**
+- ✅ 60 FPS with 100+ bullets on screen
+- ✅ No lag or stuttering
+
+---
+
+## Step 9.5: Build Standalone Game (Optional)
+
+To build a playable executable:
+
+1. **File → Package Project → Windows** (or Linux)
+2. Choose output folder
+3. Wait for build (5-10 minutes)
+4. Run the `.exe` file from output folder
+
+---
+
+## Completion Summary
+
+### Total Time Comparison
+
+| Part | Blueprint | C++ | Time Saved |
+|------|-----------|-----|------------|
+| 1. Project Setup | 5 min | 10 min | -5 min |
+| 2. Player | 60 min | 15 min | 45 min ⚡ |
+| 3. Bullet | 30 min | 10 min | 20 min ⚡ |
+| 4. Enemy | 90 min | 25 min | 65 min ⚡ |
+| 5. Spawner | 40 min | 10 min | 30 min ⚡ |
+| 6. Game Director | 45 min | 10 min | 35 min ⚡ |
+| 7. UI | 30 min | 15 min | 15 min ⚡ |
+| 8. Game Mode | 20 min | 5 min | 15 min ⚡ |
+| 9. Final Setup | 40 min | 15 min | 25 min ⚡ |
+| **TOTAL** | **6-8 hours** | **2-3 hours** | **4-5 hours saved!** ⚡⚡⚡ |
+
+### Key Benefits Achieved
+
+✅ **90% faster variable definition** - copy-paste vs clicking
+✅ **Version control friendly** - readable C++ diffs instead of binary Blueprints
+✅ **Type-safe** - compiler catches errors before runtime
+✅ **IDE support** - autocomplete, refactoring, debugging
+✅ **Easier to maintain** - code is documentation
+✅ **Reusable** - copy C++ files to new projects instantly
+
+### Hybrid Approach Used
+
+- **C++ for logic** - All game mechanics, variables, algorithms
+- **Blueprints for visuals** - Meshes, materials, colors
+- **Best of both worlds** - Fast development + visual asset management
+
+---
+
+## What's Next?
+
+**Extend the game:**
+- Add power-ups
+- Multiple enemy types
+- Boss battles
+- Sound effects and music
+- Particle effects
+- Leaderboard system
+
+**All easily done in C++** with the same copy-paste efficiency!
+
+---
+
+## Congratulations! 🎉
+
+You've built a complete bullet-hell game in Unreal Engine using C++ in 2-3 hours instead of 6-8 hours with Blueprints!
+
+---
+
+[← Previous: Part 8 (C++) - Create Game Mode](part-8-cpp-create-game-mode.md) | [Back to Index](README.md)