# Game Development in AeThex

This guide covers the core game development concepts and systems in AeThex Engine.

> [!TIP]
> New to game development? Start with the Scene System and Node Hierarchy sections. These are the foundation of everything in AeThex.

## Scene System

### What is a Scene?

A **scene** is a collection of nodes organized in a tree structure. Scenes are the building blocks of your game - they can represent:
- Game levels
- UI screens
- Characters
- Items
- Prefabs/templates

```mermaid
graph TD
    Scene[🎬 Scene File<br/>.tscn] --> Root[Root Node]
    Root --> Child1[Child Node 1]
    Root --> Child2[Child Node 2]
    Root --> Child3[Child Node 3]
    Child2 --> GrandChild1[Grandchild 1]
    Child2 --> GrandChild2[Grandchild 2]
    
    style Scene fill:#00ffff22,stroke:#00ffff
    style Root fill:#ff00ff22,stroke:#ff00ff
```

> [!NOTE]
> Scenes can be nested inside other scenes. This allows you to create reusable components and maintain a clean project structure.

### Working with Scenes

**Creating Scenes:**
```gdscript
# Load a scene
var scene = load("res://levels/main_level.tscn")

# Instance a scene
var instance = scene.instantiate()

# Add to scene tree
add_child(instance)
```

**Switching Scenes:**
```gdscript
# Change to a new scene
get_tree().change_scene_to_file("res://levels/next_level.tscn")

# Or using a packed scene
var packed_scene = load("res://levels/next_level.tscn")
get_tree().change_scene_to_packed(packed_scene)
```

> [!WARNING]
> Always use `change_scene_to_file()` or `change_scene_to_packed()` to switch scenes. Manually removing and adding root nodes can cause issues with signal connections and autoloads.

**Scene Lifecycle:**
- `_enter_tree()` - Called when node enters the scene tree
- `_ready()` - Called when node and children are ready
- `_exit_tree()` - Called when node exits the scene tree

---

## Node Hierarchy

### Understanding Nodes

**Nodes** are the fundamental building blocks in AeThex. Everything in your game is a node or inherits from the Node class.

### Node Types

**Common Node Classes:**
- `Node` - Base class for all scene objects
- `Node2D` - Base for all 2D game objects (has position, rotation, scale)
- `Node3D` - Base for all 3D game objects
- `Control` - Base for all UI elements
- `CanvasItem` - Base for anything that can be drawn

### Working with Node Hierarchy

**Adding/Removing Nodes:**
```gdscript
# Add a child node
var sprite = Sprite2D.new()
add_child(sprite)

# Remove a child
sprite.queue_free()  # Deferred removal (safe)
sprite.free()        # Immediate removal (use carefully)

# Get parent
var parent = get_parent()

# Reparent a node
sprite.reparent(new_parent)
```

**Finding Nodes:**
```gdscript
# Get a child by name
var player = get_node("Player")
# Or using shorthand
var player = $Player

# Get a node by path
var weapon = $Player/Weapon
var health = get_node("Player/Health")

# Find nodes by group
var enemies = get_tree().get_nodes_in_group("enemies")

# Find parent by type
var level = find_parent("Level")
```

**Node Groups:**
```gdscript
# Add to a group
add_to_group("enemies")
add_to_group("damageable")

# Check if in group
if is_in_group("enemies"):
    print("This is an enemy!")

# Remove from group
remove_from_group("enemies")

# Call function on all nodes in group
get_tree().call_group("enemies", "take_damage", 10)
```

---

## Signals and Callbacks

### What are Signals?

**Signals** are AeThex's implementation of the observer pattern. They allow nodes to communicate without tight coupling.

```mermaid
sequenceDiagram
    participant Player
    participant Enemy
    participant UI
    
    Player->>Player: take_damage(10)
    Player->>Player: emit_signal("health_changed", 90)
    Player->>UI: health_changed(90)
    UI->>UI: update_health_bar(90)
    
    Note over Player,UI: Signals enable loose coupling
    
    Player->>Player: health reaches 0
    Player->>Player: emit_signal("player_died")
    Player->>UI: player_died
    Player->>Enemy: player_died
    UI->>UI: show_game_over()
    Enemy->>Enemy: celebrate()
    
    style Player fill:#00ffff22,stroke:#00ffff
    style UI fill:#ff00ff22,stroke:#ff00ff
```

> [!TIP]
> Signals are perfect for situations where you want multiple systems to react to an event without creating dependencies between them.

### Built-in Signals

**Common Node Signals:**
- `ready` - Emitted when node is ready
- `tree_entered` - Node entered the scene tree
- `tree_exited` - Node left the scene tree

