🎮 DESIGN DOCUMENTS - SCRATCH → PYGAME CURRICULUM
---
PROJECT 1: KELAS 1-2 SD - "KUCING PENARI" (Scratch)
📋 Project Overview
Tujuan: Introduce Scratch interface, sprite movement, costume changes, dan basic events
Durasi: 2-3 jam (split 3 pertemuan)
Level: Beginner
Prerequisite: Belum ada
---
🎯 Learning Objectives
[ ] Memahami canvas dan sprite
[ ] Gerak sprite dengan say/think
[ ] Perubahan kostum (animation)
[ ] Respond to click events
[ ] Bermain sound/musik
---
🎨 Visual Design
```
┌─────────────────────────────────┐
│     CAT DANCER STAGE             │
│  ┌───────────────────────────┐  │
│  │                           │  │
│  │        🐱 (SPRITE)        │  │
│  │      Bisa gerak 4 arah    │  │
│  │      Bisa rotate          │  │
│  │      Bisa ubah kostum     │  │
│  │                           │  │
│  └───────────────────────────┘  │
│  Background: Warna cerah/gradasi │
└─────────────────────────────────┘

INTERAKSI:
- Klik kucing → bilang nama
- Tekan SPACE → mulai menari
- Arrow keys → gerak
- Klik tombol → ganti kostum/musik
```
---
🔧 Mechanics & Features
CORE MECHANICS:
Movement (4-directional)
When `arrow UP` pressed → move to (x, y-10)
When `arrow DOWN` pressed → move to (y+10)
Rotation smooth (turn 15 degrees)
Animation (Kostum)
Costume 1: Standing pose
Costume 2: Left leg up
Costume 3: Right leg up
Loop costume setiap 0.5s saat dancing
Click Interaction
When sprite clicked → say name (2 sec)
Random pose
Sound
Play music looping
Sound effect saat klik
BONUS FEATURES:
Spin when double-clicked
Follow mouse mode (toggle)
Rainbow pen color trail
---
📝 Step-by-Step Teaching Plan
PERTEMUAN 1 (60 menit): Sprite & Basic Movement
Goal: Siswa bisa move sprite 4 arah
Intro (5 min)
Tunjuk Scratch interface
Klik stage, klik sprite
Explain: Blocks = perintah
Demo Blok Dasar (10 min)
```
   move (10) steps
   wait (1) second
   turn (15) degrees
   ```
Tunjukkan cara drag-and-drop
Run block individual
Membuat Movement Script (30 min)
```
   WHEN [UP ARROW] PRESSED
   repeat (5) times
     move (10) steps
   
   WHEN [DOWN ARROW] PRESSED
   repeat (5) times
     move (-10) steps
   
   WHEN [LEFT ARROW] PRESSED
   turn (-15) degrees
   
   WHEN [RIGHT ARROW] PRESSED
   turn (15) degrees
   ```
Students code junto (bersama-sama)
Test each block
Experimentation (15 min)
Ubah speed (jumlah steps)
Ubah rotation angle
Kasih kebebasan eksplorasi
---
PERTEMUAN 2 (60 menit): Animation & Costume
Goal: Siswa bisa ubah kostum dengan animasi
Review Movement (5 min)
Tanya: "Gimana caranya move?"
Siswa tunjukkan sendiri
Introduce Costume Changes (15 min)
Edit sprite → upload 3 pose dancing
Show next costume block
```
   WHEN [SPACE] PRESSED
   repeat (10) times
     next costume
     wait (0.2) seconds
   ```
Create Dance Script (25 min)
```
   WHEN FLAG CLICKED
   set [is_dancing] to [false]
   
   WHEN [SPACE] PRESSED
   set [is_dancing] to [true]
   repeat until [is_dancing] = [false]
     next costume
     wait (0.2) seconds
   
   WHEN [S] PRESSED
   set [is_dancing] to [false]
   ```
Add Multiple Dance Styles (15 min)
Different speed (wait 0.1 vs 0.3)
Different costumes sequence
Play music saat dance
---
PERTEMUAN 3 (60 menit): Click Events & Sound
Goal: Siswa bisa click sprite, play sound
Click Detection (15 min)
```
   WHEN THIS SPRITE CLICKED
   say [Halo! Aku kucing penari!] for (2) seconds
   start sound [meow v]
   ```
Randomize Response (15 min)
```
   WHEN THIS SPRITE CLICKED
   pick random (1) to (3)
   if answer = 1
     say [Halo!]
   if answer = 2
     say [Apa kabar?]
   if answer = 3
     say [Ajak aku nari!]
   ```
Music Integration (15 min)
Add background music (loop)
Sound effect per action
Volume control
Polish & Testing (15 min)
Siswa present project
Peer feedback
Record video
---
💻 Block Structure (Visual Code)
```
┌─ FLAG CLICKED
│  └─ set [music] to [play until done v]
│
├─ UP ARROW PRESSED
│  └─ repeat (5) times
│     └─ move (10) steps
│
├─ SPACE PRESSED
│  └─ repeat (10) times
│     ├─ next costume
│     └─ wait (0.2) seconds
│
└─ THIS SPRITE CLICKED
   ├─ say [Halo!]
   └─ start sound [meow v]
```
---
📊 Assessment Rubric
Criteria	Excellent (4)	Good (3)	Fair (2)	Poor (1)
Movement	4-arah smooth, no overlap	3 arah bekerja	1-2 arah	Tidak berfungsi
Animation	Smooth, timing baik	Ada tapi jaky	Ada basic	Tidak ada
Interactivity	Click + sound + feedback	2 dari 3	1 dari 3	Tidak interaktif
Code Quality	Clean, organized blocks	Mostly organized	Messy tapi jalan	Tidak paham blocks
Creativity	Unique design/sounds	Standard tapi rapi	Basic + minimal effort	Copy paste only
---
⭐ Extensions (Differentiation)
EASY: Add "reset position" tombol (change x/y to 0)
MEDIUM:
Create multiple sprite dancers
Add turn left/right smooth
Score system: klik kucing +1
HARD:
Clone sprites (create army of dancers)
Broadcast message between sprites
Animation synchronization
---
📚 Materials Needed
[ ] Scratch account (free)
[ ] Cat sprite + 3 costume variations
[ ] Royalty-free dance music MP3
[ ] Sound effect (meow, bell, etc)
[ ] Projector + internet connection
---
---
PROJECT 2: KELAS 3-4 SD - "FLAPPY BIRD CLONE" (Scratch)
📋 Project Overview
Tujuan: Introduce physics simulation, random obstacles, collision detection, scoring system
Durasi: 3-4 jam (split 4 pertemuan)
Level: Intermediate
Prerequisite: Movement, events, basic variables
---
🎯 Learning Objectives
[ ] Implement gravity & physics
[ ] Random obstacle generation
[ ] Collision detection
[ ] Variable scoring system
[ ] Game state management (play/game over)
---
🎨 Visual Design
```
SCRATCH COORDINATE SYSTEM:
                    Y = 180 (TOP)
                       ▲
        Sky (Y > 0)     │
                        │
    Y = 0 (CENTER) ─────┼───── 
                        │
    Ground (Y < 0)      │
                        ▼
                    Y = -180 (BOTTOM/FLOOR)

SIDE-SCROLLING VIEW (IN GAME):
┌─────────────────────────────────┐
│ Score: 5                        │  Y = 150+ (Sky)
│ ┌──────────┐                    │
│ │  🐦  ↓   │  ┌────┐            │  Y = 0-100 (Flying zone)
│ │velocity  │  │    │ PIPE       │
│ │ = -2.5   │  │    │ (obstacle) │
│ │          │  └────┘            │
│ │          │                    │  Y = -80 (Lower zone)
│ └──────────┘                    │
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━  │  Y = -180 (FLOOR - collision!)
└─────────────────────────────────┘

COORDINATE FACTS:
✓ Higher Y = bird naik (SPACE pressed: velocity = +8)
✓ Lower Y = bird turun (gravity pulls: velocity becomes negative)
✓ Collision at Y < -180 (bird hits floor)

MECHANICS:
- Bird jatuh otomatis (gravity = -0.5 per frame)
- Klik/SPACE → flap (velocity = +8, overcome gravity)
- Pipes appear & move left
- Collision with pipe atau floor = Game Over
- Score +1 setiap pass pipe center (x=0)
```
---
🔧 Mechanics & Features
CORE MECHANICS:
Gravity System (Acceleration)
```
   Constants:
   gravity = -0.5     (downward acceleration)
   
   Each frame:
   velocity = velocity + gravity    (velocity menjadi lebih negative)
   y = y + velocity                 (apply velocity ke position)
   
   CONTOH:
   Frame 1-5: velocity = 0, -0.5, -1.0, -1.5, -2.0
   Burung jatuh semakin CEPAT (velocity naik in magnitude, negatif direction)
   ```
Jump (Flap) - Instant Velocity Change
```
   WHEN [SPACE] PRESSED
   set velocity to 8    [positive = up, overcome gravity]
   play sound [wing.mp3]
   
   Saat jump:
   - Velocity jadi positif (8)
   - y naik 8px
   - Frame berikutnya: gravity kurangin velocity → 7.5, 7.0, dst
   - Gravity terus pull sampai velocity negative lagi (turun lagi)
   ```
Obstacle Generation
```
   Clone pipe sprite every (2) seconds
   Each clone:
     - x = 240 (right edge)
     - y = random (-80 to 80)
     - Move left smoothly (-3 steps per frame)
   Delete clone when x < -50
   ```
Collision Detection
```
   IF bird touching [pipe]
   OR bird touching [ground]
   OR bird.y < 0
   THEN → set game_over to [true]
   ```
Scoring
```
   WHEN bird passes pipe center (x = 0)
   change score by (1)
   play sound [ding.mp3]
   ```
---
📝 Step-by-Step Teaching Plan
PERTEMUAN 1 (60 min): Gravity & Flap Mechanics
Goal: Bird jatuh & bisa jump
PENTING: Penjelasan Koordinat Scratch
```
Di Scratch:
Y = 0   (center)
Y > 0   (NAIK ke atas) ⬆️
Y < 0   (TURUN ke bawah) ⬇️

Gravity negatif (-0.5) = force ke bawah (Y lebih kecil = turun)
```
Intro Game Mechanics (10 min)
Demo Flappy Bird (YouTube)
Discuss: "Apa yang terjadi saat elo tap?"
Brain storm: gravity, velocity, collision
Jelaskan: velocity = kecepatan jatuh (naik terus seiring waktu)
Implement Gravity (25 min)
```
   [Create Variables: velocity, gravity]
   
   WHEN FLAG CLICKED
   set [velocity] to [0]
   set [gravity] to [-0.5]  ← NEGATIF (downward force)
   go to x: [-50] y: [100]
   
   FOREVER
     change [velocity] by [gravity]    ← velocity jadi lebih negative
     change y by [velocity]            ← IMPORTANT: apply velocity!
     
     if (y < -180)                     ← floor collision
       set y to [-180]
   ```
Test: bird jatuh semakin cepat? Good!
Trace through:
Frame 1: velocity=0, y tidak berubah
Frame 2: velocity=-0.5, y turun 0.5
Frame 3: velocity=-1.0, y turun 1.0 (lebih cepat)
Adjust gravity value: -0.3 (slow fall) vs -0.7 (fast fall)
Add Flap/Jump (15 min)
```
   WHEN [SPACE] PRESSED
   set [velocity] to [8]   ← POSITIF (naik ke atas)
   play sound [wing]
   ```
Test: klik space, bird naik
Trace: velocity=8 → y naik 8px
Lalu gravity terus pull: velocity jadi 7.5, 7.0, dst...
Adjust jump power: 6, 8, 10 (terlalu kuat?)
Experimentation (10 min)
Ubah gravity jadi -0.3 (float lambat)
Ubah gravity jadi -0.8 (hard fall)
Ubah jump jadi 6, 10, 12
Discuss: "Kombinasi mana yang feel terbaik?"
---
PERTEMUAN 2 (60 min): Pipes & Cloning
Goal: Obstacles appear dan move
Review Gravity (5 min)
Tanya: "Gimana caranya gravity?"
Tunjukkan di code
Create Pipe Sprite (10 min)
Draw/upload pipe sprite
2 costumes: pipe-up, pipe-down (gap di tengah)
Or: use 2 separate pipe sprites
Implement Pipe Cloning (30 min)
```
   [Create Variables: pipe_interval, pipe_speed]
   
   WHEN FLAG CLICKED
   set [pipe_interval] to [2]
   set [pipe_speed] to [3]
   
   FOREVER
     wait (pipe_interval) seconds
     create clone of [pipe v]
   ```
