Resurgence is a 2D Shoot ’em up for PC where the player controls a ship that has time controlling abilities.
You can get the game here: VFS Arcade
Resurgence was my final project at VFS and it was made by a team of 5 people with the help of 4 sound designers. It was built using the unity engine in a period of 3 months.
For this project I was a general programmer and worked on:
- Time rewinding system using a circular buffer.
- Implemented a state machine and an event system using scriptable objects to easily control the flow of the game.
- Created an enemy spawner design tool that allowed our level designer to create multiple waves of enemies and reuse them or modify them to have different difficulty levels.
- Created a customizable boss encounter with multiple set of weapons and attack patterns.
- Sound implementation with Wwise.
Programming Challenges
In the beginning of production we decided that we wanted to make a shoot ’em up with time rewinding mechanics, so for our prototype it was simple enough to just store the position and rotation of every game object in a linked list and remove elements after a certain size.
So then each frame we would add the current position and rotation of the tracked objects into the list and when rewinding time we just took the last recorded position and apply it to the game object.
Show example code
public class CircularStack<T>
{
private int _MaxSize = 10;
private LinkedList<T> _List = new LinkedList<T>();
public CircularStack(int size)
{
_MaxSize = size;
}
// Is the stack empty?
public bool IsEmpty()
{
return _List.Count == 0;
}
// Add a new element to the stack, deleting if past the max size
public void Push(T val)
{
// Discard elements past the max size
if (_List.Count == _MaxSize)
{
_List.RemoveFirst();
}
_List.AddLast(val);
}
// Removes and returns an object from the stack
public T Pop()
{
var tmp = _List.Last.Value;
_List.RemoveLast();
return tmp;
}
// Just return the last element without modification
public T Peek()
{
return _List.Last.Value;
}
}
As our game got bigger and more complex, our system for tracking objects wasn’t enough and was causing performance issues, especially when we had hundreds of tracked objects with their linked lists full, adding and removing positions in the same frame. So we changed our implementation and ended up using a circular implementation of a stack using an array and pointers. Given that we knew the exact size of the array in the beginning depending on the max time we would allow the player to rewind time, a fixed size array seemed like a better solution.

Show example code
public class CircularStack<T>
{
private int _NextFree;
private int _Size;
private T[] _Array;
public CircularStack(int capacity)
{
_Array = new T[capacity];
_NextFree = 0;
_Size = 0;
}
// Is the stack empty?
public bool IsEmpty()
{
return _Size == 0;
}
// Adds a new element, overrides old elements if full
public void Push(T val)
{
_Array[_NextFree] = val;
// Increase index with rollover
_NextFree = (_NextFree + 1) % _Array.Length;
if (_Size < _Array.Length)
{
_Size++;
}
}
// Removes and returns an object from the stack
public T Pop()
{
if (IsEmpty())
{
throw new IndexOutOfRangeException("Circular Stack is empty");
}
// Decrease the index with rollover
_NextFree = (_NextFree + _Array.Length - 1) % _Array.Length
_Size--;
return _Array[_NextFree];
}
// Returns the next element on the buffer
public T Peek()
{
if (IsEmpty)
{
throw new IndexOutOfRangeException("Circular Stack is empty");
}
return _Array[_NextFree];
}
// Do not delete elements but make them overwritable again
public void Clear()
{
_Size = 0;
}
}
Another big challenge we faced was rewinding stuff other than position or rotation, like events of bullets fired or movement patterns that followed a predetermined sequence. For that I started by trying to have a custom attribute “[Rewindable]” and use reflection to store these values but it turned out to be a gigantic task.
After some consultation with our teachers and mentors, they helped us reach the elegant solution of using interfaces, and IRewindable was born.
Whit this interface it was easier to manage different implementations of gameplay that needed to be rewarded, be it a specific path an enemy needed to follow or an event that needed to be called again, etc.
And it ended up being just 5 lines
public interface IRewindable
{
void Record();
void Rewind();
}
Level Design Tools
One important aspect of our game was that we wanted to have multiple difficulty levels, from an easy peasy introductory one, to a “not even the devs are good at this one” difficulty, while still being able to complete a full game in under the time we specified.
I made a wave manager system that allowed our level designer to create waves as prefabs and reuse them and test them separately or together in succession. This wave system allowed for the creation of movement patterns that were scriptable objects which determined a “path” for the enemy to follow. This patter would be reusable and we could have any number of patterns.
I also made a modifiable boss encounter which had 2 phases that would be customizable to use any of the 5 available boss weapons.