Jet Game
Fast-paced jet combat score attack built in Unreal Engine 5
Jet Game is a solo personal project developed over one week, combining fast-paced jet combat with score attack gameplay.
As the sole programmer and designer, I was responsible for all aspects of the project — from flight mechanics and combat systems to level design and UI.
Team Size
My Role
Duration
Tech Stack
Context
My Contributions
Flight System
Combat Systems
HUD & UI
Gameplay Video
Technical Breakdown
Lock-On Targeting & Gimbal Lock
Building a lock-on system for a fully 3D aircraft introduced a classic problem — gimbal lock. When using Euler angles to track and rotate toward a target, certain orientations caused the rotation axes to align, losing a degree of freedom and producing erratic snapping behaviour.
Solving this required switching the rotation representation to quaternions, which avoid the singularity entirely and interpolate smoothly across all orientations.
Failure Conditions, Pickups & Score
The game puts pressure on the player through two concurrent failure conditions — a countdown timer and a health pool. Running out of time or taking too much damage both end the run, forcing the player to balance aggression with survival.
Scattered throughout the level are pickups that grant bonus score, rewarding exploration and risk-taking on top of the core time-to-clear objective. This layered approach gives skilled players something to optimise beyond simply clearing targets as fast as possible.
UI Systems & Inclinometer
The inclinometer ball — a classic aircraft instrument showing pitch and roll — was implemented by using a SceneCapture2D component pointed at a physical ball in the world. The captured image was then fed into the HUD as a texture, giving an accurate real-time read of the jet's orientation.
While functional, this approach has a cost: a SceneCapture renders the scene an additional time each frame. In future I would replace this entirely with a Material shader that takes pitch and roll as scalar parameters, driven at runtime through a Dynamic Material Instance. This eliminates the extra render pass and keeps the effect GPU-friendly.
What I Learned
Technical
Process
What I'd Do Differently
Project Links