Clone Behavior Script (15 min)
```
   WHEN I START AS A CLONE
   set x to [240]
   set y to (random -80 to 80)
   
   REPEAT UNTIL (x < -50)
     change x by (-(pipe_speed))
     wait (0.05) seconds
   
   delete this clone
   ```
---
PERTEMUAN 3 (60 min): Collision & Scoring
Goal: Game over & score system
Collision Detection (25 min)
```
   [Create Variable: game_over]
   
   WHEN FLAG CLICKED
   set [game_over] to [false]
   
   FOREVER
     IF (bird touching [pipe]) OR (bird touching [ground])
       set [game_over] to [true]
       broadcast [GAME OVER v]
   ```
Scoring System (20 min)
```
   [Create Variable: score]
   
   // In bird script:
   FOREVER
     IF (x of pipe) = 0
       change [score] by [1]
       play sound [ding]
   
   // Alternative: use invisible "scorezone" sprite
   ```
Game Over Screen (15 min)
```
   WHEN I RECEIVE [GAME OVER]
   stop [other scripts in sprite v]
   say (join [Game Over! Score: ] [score]) for (3) seconds
   ```
---
PERTEMUAN 4 (60 min): Polish & Difficulty
Goal: Smooth gameplay, difficulty curve
Visual Polish (15 min)
Add background parallax scrolling
Animate bird rotation (tilt when falling)
Sound design (background music, SFX)
Difficulty Progression (15 min)
```
   [Create Variable: level]
   
   WHEN FLAG CLICKED
   set [level] to [1]
   
   FOREVER
     IF (score) mod 5 = 0
       set [pipe_interval] to (2 - level * 0.1)  // faster
       set [pipe_speed] to (3 + level * 0.5)     // quicker
       change [level] by [1]
   ```
Testing & Balancing (15 min)
Play test: Is it fun?
Adjust gravity, pipe speed, gap size
Get feedback dari teman
Final Review & Recording (15 min)
Clean up code (delete unused blocks)
Record gameplay video
Write score achieved
---
💻 Block Structure (Correct Physics)
```
BIRD SPRITE:
├─ WHEN FLAG CLICKED
│  ├─ set [velocity] to [0]
│  ├─ set [gravity] to [-0.5]
│  ├─ set [game_over] to [false]
│  ├─ set [score] to [0]
│  ├─ go to x: [-50] y: [100]
│  └─ show
│
├─ FOREVER (Main Physics Loop)
│  ├─ change [velocity] by [gravity]    ← velocity accelerate
│  ├─ change y by [velocity]            ← apply velocity to position
│  ├─ if (y < -180)
│  │  └─ set y to [-180]                ← floor collision
│  │
│  ├─ check collision with pipe
│  └─ check collision with floor/ceiling
│
└─ WHEN SPACE PRESSED
   └─ set [velocity] to [8]             ← jump! positive = up

PIPE SPRITE:
├─ WHEN FLAG CLICKED
│  └─ FOREVER
│     ├─ wait 2 seconds
│     └─ create clone of [pipe v]
│
└─ WHEN I START AS A CLONE
   ├─ set x to [240]
   ├─ set y to (random -80 to 80)
   └─ REPEAT until (x < -50)
      ├─ change x by [-3]
      └─ wait 0.05 seconds
      
SCORING ZONE:
└─ WHEN [bird] crosses x=0
   ├─ change [score] by [1]
   └─ play sound [ding]
```
Physics Trace Example:
```
Frame 1:
  velocity = 0
  y = 100 (no change)

Frame 2:
  velocity = 0 + (-0.5) = -0.5
  y = 100 + (-0.5) = 99.5 (turun 0.5px)

Frame 3:
  velocity = -0.5 + (-0.5) = -1.0
  y = 99.5 + (-1.0) = 98.5 (turun 1.0px, lebih cepat!)

User SPACE di Frame 3:
  velocity = 8 (reset to jump)
  
Frame 4:
  velocity = 8 + (-0.5) = 7.5
  y = 98.5 + (7.5) = 106 (naik 7.5px!)

Frame 5:
  velocity = 7.5 + (-0.5) = 7.0
  y = 106 + (7.0) = 113 (naik 7px, slowing down)
  
(gravity terus kurangin velocity sampai negative lagi)
```
---
📊 Assessment Rubric
Criteria	Excellent (4)	Good (3)	Fair (2)	Poor (1)
Gravity	Smooth realistic physics	Natural tapi sedikit jaky	Ada tapi aneh	Tidak terasa natural
Pipes	Random gap, spawn perfect timing	Mostly good, minor timing issue	Gap tidak random/timing off	Tidak ada pipes
Collision	Accurate & reliable	Works mostly	Sometimes miss/false positive	Tidak akurat
Scoring	Accurate, visual feedback	Mostly works	Count wrong sometimes	Tidak ada score
Code Quality	Clean, well-organized, efficient	Organized, some redundancy	Messy tapi berfungsi	Spaghetti code
Difficulty Curve	Progressive, fun throughout	Good pacing	Terlalu mudah/sulit	Tidak ada curve
---
⭐ Extensions
EASY:
Add highscore tracker (list)
Change bird sprite/sounds
MEDIUM:
Different pipe gap sizes per level
Power-ups (shield, slow-mo)
Multiple birds (lives system)
HARD:
Leaderboard (save top 5 scores)
Custom difficulty settings
Physics tweaking (air resistance)
---
---
PROJECT 3: KELAS 5 SD - "MINI RPG ADVENTURE" (Scratch)
📋 Project Overview
Tujuan: Complex game with dialogue, inventory, NPC interaction, simple AI, multi-screen
Durasi: 5-6 jam (split 6 pertemuan)
Level: Advanced
Prerequisite: Variables, lists, cloning, procedures, broadcasts
---
🎯 Learning Objectives
[ ] Implement NPC dialogue system (strings & arrays)
[ ] Inventory management (list-based)
[ ] Map/room system dengan transitions
[ ] Simple enemy AI (patrol, chase)
[ ] HP/health system
[ ] Quest tracking
---
🎨 Visual Design
```
FOREST RPG WORLD:

[ROOM 1: FOREST CLEARING]
┌──────────────────────────────────┐
│ ♣ TREE        ♣ TREE     ♣ TREE │ Sky Background
│                                  │
│            🧙 NPC              │
│         (Quest Giver)           │
│                                  │
│                 👤 PLAYER        │
│                                  │
│  ♦ Sword on ground (item)       │
│                                  │
│ > NORTH    [E] EXIT to House   │
└──────────────────────────────────┘

[ROOM 2: HOUSE]
┌──────────────────────────────────┐
│ │││ WALL       |||               │
│ │              │ TREASURE CHEST  │
│ │ 🛏️ BED       │                 │
│ │              │                 │
│ │ 👤 PLAYER    │                 │
│ │              │                 │
│ > BACK to Forest                 │
└──────────────────────────────────┘

UI:
┌─────────────────────────────────┐
│ HP: ♥♥♥◇◇  Inv: Sword, Potion   │
│ Quest: Find Golden Key in Cave   │
└─────────────────────────────────┘
```
---
🔧 Mechanics & Features
CORE MECHANICS:
Room/Map System
```
   [Global Variable: current_room]
   
   Rooms: {0: Forest, 1: House, 2: Cave}
   
   WHEN FLAG CLICKED
   broadcast [LOAD ROOM 0]
   
   WHEN I RECEIVE [LOAD ROOM n]
   Hide all sprites EXCEPT those in room n
   Set background
   Reset spawn points
   ```
