Skip to main content

Spaceship Shooting Example

This example extends the spaceship control demo with a complete twin-stick shooting system, demonstrating projectile spawning via the SpawnSystemFactory DSL, aiming components, level bounds collision, and state management.

Features

  • Twin-Stick Shooter Controls - Left stick for movement, right stick for aiming and shooting
  • GameLoop Architecture - Phase-based execution with Pre/Main/Post phases, typed passes, and commit points
  • GameObjectFactory - Fluent builder pattern for creating player, projectiles, and grid
  • SpawnSystemFactory DSL - Declarative spawn configuration for projectile pooling
  • Projectile Spawning - ProjectileSpawnSystem with spawn profiles and pooling
  • Level Bounds System - Arena boundaries with bounce/despawn behavior
  • State Management - Game state tracking via Session with typed GameState transitions
  • Automated Rendering - SceneRenderingSystem handles viewport-based rendering
  • ShootComponent - Configurable fire rate and projectile speed
  • Aim2DComponent - Direction tracking and firing frequency management
  • Object Pooling - Efficient projectile management via GameObjectPoolManager
  • PrefabId - Strongly-typed prefab identification for pooled entities

Building

cmake -S . -B build
cmake --build build --target spaceship_shootingmain

Running

./build/examples/spaceship_shooting/main

Controls

InputAction
Left StickMove spaceship / Rotate
Right StickAim direction / Fire projectiles
ESCExit application
~ (Tilde)Toggle ImGui overlay

Code Structure

FilePurpose
main.cppApplication entry point and game loop
SpaceshipWidget.ixxImGui widget for physics and fire rate parameter tuning

Components Used

ComponentPurpose
SceneNodeComponentLinks GameObject to scene graph
Move2DComponent2D physics with acceleration and dampening
SteeringComponentRotation control and direction
Aim2DComponentTracks aim direction and firing frequency
ShootComponentManages projectile firing with cooldown
LevelBoundsBehaviorComponentBounce/despawn at arena boundaries
AabbColliderComponentWorld-space collision bounds
SpawnedByProfileComponentLinks entity to spawn profile
PrefabIdComponentIdentifies prefab type for pooling
Active / InactiveEntity activation state tags

Systems Used

SystemPurpose
TwinStickInputSystemDual analog stick input handling
ProjectileSpawnSystemSpawns projectiles from ShootComponent
HierarchyPropagationSystemPropagates transforms through entity hierarchies
ScaleSystemApplies ScaleStateComponent sizing
SteeringSystemRotation and direction updates
Move2DSystemPhysics simulation (velocity integration)
BoundsUpdateSystemUpdates AABB colliders from transforms
LevelBoundsBehaviorSystemHandles boundary collisions
ComposeTransformSystemComputes final transforms
StateToViewportPolicyUpdateSystemActivates viewports based on game state
SceneSyncSystemSyncs transforms to scene graph
SceneRenderingSystemRenders scenes to associated viewports
TransformClearSystemClears dirty flags post-frame

Spawn System Configuration (DSL)

SpawnSystemFactory::configure(poolManager, spawnManager)
.pool(ProjectilePoolId, ProjectilePrefabId, 50)
.profile(ProjectileSpawnProfileId)
.emitterPlacement()
.done()
.commit();

GameLoop Phase Configuration

// Pre-Phase: Input, Spawning, Physics
gameLoop.phase(PhaseType::Pre)
.addPass<GameState>(GameState::Any)
.addSystem<TwinStickInputSystem>(shipGameObject)
.addCommitPoint(CommitPoint::Structural)
.addPass<GameState>(GameState::Any)
.addSystem<ProjectileSpawnSystem>(ProjectileSpawnProfileId)
.addCommitPoint(CommitPoint::Structural)
.addPass<GameState>(GameState::Any)
.addSystem<ScaleSystem>()
.addSystem<SteeringSystem>()
.addSystem<Move2DSystem>();

// Main-Phase: Collision and Bounds
gameLoop.phase(PhaseType::Main)
.addPass<GameState>(GameState::Any)
.addSystem<HierarchyPropagationSystem>()
.addSystem<BoundsUpdateSystem>()
.addSystem<LevelBoundsBehaviorSystem>()
.addCommitPoint();

// Post-Phase: Transform and Rendering
gameLoop.phase(PhaseType::Post)
.addPass<GameState>(GameState::Any)
.addSystem<ComposeTransformSystem>()
.addSystem<StateToViewportPolicyUpdateSystem<GameState, MatchState>>(stateToViewportMap)
.addSystem<SceneSyncSystem>(sceneToViewportMap)
.addSystem<SceneRenderingSystem>(renderingDevice, sceneToViewportMap)
.addSystem<TransformClearSystem>();

Command Dispatchers

The spawn system uses commands for deferred entity creation:

gameLoop.commandBuffer()
.addDispatcher<SpawnCommand>(std::make_unique<SpawnCommandDispatcher>())
.addDispatcher<DespawnCommand>(std::make_unique<DespawnCommandDispatcher>());

See Also