Back to projects
Software/2025 - Present/Active

DeadSteel

A real-time strategy game built from scratch in C# and MonoGame, with resource management, combat systems and an AI opponent.

C#Game AIReal-timeOOP

Built with

C#MonoGameObject-Oriented ProgrammingGame AIAlgorithmsGame Development

Overview

An A-Level Computer Science project built from scratch in C# using MonoGame. DeadSteel combines real-time gameplay, resource management, unit spawning, combat and an AI opponent while requiring the underlying game loop, state management and entity systems to be designed independently.

01

What I built

DeadSteel is a real-time strategy game I built for A-Level Computer Science.

I deliberately avoided using a full game engine because I wanted to understand what was actually happening underneath the game.

That meant designing the game loop, entity management, resource systems, combat, AI decisions and rendering myself.

The player manages resources, builds units and fights an AI opponent in real time. The interesting part technically is that all of those systems have to operate continuously without the game becoming unstable or unresponsive.

02

The problem

A real-time game gives you a surprisingly strict constraint: everything has to happen quickly enough to maintain a consistent frame rate.

Every unit needs updating. The AI needs to make decisions. Inputs need processing. The game needs rendering.

If one system becomes too expensive, the entire game feels it.

I therefore had to think about both software architecture and performance rather than treating each feature independently.

03

Why I built it

I wanted my A-Level project to be something I would actually enjoy building.

A game gave me a reason to learn about object-oriented design, state management, algorithms and AI while having a visible result at the end.

More importantly, building it without a large engine forced me to understand the underlying systems instead of hiding them behind high-level tools.

Architecture

The game is organised around a fixed update and draw cycle.

Game state is updated first, including player input, unit movement, resource production and AI decisions.

Rendering then displays that state without changing it.

Keeping those responsibilities separate made debugging significantly easier as the project grew.

01

Game loop

Controls the update and rendering cycle

02

Game state

Tracks units, resources, buildings and map state

03

Input system

Handles player commands and selections

04

AI system

Evaluates the game state and selects actions

05

Combat system

Movement, targeting and combat resolution

06

Renderer

Draws the world, units and interface

Engineering

Fixed timestep

Game logic advances using a controlled timestep so gameplay behaviour does not depend directly on how quickly frames are being rendered.

Entity management

Units are updated through structured collections rather than allowing increasingly deep object relationships to control the game loop.

AI decision system

The AI evaluates the current game state and chooses between economic and military actions rather than following a completely scripted sequence.

Resource economy

Units and buildings depend on accumulated resources and production times, creating a trade-off between investing in the economy and building military strength.

What broke

01

Performance degraded as the game grew

Code that worked perfectly with a small number of units started causing frame drops once the number of active entities increased.

I had to look at the cost of work happening every frame rather than simply adding more hardware.

02

Making the AI difficult without making it unfair

My first AI was either too predictable or too strong.

The solution was not simply to give it better decisions. I also had to limit how quickly it could react and what information it could use so that the opponent felt challenging rather than artificial.

03

Keeping rendering separate from simulation

Allowing rendering code to modify game state created bugs that were difficult to reproduce.

Separating simulation from presentation made the overall system much easier to reason about.

What I learned

Performance is an architectural problem

When something runs every frame, a small inefficiency becomes a large one very quickly.

AI is not just about being stronger

Good game AI needs constraints. Giving the opponent imperfect information and delayed reactions can make it more believable than simply increasing its power.

The update/render split matters

Separating what the game knows from how the game displays it is one of the most useful architectural patterns I took away from the project.

Next

  • Implement pathfinding around obstacles
  • Add multiple AI personalities
  • Introduce difficulty levels based on decision-making behaviour
  • Add save and load functionality
  • Improve combat balancing and unit variety