NPC Dialogue
```
   [NPC List Variable: dialogue_lines]
   dialogue_lines = {
     0: "Halo traveler!",
     1: "Aku cari Golden Key",
     2: "Temukan di Cave sebelah"
   }
   
   WHEN THIS SPRITE CLICKED
   broadcast [SHOW DIALOGUE] (with NPC_ID)
   
   WHEN I RECEIVE [SHOW DIALOGUE]
   set [current_dialogue_index] to 0
   show dialogue_box sprite
   repeat (3) times
     say (item [current_dialogue_index] of [dialogue_lines])
     wait 3 seconds
     change [current_dialogue_index] by 1
   ```
Inventory System
```
   [List: inventory]
   
   WHEN player touches [item sprite]
   add [item_name] to [inventory]
   delete item clone
   broadcast [UPDATE UI]
   
   WHEN key pressed [I]  // show inventory
   show inventory menu
   allow selection/use
   ```
Combat/Enemy AI
```
   [Enemy Variable: hp, patrol_range, alert_distance]
   
   PATROL MODE:
   FOREVER
     if (distance to player > alert_distance)
       move left-right in range
   
   ALERT MODE:
   IF (distance to player < alert_distance)
     chase player
     WHEN touching player
       change [player_hp] by [-10]
       say [OUCH!]
   
   DEFEAT:
   IF [hp] < 1
     broadcast [ENEMY DEFEATED]
     drop loot (clone random item)
     delete self
   ```
Quest System
```
   [List: quests = {quest_id, status, reward}]
   
   Quest status: {0: "Not Started", 1: "Active", 2: "Complete"}
   
   WHEN NPC talks
   activate quest
   
   WHEN objective completed
   set quest status to 2
   add reward to inventory
   ```
---
📝 Step-by-Step Teaching Plan
PERTEMUAN 1 (75 min): Room System & Navigation
Goal: Player move between rooms
Brainstorm Game World (10 min)
Discuss: "Apa yang mau ada di game?"
Create story outline
Sketch map (3 rooms minimum)
Create Room Backgrounds (15 min)
Paint/import 3 backgrounds
Label: forest, house, cave
Add visual cues (doors, NPCs)
Implement Room Switching (30 min)
```
   [Create Variables: current_room, spawn_x, spawn_y]
   
   WHEN FLAG CLICKED
   set [current_room] to [0]  // forest
   broadcast [LOAD ROOM 0]
   
   WHEN I RECEIVE [LOAD ROOM 0]
   switch backdrop to [forest]
   set [spawn_x] to [-50]
   set [spawn_y] to [50]
   set player position
   
   // Other rooms...
   WHEN I RECEIVE [LOAD ROOM 1]
   switch backdrop to [house]
   // etc
   ```
Player Navigation (20 min)
```
   WHEN [UP] PRESSED
   IF (y < 120) AND (current_room = 0)
     broadcast [LOAD ROOM 2]  // go to cave
   
   WHEN [LEFT] PRESSED
   IF (x < -100)
     broadcast [LOAD ROOM 1]  // go to house
   ```
Testing (5 min)
Move between rooms
Check spawn points
---
PERTEMUAN 2 (75 min): NPC & Dialogue
Goal: Talk to NPC, see dialogue
Create NPC Sprite (10 min)
Draw/import NPC character
Add emotional expression costumes
Design Dialogue System (15 min)
```
   [NPC Block:
     name: "Elder"
     dialogue: [
       "Welcome, hero!",
       "Dark forces lurk...",
       "Can you help me?"
     ]
     quest_reward: "Map"
   ]
   ```
Implement Dialogue (35 min)
```
   [Variable: dialogue_index, show_dialogue_box]
   
   WHEN THIS SPRITE CLICKED
   set [dialogue_index] to [0]
   set [show_dialogue_box] to [true]
   broadcast [NPC TALK]
   
   WHEN I RECEIVE [NPC TALK]
   REPEAT (length of [this NPC dialogue])
     say (item [dialogue_index] of [dialogue_list])
     wait 3 seconds
     change [dialogue_index] by [1]
   ```
Add Dialogue Box UI (15 min)
Create text box sprite
Show/hide with say() blocks
Add name label
---
PERTEMUAN 3 (75 min): Inventory System
Goal: Collect items, manage inventory
Design Inventory (10 min)
```
   Inventory display:
   [Item slots]
   Sword x1
   Potion x2
   Key x0
   ```
Implement Item Collection (30 min)
```
   [List: inventory]
   
   WHEN [item sprite] TOUCHED [player]
   add [item_name] to [inventory]
   say [Got Sword!] for (1) seconds
   delete this clone
   broadcast [UPDATE INVENTORY]
   ```
Display Inventory UI (25 min)
```
   WHEN [I] PRESSED  // show inventory key
   show [inventory_ui]
   
   [inventory_ui] sprite shows:
   - All items in list
   - Quantities
   - Can select/use item
   ```
Item Effects (10 min)
```
   WHEN [player] uses [potion]
   change [player_hp] by [20]
   remove [potion] from [inventory]
   say [Restored!]
   ```
---
PERTEMUAN 4 (75 min): Enemy AI
Goal: Basic enemy with patrol & chase
Design Enemy (10 min)
```
   Enemy attributes:
   - HP: 30
   - Speed: 2
   - Alert range: 100 pixels
   - Damage: 10
   - Patrol area: x (-100 to 100)
   ```
Patrol Behavior (25 min)
```
   [Variables: enemy_hp, direction, alert]
   
   WHEN FLAG CLICKED
   set [enemy_hp] to [30]
   set [direction] to [1]  // 1=right, -1=left
   
   FOREVER
     move (direction * 2) steps
     if (x > 100) OR (x < -100)
       set [direction] to (-(direction))
       turn 180 degrees
   ```
Chase & Combat (30 min)
```
   FOREVER
     if (distance to [player] < 100)
       point towards [player]
       move 3 steps
       
       if (touching [player])
         change [player_hp] by [-10]
         say [Hit!]
   
   // Defeat condition
   if [enemy_hp] < 1
     say [Defeated!]
     broadcast [ENEMY DIED]
     delete clone
   ```
Player Defense (10 min)
Implement player attack
When equipped with sword + click enemy → damage enemy
Sound effects
---
PERTEMUAN 5 (75 min): Quest System
Goal: Multi-step quests with tracking
Design Quest Structure (15 min)
```
   Quest: "Find the Golden Key"
   - Start: Talk to Elder (NPC 1)
   - Objective: Go to cave, defeat monster, take key
   - End: Return to Elder for reward
   - Reward: "Ancient Map"
   ```
Quest Tracking Variables (20 min)
```
   [List: active_quests]
   [List: quest_progress]  // 0=inactive, 1=active, 2=complete
   [List: completed_quests]
   
   Quest metadata:
   - quest_id
   - description
   - objective_text
   - reward_item
   - quest_giver
   ```
Quest Flow (35 min)
```
   STEP 1: NPC GIVES QUEST
   WHEN NPC CLICKED
   add [quest_001] to [active_quests]
   say [I need you to find key!]
   
   STEP 2: PLAYER COLLECTS ITEM
   WHEN player touches [Golden Key]
   change [quest_001_progress] by [1]
   
   STEP 3: RETURN TO NPC
   WHEN player touches [NPC] AND [quest_progress] = 1
   set [quest_001_progress] to [2]
   broadcast [QUEST COMPLETE]
   add [Ancient Map] to [inventory]
   change [gold] by [50]
   ```
Display Quest Log (5 min)
Show active quests on screen
Update progress
---
PERTEMUAN 6 (75 min): Polish & Playtesting
Goal: Complete, playable game
Visual Polish (20 min)
Smooth animations
Sound design (music + SFX)
Particle effects (defeat, collect)
Screen transitions
Balancing (20 min)
Enemy difficulty
Item availability
Quest progression pacing
Health/damage values
Playtesting (25 min)
Internal testing: Does it work?
Peer testing: Is it fun?
Bug fix
Difficulty adjustment
Presentation (10 min)
Clean up code
Record playthrough
Write brief game description
---
💻 Block Structure (Hierarchical)
```
GAME CONTROLLER:
├─ START GAME
│  ├─ Load Room 0
│  ├─ Set score to 0
│  └─ Initialize quests
│
├─ ROOM MANAGEMENT
│  ├─ Load Room (broadcast)
│  │  └─ Sprites show/hide per room
│  └─ Transition animation
│
├─ UI UPDATES
│  ├─ Update inventory display
│  ├─ Update HP bar
│  └─ Update quest log
│
└─ GAME STATE
   ├─ Check game over (HP < 0)
   └─ Check win condition (all quests done)

PLAYER SPRITE:
├─ Movement (arrow keys)
├─ Collision with NPC/items
├─ HP management
├─ Inventory use
└─ Attack (if equipped weapon)

NPC SPRITE:
├─ When clicked → dialogue
├─ Quest trigger
└─ Reaction to player state

ENEMY SPRITE:
├─ Patrol behavior
├─ Alert/chase
├─ Combat mechanics
└─ Death handling
```
---
📊 Assessment Rubric
Criteria	Excellent (4)	Good (3)	Fair (2)	Poor (1)
Room System	Multi-room, smooth transitions	Works, minor issues	2 rooms or clunky	Tidak berfungsi
NPC Dialogue	Natural flow, proper sequencing	Works mostly	Text shows wrong order	Tidak ada dialogue
Inventory	Smooth UI, item use works	Basic collection works	Collection works, UI messy	No inventory
Enemy AI	Smart behavior, responsive	Patrols & chases ok	Basic patrol	No enemy
Quest System	Multi-step, tracked accurately	Simple quest works	Tracks poorly	No quests
Code Organization	Logical structure, reusable procedures	Organized mostly	Messy but works	Spaghetti code
Creativity	Engaging story, unique mechanics	Good story + mechanics	Generic but complete	Minimal effort
Polish	Smooth, sound, visual effects	Mostly polished	Working but rough	Very rough
---
⭐ Extensions
EASY:
Add more NPCs/rooms
Change sprite/colors
More inventory items
MEDIUM:
Shop system (buy/sell items)
Health potion effect
Multiple enemy types
Sound background music
HARD:
Boss enemy with complex AI
Leaderboard (completion time)
Save/load game state
Dialogue choices (if/else branches)
Dynamic quest generation
---
---
PROJECT 4: KELAS 6 - "SPACE SHOOTER GAME" (Pygame)
📋 Project Overview
Tujuan: Understand game loop, sprite management, event handling, collision detection in Python/Pygame
Durasi: 6-8 jam (split 6-8 session)
Level: Intermediate Python
Prerequisite: Python basics (variables, loops, if/else), OOP concepts
---
🎯 Learning Objectives
[ ] Understand game loop architecture
[ ] Implement sprite-based collision detection
[ ] Handle keyboard/mouse events in Pygame
[ ] Manage multiple game objects (sprites group)
[ ] Implement scoring & game states
[ ] Create particle effects
---
🎨 Visual Design
```
SPACE SHOOTER GAME:

┌─────────────────────────────────┐
│ Score: 1250    Level: 2         │ Space Background
│                                  │ (stars)
│             ★ ★                 │
│            ★   ★                │
│                                  │
│                                  │
│              ⚡ ENEMY            │
│          ⚡       ⚡             │
│                                  │
│                                  │
│                 │ PLAYER SHIP   │
│                 ▼ (bullet up)   │
│                                  │
│    ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁   │
└─────────────────────────────────┘

SPRITES:
- Player (triangle/ship shape)
- Enemies (square/different shapes)
- Bullets (small rect/circle)
- Explosions (particle system)
- Stars (background parallax)
```
---
🔧 Mechanics & Features
CORE MECHANICS:
Game Loop
```python
   while running:
       clock.tick(60)  # 60 FPS
       
       # Handle events
       for event in pygame.event.get():
           if event.type == pygame.QUIT:
               running = False
           if event.type == pygame.KEYDOWN:
               handle_input(event.key)
       
       # Update
       player.update()
       enemies.update()
       bullets.update()
       check_collisions()
       
       # Draw
       screen.fill(BLACK)
       draw_background()
       player.draw(screen)
       enemies.draw(screen)
       bullets.draw(screen)
       
       pygame.display.flip()
   ```
Player Ship
```python
   class Player(pygame.sprite.Sprite):
       def __init__(self, x, y):
           self.x = x
           self.y = y
           self.speed = 5
           self.hp = 100
       
       def update(self):
           keys = pygame.key.get_pressed()
           if keys[K_LEFT]:
               self.x -= self.speed
           if keys[K_RIGHT]:
               self.x += self.speed
           
           self.rect.x = self.x
           self.rect.y = self.y
       
       def shoot(self):
           bullet = Bullet(self.x, self.y)
           bullets.add(bullet)
   ```
Enemy Spawning
```python
   class EnemySpawner:
       def __init__(self, spawn_rate=2):
           self.spawn_rate = spawn_rate  # per second
           self.spawn_timer = 0
       
       def update(self, dt):
           self.spawn_timer += dt
           if self.spawn_timer >= 1.0 / self.spawn_rate:
               x = random.randint(50, 750)
               enemy = Enemy(x, -30)
               enemies.add(enemy)
               self.spawn_timer = 0
   ```
Collision Detection
```python
   def check_collisions():
       # Enemy-Bullet collisions
       for enemy in enemies:
           hits = pygame.sprite.spritecollide(enemy, bullets, True)
           if hits:
               enemy.hp -= 10 * len(hits)
               if enemy.hp <= 0:
                   enemy.die()
                   score += 50
       
       # Player-Enemy collisions
       if pygame.sprite.spritecollide(player, enemies, True):
           player.hp -= 20
       
       # Enemy-Bottom screen collision
       for enemy in enemies:
           if enemy.y > HEIGHT:
               enemy.kill()
   ```
Scoring & Difficulty
```python
   score = 0
   level = 1
   
   def update_difficulty():
       global level
       if score % 500 == 0:
           level += 1
           spawner.spawn_rate += 0.5  # spawn faster
           Enemy.speed += 0.5  # move faster
   ```
---
📝 Step-by-Step Teaching Plan
SESSION 1 (90 min): Pygame Setup & Window
Goal: Create window, understand game loop
Intro to Pygame (10 min)
What is Pygame?
Show example game
Architecture overview
Installation & Setup (15 min)
```bash
   pip install pygame
   ```
Verify installation
Create project folder
Create Basic Game Window (40 min)
```python
   import pygame
   pygame.init()
   
   WIDTH, HEIGHT = 800, 600
   screen = pygame.display.set_mode((WIDTH, HEIGHT))
   pygame.display.set_caption("Space Shooter")
   
   clock = pygame.time.Clock()
   running = True
   
   while running:
       clock.tick(60)  # 60 FPS
       
       for event in pygame.event.get():
           if event.type == pygame.QUIT:
               running = False
       
       screen.fill((0, 0, 0))  # Black background
       pygame.display.flip()
   
   pygame.quit()
   ```
Explain event loop
Explain clock/FPS
Draw on screen
Add Simple Rectangle (25 min)
```python
   player_x, player_y = 400, 550
   player_speed = 5
   
   while running:
       # ... event handling ...
       
       keys = pygame.key.get_pressed()
       if keys[pygame.K_LEFT]:
           player_x -= player_speed
       if keys[pygame.K_RIGHT]:
           player_x += player_speed
       
       screen.fill((0, 0, 0))
       pygame.draw.rect(screen, (0, 255, 0), 
                       (player_x, player_y, 30, 40))
       pygame.display.flip()
   ```
---
SESSION 2 (90 min): Sprite Classes & OOP
Goal: Create Player and Enemy sprite classes
Review OOP Concepts (10 min)
Classes, init, methods
Inheritance
Quick review for those rusty
Create Player Sprite Class (40 min)
```python
   class Player(pygame.sprite.Sprite):
       def __init__(self, x, y):
           super().__init__()
           self.image = pygame.Surface((30, 40))
           self.image.fill((0, 255, 0))
           self.rect = self.image.get_rect()
           self.rect.x = x
           self.rect.y = y
           self.speed = 5
           self.hp = 100
       
       def update(self):
           keys = pygame.key.get_pressed()
           if keys[pygame.K_LEFT] and self.rect.x > 0:
               self.rect.x -= self.speed
           if keys[pygame.K_RIGHT] and self.rect.x < 770:
               self.rect.x += self.speed
       
       def shoot(self):
           return Bullet(self.rect.centerx, self.rect.top)
       
       def draw(self, screen):
           screen.blit(self.image, self.rect)
   ```
