Projects
Personal projects, prototypes, and open-source tools focused on gameplay systems and game feel.
A Unity serious game built in C# for educational use, connected to a live backend (CoachData platform). Players log in with their user account, carry progression across 10 levels, and their gameplay statistics are tracked and stored remotely to support coaching and research analysis.
About the Project
Rugby Run is a 2.5D endless-runner-style serious game set on a rugby pitch across 10 hand-crafted levels plus a standalone minigame mode. It was built for the CoachData platform — a sports education system — meaning player identity, progression, and detailed play statistics are persisted to a remote server and accessible to coaches and researchers via a live leaderboard and analytics dashboard.
Technical Highlights
- Live backend integration via REST coroutines — a custom Connection library (DataBase namespace) wraps Unity WWW coroutines to communicate with a CoachData server over HTTP. It handles login, saving and retrieving game state (level, points, speed, jumps, lives), and submitting per-session play statistics (yards run, time played, power-ups acquired).
- Persistent player progression — on login the game fetches the player's last saved level and stat upgrades from the server, restoring their exact session state. On level completion, updated values are immediately written back, ensuring no progress is lost between sessions.
- Between-level upgrade shop — after each level, players spend earned points on three upgrades: speed, extra lives (costing 2 points each), and jump charges (costing 3 points each). Slider-based UI with real-time budget tracking prevents overspending, and final selections are synced to the server before the next level loads.
- Three distinct enemy types — Enemy 1 uses Unity's NavMesh agent to pursue the player directly, with speed scaling by current level (capped at 5); Enemy 2 patrols horizontally, switching direction on wall collisions and moving faster from level 5 onward; Enemy 3 oscillates forward/backward on the Z axis, reversing every 100 fixed frames, doubling speed from level 8.
- Difficulty scaling by level — enemy speed, patrol velocity, and oscillation speed all scale from the persisted level value in the Container DontDestroyOnLoad object, making each subsequent level meaningfully harder without redesigning the scene.
- Minigame mode — a self-contained endless-runner scene where the player auto-runs at incrementally increasing speed and must jump over obstacles. It has its own game loop, highscore tracking, and returns to the main menu on completion rather than feeding into the progression system.
- Full localization system — a singleton Localization manager loads key-value JSON language files from StreamingAssets at startup, fires a LanguageChanged event when the language is switched, and exposes a get(key) API consumed by TextInserter and TextMeshPro components across all UI screens.
- Server-side analytics leaderboard — a Ranking screen fetches all players' statistics from the server and dynamically instantiates table rows to display level reached, yards run, upgrades acquired, and time played — giving coaches a live view of the full cohort's performance.
A multiplayer top-down racing game built in Unreal Engine 5 with C++. Multiple players race on the same map in real time, with projectile combat, lap timing, and a custom client-server networking layer built on top of ENet.
About the Project
CarsOnline is a networked multiplayer game with a fully custom networking stack — bypassing Unreal's built-in replication in favour of a hand-rolled client-server architecture over ENet (UDP based library). The server authorises all game state, coordinates map loading across clients, spawns and positions each player's car, and relays entity updates. Players race laps, shoot projectiles at opponents, and compete for best lap time.
Technical Highlights
- Custom networking layer over ENet — a hand-written Net namespace (CManager, CServidor, CCliente, CConexion, CPaquete) wraps ENet with a typed packet system, observer pattern for event dispatch, and a singleton manager handling connections, send/receive, and ID assignment (SERVER = 0x0, clients from 0x1 upward).
- Server-authoritative game flow — the server drives the full session lifecycle via message types (LOAD_MAP, MAP_LOADED, LOAD_PLAYER, ENTITY_MSG, CREATE_ENTITY, LOAD_PROJECTILE, DESTROY_PROJECTILE), waiting for all MAP_LOADED confirmations before staggering car spawns at offset positions.
- Dead reckoning for remote cars — clients receive periodic server snapshots (transform + velocity magnitude). If the positional error is below a threshold, the component extrapolates a target position and smoothly converges the car toward it each frame; beyond the threshold it teleports, preventing drift accumulation.
- Input prediction for the local car — the owning client simulates its own car movement immediately from local input, then applies an incremental error correction vector each tick to reconcile with server-sent transforms, keeping controls feeling responsive despite latency.
- Physics-based car movement component — a custom ActorComponent computes acceleration (with separate throttle, drag, and brake factors), lateral rotation via a speed-scaled rotation factor, velocity clamping, and average-velocity integration — all independent of Unreal's built-in vehicle physics.
- Server-side projectile authority — shooting sends a CREATE_ENTITY message to the server, which spawns the projectile and then broadcasts LOAD_PROJECTILE to each client individually. Collisions are resolved server-side and replicated to clients as DESTROY_PROJECTILE events.
- Checkpoint and lap timing system — a FinishLine actor validates laps only if the car has passed all registered checkpoints in order, tracking last lap time, best lap time, and total lap count per player.
- GameInstance-owned net manager — the CGameNetMgr lives on the GameInstance, persisting across level loads, making it the single source of truth for player and projectile ID maps throughout the session.
A story-driven 2D platformer built entirely in Lua using the Corona SDK. Players guide a cube character through 12 themed levels in sequence, collecting keys and coins, avoiding enemies, and unlocking the next stage upon completion.
About the Project
JumpCube is a complete mobile game with an intro cinematic, 12 sequential gameplay levels, and a multi-chapter ending story — each chapter rendered as a narrated scene. The game was built for both iOS and Android using the Corona SDK's physics and scene-composition system.
Technical Highlights
- Physics-based platformer — built on Corona SDK's Box2D wrapper with custom gravity (0, 12), collision detection, and per-body physics properties for the player, enemies, projectiles, and environmental objects.
- 12 themed levels via Tiled map loader — maps include Jungle, Castle, Snow, Desert, Laboratory, Moon, Candy, and Night environments, each with its own tileset, background music track, and enemy roster.
- Key and progression system — each level hides a collectible key that must be found to unlock the next stage. Progress is persisted to JSON via a save/load library, tracking unlock status and key collection per level.
- Enemy and hazard variety — level-specific enemies (monkeys, ghosts, penguins, bats, mummies, viruses) patrol the map; bombs and spike obstacles add environmental hazards, all handled through collision callbacks.
- Parallax camera and perspective layers — a custom perspective module handles foreground/background layer scrolling at different speeds, giving depth to the side-scrolling view.
- Fireball combat mechanic — the player can shoot fireballs with a dedicated button; projectiles travel across the screen and are destroyed on enemy or wall collision, with animation and audio feedback.
- Cosmetic shop and accessories — an in-game coin economy lets players purchase accessories (hats, glasses, moustache) from a shop; items are saved to a backpack and rendered on the player sprite at runtime.
- Cinematic intro and ending — six intro scenes and five finale scenes are scripted as standalone Lua scenes with images, transitions, and video playback, framing the game with a narrative arc.
A top-down survival shooter built in Unreal Engine 5 with C++. Players defend a map area against escalating waves of monsters, using a hitscan rifle, while managing health and staying within a bounded mission zone.
About the Project
TopDownSurvival is a complete Unreal Engine game built entirely in C++, covering the full game loop: main menu, gameplay level (set on Mars), pause menu, and game over screen. The architecture follows Unreal's GameMode/PlayerController/Character pattern with custom components and a modular weapon system.
Technical Highlights
- Wave manager with scaling difficulty — the GameMode drives a timer-based wave system that spawns enemies at random TargetPoints. Each new wave multiplies enemy count by a configurable difficulty factor, increasing pressure over time.
- Behaviour Tree AI — monsters use Unreal's Behaviour Tree system with a custom BT Service (BTS_PerceivePlayer) for player detection and a custom BT Task (BTT_Attack) for melee attacks, controlled by a dedicated AIController.
- Hitscan weapon system — shooting uses line traces (LineTraceSingleByChannel) from the weapon's muzzle socket to a range-capped endpoint, applying damage on hit with particle and sound feedback. Fire rate is controlled via a repeating timer.
- Reusable HealthComponent — a standalone ActorComponent handles health, damage, healing, and alive state for both the player and every monster, exposing a Blueprint-readable health percentage for UI bars.
- Mission area volume — a box-collider volume kills the player after a configurable countdown if they stray outside the playable zone, adding spatial pressure to the survival loop.
- FMOD audio integration — all sound (firing, hurt, game over, new wave) goes through FMOD events attached to actors, with a dynamic heartbeat sound whose FMOD parameter is driven in real time by the player's current health ratio.
- Low-health visual feedback — dropping below a health threshold triggers a post-process blood shader via a Material Parameter Collection, reversed on death or recovery.
- Dual input support — the PlayerController detects whether a gamepad is active and hides the world-space cursor decal accordingly, switching aim logic between mouse-cursor tracing and controller rotation.