From c36afc75e5829222a7f5f8d15397477f734bf429 Mon Sep 17 00:00:00 2001 From: Andrew Kettel Date: Fri, 4 Sep 2026 09:24:34 -0700 Subject: [PATCH] Moving documents to their own folder. --- AI_HELP.md => AI Docs/01-AI-GUIDE.md | 0 ARCHITECTURE.md => AI Docs/02-ARCHITECTURE.md | 0 AI Docs/04-TESTING-WORKFLOW.md | 455 +++++ AI Docs/05-SKILLS-REFERENCE.md | 494 ++++++ AI Docs/PLAN.md | 1475 ++++++++++++++++- AI Docs/PLAN_MORE.md | 1445 ---------------- 6 files changed, 2373 insertions(+), 1496 deletions(-) rename AI_HELP.md => AI Docs/01-AI-GUIDE.md (100%) rename ARCHITECTURE.md => AI Docs/02-ARCHITECTURE.md (100%) create mode 100644 AI Docs/04-TESTING-WORKFLOW.md create mode 100644 AI Docs/05-SKILLS-REFERENCE.md delete mode 100644 AI Docs/PLAN_MORE.md diff --git a/AI_HELP.md b/AI Docs/01-AI-GUIDE.md similarity index 100% rename from AI_HELP.md rename to AI Docs/01-AI-GUIDE.md diff --git a/ARCHITECTURE.md b/AI Docs/02-ARCHITECTURE.md similarity index 100% rename from ARCHITECTURE.md rename to AI Docs/02-ARCHITECTURE.md diff --git a/AI Docs/04-TESTING-WORKFLOW.md b/AI Docs/04-TESTING-WORKFLOW.md new file mode 100644 index 0000000..645c44c --- /dev/null +++ b/AI Docs/04-TESTING-WORKFLOW.md @@ -0,0 +1,455 @@ +# Testing Workflow Guide for YeetGeese + +This document provides a structured approach to testing Godot 4.x games, with specific focus on the tower defense mechanics of YeetGeese. It covers what to test, how to structure tests, and debugging failed tests. + +--- + +## Table of Contents + +1. [Testing Philosophy](#testing-philosophy) +2. [Test Organization](#test-organization) +3. [Test Categories](#test-categories) +4. [Writing Tests](#writing-tests) +5. [Debugging Failed Tests](#debugging-failed-tests) +6. [CI Integration](#ci-integration) + +--- + +## Testing Philosophy + +### Why Test? + +- **Regression prevention:** Catch unintended side effects from changes +- **Documentation by example:** Tests serve as usage examples +- **Design validation:** Ensure architecture matches intent +- **Confidence for refactoring:** Safe to reorganize code when tested + +### What AI Can Help With + +AI can: +- Generate boilerplate test scaffolding +- Suggest edge cases and boundary conditions +- Write mock implementations for complex systems +- Explain Godot testing framework capabilities + +### What AI Cannot Handle + +AI should NOT: +- Design game mechanics or balance (human domain) +- Make subjective quality-of-life judgments +- Replace manual playtesting of actual gameplay feel +- Generate test data for art assets (no AI-generated art rule applies) + +--- + +## Test Organization + +### Directory Structure + +``` +tests/ +├── core/ # Autoloads and global state tests +│ ├── wave_progression_test.gd +│ └── currency_manager_test.gd +├── towers/ # Tower behavior tests +│ ├── tower_base_test.gd +│ ├── projectile_spawner_test.gd +│ └── target_finder_test.gd +├── enemies/ # Enemy system tests +│ ├── enemy_mob_test.gd +│ ├── navigation_system_test.gd +│ └── spawner_test.gd +├── projectiles/ # Projectile handling tests +│ ├── goose_projectile_test.gd +│ └── impact_handler_test.gd +├── ui/ # HUD and menu tests +│ ├── health_bar_test.gd +│ └── currency_display_test.gd +├── utils/ # Utility functions +│ └── math_utils_test.gd +└── integration/ # Cross-system tests + ├── wave_complete_sequence_test.gd + └── tower_placement_integration_test.gd +``` + +### Naming Conventions + +- Files: `_test.gd` (e.g., `tower_base_test.gd`) +- Functions: `func test_()` (e.g., `func test_fire_rate_scales_with_level()`) +- Assertions: Use descriptive names like `assert_equal`, `assert_signal_emitted`, `assert_no_error` + +--- + +## Test Categories + +### Unit Tests + +Test individual functions or methods in isolation. + +**Example:** Testing a tower's fire rate calculation + +```gdscript +@tool +extends Node + +func test_fire_rate_calculation(tower: Node) -> void: + assert_equal(tower.fire_rate, 1.0) + + # Modify tower level + tower.tower_level = 2 + + # Verify fire rate changed appropriately + assert_greater(tower.fire_rate, 1.0) + assert_less(tower.fire_rate, 2.0) + +func test_damage_scaling_by_tower_level(tower: Node) -> void: + tower.tower_level = 3 + + var initial_damage = tower.get_damage_at_current_level() + tower.tower_level = 5 + + # Verify damage increased with level + assert_greater(tower.get_damage_at_current_level(), initial_damage) +``` + +**When to use:** +- Testing pure logic (math, state transitions) +- Testing Resource loading and property access +- Testing signal emission patterns + +--- + +### Integration Tests + +Test interactions between multiple systems. + +**Example:** Testing the full projectile launch sequence + +```gdscript +@tool +extends Node + +func test_projectile_launch_sequence() -> void: + # Arrange: Create mock tower and target + var tower := _create_mock_tower() + var target := _create_mock_target() + + # Act: Fire at target + tower.fire_at(target) + + # Assert: Verify projectile spawned in correct state + assert_true(tower.projectile_count == 1) + assert_equal(tower.projectiles[0].source_node, tower.$ProjectileSpawner) +``` + +**When to use:** +- Testing scene hierarchies with multiple nodes +- Verifying signal connections between systems +- Validating Godot's built-in component behavior (e.g., RigidBody2D movement) + +--- + +### Regression Tests + +Tests added when a bug is fixed to ensure it doesn't return. + +**Example:** Preventing physics tunneling after a collision fix + +```gdscript +@tool +extends Node + +func test_projectile_collision_prevents_tunneling() -> void: + # Scenario: Goose projectile moving at high speed + var projectile := _create_goose_with_velocity(100.0) + var enemy := _create_enemy_with_small_hitbox() + + # Act: Move projectile toward enemy's hitbox + projectile.yeet_from(projectile.position, enemy.position) + + # Assert: Projectile detected collision on this frame + assert_signal_emitted(projectile, 'collision_detected') +``` + +**When to use:** +- After fixing a critical bug +- When performance regression occurs +- To validate edge case handling + +--- + +## Writing Tests + +### Test Function Template + +```gdscript +@tool +extends Node + +func test_() -> void: + # Arrange: Setup the scenario + var := _create_mock_() + + # Act: Execute the action being tested + .() + + # Assert: Verify expected behavior + assert_true() + assert_false() + assert_signal_emitted(, '') +``` + +### Available Assertions + +| Assertion | Purpose | Example | +|-----------|---------|---------| +| `assert_equal(a, b)` | Check exact equality | `assert_equal(tower.level, 3)` | +| `assert_not_equal(a, b)` | Check inequality | `assert_not_equal(projectile.speed, 0.0)` | +| `assert_true(condition)` | Verify boolean is true | `assert_true(tower.is_ready())` | +| `assert_false(condition)` | Verify boolean is false | `assert_false(projectile.is_removed())` | +| `assert_greater(a, b)` | Check a > b | `assert_greater(damage_dealt, 10)` | +| `assert_less(a, b)` | Check a < b | `assert_less(enemy.health, 50.0)` | +| `assert_null(obj)` | Verify object is null | `assert_null(projectile.get_target())` | +| `assert_not_null(obj)` | Verify object exists | `assert_not_null(projectile)` | +| `assert_array_size(arr, size)` | Check array length | `assert_array_size(tower.projectiles, 4)` | + +### Signal Testing Pattern + +```gdscript +var _signal_verified = false + +func test_health_changed_signal_emits_correct_values() -> void: + var enemy := EnemyMob.new() + enemy.health_changed.connect(func(new_health) { + assert_true(_signal_verified == false) # Prevent double-firing + assert_equal(new_health, 75.0) + _signal_verified = true + }) + + enemy.take_damage(25.0) + + assert_true(_signal_verified) +``` + +### Mock Object Helpers + +Use these helper functions to create mock objects for tests: + +```gdscript +# Create a mock tower with minimal setup +func _create_mock_tower() -> Node: + var tower := TowerBase.new() + tower.tower_level = 1 + return tower + +# Create a mock enemy for collision testing +func _create_mock_enemy() -> EnemyMob: + var enemy := EnemyMob.new() + enemy.health = 50.0 + enemy.damage_taken.connect(func() { pass }) # Prevent death on damage + return enemy + +# Verify no error occurred during test +func _assert_no_error(condition: bool) -> void: + assert_true(condition, "Test completed with errors") +``` + +--- + +## Debugging Failed Tests + +### Common Failure Patterns + +#### 1. Test Completes Before Signal Fires + +**Problem:** `signal_emitted` verification fails because the test ends too early. + +**Solution:** Add a yield or use Godot's built-in coroutine system: + +```gdscript +func test_signal_fires_after_delay() -> void: + var subject := _create_subject() + subject.event.triggered.connect(_on_event_triggered) + + subject.do_something() + + # Ensure signal fires before test ends + get_tree().process_frame.connect(_on_frame_processed) + yield(get_tree(), "process_frame") # Wait for signal + + assert_true(_signal_received) + +func _on_frame_processed() -> void: + _on_event_triggered.call_deferred() +``` + +#### 2. Scene Loading in Tests Fails + +**Problem:** Godot scenes loaded via `load("res://...")` may not find their resources. + +**Solution:** Use absolute paths or ensure test assets are in proper location: + +```gdscript +# Bad: Relative path that breaks in tests +var mob_scene := load("enemy_mob.tscn").instantiate() + +# Good: Absolute resource path +var mob_scene := load("res://src/enemies/enemy_mob.tscn").instantiate() +``` + +#### 3. Random Behavior Causes Flaky Tests + +**Problem:** Tests pass sometimes but fail others due to randomness (e.g., particle emission). + +**Solution:** Disable randomness in test environment: + +```gdscript +# At start of test, seed RNG for reproducibility +Rand.randi = func() -> int: return 42 # Fixed value for testing + +# Or disable randomness for specific systems +var projectile := Projectile.new() +projectile.random_variation_enabled = false +``` + +#### 4. Physics Tunneling in Collision Tests + +**Problem:** Fast-moving projectiles miss collisions when tested with static enemies. + +**Solution:** Use multiple physics frames or smaller time steps: + +```gdscript +func test_high_velocity_collision_detection() -> void: + var projectile := _create_goose_with_velocity(200.0) + + # Run multiple physics frames for collision detection + for _ in range(5): + get_tree().physics_ticks_processed = 1 + get_tree().process_frame() + + assert_true(_collision_detected) +``` + +#### 5. Signal Connections Leak Between Tests + +**Problem:** Test A's signal handlers remain active when Test B runs. + +**Solution:** Disconnect signals at test end: + +```gdscript +func cleanup_test(subject: Node, signal_name: String) -> void: + subject.signal_removed.connect(_disconnect_signals) + + # Clear all signals from subject + var signals = subject.get_signal_list() + for s in signals: + if s.is_connected(func): + s.disconnect(func) + +# Call cleanup at end of each test function +``` + +--- + +## CI Integration (Optional for Indie Teams) + +### GitHub Actions / GitLab CI Setup + +If using a continuous integration server, add tests to build pipeline. + +**Example workflow:** + +```yaml +name: YeetGeese Tests + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Install Godot + run: | + # Download and install Godot 4.x stable + + - name: Run Tests + run: | + godot --path . --headless tests/run_all_tests.gd +``` + +### Local Test Runner Script + +Create a script to run all tests from command line: + +```gdscript +# tests/run_all_tests.gd +extends Node + +func _ready(): + var result := 0 + + # Run unit tests + for file in DirAccess.get_directories() if dir_name == "core" or dir_name == "towers": + pass # Implementation depends on test runner framework + + if result == 0: + print("All tests passed!") + else: + error("Some tests failed") + +func _exit_tree(): + quit(0) +``` + +--- + +## Testing Checklist + +### Before Writing Tests for New Feature + +- [ ] Identify the system(s) being tested +- [ ] Determine unit vs. integration testing needs +- [ ] List expected inputs and outputs +- [ ] Identify edge cases (empty arrays, null objects, etc.) + +### Test Coverage Goals + +| System Type | Recommended Test Coverage | +|-------------|---------------------------| +| Core game loop | 100% (critical path) | +| Tower logic | 90%+ | +| Enemy AI states | 85%+ | +| UI displays | 80%+ | +| Utility functions | 95%+ | + +### Review Checklist for AI-Generated Tests + +When asking AI to generate tests, verify: + +- [ ] Uses `@tool` directive for editor-only execution +- [ ] Sets up proper mock objects for isolation +- [ ] Disconnects signals at test end to prevent leaks +- [ ] Uses absolute paths for resource loading +- [ ] Handles expected error conditions gracefully +- [ ] Includes assertions for all critical behaviors + +--- + +## Summary + +**AI can help with:** +- Generating boilerplate test scaffolding +- Suggesting edge cases and boundary conditions +- Writing mock implementations for complex systems +- Explaining Godot testing framework capabilities + +**Remember:** +- Tests should be runnable in editor (`@tool` functions) +- Keep tests focused on one behavior per function +- Disconnect signals to prevent cross-test contamination +- Use absolute paths for resource loading in tests +- Document test intent with clear, descriptive names + +For more details, see `AI_HELP.md` for prompt templates when working with AI assistants on testing tasks. diff --git a/AI Docs/05-SKILLS-REFERENCE.md b/AI Docs/05-SKILLS-REFERENCE.md new file mode 100644 index 0000000..a702a36 --- /dev/null +++ b/AI Docs/05-SKILLS-REFERENCE.md @@ -0,0 +1,494 @@ +# Skills, Agents, and Commands Reference + +This document provides a reference for AI assistants working with YeetGeese. It describes available capabilities, when to use them, and best practices for interaction. + +--- + +## Table of Contents + +1. [Available Skills](#available-skills) +2. [Agent Types & Use Cases](#agent-types--use-cases) +3. [Command Reference](#command-reference) +4. [Prompt Templates](#prompt-templates) +5. [Best Practices](#best-practices) + +--- + +## Available Skills + +### `customize-opencode` + +**Purpose:** Configure and modify the AI assistant's own settings, including: +- `opencode.json`, `opencode.jsonc` files +- `.opencode/` configuration directory +- `~/.config/opencode/` user settings +- Agent definitions (subagents, skills, plugins, MCP servers) +- Permission rules + +**When to use:** When configuring the AI assistant itself, not for project code. + +**Example:** +``` +"Adjust the maximum context window size for this session." +``` + +--- + +## Agent Types & Use Cases + +### `code-gen` — Code Generation + +**Purpose:** Write new code, implement features, create boilerplate. + +**Capabilities:** +- GDScript 4 implementation +- Scene graph construction descriptions +- Resource file (`.tres`) schema design +- Signal declarations and connections +- Method implementations matching project conventions + +**When to use:** +- Implementing a new tower or projectile type +- Adding a feature to existing systems +- Creating boilerplate for common patterns +- Writing unit tests + +**Input required:** +- Target file path or node description +- Desired behavior/goal +- Any constraints (e.g., "must use Resource for stats") + +**Example prompt:** +``` +"Create a GDScript 4 class `ImpactEffect.gd` that extends Area2D. It should: +1. Detect collision with enemies in _body_entered +2. Emit signal 'effect_triggered' with damage and target Node2D +3. Apply random color variation to its texture +4. Set lifespan to 0.8 seconds +5. Include comments explaining each step" +``` + +--- + +### `debug-helper` — Debugging Assistance + +**Purpose:** Analyze errors, suggest debugging strategies, interpret profiler output. + +**Capabilities:** +- Error message interpretation (Godot/IDE/compiler) +- Suggesting debugging tool usage (Scene Debugger, Physics Monitor) +- Profiling tips and bottleneck identification +- Common pitfall recognition (e.g., physics tunneling, navmesh gaps) + +**When to use:** +- When an error occurs during implementation +- When code behaves unexpectedly +- When performance issues appear in profiler + +**Input required:** +- Error message or log output +- Relevant file paths and line numbers if available +- Brief description of expected vs. actual behavior + +**Example prompt:** +``` +"This tower stops firing after 30 seconds even though fire_rate is set to 1.0. +Error: 'get_tree()' returned null at runtime. Debug it." +``` + +--- + +### `refactor-assistant` — Refactoring Support + +**Purpose:** Break up large scripts, improve code organization, add documentation. + +**Capabilities:** +- Splitting monolithic scripts into smaller nodes +- Extracting methods into separate components +- Adding documentation and type hints +- Applying project conventions consistently + +**When to use:** +- Scripts are growing beyond 150 lines +- Multiple unrelated behaviors in one node +- Need to improve readability before review + +**Input required:** +- File path or code snippet +- Refactoring goal (e.g., "split into state machines") +- Target organization style + +**Example prompt:** +``` +"Refactor this 400-line EnemyMob.gd into smaller components: +1. Extract navigation logic to NavigationComponent +2. Extract attack behavior to AttackState +3. Keep health/currency handling in base class +4. Add documentation comments for each section" +``` + +--- + +### `test-generator` — Test Generation + +**Purpose:** Create unit tests for game logic systems. + +**Capabilities:** +- Writing Godot test cases using `@tool` functions +- Setting up mock scenes and signals +- Testing Resource-based stat changes +- Validating collision detection and hit calculations + +**When to use:** +- After implementing core logic that should be validated +- Before refactoring (to preserve behavior) +- When adding critical game mechanics + +**Input required:** +- System or function being tested +- Expected inputs and outputs +- Edge cases to cover + +**Example prompt:** +``` +"Create tests for TowerBase._can_build_at(). Test: +1. Returns true in valid tower placement zones +2. Returns false inside enemy navmesh +3. Returns false when grid coordinate exceeds bounds +4. Returns false if parent node is null" +``` + +--- + +### `design-patterns` — Design Pattern Suggestions + +**Purpose:** Recommend architecture patterns suited to specific problems. + +**Capabilities:** +- Suggesting ECS for complex entity management +- Recommending FSM for enemy AI states +- Proposing event-driven systems for decoupled components +- Advising on data-oriented vs. object-oriented design + +**When to use:** +- Before implementing a new system +- When performance becomes an issue +- When refactoring existing code + +**Input required:** +- Problem description (e.g., "I need many entities with simple movement") +- Performance constraints if any +- Preferred Godot nodes or patterns already in use + +**Example prompt:** +``` +"I'm building a system for 50+ projectiles that need to track targets, apply damage, and handle collision. +Current approach: individual RigidBody2D for each projectile. +What pattern would scale better?" +``` + +--- + +### `balance-helper` — Balance Analysis + +**Purpose:** Analyze math relationships and suggest tuning adjustments. + +**Capabilities:** +- Calculating damage per second (DPS) from fire rate and projectile stats +- Estimating kill time based on enemy HP and total damage sources +- Suggesting resource stat ranges that preserve balance space +- Identifying scaling relationships between tower levels + +**When to use:** +- Before adding new towers/enemies with different power levels +- When gameplay feels too easy or difficult +- During tuning phase of wave progression + +**Input required:** +- Current stats (damage, fire rate, enemy HP) +- Desired behavior description (e.g., "kill time should scale with tier") +- Resource file structure if applicable + +**Example prompt:** +``` +"Current: goose damage=15, fire_rate=1.0/s, chicken HP=80. +Tower Level 2 has 4 geese. Calculate total DPS and suggest enemy HP range +for level-appropriate difficulty (aim for ~30s wave duration)." +``` + +--- + +### `level-design-helper` — Level Design Assistance + +**Purpose:** Plan layout, progression, and pacing for levels or zones. + +**Capabilities:** +- Wave progression suggestions (spawn rates, path complexity) +- Tower placement zone recommendations +- Pacing analysis for difficulty curves +- Zone-based checkpoint design + +**When to use:** +- Before creating a new level or wave sequence +- When gameplay feels too repetitive or frustrating +- During playtesting feedback analysis + +**Input required:** +- Level description (size, available zones) +- Current wave structure if any +- Difficulty curve goals + +**Example prompt:** +``` +"I have 4 tower placement zones along a path with 3 turns. +Current waves: linear difficulty increase. +Suggest a progression that introduces new mechanics at zone boundaries." +``` + +--- + +### `doc-generator` — Documentation Generation + +**Purpose:** Create documentation from existing code or planning data. + +**Capabilities:** +- Generating API docs from GDScript class structures +- Writing changelogs from commit history +- Creating release notes with feature summaries +- Producing onboarding guides from project structure + +**When to use:** +- Before releasing a version +- After implementing a major feature set +- When new team members join the project + +**Input required:** +- Source code or commit messages +- Feature list for changelog entries +- Target audience (developers, players) + +**Example prompt:** +``` +"Generate API documentation for the WaveRunner system: +1. Describe each public method and its parameters +2. List signals emitted with their payloads +3. Document the Resource dependencies +4. Include usage examples" +``` + +--- + +### `onboarding-guide` — Onboarding Documentation + +**Purpose:** Create setup tutorials and getting-started guides for new developers. + +**Capabilities:** +- Environment setup instructions (OS-specific) +- Project structure explanation +- Editor scene loading order +- Common first tasks with examples + +**When to use:** +- Before bringing on new team members +- When updating project structure significantly +- For release candidate documentation + +**Input required:** +- Target OS versions supported +- Required Godot version and plugins +- Team conventions to teach + +**Example prompt:** +``` +"Write an onboarding guide for a new developer joining YeetGeese: +1. Explain folder structure (src/core, src/towers, etc.) +2. Show how to run the game from main.tscn +3. Describe the tower placement workflow +4. List common commands for debugging" +``` + +--- + +### `api-specs` — API Specification + +**Purpose:** Define external interfaces and save/load contracts. + +**Capabilities:** +- Defining save file format schemas +- Documenting modding API endpoints +- Specifying network message protocols +- Creating serialization guides + +**When to use:** +- Before implementing persistent storage +- When enabling mod support +- For multiplayer networking design + +**Input required:** +- Interface type (save format, mod API, network protocol) +- Required functionality list +- Platform constraints + +**Example prompt:** +``` +"Define a save file format for YeetGeese: +1. Must store unlocked towers and their levels +2. Must include currency progress and wave number +3. Use Godot Resource serialization (.tres files) +4. Include version field for backward compatibility" +``` + +--- + +## Command Reference + +### Code Writing Commands + +| Command | When to use | +|---------|-------------| +| `create file ` | For new classes, scenes, or resource files | +| `modify file ` | For adding methods or changing existing code | +| `describe scene ` | To generate scene tree descriptions for AI understanding | + +### Review Commands + +| Command | When to use | +|---------|-------------| +| `review code ` | For checking convention compliance | +| `optimize performance ` | For profiling suggestions in specific areas | +| `debug error ` | For interpreting errors and suggesting fixes | + +### Documentation Commands + +| Command | When to use | +|---------|-------------| +| `generate docs` | For API documentation from code | +| `write changelog` | After implementing features or fixing bugs | +| `create onboarding guide` | For new developer setup instructions | + +--- + +## Prompt Templates + +### Feature Implementation Template + +``` +Context: I'm implementing [feature name] in [system/file]. +Current state: [brief description of existing code/structure] +Goal: [what this feature should do] +Constraints: [any restrictions like "must use Resource" or "no UI changes"] + +Please provide: +1. Complete, runnable GDScript 4 code with comments +2. Scene hierarchy description if new scenes are needed +3. Any new Resources (.tres) and their structure +4. Signal declarations and connection points +``` + +### Debugging Template + +``` +Error context: [where the error occurred] +Error message: [full error output] +Expected behavior: [what should have happened] +Actual behavior: [what actually happened] +Debug steps tried: [what you've already attempted] + +Please provide: +1. Root cause analysis +2. Minimal fix with explanation +3. Prevention strategy for future occurrences +``` + +### Refactoring Template + +``` +Current code: [file path or snippet] +Issues to address: [e.g., "too monolithic", "missing docs"] +Refactoring goals: [what you want to achieve] +Target patterns: [any existing patterns to match] + +Please provide: +1. Proposed refactored structure +2. New files and their responsibilities +3. Migration steps for existing code +``` + +--- + +## Best Practices + +### 1. Always Provide Context First + +Before asking for code, share: +- The relevant file path or node description +- The GDScript version being used (Godot 4.x) +- Key related signals and methods already in place + +**Good:** +``` +"Create an ImpactEffect.gd extending Area2D with these existing methods: +- _body_entered(var area): called on collision +- emit_signal('effect_triggered', damage, target)" +``` + +**Bad:** +``` +"I need a collision effect for projectiles." +``` + +### 2. Specify Godot 4 Conventions + +When requesting code, remind AI of conventions: +- Use typed signals: `signal health_changed(new_health: float)` +- Prefer `@onready` over `$` in scripts +- Type variables and return values consistently +- Keep scenes modular (compose behavior across nodes) + +### 3. Reference Existing Architecture + +When implementing features, reference existing patterns: +``` +"Implement this using the same pattern as TowerBase.fire_at(): +- Use projectile_res.instantiate() for new goose projectiles +- Spawn from $ProjectileSpawner.global_position +- Add to parent tree immediately after instantiation" +``` + +### 4. Specify Resource Dependencies Early + +If your project uses Resources for balance: +``` +"Create a Resource-based stats file for this tower: +- Fields: damage (float), fire_rate (float), cooldown_reduction (float) +- Make it loadable as a Godot Resource (.tres) +- Show how the tower reads its stats on _ready()" +``` + +### 5. Ask for Complete, Runnable Code + +When requesting implementations: +``` +"Return complete, runnable GDScript 4 code with:" +"- Comments explaining each major section" +"- Type annotations for all variables and methods" +"- Signal declarations at top of class" +``` + +--- + +## Summary + +**Use these skills strategically:** +- `code-gen`: For new features and boilerplate +- `debug-helper`: When errors occur or behavior is wrong +- `refactor-assistant`: Before code grows unmanageable +- `test-generator`: After implementing critical logic +- `design-patterns`: When architecture becomes unclear + +**Always provide:** +- File paths, node names, and Godot version context +- Desired behavior in terms of existing patterns +- Constraints (Resource usage, signal conventions) + +**When in doubt:** Reference `AI_HELP.md` for project-specific conventions before asking questions. diff --git a/AI Docs/PLAN.md b/AI Docs/PLAN.md index 6438720..53ede15 100644 --- a/AI Docs/PLAN.md +++ b/AI Docs/PLAN.md @@ -1,72 +1,1445 @@ -Here’s a phased development roadmap for **YeetGeese**, structured around indie pacing and optimized for Godot 4.x workflows. Each phase includes core deliverables, Godot-specific implementation notes, and how the first-person TD + goose-throwing twist is handled. +Here is a practical phase plan for **YeetGeese**, a first-person tower defense game where the main weapon is thrown geese, built in **Godot 4**. I’m assuming the core fantasy is: the player is in a 3D arena, enemies approach, and the player throws geese either as projectiles, temporary turrets, or both. The plan below is structured so you can build a small playable prototype first, then expand into a full indie game. --- -### Phase 1: Pre-Production & Design (Weeks 1–3) -**Goal:** Lock scope, define the loop, set up the project structure. -- **Core Loop Doc:** Spawn wave → position/aim → throw geese → defend choke point/base → upgrade/reward → next wave. -- **Art/Tone Direction:** Stylized low-poly or cartoonish (eases iteration). Geese should read clearly in motion. -- **Technical Spec:** Node hierarchy, scene boundaries, data flow (Resource-driven balance tables recommended). -- **Godot Setup:** - - Project structure: `res://src/`, `res://art/`, `res://audio/`, `res://scenes/` with clear naming (`goose.tscn`, `enemy_spawner.gd`). - - Use Godot’s built-in version control integration or Git + `.gdignore`. - - Set up export templates early (itch.io web build for playtests, Windows/Linux for QA). +# YeetGeese Phase Plan + +## Phase 0: Game Definition & Setup +**Goal:** Define the core game, set up the Godot project, and create a clear development scope. + +### Main Tasks +1. **Write a short design document** + - One page is enough. + - Core fantasy: “Yeet geese at enemies and defend a base.” + - Core loop: + - Enemies spawn. + - Player throws geese. + - Geese damage, distract, or tower-ize enemies. + - Player earns currency. + - Player buys/upgrades geese or defenses. + - Wave ends. + - Next wave becomes harder. + +2. **Define the MVP** + A small but complete version of the game should include: + - One arena. + - One player controller. + - One goose type. + - Two enemy types. + - Five waves. + - Basic economy. + - Basic UI: + - Health. + - Currency. + - Wave number. + - Pause menu. + - Win/lose state. + +3. **Set up the Godot project** + - Godot version: Godot 4.x. + - Project type: 3D. + - Renderer: Forward+ for better visuals, Mobile/Compatibility if targeting low-end devices. + - Create folders: + ```text + res:// + scripts/ + scenes/ + assets/ + audio/ + meshes/ + textures/ + materials/ + animations/ + ui/ + data/ + autoload/ + tests/ + ``` + - Set up Git. + - Add `.gitignore` for Godot artifacts. + - Add a simple README. + +4. **Set up basic project architecture** + Create autoloads such as: + - `GameState.gd` + - Handles wave state, score, currency, lives, pause. + - `EventBus.gd` + - Central signals for gameplay events. + - `AudioManager.gd` + - Plays sfx and music. + - `SettingsManager.gd` + - Saves settings and unlockables. + +5. **Define collision layers** + Suggested collision setup: + - `1`: Environment / terrain. + - `2`: Player. + - `3`: Enemy. + - `4`: Goose projectile. + - `5`: Goose turret. + - `6`: Pickups / currency. + - `7`: UI / trigger zones. + +6. **Set up input map** + Suggested inputs: + - `Move_Forward`: W + - `Move_Backward`: S + - `Move_Left`: A + - `Move_Right`: D + - `Aim`: Mouse look. + - `Throw_Goose`: Left mouse button. + - `Switch_Goose`: 1 / 2 / 3 or Q. + - `Reload_Or_Refill`: R. + - `Pause`: Escape. + - `Sprint`: Shift, if used. + - `Crouch`: C, if used. + +### Exit Criteria +- You have a clear MVP scope. +- Godot project opens cleanly. +- Basic folders, autoloads, input map, and collision setup exist. +- The team knows what the first playable prototype must contain. --- -### Phase 2: Core Prototype (Weeks 4–6) -**Goal:** Playable loop with no art polish. Prove the throw mechanic & TD flow work in first-person. -- **FPS Controller:** `CharacterBody3D` + mouse look (`Input.mouse_mode = Input.MOUSE_MODE_CAPTURED`). Add walk/run, crouch if needed for aiming stability. -- **Goose Throw System:** - - Instantiation: `var g = preload("res://scenes/goose.tscn").instantiate()` → add to a dedicated `ProjectileLayer` node so geese don’t collide with each other or the player. - - Physics/projectile logic: Apply initial velocity + gravity via `_physics_process()`, or use `RigidBody3D` for bouncy, chaotic honking (lean into it). - - Aim assist/crosshair via a fixed `Sprite3D` in front of the camera. -- **Enemy Pathing:** `NavigationRegion3D` on level geometry → enemies inherit `NavigationAgent3D` to route toward your base/heart node. -- **Wave Manager:** Autoload or scene-local manager that tracks spawn timers, enemy count, and triggers UI/audio events via signals. -- **Godot Tip:** Use **Signals** everywhere (`goose_impact`, `wave_cleared`) to keep systems decoupled. Balance numbers live in a `.tres` Resource file so you can tweak mid-playtest without touching code. +# Phase 1: Core Playable Prototype +**Goal:** Prove that throwing geese at enemies in a first-person tower defense arena is fun. + +This is the most important phase. Do not focus on art yet. Use greybox shapes and placeholder audio. + +## Core Systems to Build + +### 1. First-Person Player Controller +Create a first-person controller using Godot’s `CharacterBody3D`. + +Basic structure: +```text +Player + - Camera3D + - ThrowOrigin (Marker3D at hand/gun position) +``` + +Player behavior: +- Mouse look. +- WASD movement. +- Ground snapping or simple gravity. +- Optional head bob. +- Optional sprint. +- Throw input triggers projectile creation. + +### 2. Goose Projectile +The goose can be a simple `Area3D` or `RigidBody3D`. + +For a first prototype, I recommend: +```text +GooseProjectile + - Area3D + - MeshInstance3D + - CollisionShape3D + - AnimationPlayer +``` + +Behavior: +- Spawn from `ThrowOrigin`. +- Apply velocity based on camera direction. +- Apply spin. +- Apply gravity or custom flight curve. +- Detect collision with enemies. +- On hit: + - Damage enemy. + - Play honk. + - Spawn hit effect. + - Queue free after lifetime or impact. + +Simplified throw logic: +```gdscript +var throw_dir := -camera.global_transform.basis.z +projectile.linear_velocity = throw_dir * throw_speed +projectile.angular_velocity = Vector3(0, 12, 0) +``` + +### 3. Enemy +Start with one enemy type. + +Enemy structure: +```text +Enemy + - Area3D or CharacterBody3D + - MeshInstance3D + - CollisionShape3D + - Health component +``` + +Enemy behavior: +- Spawn at a point. +- Move toward base or player. +- Attack player or base when close. +- Take damage. +- Die and drop currency. + +For the first prototype, simple movement is enough: +```gdscript +var direction := (target.global_position - global_position).normalized() +velocity = direction * speed +move_and_slide() +``` + +If using a base to defend: +- Target the base. +- If base is destroyed, player loses. + +If the player is the base: +- Target the player. +- If player dies, lose. + +### 4. Basic Wave Spawner +Create a simple wave manager. + +Wave manager behavior: +- Start wave. +- Spawn enemies over time. +- Track remaining enemies. +- When all enemies are dead, start next wave. +- After final wave, player wins. + +Data structure example: +```gdscript +class_name WaveDef +extends Resource + +@export var enemies: Array[EnemyDef] = [] +@export var spawn_interval: float = 1.0 +@export var reward: int = 10 +``` + +### 5. Basic Economy +- Enemy dies. +- Player gains goose coins or feathers. +- Player can buy additional goose throws or a better goose. + +For the first prototype: +- 100 starting feathers. +- Goose throw costs 0. +- Enemy drops 5 feathers. +- Every 10 enemies, unlock one extra goose in reserve. +- Or buy a “Strong Goose” that does more damage. + +### 6. Minimal UI +Use Godot’s Control nodes. + +Required UI: +- Top-left: + - Player health. + - Feathers/currency. +- Top-right: + - Wave number. + - Enemies remaining. +- Center: + - Crosshair. +- Menu: + - Resume. + - Restart. + - Quit. + +### 7. Win/Lose State +- Win: survive all prototype waves. +- Lose: player health reaches 0 or base health reaches 0. + +Show simple message: +- “Victory!” +- “Defeated…” + +## Prototype Deliverables +A single playable scene where the player can: +- Move in first person. +- Look with the mouse. +- Throw geese. +- Geese hit enemies. +- Enemies move, take damage, and die. +- Currency increases. +- Waves progress. +- Player can win or lose. + +## Exit Criteria +- The core loop is playable. +- Throwing geese feels responsive. +- Enemies can be killed. +- Waves work. +- Economy works minimally. +- The game has a clear win/lose state. --- -### Phase 3: Vertical Slice & Systems (Weeks 7–10) -**Goal:** One polished, complete level with full UI/audio/save functionality. -- **HUD/UI:** `CanvasLayer` for health bar, score, throw cooldown/charge meter. Use Godot’s control nodes + anchors; test on multiple resolutions early. -- **Progression/Upsell:** Goose powerups (bigger honk radius, sticky geese, flock shot) stored in a player stat Resource. -- **Audio Pipeline:** `AudioStreamPlayer3D` for spatialized throws/honks, `AudioBus` layout for SFX/music/Master so you can mix per platform. -- **Save System:** Serialize wave progress/unlocks to JSON or a Godot `ResourceSaver` file in `user://`. Load on startup via an autoload `GameManager`. -- **Playtesting Loop:** Build → share itch web build → iterate cooldowns/damage/spawn curves using your balance Resource. -- **Godot Tip:** Use the **Debugger > Profiler** to watch FPS/memory while waves scale up. Enable `Rendering > Quality > VoxelGI` or baked lighting if you go 3D art-heavy, but keep it lightweight for indie budgets. +# Phase 2: Tower Defense Core Systems +**Goal:** Turn the prototype into a real tower defense game by adding towers, upgrades, enemy variety, and a more complete loop. + +This phase is where YeetGeese becomes its own genre hybrid: first-person action + tower defense strategy. + +## Design Decision: How Do Geese Function as Towers? + +You need to choose one or more goose roles. + +### Option A: Thrown Goose as Projectile +The goose is a flying attack. + +Examples: +- Standard Goose: medium damage. +- Heavy Goose: slow, high damage. +- Fast Goose: fast, low damage, piercing. +- Exploding Goose: AoE damage. +- Homing Goose: slight curve toward nearest enemy. + +### Option B: Goose Becomes a Turret +When thrown, the goose lands and stays for a short time. + +Examples: +- The goose pecks nearby enemies. +- The goose honks to stun enemies. +- The goose guards a path. +- The goose dies after 10 seconds. + +### Option C: Goose as Companion +The goose follows the player and occasionally attacks. + +Examples: +- Player throws goose. +- Goose attaches to player for a time. +- It pecks the nearest enemy. +- It dies after taking too much damage. + +I recommend starting with **Option A + Option B** as the core fantasy: +- Some geese are projectile weapons. +- Some geese land and become temporary turrets. +- This gives both action and tower defense. --- -### Phase 4: Content Production & Levels (Weeks 11–16) -**Goal:** Ship the full game scope. Multiple arenas, enemy variety, upgrade tree. -- **Level Design:** Build 5–8 distinct arenas using modular `GridMap` or instanced scene pieces. Vary choke points to force different throw angles/strategies. -- **Enemy Types:** Rushers, tanks that absorb hits before routing, splitters, maybe a "farmer" enemy that drops currency you can grab between waves. -- **Goose Synergy:** Add placement-style mechanics if desired (e.g., drop a `GooseNest.tscn` that auto-throws weak geese while you aim heavy throws). Keep the first-person perspective central to aiming. -- **Polish Systems:** Screen shake on big hits, hit markers, dynamic music intensity tied to wave danger level. -- **Godot Tip:** Preload heavy scenes with `ResourceLoader.load_threaded_request()` if levels are large. Use `Object.set_physics_process_group()` for systems that need to run independently of the main loop (rare but useful for spawners). +## Phase 2 Systems + +### 1. Goose Definitions +Make geese data-driven using Godot Resources. + +Example: +```gdscript +class_name GooseDef +extends Resource + +@export var id: String +@export var display_name: String +@export var cost: int +@export var damage: float +@export var throw_speed: float +@export var spin_speed: float +@export var lifetime: float +@export var knockback: float +@export var stun_duration: float +@export var can_become_turret: bool +@export var turret_duration: float +@export var turret_damage: float +@export var turret_attack_interval: float +@export var icon: Texture2D +``` + +Initial goose types: +1. **Basic Goose** + - Cheap. + - Medium damage. + - Standard speed. + +2. **Angry Goose** + - Higher damage. + - Knockback. + - Slightly slower. + +3. **Honk Goose** + - Low damage. + - Stuns enemies briefly. + - Useful for crowd control. + +4. **Turret Goose** + - Lands and pecks nearby enemies for 6 seconds. + - Creates a mini tower. + +5. **Bomb Goose** + - Explodes on impact. + - Area damage. + +### 2. Enemy Definitions +Create data-driven enemy resources. + +Example: +```gdscript +class_name EnemyDef +extends Resource + +@export var id: String +@export var display_name: String +@export var health: float +@export var speed: float +@export var damage: float +@export var attack_range: float +@export var attack_cooldown: float +@export var reward: int +@export var scale: float +@export var color: Color +@export var mesh: PackedScene +``` + +Initial enemy types: +1. **Slow Grunt** + - Low health. + - Low speed. + - Low damage. + +2. **Runner** + - Fast. + - Low health. + - Reaches base/player quickly. + +3. **Tank** + - Slow. + - High health. + - High damage. + +4. **Spitter** + - Keeps distance. + - Ranged attack. + +5. **Boss** + - Appears at wave 5 or 10. + - High health. + - Special attack. + +### 3. Wave Manager Expansion +Add: +- Enemy groups. +- Spawn intervals. +- Enemy paths. +- Wave scaling. +- Boss waves. +- Wave rewards. + +Example: +```gdscript +class_name WaveDef +extends Resource + +@export var wave_number: int +@export var enemies: Array[EnemyGroup] +@export var reward: int +``` + +```gdscript +class_name EnemyGroup +extends Resource + +@export var enemy_def: EnemyDef +@export var count: int +@export var spawn_interval: float +@export var spawn_delay: float +``` + +### 4. Tower Placement System +If geese become turrets, create a tower placement system. + +Possible approach: +- Player throws a Turret Goose at the ground. +- Goose lands. +- After a short delay, it becomes a turret. +- Turret has: + - Health. + - Duration. + - Range. + - Damage. + - Attack cooldown. + - Target priority. + +Turret target priority: +1. Closest enemy. +2. Weakest enemy. +3. Enemy closest to base/player. + +### 5. Upgrade System +Start simple. + +Upgrade paths: +- Goose damage. +- Goose speed. +- Goose knockback. +- Turret duration. +- Turret range. +- Starting feathers. +- Enemy slow effect. +- Player movement speed. + +Example upgrade structure: +```gdscript +class_name UpgradeDef +extends Resource + +@export var id: String +@export var display_name: String +@export var description: String +@export var cost: int +@export var max_level: int +@export var effects: Dictionary +``` + +### 6. Player Inventory / Goose Selection +Add a simple selection system. + +Player can have: +- Currently selected goose. +- Multiple goose slots. +- Limited reserve count. +- Refill timer or cost to refill. + +UI: +- Bottom center shows selected goose. +- Number keys switch goose. +- Mouse wheel could switch goose. + +### 7. Enemy AI Improvements +Add: +- Pathfinding or waypoint movement. +- Avoidance. +- Attack behavior. +- Stun behavior. +- Fear of honking. +- Aggro changes. + +For early development, simple movement is fine: +- Move toward target. +- If blocked, slide or rotate. +- If in attack range, stop and attack. + +Later, consider: +- NavigationRegion3D. +- NavMesh. +- Waypoints. +- Behavior tree or simple state machine. + +### 8. Base / Objective System +Choose one of these: + +#### Player as Objective +Enemies attack the player directly. + +Pros: +- Simple. +- Feels first-person. + +Cons: +- Less tower defense feel. + +#### Base as Objective +Enemies attack a base, shrine, goose farm, or cheese stockpile. + +Pros: +- More tower defense. +- Player can move freely. + +Cons: +- Need base defense logic. + +Recommended hybrid: +- There is a base to defend. +- Player can also be damaged by enemies. +- Losing happens if base health reaches 0 or player dies. + +### 9. Audio +Add placeholder audio first, then replace later. + +Required sounds: +- Goose honk. +- Throw whoosh. +- Impact. +- Enemy death. +- Enemy attack. +- Wave start. +- Wave complete. +- UI click. +- Coin pickup. +- Boss warning. + +Use: +```text +AudioStreamPlayer +AudioStreamPlayer3D +``` + +For geese and nearby enemies, use 3D audio. + +### 10. Particles & Juice +Add small visual/audio feedback: +- Goose trail. +- Hit particles. +- Enemy death burst. +- Feather explosion. +- Screen shake on heavy hits. +- Slow motion on boss kill, if desired. + +This phase is where the game starts feeling like a game rather than a tech demo. + +## Exit Criteria +- Multiple goose types exist. +- Multiple enemy types exist. +- Waves are data-driven. +- Turret geese can be placed. +- Upgrades exist. +- Player can select geese. +- Economy loop is complete. +- One full level is playable from start to finish. +- The game has a basic sense of progression. --- -### Phase 5: Polish, QA & Launch Prep (Weeks 17–20) -**Goal:** Stable, performant, release-ready build. -- **QA & Optimization:** Fix collision layer conflicts, clamp delta time drift, profile with Godot’s built-in profiler. Enable `Editor > Project Settings > Rendering > Quality` scaling for low-end PCs. -- **Input/Accessibility:** Remappable controls via `ProjectSettings.input_map`, colorblind-safe UI, volume sliders tied to your AudioBus layout. -- **Export & Distribution:** Test each export template on target OS. Set up itch.io page + demo build (Godot’s one-click web export is perfect here). -- **Launch Assets:** Record gameplay in Godot with `Movie Maker` mode or external software, cut a trailer, write store description focusing on the "first-person TD + thrown geese" hook. +# Phase 3: Vertical Slice +**Goal:** Create one polished, complete level that represents the final game quality. + +This is the phase used for feedback, publisher meetings, demo day, or Steam Next Fest. + +## Scope +One full level with: +- 10 waves. +- 3–5 goose types. +- 4–6 enemy types. +- 1 boss. +- 1 upgrade shop. +- 1 themed arena. +- Final art placeholders or low-poly stylized art. +- Final UI. +- Final audio. +- Tutorial. +- Options menu. +- Performance target. + +## Art Direction +YeetGeese should probably be: +- Stylized. +- Bright. +- Funny. +- Slightly absurd. +- Easy to read in fast action. + +Visual pillars: +1. **Readable silhouettes** + - Enemies must be easy to identify. + - Geese should be very visible. + +2. **Strong color separation** + - Player geese: white, yellow, orange. + - Enemies: red, purple, dark colors. + - Environment: neutral or complementary. + +3. **Comedic animation** + - Goose flapping. + - Enemy squish. + - Honk shockwave. + - Feather explosion. + - Boss rage face. + +## Level Design +Create one strong arena. + +Suggested arena concepts: +- Farmyard at dusk. +- Mall parking lot. +- Office building break room. +- Beach boardwalk. +- Giant kitchen. +- Airport terminal. +- Medieval goose castle. + +Arena should have: +- Spawn points. +- Clear player movement space. +- Cover or terrain features. +- 2–3 chokepoints. +- Visual landmarks. +- Safe zone. +- Base or objective. + +## UI Polish +Create a clean, humorous UI. + +Menus: +- Main menu. +- Level select. +- Upgrade shop. +- Pause. +- Game over. +- Victory. +- Options. +- Credits. + +HUD: +- Health. +- Base health, if separate. +- Feathers/currency. +- Wave counter. +- Enemies remaining. +- Selected goose. +- Goose inventory. +- Upgrade prompts. +- Boss health bar. + +Accessibility: +- Text size options. +- Colorblind mode. +- Subtitles for audio cues. +- Mouse sensitivity slider. +- Invert Y axis. +- Left-hand mode. +- Reduced screen shake. +- High contrast mode. + +## Audio Polish +Add: +- Main menu music. +- Gameplay music. +- Boss music. +- Victory theme. +- Defeat jingle. +- Final goose honk. + +Audio mixing: +- Sfx should not overpower music. +- Goose honks should feel satisfying. +- Enemy damage should be clear. +- UI sounds should be subtle. + +## Performance Goals +For a first-person 3D indie game, aim for: +- 60 FPS on mid-range PC. +- 30 FPS minimum on low-end PC. +- Stable frame time. +- Low memory usage. +- No major hitching during waves. + +Optimization checklist: +- Use instancing for repeated meshes. +- Limit particle count. +- Pool projectiles and enemies. +- Avoid excessive collision checks. +- Use LOD if needed. +- Batch static geometry where possible. +- Avoid dynamic shadows on too many objects. +- Monitor memory with Godot debugger. + +## Vertical Slice Deliverables +- One polished level. +- Complete gameplay loop. +- One boss. +- Upgrades. +- Full UI. +- Full audio. +- Options. +- Tutorial. +- Performance acceptable. +- Playable 10–15 minute experience. + +## Exit Criteria +- A first-time player can understand the game within 2 minutes. +- The level is fun to play. +- The goose mechanic feels central and satisfying. +- The game looks and sounds cohesive. +- It runs well enough to share. +- You have a demo build for testing. --- -### Godot Architecture Recommendations for YeetGeese -1. **Scene-First Design:** Every entity is its own `.tscn` + `.gd`. Player, Goose, Enemy, Spawner, HUD each encapsulated. -2. **Data-Driven Balance:** All numbers (throw cooldown, goose mass, enemy HP/spawn rate) live in `Resource` files or JSON autoloads. Swap balance tables without recompiling. -3. **Signal Bus Pattern:** A lightweight autoload (`Signals.gd`) holding global events (`wave_started`, `enemy_died`, `base_hit`) keeps your manager code clean and UI/audio reactive. -4. **Collision Layers:** Player/Geese on layer 1, Enemies on 2, Base on 3. Geese mask enemies+base only → no self-collision or environment clutter hits. +# Phase 4: Full Production +**Goal:** Expand the vertical slice into the full game. + +This phase depends on your final scope, but for an indie game, I would keep it tight. + +## Recommended Final Game Scope +For a first indie release, target: +- 3–5 levels. +- 8–12 goose types. +- 8–12 enemy types. +- 2–3 bosses. +- 1 upgrade tree or simple upgrade shop. +- Endless mode. +- Daily challenge, if feasible. +- Steam achievements. +- Localization optional for launch. + +Do not overexpand. The best indie games are focused. --- -### Immediate Next Steps -1. Block out the scene hierarchy in Godot: `Main.tscn` → `Player`, `WaveManager`, `HUD`. -2. Implement the goose throw prototype with a placeholder `RigidBody3D` + gravity + damage on collision. -3. Wire one enemy using `NavigationAgent3D` toward your base node. -4. Get the web export working and share a raw prototype build to test aiming feel in first-person. \ No newline at end of file +## Phase 4A: Content Pipeline +**Goal:** Build a repeatable pipeline for adding content without breaking the game. + +### Goose Creation Pipeline +For each goose: +1. Create `GooseDef` resource. +2. Add mesh/animation. +3. Add sound. +4. Add projectile behavior. +5. Add turret behavior, if applicable. +6. Add icon. +7. Add description. +8. Add balance values. +9. Test in game. +10. Add to shop or unlock system. + +### Enemy Creation Pipeline +For each enemy: +1. Create `EnemyDef` resource. +2. Add mesh. +3. Add animations. +4. Add attack behavior. +5. Add movement behavior. +6. Add health/speed/damage. +7. Add death effect. +8. Add reward. +9. Add wave data. +10. Balance. + +### Level Creation Pipeline +For each level: +1. Build arena. +2. Place spawn points. +3. Place base/objective. +4. Define wave table. +5. Add level-specific modifiers. +6. Add level reward. +7. Add level unlock. +8. Playtest. +9. Balance. +10. Polish. + +Example level modifiers: +- Enemies spawn faster. +- Geese have less range. +- Turrets last longer. +- Enemies are immune to stun. +- Currency drops increase. +- Dark lighting. +- Moving platforms. +- Obstacles. + +--- + +## Phase 4B: Progression Systems +**Goal:** Give players a reason to keep playing. + +Add one or more of these: +- Level unlocks. +- Goose unlocks. +- Upgrade unlocks. +- Cosmetic goose skins. +- Achievements. +- Endless mode. +- Score leaderboard. +- Daily challenge seed. + +Avoid complex RPG stats. Keep it arcade-like. + +## Phase 4C: Game Modes +Start with: +1. **Campaign** + - Fixed levels. + - Progressive difficulty. + +2. **Endless Mode** + - Waves scale forever. + - Difficulty increases. + - Score-based. + +Optional: +3. **Speedrun Mode** + - Timer. + - Minimal upgrades. + - High score. + +4. **Daily Challenge** + - Seeded wave layout. + - Seeded goose modifiers. + +## Phase 4D: Balance +Create a simple balance sheet. + +Track: +- Goose cost. +- Goose damage. +- Goose speed. +- Enemy health. +- Enemy speed. +- Enemy damage. +- Wave reward. +- Upgrade cost. +- Level reward. + +Balance goals: +- Player should never feel helpless. +- Player should not one-shot everything. +- Waves should ramp gradually. +- Bosses should feel powerful but defeatable. +- Upgrades should matter. +- Late-game geese should feel exciting. + +Use playtesting data: +- Where do players die? +- Which goose is never used? +- Which enemy feels unfair? +- Is the economy too tight? +- Are waves too dense? + +--- + +# Phase 5: Polish & Optimization +**Goal:** Make the game feel stable, responsive, and fun to play repeatedly. + +## Gameplay Feel +Tune: +- Throw speed. +- Goose arc. +- Spin. +- Hit pause. +- Knockback. +- Camera recoil. +- Screen shake. +- Enemy death feedback. +- Coin pickup feedback. +- Wave transition feel. + +The “yeet” should feel satisfying. + +Possible tricks: +- Slight slow motion on big goose hits. +- Strong honk sound. +- Feather burst. +- Camera punch. +- Enemy squash animation. +- Sound layering: + - Whoosh + honk + impact. + +## Input Feel +Tune: +- Mouse sensitivity. +- Mouse acceleration. +- Movement speed. +- Acceleration. +- Friction. +- Air control, if jumping is added. +- Throw cooldown. +- Switching goose speed. + +## Visual Polish +- Final materials. +- Lighting. +- Fog, if used. +- Skybox. +- Environmental details. +- UI animations. +- Level transitions. +- Victory/defeat sequences. + +## Audio Polish +- Final music. +- Final sfx. +- Mix levels. +- Spatial audio. +- Ducking of music during important events. + +## Bug Fixing +Create bug categories: +- Critical: crashes, broken save, impossible win/loss. +- High: broken core mechanic. +- Medium: annoying gameplay issue. +- Low: visual or minor audio issue. + +Use a board: +- Backlog. +- In Progress. +- Ready for Review. +- Done. + +## Testing +Playtest: +- First-time players. +- Friends who understand the game. +- People who do not understand the game. + +Ask: +- Did you understand the goal? +- Did you know how to throw geese? +- Did you know what currency was for? +- Did you know what the base was? +- Which goose was your favorite? +- Which wave was hardest? +- What felt unfair? + +## Optimization +Check: +- FPS. +- Frame time. +- Memory. +- Draw calls. +- Physics cost. +- Particle count. +- Audio instance count. +- Object pooling efficiency. +- Collision overlap cost. +- Scene load time. + +--- + +# Phase 6: Launch Preparation +**Goal:** Prepare for release or demo distribution. + +## Store Page +Prepare: +- Title. +- Description. +- Short description. +- Features. +- System requirements. +- Screenshots. +- Trailer. +- Key art. +- Icon. +- Tags: + - Indie. + - Tower Defense. + - First-Person. + - Action. + - Strategy. + - Funny. + - Animals. + - Geese. + +## Build +Create final build: +- Windows. +- Linux, if desired. +- macOS, if desired. +- Steam build, if publishing on Steam. + +## Checklist +- Game starts correctly. +- Save file works. +- Options persist. +- No missing textures. +- No missing audio. +- No console errors. +- Performance acceptable. +- Achievements work. +- Leaderboards work, if present. +- Localization files work, if present. +- Legal information included. +- Credits included. +- ESRB/PEGI info available, if required. +- Refund policy understood. + +## Marketing +Prepare: +- Dev log. +- Screenshots. +- Short trailer. +- Gameplay clips. +- Press kit. +- Community posts. +- Demo build, if using Steam Next Fest or similar. + +--- + +# Phase 7: Post-Launch +**Goal:** Support the game and extend its life. + +## Immediate Post-Launch +- Monitor bugs. +- Patch critical issues. +- Respond to player feedback. +- Balance early. +- Collect reviews. +- Track crash reports. + +## Optional Updates +- New goose skin. +- New enemy. +- New level. +- New game mode. +- Boss rush. +- Daily challenge. +- Localization. +- Controller support, if not already present. + +--- + +# Suggested Godot Architecture + +Here is a practical scene/component structure. + +## Autoloads + +### `GameState.gd` +Handles global game state. + +Signals: +```gdscript +signal health_changed(value) +signal base_health_changed(value) +signal currency_changed(value) +signal wave_started(wave_number) +signal wave_completed(wave_number) +signal game_over() +signal victory() +``` + +Variables: +```gdscript +var player_health: int = 100 +var base_health: int = 100 +var currency: int = 0 +var current_wave: int = 1 +var total_waves: int = 10 +var is_paused: bool = false +var is_game_over: bool = false +``` + +### `EventBus.gd` +Central gameplay events. + +Signals: +```gdscript +signal goose_thrown(goose: Node3D) +signal goose_hit(target: Node3D, damage: float) +signal enemy_died(enemy: Node3D) +signal enemy_spawned(enemy: Node3D) +signal turret_placed(turret: Node3D) +signal upgrade_purchased(upgrade_id: String) +``` + +### `AudioManager.gd` +Plays audio. + +```gdscript +func play_sfx(id: String) -> void: + # play sound + pass +``` + +--- + +## Scene Structure + +### `Main.tscn` +```text +Main + - WorldEnvironment + - DirectionalLight3D + - Camera3D, if needed + - Player + - EnemySpawner + - Base + - UI + - AudioStreamPlayer +``` + +### `Player.tscn` +```text +Player + - CharacterBody3D + - CollisionShape3D + - Camera3D + - ThrowOrigin + - Hand / GooseModel + - AnimationPlayer + - AudioStreamPlayer3D +``` + +### `GooseProjectile.tscn` +```text +GooseProjectile + - Area3D + - CollisionShape3D + - MeshInstance3D + - GPUParticles3D + - AudioStreamPlayer3D +``` + +### `Enemy.tscn` +```text +Enemy + - CharacterBody3D + - CollisionShape3D + - MeshInstance3D + - AudioStreamPlayer3D + - HealthBar +``` + +### `TurretGoose.tscn` +```text +TurretGoose + - Area3D + - CollisionShape3D + - MeshInstance3D + - TargetDetector + - PeckAnimation + - AudioStreamPlayer3D +``` + +--- + +# Suggested Script Examples + +## Player Throw Input +Simplified: +```gdscript +@onready var camera: Camera3D = $Camera3D +@onready var throw_origin: Marker3D = $ThrowOrigin +@onready var goose_projectile_scene: PackedScene = preload("res://scenes/GooseProjectile.tscn") + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed("Throw_Goose"): + throw_goose() + +func throw_goose() -> void: + var goose = goose_projectile_scene.instantiate() + goose.global_position = throw_origin.global_position + goose.global_transform = camera.global_transform + get_parent().add_child(goose) + EventBus.goose_thrown.emit(goose) + AudioManager.play_sfx("goose_throw") +``` + +## Goose Projectile +```gdscript +extends Area3D + +@export var throw_speed: float = 25.0 +@export var spin_speed: float = 15.0 +@export var lifetime: float = 2.0 + +var age: float = 0.0 + +func _ready() -> void: + body_entered.connect(_on_body_entered) + +func _process(delta: float) -> void: + age += delta + if age > lifetime: + queue_free() + +func _on_body_entered(body: Node3D) -> void: + if body.has_method("take_damage"): + body.take_damage(10.0) + AudioManager.play_sfx("goose_hit") + queue_free() +``` + +## Enemy Health +```gdscript +extends CharacterBody3D + +@export var max_health: float = 30.0 +var health: float = 30.0 + +func _ready() -> void: + health = max_health + +func take_damage(amount: float) -> void: + health -= amount + if health <= 0: + die() + +func die() -> void: + EventBus.enemy_died.emit(self) + AudioManager.play_sfx("enemy_die") + queue_free() +``` + +## Wave Manager +```gdscript +extends Node + +@export var waves: Array[Resource] = [] +@export var spawn_position: Marker3D + +var current_wave_index: int = 0 + +func _ready() -> void: + start_wave() + +func start_wave() -> void: + if current_wave_index >= waves.size(): + GameState.victory.emit() + return + + var wave: WaveDef = waves[current_wave_index] + GameState.wave_started.emit(current_wave_index + 1) + spawn_wave(wave) + current_wave_index += 1 + +func spawn_wave(wave: WaveDef) -> void: + # spawn enemies according to wave data + pass +``` + +--- + +# Recommended Development Timeline + +This assumes a small team or solo developer working part-time. + +| Phase | Duration | Output | +|---|---:|---| +| Phase 0: Definition & Setup | 1–2 weeks | Project setup, MVP scope | +| Phase 1: Prototype | 2–4 weeks | Playable throw-enemy loop | +| Phase 2: Core Systems | 4–6 weeks | Waves, economy, towers, upgrades | +| Phase 3: Vertical Slice | 4–8 weeks | Polished one-level demo | +| Phase 4: Full Production | 8–16 weeks | Full game content | +| Phase 5: Polish & Optimization | 2–4 weeks | Stable, fun build | +| Phase 6: Launch Prep | 2–3 weeks | Store page, build, marketing | +| Phase 7: Post-Launch | Ongoing | Patches, updates | + +For a tighter indie scope, the full project could be around **6–12 months part-time** or **2–4 months full-time**, depending on art, animation, and scope. + +--- + +# Biggest Risks & How to Avoid Them + +## 1. Scope Creep +**Risk:** You add too many goose types, enemy types, and mechanics. + +**Solution:** +- Finish the vertical slice before adding more content. +- Keep the MVP small. +- Cut anything that is not core to “thrown geese.” + +## 2. First-Person + Tower Defense Confusion +**Risk:** Players do not understand whether this is a shooter, platformer, or tower defense. + +**Solution:** +- Make the base/objective very visible. +- Use a clear HUD. +- Use a short tutorial. +- Make enemies clearly path toward the objective. + +## 3. Goose Throwing Feels Weak +**Risk:** The main mechanic does not feel satisfying. + +**Solution:** +- Invest heavily in feel. +- Add spin, arc, honks, feathers, hit pause, and screen shake. +- Playtest frequently. + +## 4. Enemy AI Gets Too Complex +**Risk:** You spend too long making advanced AI. + +**Solution:** +- Use simple movement first. +- Use waypoint paths or straight-line targeting. +- Add pathfinding only if needed. + +## 5. Art Scope Becomes Too Big +**Risk:** You try to build beautiful environments before the game is fun. + +**Solution:** +- Use low-poly stylized assets. +- Keep materials simple. +- Use strong color and silhouette. +- Polish one level before expanding. + +## 6. Performance Problems +**Risk:** Too many geese, enemies, and particles cause frame drops. + +**Solution:** +- Pool projectiles and enemies. +- Limit simultaneous enemies. +- Limit particles. +- Use simple collision shapes. +- Test performance early. + +--- + +# Minimum Playable Version Checklist + +Use this as your Phase 1 target. + +- [ ] First-person player can move. +- [ ] Mouse look works. +- [ ] Player can throw a goose. +- [ ] Goose flies forward. +- [ ] Goose spins. +- [ ] Goose hits enemy. +- [ ] Enemy takes damage. +- [ ] Enemy dies. +- [ ] Player gains currency. +- [ ] Wave 1 starts. +- [ ] Wave 2 starts after wave 1 completes. +- [ ] Player can win after final wave. +- [ ] Player can lose if health reaches 0. +- [ ] Basic UI shows health, currency, wave. +- [ ] Pause menu works. +- [ ] Placeholder goose sound plays. +- [ ] Placeholder enemy death sound plays. +- [ ] No major crashes in a 5-minute playtest. + +--- + +# Suggested First 14 Days + +If you want a very concrete start, do this for two weeks. + +## Days 1–3: Setup +- Create Godot project. +- Set up folders. +- Set up Git. +- Create autoloads. +- Create input actions. +- Create collision layers. +- Create simple greybox arena. + +## Days 4–7: Player + Goose +- Build first-person controller. +- Add mouse look. +- Add throw input. +- Create goose projectile. +- Make goose fly forward. +- Add basic collision. +- Add placeholder honk. + +## Days 8–10: Enemy +- Create enemy. +- Make enemy move toward player or base. +- Make enemy take damage. +- Make enemy die. +- Add placeholder enemy mesh. +- Add enemy death sound. + +## Days 11–13: Waves + UI +- Create wave manager. +- Spawn 3 enemies in wave 1. +- Spawn 5 enemies in wave 2. +- Add HUD. +- Add win/lose screens. + +## Day 14: Playtest +- Play the full loop. +- Note what feels bad. +- Fix the most important issue. +- Decide the next goose type to add. + +--- + +# Final Recommendation + +Start with this exact loop: + +> **Move → Aim → Yeet Goose → Goose Honks → Enemy Squishes → Feathers Drop → Next Wave** + +Once that loop feels good, add: +1. Turret geese. +2. Upgrades. +3. Enemy variety. +4. Bosses. +5. More levels. +6. Polish. + +The game does not need a complicated tower defense economy to be fun. It needs a satisfying goose throw, readable enemies, and a clear objective. If the goose yeet feels great, the rest will follow. \ No newline at end of file diff --git a/AI Docs/PLAN_MORE.md b/AI Docs/PLAN_MORE.md deleted file mode 100644 index 53ede15..0000000 --- a/AI Docs/PLAN_MORE.md +++ /dev/null @@ -1,1445 +0,0 @@ -Here is a practical phase plan for **YeetGeese**, a first-person tower defense game where the main weapon is thrown geese, built in **Godot 4**. I’m assuming the core fantasy is: the player is in a 3D arena, enemies approach, and the player throws geese either as projectiles, temporary turrets, or both. The plan below is structured so you can build a small playable prototype first, then expand into a full indie game. - ---- - -# YeetGeese Phase Plan - -## Phase 0: Game Definition & Setup -**Goal:** Define the core game, set up the Godot project, and create a clear development scope. - -### Main Tasks -1. **Write a short design document** - - One page is enough. - - Core fantasy: “Yeet geese at enemies and defend a base.” - - Core loop: - - Enemies spawn. - - Player throws geese. - - Geese damage, distract, or tower-ize enemies. - - Player earns currency. - - Player buys/upgrades geese or defenses. - - Wave ends. - - Next wave becomes harder. - -2. **Define the MVP** - A small but complete version of the game should include: - - One arena. - - One player controller. - - One goose type. - - Two enemy types. - - Five waves. - - Basic economy. - - Basic UI: - - Health. - - Currency. - - Wave number. - - Pause menu. - - Win/lose state. - -3. **Set up the Godot project** - - Godot version: Godot 4.x. - - Project type: 3D. - - Renderer: Forward+ for better visuals, Mobile/Compatibility if targeting low-end devices. - - Create folders: - ```text - res:// - scripts/ - scenes/ - assets/ - audio/ - meshes/ - textures/ - materials/ - animations/ - ui/ - data/ - autoload/ - tests/ - ``` - - Set up Git. - - Add `.gitignore` for Godot artifacts. - - Add a simple README. - -4. **Set up basic project architecture** - Create autoloads such as: - - `GameState.gd` - - Handles wave state, score, currency, lives, pause. - - `EventBus.gd` - - Central signals for gameplay events. - - `AudioManager.gd` - - Plays sfx and music. - - `SettingsManager.gd` - - Saves settings and unlockables. - -5. **Define collision layers** - Suggested collision setup: - - `1`: Environment / terrain. - - `2`: Player. - - `3`: Enemy. - - `4`: Goose projectile. - - `5`: Goose turret. - - `6`: Pickups / currency. - - `7`: UI / trigger zones. - -6. **Set up input map** - Suggested inputs: - - `Move_Forward`: W - - `Move_Backward`: S - - `Move_Left`: A - - `Move_Right`: D - - `Aim`: Mouse look. - - `Throw_Goose`: Left mouse button. - - `Switch_Goose`: 1 / 2 / 3 or Q. - - `Reload_Or_Refill`: R. - - `Pause`: Escape. - - `Sprint`: Shift, if used. - - `Crouch`: C, if used. - -### Exit Criteria -- You have a clear MVP scope. -- Godot project opens cleanly. -- Basic folders, autoloads, input map, and collision setup exist. -- The team knows what the first playable prototype must contain. - ---- - -# Phase 1: Core Playable Prototype -**Goal:** Prove that throwing geese at enemies in a first-person tower defense arena is fun. - -This is the most important phase. Do not focus on art yet. Use greybox shapes and placeholder audio. - -## Core Systems to Build - -### 1. First-Person Player Controller -Create a first-person controller using Godot’s `CharacterBody3D`. - -Basic structure: -```text -Player - - Camera3D - - ThrowOrigin (Marker3D at hand/gun position) -``` - -Player behavior: -- Mouse look. -- WASD movement. -- Ground snapping or simple gravity. -- Optional head bob. -- Optional sprint. -- Throw input triggers projectile creation. - -### 2. Goose Projectile -The goose can be a simple `Area3D` or `RigidBody3D`. - -For a first prototype, I recommend: -```text -GooseProjectile - - Area3D - - MeshInstance3D - - CollisionShape3D - - AnimationPlayer -``` - -Behavior: -- Spawn from `ThrowOrigin`. -- Apply velocity based on camera direction. -- Apply spin. -- Apply gravity or custom flight curve. -- Detect collision with enemies. -- On hit: - - Damage enemy. - - Play honk. - - Spawn hit effect. - - Queue free after lifetime or impact. - -Simplified throw logic: -```gdscript -var throw_dir := -camera.global_transform.basis.z -projectile.linear_velocity = throw_dir * throw_speed -projectile.angular_velocity = Vector3(0, 12, 0) -``` - -### 3. Enemy -Start with one enemy type. - -Enemy structure: -```text -Enemy - - Area3D or CharacterBody3D - - MeshInstance3D - - CollisionShape3D - - Health component -``` - -Enemy behavior: -- Spawn at a point. -- Move toward base or player. -- Attack player or base when close. -- Take damage. -- Die and drop currency. - -For the first prototype, simple movement is enough: -```gdscript -var direction := (target.global_position - global_position).normalized() -velocity = direction * speed -move_and_slide() -``` - -If using a base to defend: -- Target the base. -- If base is destroyed, player loses. - -If the player is the base: -- Target the player. -- If player dies, lose. - -### 4. Basic Wave Spawner -Create a simple wave manager. - -Wave manager behavior: -- Start wave. -- Spawn enemies over time. -- Track remaining enemies. -- When all enemies are dead, start next wave. -- After final wave, player wins. - -Data structure example: -```gdscript -class_name WaveDef -extends Resource - -@export var enemies: Array[EnemyDef] = [] -@export var spawn_interval: float = 1.0 -@export var reward: int = 10 -``` - -### 5. Basic Economy -- Enemy dies. -- Player gains goose coins or feathers. -- Player can buy additional goose throws or a better goose. - -For the first prototype: -- 100 starting feathers. -- Goose throw costs 0. -- Enemy drops 5 feathers. -- Every 10 enemies, unlock one extra goose in reserve. -- Or buy a “Strong Goose” that does more damage. - -### 6. Minimal UI -Use Godot’s Control nodes. - -Required UI: -- Top-left: - - Player health. - - Feathers/currency. -- Top-right: - - Wave number. - - Enemies remaining. -- Center: - - Crosshair. -- Menu: - - Resume. - - Restart. - - Quit. - -### 7. Win/Lose State -- Win: survive all prototype waves. -- Lose: player health reaches 0 or base health reaches 0. - -Show simple message: -- “Victory!” -- “Defeated…” - -## Prototype Deliverables -A single playable scene where the player can: -- Move in first person. -- Look with the mouse. -- Throw geese. -- Geese hit enemies. -- Enemies move, take damage, and die. -- Currency increases. -- Waves progress. -- Player can win or lose. - -## Exit Criteria -- The core loop is playable. -- Throwing geese feels responsive. -- Enemies can be killed. -- Waves work. -- Economy works minimally. -- The game has a clear win/lose state. - ---- - -# Phase 2: Tower Defense Core Systems -**Goal:** Turn the prototype into a real tower defense game by adding towers, upgrades, enemy variety, and a more complete loop. - -This phase is where YeetGeese becomes its own genre hybrid: first-person action + tower defense strategy. - -## Design Decision: How Do Geese Function as Towers? - -You need to choose one or more goose roles. - -### Option A: Thrown Goose as Projectile -The goose is a flying attack. - -Examples: -- Standard Goose: medium damage. -- Heavy Goose: slow, high damage. -- Fast Goose: fast, low damage, piercing. -- Exploding Goose: AoE damage. -- Homing Goose: slight curve toward nearest enemy. - -### Option B: Goose Becomes a Turret -When thrown, the goose lands and stays for a short time. - -Examples: -- The goose pecks nearby enemies. -- The goose honks to stun enemies. -- The goose guards a path. -- The goose dies after 10 seconds. - -### Option C: Goose as Companion -The goose follows the player and occasionally attacks. - -Examples: -- Player throws goose. -- Goose attaches to player for a time. -- It pecks the nearest enemy. -- It dies after taking too much damage. - -I recommend starting with **Option A + Option B** as the core fantasy: -- Some geese are projectile weapons. -- Some geese land and become temporary turrets. -- This gives both action and tower defense. - ---- - -## Phase 2 Systems - -### 1. Goose Definitions -Make geese data-driven using Godot Resources. - -Example: -```gdscript -class_name GooseDef -extends Resource - -@export var id: String -@export var display_name: String -@export var cost: int -@export var damage: float -@export var throw_speed: float -@export var spin_speed: float -@export var lifetime: float -@export var knockback: float -@export var stun_duration: float -@export var can_become_turret: bool -@export var turret_duration: float -@export var turret_damage: float -@export var turret_attack_interval: float -@export var icon: Texture2D -``` - -Initial goose types: -1. **Basic Goose** - - Cheap. - - Medium damage. - - Standard speed. - -2. **Angry Goose** - - Higher damage. - - Knockback. - - Slightly slower. - -3. **Honk Goose** - - Low damage. - - Stuns enemies briefly. - - Useful for crowd control. - -4. **Turret Goose** - - Lands and pecks nearby enemies for 6 seconds. - - Creates a mini tower. - -5. **Bomb Goose** - - Explodes on impact. - - Area damage. - -### 2. Enemy Definitions -Create data-driven enemy resources. - -Example: -```gdscript -class_name EnemyDef -extends Resource - -@export var id: String -@export var display_name: String -@export var health: float -@export var speed: float -@export var damage: float -@export var attack_range: float -@export var attack_cooldown: float -@export var reward: int -@export var scale: float -@export var color: Color -@export var mesh: PackedScene -``` - -Initial enemy types: -1. **Slow Grunt** - - Low health. - - Low speed. - - Low damage. - -2. **Runner** - - Fast. - - Low health. - - Reaches base/player quickly. - -3. **Tank** - - Slow. - - High health. - - High damage. - -4. **Spitter** - - Keeps distance. - - Ranged attack. - -5. **Boss** - - Appears at wave 5 or 10. - - High health. - - Special attack. - -### 3. Wave Manager Expansion -Add: -- Enemy groups. -- Spawn intervals. -- Enemy paths. -- Wave scaling. -- Boss waves. -- Wave rewards. - -Example: -```gdscript -class_name WaveDef -extends Resource - -@export var wave_number: int -@export var enemies: Array[EnemyGroup] -@export var reward: int -``` - -```gdscript -class_name EnemyGroup -extends Resource - -@export var enemy_def: EnemyDef -@export var count: int -@export var spawn_interval: float -@export var spawn_delay: float -``` - -### 4. Tower Placement System -If geese become turrets, create a tower placement system. - -Possible approach: -- Player throws a Turret Goose at the ground. -- Goose lands. -- After a short delay, it becomes a turret. -- Turret has: - - Health. - - Duration. - - Range. - - Damage. - - Attack cooldown. - - Target priority. - -Turret target priority: -1. Closest enemy. -2. Weakest enemy. -3. Enemy closest to base/player. - -### 5. Upgrade System -Start simple. - -Upgrade paths: -- Goose damage. -- Goose speed. -- Goose knockback. -- Turret duration. -- Turret range. -- Starting feathers. -- Enemy slow effect. -- Player movement speed. - -Example upgrade structure: -```gdscript -class_name UpgradeDef -extends Resource - -@export var id: String -@export var display_name: String -@export var description: String -@export var cost: int -@export var max_level: int -@export var effects: Dictionary -``` - -### 6. Player Inventory / Goose Selection -Add a simple selection system. - -Player can have: -- Currently selected goose. -- Multiple goose slots. -- Limited reserve count. -- Refill timer or cost to refill. - -UI: -- Bottom center shows selected goose. -- Number keys switch goose. -- Mouse wheel could switch goose. - -### 7. Enemy AI Improvements -Add: -- Pathfinding or waypoint movement. -- Avoidance. -- Attack behavior. -- Stun behavior. -- Fear of honking. -- Aggro changes. - -For early development, simple movement is fine: -- Move toward target. -- If blocked, slide or rotate. -- If in attack range, stop and attack. - -Later, consider: -- NavigationRegion3D. -- NavMesh. -- Waypoints. -- Behavior tree or simple state machine. - -### 8. Base / Objective System -Choose one of these: - -#### Player as Objective -Enemies attack the player directly. - -Pros: -- Simple. -- Feels first-person. - -Cons: -- Less tower defense feel. - -#### Base as Objective -Enemies attack a base, shrine, goose farm, or cheese stockpile. - -Pros: -- More tower defense. -- Player can move freely. - -Cons: -- Need base defense logic. - -Recommended hybrid: -- There is a base to defend. -- Player can also be damaged by enemies. -- Losing happens if base health reaches 0 or player dies. - -### 9. Audio -Add placeholder audio first, then replace later. - -Required sounds: -- Goose honk. -- Throw whoosh. -- Impact. -- Enemy death. -- Enemy attack. -- Wave start. -- Wave complete. -- UI click. -- Coin pickup. -- Boss warning. - -Use: -```text -AudioStreamPlayer -AudioStreamPlayer3D -``` - -For geese and nearby enemies, use 3D audio. - -### 10. Particles & Juice -Add small visual/audio feedback: -- Goose trail. -- Hit particles. -- Enemy death burst. -- Feather explosion. -- Screen shake on heavy hits. -- Slow motion on boss kill, if desired. - -This phase is where the game starts feeling like a game rather than a tech demo. - -## Exit Criteria -- Multiple goose types exist. -- Multiple enemy types exist. -- Waves are data-driven. -- Turret geese can be placed. -- Upgrades exist. -- Player can select geese. -- Economy loop is complete. -- One full level is playable from start to finish. -- The game has a basic sense of progression. - ---- - -# Phase 3: Vertical Slice -**Goal:** Create one polished, complete level that represents the final game quality. - -This is the phase used for feedback, publisher meetings, demo day, or Steam Next Fest. - -## Scope -One full level with: -- 10 waves. -- 3–5 goose types. -- 4–6 enemy types. -- 1 boss. -- 1 upgrade shop. -- 1 themed arena. -- Final art placeholders or low-poly stylized art. -- Final UI. -- Final audio. -- Tutorial. -- Options menu. -- Performance target. - -## Art Direction -YeetGeese should probably be: -- Stylized. -- Bright. -- Funny. -- Slightly absurd. -- Easy to read in fast action. - -Visual pillars: -1. **Readable silhouettes** - - Enemies must be easy to identify. - - Geese should be very visible. - -2. **Strong color separation** - - Player geese: white, yellow, orange. - - Enemies: red, purple, dark colors. - - Environment: neutral or complementary. - -3. **Comedic animation** - - Goose flapping. - - Enemy squish. - - Honk shockwave. - - Feather explosion. - - Boss rage face. - -## Level Design -Create one strong arena. - -Suggested arena concepts: -- Farmyard at dusk. -- Mall parking lot. -- Office building break room. -- Beach boardwalk. -- Giant kitchen. -- Airport terminal. -- Medieval goose castle. - -Arena should have: -- Spawn points. -- Clear player movement space. -- Cover or terrain features. -- 2–3 chokepoints. -- Visual landmarks. -- Safe zone. -- Base or objective. - -## UI Polish -Create a clean, humorous UI. - -Menus: -- Main menu. -- Level select. -- Upgrade shop. -- Pause. -- Game over. -- Victory. -- Options. -- Credits. - -HUD: -- Health. -- Base health, if separate. -- Feathers/currency. -- Wave counter. -- Enemies remaining. -- Selected goose. -- Goose inventory. -- Upgrade prompts. -- Boss health bar. - -Accessibility: -- Text size options. -- Colorblind mode. -- Subtitles for audio cues. -- Mouse sensitivity slider. -- Invert Y axis. -- Left-hand mode. -- Reduced screen shake. -- High contrast mode. - -## Audio Polish -Add: -- Main menu music. -- Gameplay music. -- Boss music. -- Victory theme. -- Defeat jingle. -- Final goose honk. - -Audio mixing: -- Sfx should not overpower music. -- Goose honks should feel satisfying. -- Enemy damage should be clear. -- UI sounds should be subtle. - -## Performance Goals -For a first-person 3D indie game, aim for: -- 60 FPS on mid-range PC. -- 30 FPS minimum on low-end PC. -- Stable frame time. -- Low memory usage. -- No major hitching during waves. - -Optimization checklist: -- Use instancing for repeated meshes. -- Limit particle count. -- Pool projectiles and enemies. -- Avoid excessive collision checks. -- Use LOD if needed. -- Batch static geometry where possible. -- Avoid dynamic shadows on too many objects. -- Monitor memory with Godot debugger. - -## Vertical Slice Deliverables -- One polished level. -- Complete gameplay loop. -- One boss. -- Upgrades. -- Full UI. -- Full audio. -- Options. -- Tutorial. -- Performance acceptable. -- Playable 10–15 minute experience. - -## Exit Criteria -- A first-time player can understand the game within 2 minutes. -- The level is fun to play. -- The goose mechanic feels central and satisfying. -- The game looks and sounds cohesive. -- It runs well enough to share. -- You have a demo build for testing. - ---- - -# Phase 4: Full Production -**Goal:** Expand the vertical slice into the full game. - -This phase depends on your final scope, but for an indie game, I would keep it tight. - -## Recommended Final Game Scope -For a first indie release, target: -- 3–5 levels. -- 8–12 goose types. -- 8–12 enemy types. -- 2–3 bosses. -- 1 upgrade tree or simple upgrade shop. -- Endless mode. -- Daily challenge, if feasible. -- Steam achievements. -- Localization optional for launch. - -Do not overexpand. The best indie games are focused. - ---- - -## Phase 4A: Content Pipeline -**Goal:** Build a repeatable pipeline for adding content without breaking the game. - -### Goose Creation Pipeline -For each goose: -1. Create `GooseDef` resource. -2. Add mesh/animation. -3. Add sound. -4. Add projectile behavior. -5. Add turret behavior, if applicable. -6. Add icon. -7. Add description. -8. Add balance values. -9. Test in game. -10. Add to shop or unlock system. - -### Enemy Creation Pipeline -For each enemy: -1. Create `EnemyDef` resource. -2. Add mesh. -3. Add animations. -4. Add attack behavior. -5. Add movement behavior. -6. Add health/speed/damage. -7. Add death effect. -8. Add reward. -9. Add wave data. -10. Balance. - -### Level Creation Pipeline -For each level: -1. Build arena. -2. Place spawn points. -3. Place base/objective. -4. Define wave table. -5. Add level-specific modifiers. -6. Add level reward. -7. Add level unlock. -8. Playtest. -9. Balance. -10. Polish. - -Example level modifiers: -- Enemies spawn faster. -- Geese have less range. -- Turrets last longer. -- Enemies are immune to stun. -- Currency drops increase. -- Dark lighting. -- Moving platforms. -- Obstacles. - ---- - -## Phase 4B: Progression Systems -**Goal:** Give players a reason to keep playing. - -Add one or more of these: -- Level unlocks. -- Goose unlocks. -- Upgrade unlocks. -- Cosmetic goose skins. -- Achievements. -- Endless mode. -- Score leaderboard. -- Daily challenge seed. - -Avoid complex RPG stats. Keep it arcade-like. - -## Phase 4C: Game Modes -Start with: -1. **Campaign** - - Fixed levels. - - Progressive difficulty. - -2. **Endless Mode** - - Waves scale forever. - - Difficulty increases. - - Score-based. - -Optional: -3. **Speedrun Mode** - - Timer. - - Minimal upgrades. - - High score. - -4. **Daily Challenge** - - Seeded wave layout. - - Seeded goose modifiers. - -## Phase 4D: Balance -Create a simple balance sheet. - -Track: -- Goose cost. -- Goose damage. -- Goose speed. -- Enemy health. -- Enemy speed. -- Enemy damage. -- Wave reward. -- Upgrade cost. -- Level reward. - -Balance goals: -- Player should never feel helpless. -- Player should not one-shot everything. -- Waves should ramp gradually. -- Bosses should feel powerful but defeatable. -- Upgrades should matter. -- Late-game geese should feel exciting. - -Use playtesting data: -- Where do players die? -- Which goose is never used? -- Which enemy feels unfair? -- Is the economy too tight? -- Are waves too dense? - ---- - -# Phase 5: Polish & Optimization -**Goal:** Make the game feel stable, responsive, and fun to play repeatedly. - -## Gameplay Feel -Tune: -- Throw speed. -- Goose arc. -- Spin. -- Hit pause. -- Knockback. -- Camera recoil. -- Screen shake. -- Enemy death feedback. -- Coin pickup feedback. -- Wave transition feel. - -The “yeet” should feel satisfying. - -Possible tricks: -- Slight slow motion on big goose hits. -- Strong honk sound. -- Feather burst. -- Camera punch. -- Enemy squash animation. -- Sound layering: - - Whoosh + honk + impact. - -## Input Feel -Tune: -- Mouse sensitivity. -- Mouse acceleration. -- Movement speed. -- Acceleration. -- Friction. -- Air control, if jumping is added. -- Throw cooldown. -- Switching goose speed. - -## Visual Polish -- Final materials. -- Lighting. -- Fog, if used. -- Skybox. -- Environmental details. -- UI animations. -- Level transitions. -- Victory/defeat sequences. - -## Audio Polish -- Final music. -- Final sfx. -- Mix levels. -- Spatial audio. -- Ducking of music during important events. - -## Bug Fixing -Create bug categories: -- Critical: crashes, broken save, impossible win/loss. -- High: broken core mechanic. -- Medium: annoying gameplay issue. -- Low: visual or minor audio issue. - -Use a board: -- Backlog. -- In Progress. -- Ready for Review. -- Done. - -## Testing -Playtest: -- First-time players. -- Friends who understand the game. -- People who do not understand the game. - -Ask: -- Did you understand the goal? -- Did you know how to throw geese? -- Did you know what currency was for? -- Did you know what the base was? -- Which goose was your favorite? -- Which wave was hardest? -- What felt unfair? - -## Optimization -Check: -- FPS. -- Frame time. -- Memory. -- Draw calls. -- Physics cost. -- Particle count. -- Audio instance count. -- Object pooling efficiency. -- Collision overlap cost. -- Scene load time. - ---- - -# Phase 6: Launch Preparation -**Goal:** Prepare for release or demo distribution. - -## Store Page -Prepare: -- Title. -- Description. -- Short description. -- Features. -- System requirements. -- Screenshots. -- Trailer. -- Key art. -- Icon. -- Tags: - - Indie. - - Tower Defense. - - First-Person. - - Action. - - Strategy. - - Funny. - - Animals. - - Geese. - -## Build -Create final build: -- Windows. -- Linux, if desired. -- macOS, if desired. -- Steam build, if publishing on Steam. - -## Checklist -- Game starts correctly. -- Save file works. -- Options persist. -- No missing textures. -- No missing audio. -- No console errors. -- Performance acceptable. -- Achievements work. -- Leaderboards work, if present. -- Localization files work, if present. -- Legal information included. -- Credits included. -- ESRB/PEGI info available, if required. -- Refund policy understood. - -## Marketing -Prepare: -- Dev log. -- Screenshots. -- Short trailer. -- Gameplay clips. -- Press kit. -- Community posts. -- Demo build, if using Steam Next Fest or similar. - ---- - -# Phase 7: Post-Launch -**Goal:** Support the game and extend its life. - -## Immediate Post-Launch -- Monitor bugs. -- Patch critical issues. -- Respond to player feedback. -- Balance early. -- Collect reviews. -- Track crash reports. - -## Optional Updates -- New goose skin. -- New enemy. -- New level. -- New game mode. -- Boss rush. -- Daily challenge. -- Localization. -- Controller support, if not already present. - ---- - -# Suggested Godot Architecture - -Here is a practical scene/component structure. - -## Autoloads - -### `GameState.gd` -Handles global game state. - -Signals: -```gdscript -signal health_changed(value) -signal base_health_changed(value) -signal currency_changed(value) -signal wave_started(wave_number) -signal wave_completed(wave_number) -signal game_over() -signal victory() -``` - -Variables: -```gdscript -var player_health: int = 100 -var base_health: int = 100 -var currency: int = 0 -var current_wave: int = 1 -var total_waves: int = 10 -var is_paused: bool = false -var is_game_over: bool = false -``` - -### `EventBus.gd` -Central gameplay events. - -Signals: -```gdscript -signal goose_thrown(goose: Node3D) -signal goose_hit(target: Node3D, damage: float) -signal enemy_died(enemy: Node3D) -signal enemy_spawned(enemy: Node3D) -signal turret_placed(turret: Node3D) -signal upgrade_purchased(upgrade_id: String) -``` - -### `AudioManager.gd` -Plays audio. - -```gdscript -func play_sfx(id: String) -> void: - # play sound - pass -``` - ---- - -## Scene Structure - -### `Main.tscn` -```text -Main - - WorldEnvironment - - DirectionalLight3D - - Camera3D, if needed - - Player - - EnemySpawner - - Base - - UI - - AudioStreamPlayer -``` - -### `Player.tscn` -```text -Player - - CharacterBody3D - - CollisionShape3D - - Camera3D - - ThrowOrigin - - Hand / GooseModel - - AnimationPlayer - - AudioStreamPlayer3D -``` - -### `GooseProjectile.tscn` -```text -GooseProjectile - - Area3D - - CollisionShape3D - - MeshInstance3D - - GPUParticles3D - - AudioStreamPlayer3D -``` - -### `Enemy.tscn` -```text -Enemy - - CharacterBody3D - - CollisionShape3D - - MeshInstance3D - - AudioStreamPlayer3D - - HealthBar -``` - -### `TurretGoose.tscn` -```text -TurretGoose - - Area3D - - CollisionShape3D - - MeshInstance3D - - TargetDetector - - PeckAnimation - - AudioStreamPlayer3D -``` - ---- - -# Suggested Script Examples - -## Player Throw Input -Simplified: -```gdscript -@onready var camera: Camera3D = $Camera3D -@onready var throw_origin: Marker3D = $ThrowOrigin -@onready var goose_projectile_scene: PackedScene = preload("res://scenes/GooseProjectile.tscn") - -func _unhandled_input(event: InputEvent) -> void: - if event.is_action_pressed("Throw_Goose"): - throw_goose() - -func throw_goose() -> void: - var goose = goose_projectile_scene.instantiate() - goose.global_position = throw_origin.global_position - goose.global_transform = camera.global_transform - get_parent().add_child(goose) - EventBus.goose_thrown.emit(goose) - AudioManager.play_sfx("goose_throw") -``` - -## Goose Projectile -```gdscript -extends Area3D - -@export var throw_speed: float = 25.0 -@export var spin_speed: float = 15.0 -@export var lifetime: float = 2.0 - -var age: float = 0.0 - -func _ready() -> void: - body_entered.connect(_on_body_entered) - -func _process(delta: float) -> void: - age += delta - if age > lifetime: - queue_free() - -func _on_body_entered(body: Node3D) -> void: - if body.has_method("take_damage"): - body.take_damage(10.0) - AudioManager.play_sfx("goose_hit") - queue_free() -``` - -## Enemy Health -```gdscript -extends CharacterBody3D - -@export var max_health: float = 30.0 -var health: float = 30.0 - -func _ready() -> void: - health = max_health - -func take_damage(amount: float) -> void: - health -= amount - if health <= 0: - die() - -func die() -> void: - EventBus.enemy_died.emit(self) - AudioManager.play_sfx("enemy_die") - queue_free() -``` - -## Wave Manager -```gdscript -extends Node - -@export var waves: Array[Resource] = [] -@export var spawn_position: Marker3D - -var current_wave_index: int = 0 - -func _ready() -> void: - start_wave() - -func start_wave() -> void: - if current_wave_index >= waves.size(): - GameState.victory.emit() - return - - var wave: WaveDef = waves[current_wave_index] - GameState.wave_started.emit(current_wave_index + 1) - spawn_wave(wave) - current_wave_index += 1 - -func spawn_wave(wave: WaveDef) -> void: - # spawn enemies according to wave data - pass -``` - ---- - -# Recommended Development Timeline - -This assumes a small team or solo developer working part-time. - -| Phase | Duration | Output | -|---|---:|---| -| Phase 0: Definition & Setup | 1–2 weeks | Project setup, MVP scope | -| Phase 1: Prototype | 2–4 weeks | Playable throw-enemy loop | -| Phase 2: Core Systems | 4–6 weeks | Waves, economy, towers, upgrades | -| Phase 3: Vertical Slice | 4–8 weeks | Polished one-level demo | -| Phase 4: Full Production | 8–16 weeks | Full game content | -| Phase 5: Polish & Optimization | 2–4 weeks | Stable, fun build | -| Phase 6: Launch Prep | 2–3 weeks | Store page, build, marketing | -| Phase 7: Post-Launch | Ongoing | Patches, updates | - -For a tighter indie scope, the full project could be around **6–12 months part-time** or **2–4 months full-time**, depending on art, animation, and scope. - ---- - -# Biggest Risks & How to Avoid Them - -## 1. Scope Creep -**Risk:** You add too many goose types, enemy types, and mechanics. - -**Solution:** -- Finish the vertical slice before adding more content. -- Keep the MVP small. -- Cut anything that is not core to “thrown geese.” - -## 2. First-Person + Tower Defense Confusion -**Risk:** Players do not understand whether this is a shooter, platformer, or tower defense. - -**Solution:** -- Make the base/objective very visible. -- Use a clear HUD. -- Use a short tutorial. -- Make enemies clearly path toward the objective. - -## 3. Goose Throwing Feels Weak -**Risk:** The main mechanic does not feel satisfying. - -**Solution:** -- Invest heavily in feel. -- Add spin, arc, honks, feathers, hit pause, and screen shake. -- Playtest frequently. - -## 4. Enemy AI Gets Too Complex -**Risk:** You spend too long making advanced AI. - -**Solution:** -- Use simple movement first. -- Use waypoint paths or straight-line targeting. -- Add pathfinding only if needed. - -## 5. Art Scope Becomes Too Big -**Risk:** You try to build beautiful environments before the game is fun. - -**Solution:** -- Use low-poly stylized assets. -- Keep materials simple. -- Use strong color and silhouette. -- Polish one level before expanding. - -## 6. Performance Problems -**Risk:** Too many geese, enemies, and particles cause frame drops. - -**Solution:** -- Pool projectiles and enemies. -- Limit simultaneous enemies. -- Limit particles. -- Use simple collision shapes. -- Test performance early. - ---- - -# Minimum Playable Version Checklist - -Use this as your Phase 1 target. - -- [ ] First-person player can move. -- [ ] Mouse look works. -- [ ] Player can throw a goose. -- [ ] Goose flies forward. -- [ ] Goose spins. -- [ ] Goose hits enemy. -- [ ] Enemy takes damage. -- [ ] Enemy dies. -- [ ] Player gains currency. -- [ ] Wave 1 starts. -- [ ] Wave 2 starts after wave 1 completes. -- [ ] Player can win after final wave. -- [ ] Player can lose if health reaches 0. -- [ ] Basic UI shows health, currency, wave. -- [ ] Pause menu works. -- [ ] Placeholder goose sound plays. -- [ ] Placeholder enemy death sound plays. -- [ ] No major crashes in a 5-minute playtest. - ---- - -# Suggested First 14 Days - -If you want a very concrete start, do this for two weeks. - -## Days 1–3: Setup -- Create Godot project. -- Set up folders. -- Set up Git. -- Create autoloads. -- Create input actions. -- Create collision layers. -- Create simple greybox arena. - -## Days 4–7: Player + Goose -- Build first-person controller. -- Add mouse look. -- Add throw input. -- Create goose projectile. -- Make goose fly forward. -- Add basic collision. -- Add placeholder honk. - -## Days 8–10: Enemy -- Create enemy. -- Make enemy move toward player or base. -- Make enemy take damage. -- Make enemy die. -- Add placeholder enemy mesh. -- Add enemy death sound. - -## Days 11–13: Waves + UI -- Create wave manager. -- Spawn 3 enemies in wave 1. -- Spawn 5 enemies in wave 2. -- Add HUD. -- Add win/lose screens. - -## Day 14: Playtest -- Play the full loop. -- Note what feels bad. -- Fix the most important issue. -- Decide the next goose type to add. - ---- - -# Final Recommendation - -Start with this exact loop: - -> **Move → Aim → Yeet Goose → Goose Honks → Enemy Squishes → Feathers Drop → Next Wave** - -Once that loop feels good, add: -1. Turret geese. -2. Upgrades. -3. Enemy variety. -4. Bosses. -5. More levels. -6. Polish. - -The game does not need a complicated tower defense economy to be fun. It needs a satisfying goose throw, readable enemies, and a clear objective. If the goose yeet feels great, the rest will follow. \ No newline at end of file