Create Enemy Sprite Class (25 min)
```python
   class Enemy(pygame.sprite.Sprite):
       def __init__(self, x, y):
           super().__init__()
           self.image = pygame.Surface((30, 30))
           self.image.fill((255, 0, 0))
           self.rect = self.image.get_rect()
           self.rect.x = x
           self.rect.y = y
           self.speed = 3
           self.hp = 10
       
       def update(self):
           self.rect.y += self.speed
           if self.rect.y > HEIGHT:
               self.kill()
       
       def take_damage(self, amount):
           self.hp -= amount
           if self.hp <= 0:
               self.kill()
   ```
Integrate into Main Loop (15 min)
```python
   player = Player(400, 550)
   enemies = pygame.sprite.Group()
   
   while running:
       player.update()
       
       for enemy in enemies:
           enemy.update()
       
       screen.fill((0, 0, 0))
       player.draw(screen)
       for enemy in enemies:
           enemy.draw(screen)
       pygame.display.flip()
   ```
---
SESSION 3 (90 min): Bullets & Shooting
Goal: Implement bullet system with collision
Create Bullet Class (25 min)
```python
   class Bullet(pygame.sprite.Sprite):
       def __init__(self, x, y):
           super().__init__()
           self.image = pygame.Surface((5, 10))
           self.image.fill((255, 255, 0))
           self.rect = self.image.get_rect()
           self.rect.centerx = x
           self.rect.y = y
           self.speed = 7
       
       def update(self):
           self.rect.y -= self.speed
           if self.rect.y < 0:
               self.kill()
   ```
Implement Shooting Mechanic (30 min)
```python
   bullets = pygame.sprite.Group()
   shoot_cooldown = 0
   
   while running:
       shoot_cooldown -= 1
       
       for event in pygame.event.get():
           if event.type == pygame.KEYDOWN:
               if event.key == pygame.K_SPACE and shoot_cooldown < 0:
                   bullet = player.shoot()
                   bullets.add(bullet)
                   shoot_cooldown = 10  # 10 frame cooldown
       
       player.update()
       bullets.update()
       
       # Draw
       for bullet in bullets:
           bullet.draw(screen)
   ```
Collision Detection: Bullet-Enemy (25 min)
```python
   def check_collisions():
       for bullet in bullets:
           hits = pygame.sprite.spritecollide(bullet, enemies, False)
           for enemy in hits:
               enemy.take_damage(10)
               bullet.kill()
   ```
Test Shooting (10 min)
Shoot bullets
Verify they disappear at top
Verify enemies take damage
---
SESSION 4 (90 min): Enemy Spawning & Waves
Goal: Spawn enemies, increase difficulty, wave system
Create Enemy Spawner Class (30 min)
```python
   class EnemySpawner:
       def __init__(self, spawn_rate=1):
           self.spawn_rate = spawn_rate  # enemies per second
           self.spawn_timer = 0
       
       def update(self, dt):
           self.spawn_timer += dt
           if self.spawn_timer >= 1.0 / self.spawn_rate:
               x = random.randint(30, WIDTH - 30)
               enemy = Enemy(x, -30)
               self.spawn_timer = 0
               return enemy
           return None
   ```
Integrate Spawner (20 min)
```python
   spawner = EnemySpawner(spawn_rate=2)
   
   while running:
       dt = clock.tick(60) / 1000.0  # delta time in seconds
       
       new_enemy = spawner.update(dt)
       if new_enemy:
           enemies.add(new_enemy)
       
       # ... rest of loop
   ```
Increase Difficulty Over Time (25 min)
```python
   score = 0
   level = 1
   
   def update_difficulty(spawn_rate):
       if score % 500 == 0 and score != 0:
           level += 1
           spawn_rate += 0.3
           Enemy.base_speed += 0.5
       return spawn_rate
   
   # In main loop:
   spawner.spawn_rate = update_difficulty(spawner.spawn_rate)
   ```
Test Spawning (15 min)
Enemies spawn smoothly
Difficulty increases
No lag
---
SESSION 5 (90 min): Scoring, UI, Game States
Goal: Score tracking, UI display, game over
Implement Scoring (20 min)
```python
   score = 0
   level = 1
   
   def check_collisions():
       for bullet in bullets:
           hits = pygame.sprite.spritecollide(bullet, enemies, False)
           for enemy in hits:
               enemy.take_damage(10)
               if enemy.hp <= 0:
                   score += 100  # Points per enemy
   
   def check_player_collision():
       hits = pygame.sprite.spritecollide(player, enemies, False)
       for enemy in hits:
           player.hp -= 10
           enemy.kill()
   ```
Create UI System (30 min)
```python
   def draw_ui(screen, score, level, player_hp):
       font = pygame.font.Font(None, 36)
       
       score_text = font.render(f"Score: {score}", True, (255, 255, 255))
       level_text = font.render(f"Level: {level}", True, (255, 255, 255))
       hp_text = font.render(f"HP: {player_hp}", True, (255, 0, 0))
       
       screen.blit(score_text, (10, 10))
       screen.blit(level_text, (WIDTH - 200, 10))
       screen.blit(hp_text, (10, 50))
   ```
Game States (25 min)
```python
   GAME_STATE = "PLAYING"  # PLAYING, GAME_OVER, PAUSED
   
   while running:
       if GAME_STATE == "PLAYING":
           # update game
           player.update()
           enemies.update()
           bullets.update()
           
           if player.hp <= 0:
               GAME_STATE = "GAME_OVER"
       
       elif GAME_STATE == "GAME_OVER":
           # show game over screen
           draw_game_over_screen(screen, score)
       
       # Draw
       draw_game(screen)
       pygame.display.flip()
   ```
