Need help with making a live character swap system

poetax

Member
I'm still somewhat new to GML and could use some help with building a primary system I'd like to have in my game. I would like to have the player be able to quickly swap between 4 playable characters in an action RPG game. Each playable character has it's own moveset, sprites, and stats, such as height (for going under things) and will eventually have their own stamina bar that will refill while another character is being used.

I currently have all my playable characters as separate objects tied to a parent so they can inherit common properties, and my code currently allows me to swap characters by using a player_control object to facilitate swapping. It destroys the old player object instance, and creates a new player object instance where the old one was standing. I was attempting to make the game able to cycle through more playable characters when I ran into an issue with my idea. Creating and destroying instances means that it could be hard to save things like health/stamina, and I also wanted to start out with a small party of 2 playable characters and expand it to 3, then 4 as the game goes on. I would need to have some way to change variables for what characters are currently in the party and currently playable (they may faint), and have them able to be added or subtracted to my character swap code. Destroying/creating instances wipes those variable states clean, so it's hard to keep track of data. I've tried making a data structure storing which characters were playable, but it needs to have a current instance of each player object running, which obviously I do not have when I am creating and destroying them.

Should I go in a different direction, such as keeping all the players in one object?

Here is my current player change code

GML:
if (input_c){
    instance_destroy(current_player); //destroy the old current player
    instance_create_layer(x, y, "objects", obj_rekkie);  //create the new current player
    current_player = obj_rekkie;
}
code I was trying to create when I realized it works on instances of objects, not the objects themselves. variable "playable" is a true/false declared in the create event on each object

GML:
var yy = 0; //local var for looping through the data structure
var pgrid = ds_playable; //local variable to be used with the "with" statement
with(obj_player_template){ //with each of the children of player_template, perform the code: (problem, this only runs currant instances in the game)
    pgrid[# 0,yy] = id; //loop through instances and add their ID's
    pgrid[# 1,yy] = playable;    //loop through and state if they are playable or not
    yy++; //incriment y and do it again till there is nothing left
}
 
Last edited:

TheouAegis

Member
Don't destroy anything. Just create your 4 characters and let them be. You can either deactivate the ones not in control and increase their stamina using dot notation (you can't use with on deactivated instances, as you must reference them directly via their id), or you can simply use a variable specifying which object is controlled and have the objects ignore all code if they're not the one being controlled. If you want them hidden, just change their visibility to 0 (or reduce their alpha so the player can see where they are without cluttering up too much screen space).
 

Nidoking

Member
It's often a good pattern to separate the graphical, data, and control elements for an entity. In this case, you might keep the control and graphical elements together, and that will be the part you destroy or deactivate as necessary. The data element would be separate and persistent. Also, beware deactivating instances if you're changing rooms.
 

poetax

Member
Don't destroy anything. Just create your 4 characters and let them be. You can either deactivate the ones not in control and increase their stamina using dot notation (you can't use with on deactivated instances, as you must reference them directly via their id), or you can simply use a variable specifying which object is controlled and have the objects ignore all code if they're not the one being controlled. If you want them hidden, just change their visibility to 0 (or reduce their alpha so the player can see where they are without cluttering up too much screen space).
I guess I should have mentioned that only the playable character will be visible on screen, kinda like a tag in/tag out. Attached is what the game currently looks like when pressing C. I'll look into deactivating instances, cause that sounds like something I could do. https://va.media.tumblr.com/tumblr_r11f05RUSN1rsyatd_720.mp4
 

poetax

Member
It's often a good pattern to separate the graphical, data, and control elements for an entity. In this case, you might keep the control and graphical elements together, and that will be the part you destroy or deactivate as necessary. The data element would be separate and persistent. Also, beware deactivating instances if you're changing rooms.
Yeah that seems like a good pattern, I'll have to keep that in mind. I'm using a separate object for control to facilitate switching between the playable characters, and was probably going to store data in it that object that could be loaded when characters are switched in and out. I haven't used deactivate commands at all, so I'll look into it. I'm a little worried having the character instances ghosting about in the room when not in use, but I'm not sure what else to do besides load them all into one instance.
 

TheouAegis

Member
If you are only allowing one character at a time like in Castlevania 3 or Bloodstained Curse Of The Moon, you could just keep all PC code in functions and just have one player object changing sprites and running only the functions associated with the active PC.

If you want them to just idle around like in Lost Vikings, 3 PCs ignoring the player will have no real impact on the program. Even if you make them snake around behind the active PC, it would still be a negligible performance cost. It all just depends on what style you are ultimately going for.
 
Top