**Input Signals:**
- `Area2D.body_entered(body)` - Another body entered the area
- `Area2D.body_exited(body)` - Another body left the area
- `Button.pressed()` - Button was clicked

> [!NOTE]
> Most built-in nodes come with useful signals. Check the documentation for each node type to see what signals are available.

### Creating Custom Signals

```gdscript
extends Node

# Declare signals
signal health_changed(new_health)
signal player_died
signal item_collected(item_name, quantity)

var health = 100

func take_damage(amount):
    health -= amount
    emit_signal("health_changed", health)
    
    if health <= 0:
        emit_signal("player_died")

func collect_item(item, qty):
    emit_signal("item_collected", item, qty)
```

### Connecting to Signals

**Code-based Connections:**
```gdscript
# Connect to a signal
player.health_changed.connect(_on_health_changed)

# With custom parameters
player.health_changed.connect(_on_health_changed.bind("extra_param"))

# One-shot connection (auto-disconnects after first emit)
player.health_changed.connect(_on_health_changed, CONNECT_ONE_SHOT)

# Disconnect from signal
player.health_changed.disconnect(_on_health_changed)

func _on_health_changed(new_health):
    print("Health is now: ", new_health)
```

**Lambda Connections:**
```gdscript
button.pressed.connect(func(): print("Button clicked!"))
```

---

## Physics

### 2D Physics

**RigidBody2D** - Dynamic physics body affected by forces:
```gdscript
extends RigidBody2D

func _ready():
    # Set physics properties
    mass = 10.0
    gravity_scale = 1.0
    linear_damp = 0.1
    angular_damp = 0.1

func _physics_process(delta):
    # Apply force
    apply_force(Vector2(100, 0))
    
    # Apply impulse (instant)
    apply_impulse(Vector2(0, -500))
    
    # Apply torque (rotation)
    apply_torque(100)
```

**StaticBody2D** - Immovable physics body (walls, floors):
```gdscript
extends StaticBody2D

func _ready():
    # Static bodies don't move
    # Used for terrain, walls, platforms
    pass
```

**CharacterBody2D** - For player-controlled movement:
```gdscript
extends CharacterBody2D

var speed = 300.0
var jump_velocity = -400.0
var gravity = 980.0

func _physics_process(delta):
    # Apply gravity
    if not is_on_floor():
        velocity.y += gravity * delta
    
    # Handle jump
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = jump_velocity
    
    # Get input direction
    var direction = Input.get_axis("move_left", "move_right")
    velocity.x = direction * speed
    
    # Move with collision detection
    move_and_slide()
```

### 3D Physics

**RigidBody3D:**
```gdscript
extends RigidBody3D

func _ready():
    mass = 10.0
    gravity_scale = 1.0

func apply_jump():
    apply_central_impulse(Vector3.UP * 500)
```

**CharacterBody3D:**
```gdscript
extends CharacterBody3D

var speed = 5.0
var jump_strength = 10.0
var gravity = 20.0

func _physics_process(delta):
    if not is_on_floor():
        velocity.y -= gravity * delta
    
    if Input.is_action_just_pressed("jump") and is_on_floor():
        velocity.y = jump_strength
    
    var input_dir = Input.get_vector("left", "right", "forward", "back")
    var direction = (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
    
    velocity.x = direction.x * speed
    velocity.z = direction.z * speed
    
    move_and_slide()
```

### Collision Shapes

**Adding Collision Shapes:**
```gdscript
# Collision shapes must be children of physics bodies
# Common shapes:
# - CollisionShape2D / CollisionShape3D
# - RectangleShape2D, CircleShape2D, CapsuleShape2D
# - BoxShape3D, SphereShape3D, CapsuleShape3D

# In code:
var collision = CollisionShape2D.new()
var shape = CircleShape2D.new()
shape.radius = 32
collision.shape = shape
add_child(collision)
```

### Physics Layers

**Collision Layers & Masks:**
```gdscript
# Layer: What layers this body is on (up to 32)
collision_layer = 0b0001  # Layer 1

# Mask: What layers this body can collide with
collision_mask = 0b0010   # Can collide with layer 2

# Common setup:
# Layer 1: Player
# Layer 2: Enemies  
# Layer 3: Environment
# Layer 4: Collectibles

# Player collides with enemies and environment:
collision_layer = 1      # Binary: 0001
collision_mask = 6       # Binary: 0110 (layers 2 and 3)
```