Game Over Screen (15 min)
```python
   def draw_game_over_screen(screen, final_score):
       font_large = pygame.font.Font(None, 72)
       font_small = pygame.font.Font(None, 36)
       
       game_over_text = font_large.render("GAME OVER", True, (255, 0, 0))
       score_text = font_small.render(f"Final Score: {final_score}", True, (255, 255, 255))
       restart_text = font_small.render("Press SPACE to restart", True, (255, 255, 255))
       
       screen.blit(game_over_text, (200, 200))
       screen.blit(score_text, (250, 300))
       screen.blit(restart_text, (150, 400))
   ```
---
SESSION 6 (90 min): Polish & Effects
Goal: Add sound, particles, visual effects
Add Sound Effects (25 min)
```python
   pygame.mixer.init()
   
   shoot_sound = pygame.mixer.Sound('shoot.wav')
   explosion_sound = pygame.mixer.Sound('explosion.wav')
   bgm = pygame.mixer.Sound('music.wav')
   
   # In shooting:
   shoot_sound.play()
   
   # When enemy dies:
   explosion_sound.play()
   
   # Background:
   bgm.play(-1)  # loop
   ```
Particle System (30 min)
```python
   class Particle(pygame.sprite.Sprite):
       def __init__(self, x, y, vx, vy):
           super().__init__()
           self.rect = pygame.Rect(x, y, 3, 3)
           self.vx, self.vy = vx, vy
           self.lifetime = 30
       
       def update(self):
           self.rect.x += self.vx
           self.rect.y += self.vy
           self.lifetime -= 1
           if self.lifetime <= 0:
               self.kill()
       
       def draw(self, screen):
           pygame.draw.circle(screen, (255, 255, 0), 
                            self.rect.center, 2)
   
   # When enemy dies:
   for _ in range(10):
       angle = random.uniform(0, 2*math.pi)
       vx = 3 * math.cos(angle)
       vy = 3 * math.sin(angle)
       particles.add(Particle(enemy.rect.centerx, 
                              enemy.rect.centery, vx, vy))
   ```
Visual Enhancements (20 min)
Animated sprites (sprite sheet)
Screen shake on collision
Color gradients
Trail effects for bullets
Performance Optimization (15 min)
```python
   # Remove off-screen bullets/enemies proactively
   for bullet in bullets:
       if bullet.rect.y < -10:
           bullet.kill()
   
   for enemy in enemies:
       if enemy.rect.y > HEIGHT + 10:
           enemy.kill()
   
   # Limit max objects
   if len(enemies) > 50:
       oldest_enemy = min(enemies, key=lambda e: e.spawn_time)
       oldest_enemy.kill()
   ```
---
SESSION 7-8 (180 min): Testing, Balancing, Refactoring
Goal: Complete, polished game
Code Review & Refactoring (60 min)
Extract magic numbers to constants
Add comments
Remove dead code
Organize into separate files (player.py, enemy.py, etc)
Balancing & Tweaking (60 min)
```python
   # Adjust these values:
   PLAYER_SPEED = 5
   PLAYER_HP = 100
   BULLET_SPEED = 7
   ENEMY_SPAWN_RATE = 2
   ENEMY_SPEED = 3
   ENEMY_DAMAGE = 10
   ```
Play test multiple times
Get feedback: too hard? too easy?
Adjust spawning, damage, health
Testing Checklist (30 min)
[ ] Game starts properly
[ ] Player movement works
[ ] Shooting works
[ ] Enemies spawn smoothly
[ ] Collision detection accurate
[ ] Scoring works
[ ] Game over triggers correctly
[ ] Sound plays (if added)
[ ] No crashes after 5 minutes play
[ ] Difficulty increases smoothly
Final Polish (30 min)
Record gameplay video
Write README
Add high score tracking (optional)
Package/submit
---
💻 Code Structure (Architecture)
```
space_shooter/
├── main.py
├── player.py
├── enemy.py
├── bullet.py
├── particle.py
├── spawner.py
├── constants.py
└── assets/
    ├── sounds/
    └── images/

main.py structure:
├─ Import modules
├─ Initialize Pygame
├─ Create game objects
├─ Main game loop:
│  ├─ Handle events
│  ├─ Update game state
│  ├─ Check collisions
│  ├─ Render
│  └─ Control FPS
└─ Cleanup
```
---
📊 Assessment Rubric
Criteria	Excellent (4)	Good (3)	Fair (2)	Poor (1)
Player Movement	Smooth, responsive, bounded	Works well	Slightly laggy	Broken
Shooting	Smooth, rate-limited, particles	Works well	Cooldown issues	Broken
Enemy Spawning	Smooth waves, difficulty curve	Mostly smooth	Spawning issues	No enemies
Collision Detection	Accurate, no false positives	Mostly accurate	Some issues	Broken
Scoring & UI	Clear, accurate, well-positioned	Works correctly	Minor issues	Broken
Game States	Smooth transitions, proper handling	Works ok	Some edge cases	Broken
Code Quality	Clean, organized, well-commented	Organized mostly	Messy	Spaghetti
Polish	Sound, effects, smooth 60 FPS	Good performance	Minor lag	Very laggy
Gameplay	Fun, balanced, engaging	Good fun	Playable	Boring
---
⭐ Extensions
EASY:
Change colors/sprites
Add high score file saving
More enemy types
MEDIUM:
Power-ups (rapid fire, shield)
Boss enemy with patterns
Multiple levels/stages
Sound volume control
HARD:
Screen shake effects
Leaderboard system
Enemy AI patterns (sine wave movement)
Procedural level generation
Multiplayer mode
---
---
📚 SUMMARY TABLE
Project	Level	Jenjang	Duration	Key Concepts
Kucing Penari	Beginner	1-2 SD	2-3 jam	Events, sprites, animation
Flappy Bird	Intermediate	3-4 SD	3-4 jam	Physics, collision, random
Mini RPG	Advanced	5 SD	5-6 jam	Lists, clones, procedures
Space Shooter	Intermediate	6 SD	6-8 jam	OOP, pygame loop, game states
---
🎯 PROGRESSION ALIGNMENT
Grade 1-2 → 3-4 → 5 → 6
Complexity: Simple interaction → Mechanics → Complex systems → Professional code
Concepts: Events → Logic → Data structures → OOP + Architecture
Assessment: Observation → Rubrics → Code review → Complete evaluation