Introducción al Desarrollo de Videojuegos con GameMaker · Module 11: Complete Development of a 2D Platformer
End-to-End Game Testing from Start to Finish
Lesson 55 of 60 · 60 min
Also available in: ES
Introduction to End-to-End Testing and Quality Assurance
Throughout the previous ten modules and the preceding lessons of Module 11, you have built the foundational pillars of a 2D platformer piece by piece: the movement engine with inertia and gravity simulation, horizontal and vertical collision detection, finite state machines for animation, patrolling enemies, collectibles, the heads-up display (HUD), the audio manager, and smooth level transitions. However, assembling technical components does not automatically guarantee a cohesive, bug-free gameplay experience.
End-to-end testing (often referred to in the industry as *End-to-End Playtesting* or E2E testing) consists of evaluating the game as an uninterrupted, unified whole. Rather than verifying a script or an object in isolation within a sandbox test room, end-to-end testing follows the exact path experienced by the end player: from booting the game at the main menu, through the intro screen, across all sequential levels with their hazards and rewards, all the way to the victory screen or restarting after a Game Over.
It is critical to distinguish between two activities that beginner developers often confuse: playing your own game for enjoyment versus methodically evaluating the software with a Quality Assurance (QA) mindset. When playing as a creator, your subconscious naturally follows intended paths, respects planned timings, and steers clear of problematic geometry seams. Methodical testing demands the exact opposite: pushing logic boundaries, pressing keys unpredictably, triggering simultaneous action combinations, and exploring every corner with the explicit goal of breaking the game so you can fix it before release.