**Checking Collisions:**
```gdscript
# CharacterBody2D/3D
func _physics_process(delta):
    move_and_slide()
    
    for i in get_slide_collision_count():
        var collision = get_slide_collision(i)
        print("Collided with: ", collision.get_collider().name)

# Area2D/3D signals
func _ready():
    body_entered.connect(_on_body_entered)

func _on_body_entered(body):
    if body.is_in_group("player"):
        print("Player entered area!")
```

---

## UI System

### Control Nodes

**Control** is the base class for all UI elements. Common UI nodes:

**Buttons:**
- `Button` - Standard push button
- `CheckButton` - Toggle button
- `OptionButton` - Dropdown menu

**Text:**
- `Label` - Display text
- `RichTextLabel` - Text with formatting (BBCode)
- `LineEdit` - Single-line text input
- `TextEdit` - Multi-line text input

**Containers:**
- `VBoxContainer` - Vertical layout
- `HBoxContainer` - Horizontal layout
- `GridContainer` - Grid layout
- `MarginContainer` - Adds margins
- `PanelContainer` - Background panel

### Basic UI Example

```gdscript
extends Control

func _ready():
    # Create a button
    var button = Button.new()
    button.text = "Click Me"
    button.pressed.connect(_on_button_pressed)
    add_child(button)
    
    # Create a label
    var label = Label.new()
    label.text = "Score: 0"
    add_child(label)

func _on_button_pressed():
    print("Button clicked!")
```

### Layouts and Containers

**Automatic Layouts:**
```gdscript
# VBoxContainer - stacks children vertically
var vbox = VBoxContainer.new()
vbox.add_child(Button.new())
vbox.add_child(Button.new())
vbox.add_child(Button.new())

# HBoxContainer - arranges children horizontally
var hbox = HBoxContainer.new()
hbox.add_theme_constant_override("separation", 10)  # 10px spacing

# GridContainer - grid layout
var grid = GridContainer.new()
grid.columns = 3
for i in 9:
    grid.add_child(Button.new())
```

**Anchors and Margins:**
```gdscript
# Anchors determine where control is positioned (0.0 to 1.0)
var panel = Panel.new()

# Center the panel
panel.anchor_left = 0.5
panel.anchor_top = 0.5
panel.anchor_right = 0.5
panel.anchor_bottom = 0.5

# Offset from anchor point
panel.offset_left = -100
panel.offset_top = -50
panel.offset_right = 100
panel.offset_bottom = 50
```

### Themes

**Applying Themes:**
```gdscript
# Load a theme
var theme = load("res://themes/main_theme.tres")
theme = theme  # Apply to root Control

# Or set individual theme overrides
var button = Button.new()
button.add_theme_color_override("font_color", Color.CYAN)
button.add_theme_font_size_override("font_size", 24)
```

### Responsive Design

**Size Flags:**
```gdscript
var label = Label.new()

# Expand horizontally
label.size_flags_horizontal = Control.SIZE_EXPAND_FILL

# Shrink to content
label.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
```

**Handling Resize:**
```gdscript
extends Control

func _ready():
    get_viewport().size_changed.connect(_on_viewport_resized)

func _on_viewport_resized():
    var viewport_size = get_viewport_rect().size
    print("New size: ", viewport_size)
    # Adjust UI layout
```

---

## Audio System

### AudioStreamPlayer

Three types of audio players:
- `AudioStreamPlayer` - 2D positional audio
- `AudioStreamPlayer2D` - 2D positional audio
- `AudioStreamPlayer3D` - 3D spatial audio

### Playing Sounds

**Basic Audio:**
```gdscript
extends Node

@onready var sfx_player = $AudioStreamPlayer
@onready var music_player = $MusicPlayer

func _ready():
    # Load and play sound
    var sound = load("res://sounds/jump.ogg")
    sfx_player.stream = sound
    sfx_player.play()

func play_sound(sound_path: String):
    sfx_player.stream = load(sound_path)
    sfx_player.play()
```

### Music Management

**Background Music:**
```gdscript
extends Node

var current_music = null
var music_player = AudioStreamPlayer.new()

func _ready():
    add_child(music_player)
    music_player.finished.connect(_on_music_finished)

func play_music(music_path: String, loop: bool = true):
    var music = load(music_path)
    music_player.stream = music
    music_player.play()
    
    if loop:
        music_player.finished.connect(func(): music_player.play())
    
    current_music = music_path

func stop_music():
    music_player.stop()

func fade_out_music(duration: float = 1.0):
    var tween = create_tween()
    tween.tween_property(music_player, "volume_db", -80, duration)
    tween.tween_callback(stop_music)

func fade_in_music(duration: float = 1.0):
    music_player.volume_db = -80
    music_player.play()
    var tween = create_tween()
    tween.tween_property(music_player, "volume_db", 0, duration)
```

