A downloadable game

[Last updated October 26th, 2025]

The Escapist:

|2D Action RPG| Godot 4 | Solo Developer | 

Github with code and scripts: https://github.com/Jea2933

  • Code: Developed in C# and GDScript (a variation of Python)
  • Music: Being composed in FL Studio
  • Art: Currently using public assets. Will eventually be independently drawn with a collaborating artist (currently recruiting)
    • The opening cutscene was fully created and animated by myself in Aseprite

Synopsis:

Play the game you want to play as you explore four identical worlds simultaneously. Your gameplay habits will influence the dialogue, story (or lack thereof), main character, music, and environment as you explore this 2D role playing game.

---------------------------------------------------------------------------------------

Gameplay Mechanics: 

Character Switching

  • Switch between 3 different characters using the 1, 2, or 3 keys respectively
  • Switching characters also switches to their respective world 
    • Character 1 resides in World 1, Character 2 is in World 2, and Character 3 is in World 3


Location Sharing:

  • All characters share the same location across their respective worlds. 
  • Example: If character 1 moves 5 feet to the left, then all other characters will have moved to this location as well. 


Character Abilities: 

  • All characters have their own button press for activating their powers
    • Player 1 (Shield) -> Q Key
    • Player 2 (Teleportation) -> Left Mouse Click
    • Player 3 (Super Speed) -> Space Bar


Ability Sharing:

  • Characters share their abilities between each other across their worlds.
  • Example: If Player 1 teleports 5 feet to the right, Player 2 will have teleported in this same spot in their own world as well. 

Auto Switch when using abilities: 

  • Using a character's abilities via their respective button press, even when the character isn't active, automatically switches to the respective character (and world) that possesses these powers, while also using the ability
  • Example: Playing as Character 1, using left mouse click will immediately teleport all characters to the mouse's location, while also switching back to Character 2 (who's power is teleportation)
  • This feature is essentially like using different Elemental Bursts/Skills in Genshin Impact, but skips the step of having to switch to the character first with number keys
  •  In this video, I am switching from the bear character to the girl by using left mouse click on an area.
    • Godot switches to the perspective of the character that owns the ability.
    • In this case, the girl has the teleportation ability, which is being used and "shared", so it automatically switches to the girl's perspective and world.
  • I then go back to the bear character by pressing the 1 key (which cannot be seen in-video). 
  • After switching back to the bear character, you'll notice that he is not in the same location that he was left in, but instead is in the position that the girl was last set to.

Why?

  • This is done to allow players to simply use the character's abilities without having to first press a number key to switch to the character first.
  • Eg. instead of pressing the 2 key to switch to the girl, then use her teleportation abilities, you can simply press anywhere with left mouse click from any world to switch to her perspective and activate her abilities (which are being shared to all characters)

Desired Effect:

  • This creates a seamless gameplay experience where players explore 3 different worlds simultaneously by effortlessly switching from player to player by simply using their abilities.
  • You can see this in practice in the video below by noticing how the ability timers in the top left of the screen activate immediately when a character is switched into.
  • Common question: "What if you just want to switch to the character without using their abilities?"
    • Then you'd press the 1, 2, or 3 keys for the character you want. Their powers are only activated by using their "shortcut" keys (Q, Mouse Click, and Space respectively)

Code and Scripts:

  • Game Manager:
    • There are two Game Managers- one is in C# (Gamemanager.cs), while the other is in GDScript (GDManager.gd)
    • These two global scripts cover most major variables in the game.
    • GDManager.gd:
      • Character 1 Shield Script: Deep Dive 
      • The shield is created in my GameManager because it's intended to persist across all three worlds and characters (if Character 1 uses it, Characters 2 and 3 are also protected by it, as it is not bound only to the character's world. 
      • By instantiating the shield (a simple Sprite2D) within GDManager, the shield can be used regardless of the current world being played.

--------------------------------------------------------------------------------

func use_shield(event):
if event.is_action_pressed("ui_q"):
GameManager.current_world_index = 0
GameManager.current_player_index = 0
if GameManager.player1dead:
return
if shield_timer_stopped: 
return
if synced == false:
if GameManager.current_player_index == 0:
if !limited_shield: #if the shield lasts indefinitely
if !GameManager.current_player_index == 0: #if the game is not set to player 1
pass #if the game isn't on player 1 when q is pressed, do nothing
shield_active = !shield_active
if !shield_active:
AudioManager.playSound("res://Audio/shield_gone.ogg")
#shield2.visible = shield_active
print("Player 1's shield is ", "on" if shield_active else "off")
else:
shield_active = !shield_active
shield.visible = shield_active
if shield_active:
AudioManager.playSound("res://Audio/shield_ring.mp3")
shield_timer.start()
print("Player 1's shield is on")
#print("Player 1's shield is ", "on" if shield_active else "off")
else:
AudioManager.playSound("res://Audio/shield_gone.ogg")
print("Player 1's shield is deactivated (from button press)")
shield_timer.stop()
if synced == true:
shield_active = !shield_active
shield.visible = shield_active
if shield_active == true: #if the shield turns on when Q is pressed
shield.get_node("StaticBody2D/CollisionShape2D").disabled = false
shield_timer.start()
if GameManager.current_player_index != 0:
GameManager.current_player_index = 0
GameManager.current_world_index = 0
if shield_active == false: #if the shield becomes inactive on Q press
shield.get_node("StaticBody2D/CollisionShape2D").disabled = true
shield_timer.stop()
shield_timer_stopped = true
shield_timer_short.start()

--------------------------------------------------------------------------------



GDScript: https://gist.github.com/Jea2933/825f8ecb94d66e1ea93ed60939a4beaf

C#: https://gist.github.com/Jea2933/fd6d0f1ffd3a800196e1e90355dde13c

Programming Player Movement (State Machines & Scene Inheritance)

For player movement, I created a base player script for code that all players will use (titled "player.gd"). I then gave each player their own inherited player script that extends from the original player script (titled "player1", "player2", and "player3" respectively). 

As of right now, each inherited player script only manages their respective state machines for basic player movement. However, the player's scripts will inevitably grow as I continue to implement each character's own abilities that are exclusive to them. 

---------------------------------------------------------------------------------------------

Programming & Development

The game is being made in Godot 4. Most of the scripts so far have been developed in Godot's native language, GDScript. However, recently I have decided to begin incorporating C# into my development process, as this programming language is more universal to other game development workstations such as Unity, and is used almost everywhere in the game development industry. I have began to "adapt" my Level script (originally written in GDScript) into C#, and will continue to use C# over GDScript whenever possible. However, the game as a whole will most likely use scripts from both languages. 

Here is the C# adaptation of my Level script that is still being written [Outdated as of 11/12/24, will update soon!]

https://gist.github.com/Jea2933/8ebd0adca2e1e90d9da105868f965dec

For reference, here is the original Level script, originally written in GDScript: 

https://gist.github.com/Jea2933/1924600d5c4db092f4759aab975ac880


I have two global scripts for managing Player and World management, titled PlayerManager & GlobalManager respectively. These scripts are written in C# and keep track of which Character and World is set (however, for now, Character 1 will always be in World 1, Character 2 will always be in World 2, and so on). 

---------------------------------------------------------------------------------------------

All Scripts [Currently outdated, will update them soon!]

Game Manager Script:  https://gist.github.com/Jea2933/5c967d25942f311149db125f92fa25fb

Level Script:  

https://gist.github.com/Jea2933/1924600d5c4db092f4759aab975ac880

Main Player Script:

https://gist.github.com/Jea2933/cd7ac78ba11e8f2c5d90eaac862637b4

(The following scripts are almost identical, but are put here for reference)

Player1 Script: 

https://gist.github.com/Jea2933/2e6448acd3f724e3cd1f4f58005af0e4

Player2 Script: 

https://gist.github.com/Jea2933/6705163481ea27c13b07761216dca37d

Player3 Script: 

https://gist.github.com/Jea2933/4501bf79d98c25e8f7b65931df6a1852

---------------------------------------------------------------------------------------------

Updated 14 days ago
StatusIn development
AuthorJacob36
GenreRole Playing

Development log