The Complete Game Flow and Critical Transitions
To guarantee an airtight game flow, you must strictly map every transition connecting the project's rooms. In GameMaker, improper room management is the primary source of null-reference crashes, duplicated controller instances, and memory leaks caused by unreleased data structures.
Let us analyze the transition stages across a full playthrough that require verification in your project:
| Source State / Room | Trigger Event | Expected Destination | Common Technical Risks |
|---|---|---|---|
| rm_menu | Click 'Start Game' button | rm_level_1 | Uninitialized global variables; score and player lives failing to reset. |
| rm_level_1 | Player collides with obj_door / exit goal | rm_level_2 | Duplication of persistent instances (such as obj_game_manager); player health data failing to carry over. |
| Any gameplay level | Press pause key (vk_escape) | On-screen pause menu | Game clock keeps ticking; background animations or alarms continue running; audio tracks overlap. |
| Any gameplay level | Player health reaches 0 or falls into pit | Checkpoint restart or rm_gameover | Player instance is destroyed, causing dependent scripts to throw fatal crash errors. |
| rm_level_2 (Final level) | Reaching the final goal | rm_victory | Previous stage music keeps playing beneath victory theme; exit buttons become unresponsive. |
| rm_victory or rm_gameover | Click 'Retry' or 'Main Menu' | rm_level_1 or rm_menu | Previous inventory, health, or score carry over instead of resetting to baseline values. |
Any breakdown in this sequence shatters player immersion. If running out of lives and clicking 'Retry' respawns the player in level two instead of resetting their score and returning them to the beginning, the global manager's flow logic is broken. If switching rooms causes level one's music to overlap with level two's music, your audio controller is failing to halt the outgoing sound stream.
Designing and Applying a QA Checklist
A comprehensive test session must never be approached at random. Professional game studios rely on standardized checklists organized by functional disciplines. Below is the testing matrix you should apply sequentially across your complete prototype.
1. Player Mechanics and Core Physics
Begin by verifying control responsiveness under both stationary and continuous movement conditions:
| Test Item | Verification Procedure | Success Criteria |
|---|---|---|
| Acceleration and friction response | Walk briefly and release the controls; reverse direction abruptly. | The character decelerates smoothly according to configured friction values, without snapping instantly or sliding indefinitely. |
| Variable jump height | Tap the jump key lightly versus holding it down. | A quick tap yields noticeably less vertical lift than holding the key through the jump arc. |
| Coyote Time window | Run and deliberately step off a ledge before pressing jump. | The jump registers reliably within the configured frame window (e.g., 6 to 8 steps) after losing ground contact. |
| Ceiling and corner collisions | Jump flush against a solid vertical wall or strike angled ceilings. | Vertical velocity (vsp) immediately resets to 0; the sprite does not clip or embed into the solid block. |
| Facing direction flip (image_xscale) | Turn left and right while walking, jumping, and falling. | The sprite flips across its centered origin without unexpected positional offsets or jitter. |
2. Combat, Hazards, and Checkpoints
Next, expose the player character to environmental hazards to confirm that the damage and respawn cycle operates with mathematical consistency:
| Mechanic | Condition Under Test | Expected Outcome |
|---|---|---|
| Jump attack on enemy | Land squarely on top of a patrolling enemy instance. | The enemy is eliminated or enters its death state; the player gains an elastic upward bounce. |
| Lateral enemy collision | Walk directly into an enemy from the side. | The player loses 1 hit point, triggers invulnerability frames (visual sprite flashing), and receives directional knockback. |
| Death zone / Pitfall | Drop off the bottom boundary of the level layout. | Upon leaving the view or touching obj_killzone, one life is deducted and the player respawns at the latest active checkpoint. |
| Checkpoint activation | Pass through a checkpoint marker and deliberately take lethal damage afterward. | The player respawns at the checkpoint's recorded x and y coordinates rather than the room's default spawn point. |
3. Collectibles, UI, and Audio
Finally, validate sensory and visual synchronization against the internal logic state:
| Component | Required Test | Visual and Audio Verification |
|---|---|---|
| Coins and gems | Collect isolated pickups and long consecutive lines at top speed. | Each pickup plays its collection effect/sound and self-destructs; the HUD counter increments immediately without lag. |
| Draw GUI coordinate anchoring | Resize the display window or traverse stages with an active tracking camera. | HUD elements remain pinned to screen-relative coordinates without drifting, vibrating, or lagging behind camera motion. |
| Music track looping | Remain stationary within a level for several minutes. | The background audio track loops seamlessly without audible gaps, pops, or volume resets at the loop seam. |
| Sound effect (SFX) layering | Execute multiple actions in one second (jump, land, hit enemy, grab coin). | Audio effects mix cleanly across available channels without cutting each other off abruptly or clipping the output. |
Edge Cases and Stress Testing
An *edge case* is a scenario that emerges only at the operational extremes of your game's parameters—frequently when two or more rare events execute on the exact same simulation step. These bugs are the hardest to detect through casual playtesting, yet they are the ones that most frequently frustrate players after release.
Here are three critical edge cases common in 2D platformers developed in GameMaker and how to stress-test them:
💡 Golden rule of instance deactivation: Whenever you use instance_deactivate_all(true) to freeze gameplay for a pause menu, always ensure the controller object listening for the unpause key is set to persistent and explicitly excluded from deactivation. Otherwise, the engine stops evaluating its Step event, forcing the user to terminate the process.
Implementing an In-Game Testing Suite (Debug Suite)
Testing an entire game linearly over and over is wildly inefficient if every minor adjustment to level two requires playing through level one from scratch. To accelerate end-to-end testing, professional developers implement debug hotkeys. These developer shortcuts allow you to skip rooms, modify resources instantly, and inspect runtime telemetry.
It is vital to route all debug hotkeys through a single master switch or global boolean variable. That way, the entire suite can be disabled with a single toggle before publishing your production build, preventing players from accidentally invoking cheat commands.
Below is the recommended implementation to integrate a testing suite inside your global game controller (typically named obj_game_manager).
// ====================================================================
// OBJECT: obj_game_manager
// EVENT: Create
// ====================================================================
// Master flag that enables or disables debug utilities.
// Set to false before exporting the commercial release build.
global.debug_mode = true;
// Flag to toggle on-screen collision masks and technical telemetry
global.show_debug_overlay_custom = false;// ====================================================================
// OBJECT: obj_game_manager
// EVENT: Step
// ====================================================================
// Only evaluate input if debug mode is active
if (global.debug_mode) {
// F1: Instantly restart the current room to test repetitive scenarios
if (keyboard_check_pressed(vk_f1)) {
room_restart();
}
// F2: Advance directly to the next room in the Asset Browser hierarchy
if (keyboard_check_pressed(vk_f2)) {
if (room_next(room) != -1) {
room_goto_next();
} else {
// If at the final room, loop back to the main menu
room_goto(rm_menu);
}
}
// F3: Restore player health to max and replenish reserve lives
if (keyboard_check_pressed(vk_f3)) {
if (instance_exists(obj_player)) {
obj_player.hp = obj_player.max_hp;
global.player_lives = 3;
}
}
// F4: Grant coins and score instantly to verify HUD behavior
if (keyboard_check_pressed(vk_f4)) {
global.coins += 10;
global.game_score += 100;
}
// F5: Toggle on-screen performance and telemetry overlay
if (keyboard_check_pressed(vk_f5)) {
global.show_debug_overlay_custom = !global.show_debug_overlay_custom;
}
}In addition to keyboard shortcuts, having real-time engine metrics visible on-screen is invaluable for diagnosing frame stutter, memory leaks, or erratic step rates. We can render this data inside the manager's Draw GUI event.
// ====================================================================
// OBJECT: obj_game_manager
// EVENT: Draw GUI
// ====================================================================
// Only draw the overlay if debug mode and the overlay toggle are active
if (global.debug_mode && global.show_debug_overlay_custom) {
// Visual styling for the telemetry backing panel
draw_set_color(c_black);
draw_set_alpha(0.7);
draw_rectangle(10, 10, 320, 190, false);
draw_set_alpha(1.0);
draw_set_color(c_lime);
draw_set_font(-1); // Use default system font for maximum clarity
// Engine metrics and room information
draw_text(20, 20, "--- DEBUG TELEMETRY ---");
draw_text(20, 40, "Real FPS: " + string(fps_real));
draw_text(20, 60, "Target FPS: " + string(fps));
draw_text(20, 80, "Active Instances: " + string(instance_count));
draw_text(20, 100, "Current Room: " + room_get_name(room));
// Player-specific telemetry if an instance exists
if (instance_exists(obj_player)) {
draw_text(20, 125, "Player X: " + string(round(obj_player.x)) + " | Y: " + string(round(obj_player.y)));
draw_text(20, 145, "Velocity H: " + string(obj_player.hsp) + " | V: " + string(obj_player.vsp));
draw_text(20, 165, "Grounded: " + string(obj_player.grounded));
} else {
draw_set_color(c_red);
draw_text(20, 125, "Player: [NOT FOUND IN ROOM]");
}
// Reset draw color so subsequent GUI draws are unaffected
draw_set_color(c_white);
}With these tools enabled, balance and stability testing becomes fast and methodical. You can jump directly into level two using F2, verify whether a distant platform is reachable by checking exact hsp and vsp values on-screen via F5, and instantly restore health with F3 after testing a hazard jump.
Logging, Documenting, and Methodically Fixing Bugs
During an end-to-end run, you will inevitably spot subtle irregularities: an audio loop failing to halt during a level shift, a patrolling enemy wandering off its platform after taking damage on a ledge, or HUD text overlapping under non-standard window sizes. Attempting to stop testing and patch each bug the moment you see it is poor practice: it disrupts testing momentum and frequently leads to hurried hotfixes that introduce fresh bugs elsewhere.
Professional workflows dictate logging every discovery into a structured bug report. A well-crafted bug report must include the following minimum fields:
| Field | Description | Practical Report Example |
|---|---|---|
| ID & Title | Unique identifier and concise description of the bug. | #BUG-014: Loss of vertical control when unpausing mid-jump. |
| Severity | Impact rating: Critical (crash), High (blocker), Medium (logic), Low (cosmetic). | High Severity (prevents intended level progression). |
| Reproducibility | Occurrence rate: Always (100%), Often (~50%), Rare (<10%). | Always (100% of attempts following documented steps). |
| Steps to Reproduce | Numbered, clear, chronological steps to trigger the bug reliably. | 1. Load rm_level_1. 2. Jump using Spacebar. 3. At apex of jump, press Escape to pause. 4. Press Escape again to unpause. |
| Observed Behavior | What the game incorrectly did. | Character remains suspended in mid-air with zero gravity; vsp stays frozen at 0 and ignores directional input. |
| Expected Behavior | What the game should have done according to design specs. | Character resumes stored vertical velocity and falls naturally back toward the ground surface. |
Let us examine how this bug report is resolved in code through a concrete example:
Regression Testing: Maintaining Ongoing Stability
The term *regression testing* refers to the practice of systematically verifying that bug fixes have not broken existing, working mechanics. It is one of the most common pitfalls in indie game development: tweaking collision math to prevent the player from catching on corner tiles can easily cause enemies to miss floor edges and fall through the world.
To run effective regression checks in your platformer, whenever you modify a core script (such as collision calculations or health tracking), you must immediately run a targeted audit across three foundational areas:
| Core System | Immediate Regression Checklist |
|---|---|
| Universal collisions | Verify player collision against vertical solid walls; check that patrolling enemies still turn around at wall markers; ensure floating pickups cannot be nudged or displaced. |
| Player state transitions | Confirm clean transitions between: idle -> run -> jump -> fall -> land. Ensure no animation states become stuck on a static frame. |
| Persistence and global data | Verify that losing a life and respawning does not reset collected coins prematurely, nor duplicate them when crossing the next level doorway. |
Practical Exercises
Put these workflows into practice to diagnose, harden, and certify the stability of your complete 2D platformer project:
Exercise 1: Full Game Loop Playthrough and QA Matrix Run
Launch your project from the initial 'rm_menu' room and complete a full playthrough from start to finish without using developer cheats or shortcuts. Follow this exact route: click 'Start', beat Level 1 while collecting at least 5 coins, pass through the exit door into Level 2, deliberately take damage from a patrolling enemy to verify hit-point loss and invulnerability flashing, cross the final goal to trigger 'rm_victory', and click the button to return to the main menu. Finally, confirm that lives, health, and score reset fully upon starting a second playthrough.
**Verification criteria:** The entire session must produce zero errors in the GameMaker output console, rooms must chain seamlessly without duplicating persistent managers, and all HUD variables must restore their default values upon returning to the main menu.
Exercise 2: Integrating the Debug Shortcut Suite
Add the Create, Step, and Draw GUI events detailed in this lesson to your 'obj_game_manager' object to equip your project with an in-game developer suite. Add an additional shortcut on the F6 key that instantly teleports the player to the coordinates of the latest active checkpoint, or back to the room's start coordinates if no checkpoint has been reached. Verify that the entire debug block is strictly guarded by 'global.debug_mode'.
**Verification criteria:** Pressing F6 during gameplay should smoothly teleport the character without errors. When you set 'global.debug_mode = false;' and recompile, none of the hotkeys (F1 through F6) or the telemetry panel should respond or render.
Exercise 3: Simulating, Logging, and Fixing an Edge Case
In a test sandbox room, construct a scenario where the player jumps into a solid ceiling while simultaneously colliding horizontally with a vertical corner wall. Observe whether the character clips into solid geometry or gets stuck suspended. If an issue occurs, document it using the bug report template (ID, Severity, Reproducibility, Steps, Expected vs. Observed) and refine your collision routine in obj_player's Step event to ensure both 'vsp = 0' and 'hsp = 0' resolve cleanly using sign-based step checks.
**Verification criteria:** Following your fix, the character must slide or drop away from the corner cleanly regardless of approach velocity, remaining strictly outside solid boundary masks at all times.
Summary
- End-to-end testing evaluates the game as an unbroken, cohesive experience from the title screen to victory or defeat, rather than validating isolated mechanics.
- There is a fundamental difference between playing for fun and testing for QA: technical testing intentionally attempts to break game logic using unexpected combinations of actions.
- Standardized checklists ensure thorough coverage across player mechanics, collisions, combat, room transitions, audio streams, and user interface elements.
- Edge cases, such as simultaneous damage and room transitions or pausing during active fades, represent the greatest risks to game stability.
- Integrating a debug suite protected by a global toggle dramatically speeds up playtesting and inspection without compromising commercial builds.
- Every detected bug should be documented systematically before being fixed, and each code revision must undergo regression testing to protect previously working systems.
Practise what you learned
Exercise 1 · 1 point
What does End-to-End Playtesting consist of, according to the lesson?
Exercise 2 · 1 point
When implementing a pause system with instance_deactivate_all(true), the object listening for the resume input must be persistent and excluded from deactivation to prevent the game loop from freezing permanently.
Exercise 3 · 1 point
Match each edge case or technical concept with the situation or risk described in the lesson:
- Tunneling
- Simultaneous death and room transition
- Pausing during transient states
- Debug hotkeys
Sign in to save your progress — Sign in