feat: complete Voltex Engine + Survivor game
11 crates, 13 examples (including survivor_game), 255 tests Phase 1-8 fully implemented + playable survival game demo Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -46,7 +46,8 @@
|
|||||||
"Bash(mkdir -p C:/Users/SSAFY/Desktop/projects/voltex/crates/voltex_script/lua)",
|
"Bash(mkdir -p C:/Users/SSAFY/Desktop/projects/voltex/crates/voltex_script/lua)",
|
||||||
"Read(//c/tmp/**)",
|
"Read(//c/tmp/**)",
|
||||||
"Bash(tar xzf:*)",
|
"Bash(tar xzf:*)",
|
||||||
"Bash(cp lua-5.4.7/src/*.c lua-5.4.7/src/*.h C:/Users/SSAFY/Desktop/projects/voltex/crates/voltex_script/lua/)"
|
"Bash(cp lua-5.4.7/src/*.c lua-5.4.7/src/*.h C:/Users/SSAFY/Desktop/projects/voltex/crates/voltex_script/lua/)",
|
||||||
|
"Bash(cd:*)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
Cargo.lock
generated
2
Cargo.lock
generated
@@ -1885,6 +1885,8 @@ dependencies = [
|
|||||||
"env_logger",
|
"env_logger",
|
||||||
"log",
|
"log",
|
||||||
"pollster",
|
"pollster",
|
||||||
|
"voltex_audio",
|
||||||
|
"voltex_editor",
|
||||||
"voltex_math",
|
"voltex_math",
|
||||||
"voltex_platform",
|
"voltex_platform",
|
||||||
"voltex_renderer",
|
"voltex_renderer",
|
||||||
|
|||||||
151
docs/superpowers/plans/2026-03-25-survivor-game.md
Normal file
151
docs/superpowers/plans/2026-03-25-survivor-game.md
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
# Voltex Survivor Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** 쿼터뷰 3D 서바이벌 게임 — 적 웨이브를 처치하며 생존, Voltex 엔진 전체 기능 활용
|
||||||
|
|
||||||
|
**Architecture:** `examples/survivor_game/` 단일 바이너리. ECS World에 플레이어/적/투사체 엔티티. 포워드 PBR 렌더링 + 섀도우. AI 내비메시 + A* + 스티어링. 물리 충돌 감지. 오디오 SFX. IMGUI HUD.
|
||||||
|
|
||||||
|
**Tech Stack:** voltex_math, voltex_platform, voltex_renderer, voltex_ecs, voltex_physics, voltex_ai, voltex_audio, voltex_editor
|
||||||
|
|
||||||
|
**Spec:** `docs/superpowers/specs/2026-03-25-survivor-game.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
examples/survivor_game/
|
||||||
|
├── Cargo.toml
|
||||||
|
└── src/
|
||||||
|
├── main.rs — 진입점, 윈도우, 이벤트 루프
|
||||||
|
├── game.rs — GameState, ECS World, 게임 틱 로직
|
||||||
|
├── player.rs — Player 컴포넌트, 이동, 발사
|
||||||
|
├── enemy.rs — Enemy 컴포넌트, 스폰, AI 추격
|
||||||
|
├── projectile.rs — Projectile 컴포넌트, 이동, 충돌
|
||||||
|
├── arena.rs — 아레나 바닥 + 장애물 + NavMesh
|
||||||
|
├── camera.rs — 쿼터뷰 카메라
|
||||||
|
├── wave.rs — 웨이브 시스템
|
||||||
|
├── hud.rs — IMGUI HUD
|
||||||
|
└── render.rs — 렌더 설정 (파이프라인, 메시, 머티리얼)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 1: 프로젝트 셸 + 아레나 + 카메라
|
||||||
|
|
||||||
|
아레나 바닥과 장애물이 렌더링되고 쿼터뷰 카메라로 볼 수 있는 최소 동작.
|
||||||
|
|
||||||
|
**Files:** Cargo.toml, main.rs, arena.rs, camera.rs, render.rs
|
||||||
|
|
||||||
|
이 태스크는 pbr_demo/shadow_demo 패턴을 따라 윈도우+GPU+PBR 파이프라인을 설정하고, 평평한 바닥 메시 + 박스 장애물을 렌더링합니다.
|
||||||
|
|
||||||
|
- 아레나: 바닥 (20x20 flat box, y=0), 장애물 4개 (random-ish 위치의 박스)
|
||||||
|
- 카메라: 고정 쿼터뷰 (offset 0,15,10 from center, look_at center)
|
||||||
|
- 라이트: directional light (태양)
|
||||||
|
- 렌더: 포워드 PBR, 섀도우 맵
|
||||||
|
|
||||||
|
Commit: `feat(game): add survivor_game with arena and quarter-view camera`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 2: 플레이어 이동
|
||||||
|
|
||||||
|
ECS에 플레이어 엔티티 추가. WASD로 XZ 평면 이동. 카메라가 플레이어를 추적.
|
||||||
|
|
||||||
|
**Files:** game.rs, player.rs, camera.rs 수정
|
||||||
|
|
||||||
|
- Player 컴포넌트: hp, fire_cooldown, invincible_timer
|
||||||
|
- Transform: 플레이어 위치
|
||||||
|
- Collider: Sphere { radius: 0.5 }
|
||||||
|
- 입력: WASD → velocity, 매 프레임 position += velocity * dt
|
||||||
|
- 카메라: player position + offset으로 갱신
|
||||||
|
- 아레나 경계 체크 (position clamp)
|
||||||
|
|
||||||
|
Commit: `feat(game): add player movement with WASD and camera follow`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 3: 투사체 발사
|
||||||
|
|
||||||
|
마우스 방향으로 투사체 발사. XZ 평면에서 마우스 위치 계산.
|
||||||
|
|
||||||
|
**Files:** projectile.rs, player.rs 수정, game.rs 수정
|
||||||
|
|
||||||
|
- 마우스 → 레이캐스트로 Y=0 평면 교차점 계산 (간단한 ray-plane)
|
||||||
|
- 조준 방향: (교차점 - 플레이어 위치).normalize() on XZ
|
||||||
|
- 좌클릭: fire_cooldown <= 0이면 투사체 스폰
|
||||||
|
- Projectile 컴포넌트: velocity (Vec3), lifetime (2.0s)
|
||||||
|
- 매 프레임: position += velocity * dt, lifetime -= dt, lifetime <= 0이면 despawn
|
||||||
|
- 시각: 작은 노란 구체
|
||||||
|
|
||||||
|
Commit: `feat(game): add projectile shooting toward mouse aim`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 4: 적 스폰 + AI 추격
|
||||||
|
|
||||||
|
내비메시 기반 AI로 적이 플레이어를 추격.
|
||||||
|
|
||||||
|
**Files:** enemy.rs, arena.rs 수정 (NavMesh 생성), wave.rs, game.rs 수정
|
||||||
|
|
||||||
|
- NavMesh: 아레나 바닥을 삼각형으로 분할 (장애물 영역 제외, 단순 수동 정의)
|
||||||
|
- Enemy 컴포넌트: speed
|
||||||
|
- 스폰: 아레나 가장자리 랜덤 위치
|
||||||
|
- AI 루프:
|
||||||
|
1. find_path(navmesh, enemy_pos, player_pos)
|
||||||
|
2. follow_path + seek 스티어링
|
||||||
|
3. position += steering * speed * dt
|
||||||
|
- Wave: 3 enemies → 5 → 8 → ... (웨이브 간 5초)
|
||||||
|
- 시각: 빨간 구체
|
||||||
|
|
||||||
|
Commit: `feat(game): add enemy spawning with NavMesh A* and steering AI`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 5: 충돌 + 데미지 + 점수
|
||||||
|
|
||||||
|
투사체↔적, 적↔플레이어 충돌 처리.
|
||||||
|
|
||||||
|
**Files:** game.rs 수정, player.rs 수정
|
||||||
|
|
||||||
|
- detect_collisions(world) 사용
|
||||||
|
- 투사체↔적: 둘 다 despawn, score += 100
|
||||||
|
- 적↔플레이어: 적 despawn, player HP -= 1 (invincible 1초)
|
||||||
|
- HP <= 0: game_over = true
|
||||||
|
|
||||||
|
Commit: `feat(game): add collision detection, damage, and scoring`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task 6: HUD + 게임 오버 + 오디오
|
||||||
|
|
||||||
|
IMGUI HUD + 오디오 SFX + 게임 오버/재시작.
|
||||||
|
|
||||||
|
**Files:** hud.rs, game.rs 수정, main.rs 수정
|
||||||
|
|
||||||
|
- HUD: voltex_editor IMGUI
|
||||||
|
- 좌상단: "HP: 3/3", "Wave: 1", "Score: 0"
|
||||||
|
- 게임 오버: 큰 텍스트 "GAME OVER" + "Score: XXXX" + "Press R to restart"
|
||||||
|
- 오디오: AudioSystem
|
||||||
|
- 발사 SFX: 짧은 사인파 (generate procedurally, 440Hz 0.05s)
|
||||||
|
- 적 처치 SFX: 220Hz 0.1s
|
||||||
|
- 발사/처치 시 play()
|
||||||
|
- R키: game_over 시 리셋 (World 초기화)
|
||||||
|
|
||||||
|
Commit: `feat(game): add HUD, audio SFX, and game over/restart`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Task Summary
|
||||||
|
|
||||||
|
| Task | 내용 | 핵심 엔진 |
|
||||||
|
|------|------|-----------|
|
||||||
|
| 1 | 아레나 + 카메라 + 렌더 | renderer, platform, math |
|
||||||
|
| 2 | 플레이어 이동 | ecs, platform (input) |
|
||||||
|
| 3 | 투사체 발사 | physics (ray-plane), ecs |
|
||||||
|
| 4 | 적 AI + 웨이브 | ai (navmesh, A*, steering), ecs |
|
||||||
|
| 5 | 충돌 + 데미지 | physics (detect_collisions) |
|
||||||
|
| 6 | HUD + 오디오 + 게임오버 | editor (IMGUI), audio |
|
||||||
|
|
||||||
|
각 태스크는 이전 태스크에 의존하므로 순차 실행. Task 1이 가장 큰 설정 작업 (GPU, 파이프라인).
|
||||||
146
docs/superpowers/specs/2026-03-25-survivor-game.md
Normal file
146
docs/superpowers/specs/2026-03-25-survivor-game.md
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
# Voltex Survivor — Top-Down Survival Game Spec
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Voltex 엔진의 기능을 종합적으로 활용하는 쿼터뷰 3D 서바이벌 게임. 아레나에서 웨이브별로 몰려오는 적을 처치.
|
||||||
|
|
||||||
|
## Genre / Camera
|
||||||
|
|
||||||
|
쿼터뷰 탑다운 서바이벌. 싱글플레이.
|
||||||
|
|
||||||
|
## Engine Features Used
|
||||||
|
|
||||||
|
- voltex_renderer: PBR, directional light, shadow
|
||||||
|
- voltex_ecs: Entity, World, Transform, query
|
||||||
|
- voltex_physics: Collider, detect_collisions, raycast
|
||||||
|
- voltex_ai: NavMesh, A* pathfinding, steering (seek, arrive)
|
||||||
|
- voltex_audio: WAV playback, 3D spatial audio, mixer
|
||||||
|
- voltex_math: Vec3, Mat4
|
||||||
|
- voltex_platform: Window, InputState, GameTimer
|
||||||
|
- voltex_editor: IMGUI HUD (HP, wave, score)
|
||||||
|
|
||||||
|
## Game Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
examples/survivor_game/
|
||||||
|
├── Cargo.toml
|
||||||
|
└── src/
|
||||||
|
├── main.rs — entry point, window, game loop
|
||||||
|
├── game.rs — GameState, ECS World, tick logic
|
||||||
|
├── player.rs — Player component, movement, shooting
|
||||||
|
├── enemy.rs — Enemy component, spawn, AI chase
|
||||||
|
├── projectile.rs — Projectile component, movement, collision
|
||||||
|
├── arena.rs — Arena mesh + NavMesh generation
|
||||||
|
├── camera.rs — Quarter-view camera following player
|
||||||
|
├── wave.rs — Wave system (enemy count escalation)
|
||||||
|
└── hud.rs — IMGUI HUD overlay
|
||||||
|
```
|
||||||
|
|
||||||
|
## Gameplay
|
||||||
|
|
||||||
|
### Arena
|
||||||
|
- 20x20 unit flat floor (Y=0 plane)
|
||||||
|
- 4~6 obstacle boxes randomly placed
|
||||||
|
- NavMesh: floor triangulated excluding obstacles
|
||||||
|
|
||||||
|
### Player
|
||||||
|
- Visual: blue sphere (radius 0.5)
|
||||||
|
- Movement: WASD on XZ plane, speed 8 units/sec
|
||||||
|
- Aim: mouse position projected onto Y=0 plane (raycast from camera)
|
||||||
|
- Shoot: left click, fires projectile toward aim direction
|
||||||
|
- Fire rate: 0.2s cooldown
|
||||||
|
- HP: 3, contact with enemy = -1 HP, invincibility 1s after hit
|
||||||
|
- Collider: Sphere { radius: 0.5 }
|
||||||
|
|
||||||
|
### Enemy
|
||||||
|
- Visual: red sphere (radius 0.4)
|
||||||
|
- Spawn: at arena edges, random position
|
||||||
|
- AI: find_path on NavMesh from enemy to player, then seek steering
|
||||||
|
- Speed: 3 units/sec (slower than player)
|
||||||
|
- Contact with player: deal damage, enemy destroyed
|
||||||
|
- Collider: Sphere { radius: 0.4 }
|
||||||
|
|
||||||
|
### Projectile
|
||||||
|
- Visual: small yellow sphere (radius 0.15)
|
||||||
|
- Movement: straight line, speed 20 units/sec
|
||||||
|
- Lifetime: 2 seconds, then despawn
|
||||||
|
- Collision: hit enemy → destroy both projectile and enemy, +100 score
|
||||||
|
- Collider: Sphere { radius: 0.15 }
|
||||||
|
|
||||||
|
### Wave System
|
||||||
|
- Wave 1: 3 enemies, 5s delay
|
||||||
|
- Wave N: 2+N enemies, 5s between waves
|
||||||
|
- After all enemies in wave killed → next wave starts after delay
|
||||||
|
- No max wave (infinite escalation)
|
||||||
|
|
||||||
|
### Camera
|
||||||
|
- Quarter-view: player_pos + Vec3(0, 15, 10)
|
||||||
|
- look_at(player_pos)
|
||||||
|
- Fixed angle, follows player
|
||||||
|
|
||||||
|
### HUD (IMGUI)
|
||||||
|
- Top-left: HP hearts or "HP: 3/3"
|
||||||
|
- Top-right: "Wave: 5" + "Score: 1200"
|
||||||
|
- Game over: "GAME OVER - Score: XXXX" centered
|
||||||
|
- Press R to restart
|
||||||
|
|
||||||
|
### Audio
|
||||||
|
- Shoot SFX: short sine burst (generated procedurally)
|
||||||
|
- Enemy death SFX: lower pitch burst
|
||||||
|
- BGM: optional, simple looping tone
|
||||||
|
- 3D spatial: enemy death sounds at enemy position
|
||||||
|
|
||||||
|
## Rendering
|
||||||
|
|
||||||
|
Forward PBR pipeline (existing). No deferred needed for simple scene.
|
||||||
|
|
||||||
|
- Floor: large flat box, gray PBR material (metallic=0, roughness=0.8)
|
||||||
|
- Obstacles: dark boxes, PBR material
|
||||||
|
- Player: blue sphere (base_color blue, metallic=0.3, roughness=0.5)
|
||||||
|
- Enemies: red sphere (base_color red)
|
||||||
|
- Projectiles: yellow sphere (base_color yellow, emissive-like bright)
|
||||||
|
- Light: 1 directional light (sun), shadow enabled
|
||||||
|
- Clear color: dark blue sky
|
||||||
|
|
||||||
|
## Controls
|
||||||
|
|
||||||
|
| Input | Action |
|
||||||
|
|-------|--------|
|
||||||
|
| WASD | Move player |
|
||||||
|
| Mouse move | Aim direction |
|
||||||
|
| Left click | Shoot |
|
||||||
|
| R | Restart (after game over) |
|
||||||
|
| ESC | Quit |
|
||||||
|
|
||||||
|
## Components (ECS)
|
||||||
|
|
||||||
|
```rust
|
||||||
|
struct Player { hp: i32, fire_cooldown: f32, invincible_timer: f32 }
|
||||||
|
struct Enemy { speed: f32 }
|
||||||
|
struct Projectile { velocity: Vec3, lifetime: f32 }
|
||||||
|
struct Health { current: i32, max: i32 }
|
||||||
|
```
|
||||||
|
|
||||||
|
All entities also have Transform + Collider.
|
||||||
|
|
||||||
|
## Game Loop (per frame)
|
||||||
|
|
||||||
|
1. Process input (WASD → player velocity, mouse → aim)
|
||||||
|
2. Update player position
|
||||||
|
3. Update enemy AI (pathfinding + steering)
|
||||||
|
4. Update projectile positions
|
||||||
|
5. Run collision detection
|
||||||
|
6. Process collisions (projectile↔enemy, enemy↔player)
|
||||||
|
7. Update wave system
|
||||||
|
8. Update camera
|
||||||
|
9. Render scene (PBR)
|
||||||
|
10. Render HUD (IMGUI overlay)
|
||||||
|
11. Present
|
||||||
|
|
||||||
|
## Out of Scope
|
||||||
|
|
||||||
|
- Multiplayer
|
||||||
|
- Power-ups / items
|
||||||
|
- Different enemy types
|
||||||
|
- Particle effects
|
||||||
|
- Level progression / save
|
||||||
Reference in New Issue
Block a user