### Sound Effects

**Sound Effect Pool:**
```gdscript
extends Node

var sfx_players = []
var pool_size = 8

func _ready():
    # Create a pool of audio players
    for i in pool_size:
        var player = AudioStreamPlayer.new()
        add_child(player)
        sfx_players.append(player)

func play_sfx(sound_path: String, volume_db: float = 0.0):
    # Find available player
    for player in sfx_players:
        if not player.playing:
            player.stream = load(sound_path)
            player.volume_db = volume_db
            player.play()
            return
    
    # If all busy, use first one
    sfx_players[0].stream = load(sound_path)
    sfx_players[0].volume_db = volume_db
    sfx_players[0].play()
```

### 3D Audio

**Spatial Audio:**
```gdscript
extends Node3D

@onready var audio_3d = $AudioStreamPlayer3D

func _ready():
    # Configure 3D audio
    audio_3d.max_distance = 50.0      # Max hearing distance
    audio_3d.attenuation_model = AudioStreamPlayer3D.ATTENUATION_INVERSE_DISTANCE
    audio_3d.unit_size = 1.0
    
    # Play sound at this position
    audio_3d.stream = load("res://sounds/explosion.ogg")
    audio_3d.play()

func play_3d_sound_at(sound_path: String, position: Vector3):
    var player = AudioStreamPlayer3D.new()
    add_child(player)
    player.global_position = position
    player.stream = load(sound_path)
    player.play()
    
    # Remove when finished
    await player.finished
    player.queue_free()
```

---

## Workflow & Tools

### Studio IDE Integration

AeThex Studio provides a full IDE experience with:

**Code Editor:**
- GDScript syntax highlighting
- Autocomplete and intellisense
- Inline documentation
- Error checking and linting
- Code folding and navigation

**Scene Tree:**
- Visual node hierarchy
- Drag-and-drop node creation
- Inspector panel for properties
- Live scene editing

**Asset Browser:**
- File system navigation
- Asset preview (images, 3D models)
- Drag-and-drop import
- Asset metadata

**Live Reload:**
```gdscript
# Changes are hot-reloaded automatically
# No need to restart the game
# Scripts reload on save
```

**Studio Bridge:**
```gdscript
# Check if running in Studio
if AeThexStudio.is_available():
    print("Running in AeThex Studio")
    
    # Send messages to Studio
    AeThexStudio.log_message("Custom debug info")
    
    # Open file in Studio
    AeThexStudio.open_file("res://scripts/player.gd")
```

### Version Control

**Git Integration:**
```bash
# Initialize repository
cd your_project
git init

# AeThex-specific .gitignore
echo ".import/" >> .gitignore
echo "*.import" >> .gitignore
echo ".godot/" >> .gitignore
echo "export_presets.cfg" >> .gitignore

# Commit
git add .
git commit -m "Initial commit"
```

**Collaboration Workflow:**
```bash
# Create feature branch
git checkout -b feature/player-movement

# Make changes and commit
git add scripts/player.gd
git commit -m "Implement player movement"

# Push branch
git push origin feature/player-movement

# Create pull request on GitHub
# Review and merge
```

**Managing Merge Conflicts:**
```bash
# Update from main
git checkout main
git pull

# Merge into feature branch
git checkout feature/player-movement
git merge main

# If conflicts occur, resolve them in editor
# Then:
git add .
git commit -m "Resolve merge conflicts"
```

**Branching Strategy:**
- `main` - Stable, production-ready code
- `develop` - Integration branch for features
- `feature/*` - Individual features
- `hotfix/*` - Emergency fixes
- `release/*` - Release preparation

**Best Practices:**
1. Commit often with clear messages
2. Use branches for new features
3. Keep commits atomic (one logical change)
4. Pull before pushing
5. Review code before merging
6. Use `.gitattributes` for binary files:
```
*.tscn merge=binary
*.tres merge=binary
*.asset merge=binary
```

---

## Next Steps

- **API Reference:** See [API_REFERENCE.md](API_REFERENCE.md) for AeThex cloud services
- **First Game Tutorial:** Build a complete game in [FIRST_GAME_TUTORIAL.md](tutorials/FIRST_GAME_TUTORIAL.md)
- **Studio Integration:** Learn more at [STUDIO_INTEGRATION.md](STUDIO_INTEGRATION.md)
- **Architecture:** Understand the engine at [ARCHITECTURE_OVERVIEW.md](ARCHITECTURE_OVERVIEW.md)
