The Survivors

2D Story-Based Metroidvania | GameMaker Studio 2

Made with: GameMaker Genre: Action Adventure Status: Released(Demo)
Screenshot of The Survivors

The Survivors is a 2D story-based Metroidvania that blends deliberate combat, exploration, and narrative depth. It’s built to feel like a AAA experience in a 2D world. A story told through responsive gameplay, world exploring and environmental tension.


I handled every aspect of gameplay programming from the combat and AI to the camera system, UI, resource management, and traversal logic. Each system interacts dynamically: stamina governs how long players can use certain mechanics like crouching and blocking while the Focus mechanic slows perception during key moments, and cinematic sequences use shader-based black bars and transitions to guide pacing and communicate with the player.


My biggest technical challenge was making dozens of interconnected systems work together seamlessly. Combat, input handling, the pause menu, saving/loading, and cinematic triggers all needed to operate independently but still communicate when states changed. Through multiple iterations and rewrites, I built a structure that could handle these transitions cleanly without performance dips or unpredictable behavior.


One of the visual effects I developed for my game was a “Poisoned” screen shader. When the player takes damage from enemies with a venom attack, this shader activates to distort and tint the scene, creating a feeling of disorientation. The vertex and fragment shaders below work together to simulate both wave-like motion and subtle chromatic aberration.



		// Vertex Shader (poison.vsh)
		// Basic pass-through vertex transform
		attribute vec3 in_Position;
		attribute vec2 in_TextureCoord;
		varying vec2 v_vTexcoord;
		varying vec4 v_vColour;

		void main() {
			vec4 object_space_pos = vec4(in_Position.x, in_Position.y, in_Position.z, 1.0);
			gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
			v_vTexcoord = in_TextureCoord;
			v_vColour = vec4(1.0); // full color
		}
		


		// Fragment Shader (poison.fsh)
		// Applies distortion and color shift to mimic a poisoned visual effect
		varying vec2 v_vTexcoord;
		varying vec4 v_vColour;
		uniform float u_time;
		uniform float u_intensity;

		void main() {
			vec2 uv = v_vTexcoord;
			
			// Sinusoidal horizontal distortion (like a toxin pulse)
			float wave = sin(uv.y * 10.0 + u_time * 2.0) * 0.01 * u_intensity;
			uv.x += wave;
			
			// chromatic aberration
			float aberration = 0.005 * u_intensity;
			vec3 color;
			color.r = texture2D(gm_BaseTexture, uv + vec2(aberration, 0.0)).r;
			color.g = texture2D(gm_BaseTexture, uv).g;
			color.b = texture2D(gm_BaseTexture, uv - vec2(aberration, 0.0)).b;
			
			gl_FragColor = vec4(color, 1.0);
		}
		

The effect’s intensity scales dynamically using the u_intensity uniform, which ties directly to the player’s status variables. As the poison timer ticks down, the distortion fades, restoring clarity and grounding the player back into the world. The result is a feedback system that’s visual, reactive, and grounded in gameplay logic.


One of my favorite design choices was the “claustrophobia” mechanic. When the player crawls through tight spaces with low stamina, the environment subtly reacts: the screen darkens, sound dampens, and the player’s breathing becomes audible. It’s a small system, but it captures the psychological tension I wanted players to feel in moments of exhaustion and confinement.


Every effect, from the Focus shader to the boss combats was programmed from scratch. Cutscenes were built using in-engine timing and input locks rather than pre-rendered videos, so the world always feels alive. Character animations, music, and sound effects were contributed by freelancers, but every system behind them,every collision, transition, and behavior was written by me.


The Survivors taught me more than any of my Computer Science classes could about the marriage between design and engineering. I learned that “feel” is engineered through timing, feedback, and constraint. And that code is only as good as the story it helps tell. This project became my foundation for understanding how gameplay systems can drive emotional storytelling as well help me decide the career I am currently pursuing.