Skip to content

feat: Implement Render System, Projectile Rotation, and Trajectory Visuals (#91) - #185

Merged
Vallykrie merged 3 commits into
stagingfrom
91-task-10-render-system-animation-system-trajectory-render-system
May 18, 2026
Merged

Vallykrie merged 3 commits into
stagingfrom
91-task-10-render-system-animation-system-trajectory-render-system

Conversation

@Vallykrie

Copy link
Copy Markdown
Member

**What

This PR implements the core visual synchronization and rendering systems required by the ECS architecture, fulfilling Issue #91 and its sub-tasks (#94, #97).

  • RenderSystem: Synchronizes all entity SpriteComponent node positions to their underlying logical TransformComponent position.
  • Entity Facing: Adjusts the xScale of PlayerEntity nodes automatically so players face the correct direction (player.facing).
  • Projectile Rotation: Dynamically sets the zRotation of the ProjectileEntity to align with its trajectory based on its VelocityComponent using atan2.
  • Projectile Trail: Added a programmatic SKEmitterNode particle trail that follows the bread/toaster during flight.
  • TrajectoryRenderSystem: Ensured the trajectory arc renders as a dashed/dotted line (dashingWithPhase) and cleanly clears itself when exiting AimState.
  • AnimationSystem: Centralized animation loop cleanly processes and drains all queued SKActions per frame.

Why

  • Strict ECS Compliance: We need a "single writer" for visual updates to prevent race conditions and stuttering. Physics and logic systems only modify the TransformComponent, and the RenderSystem cleanly maps that data to SpriteKit at the end of the frame.
  • Visual Polish: Projectiles flying without rotation or trails look unnatural. Dynamically aligning the projectile angle to its velocity makes the physics feel impactful, while the dashed trajectory arc clearly communicates aiming intentions to the player as described in the GDD.

How

  • Render Loop: RenderSystem.update() is called at the very end of GameScene.update(). It extracts TransformComponent and SpriteComponent to update .position.
  • Math: Used atan2(velocity.dy, velocity.dx) to calculate the continuous angle of flight for any entity with a VelocityComponent.
  • Arc Styling: Updated CGMutablePath handling in TrajectoryRenderSystem to use .copy(dashingWithPhase: 0, lengths: [10.0, 10.0]) before assigning it to the SKShapeNode.
  • Trail: Instantiated an SKEmitterNode directly in ProjectileEntity's initialization, utilizing a fallback white particle config since we don't have an .sks asset yet.

Notes

@Vallykrie Vallykrie self-assigned this May 18, 2026
@Vallykrie
Vallykrie merged commit 0f26e22 into staging May 18, 2026
2 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant