So I am currently working on a 2D RPG at the moment, trying to self teach while looking for as much assistance from others as I can.
The purpose for this post is Character Class Selection and possible sprite spawning and specific player based on the specified selection.
I currently have a basic menu screen, a character selection screen and a basic world scene which will be used as the first level/area for the game. My player scene is a completely separate from the world scene as I can just inherent the player scene into multiple world scenes.
Is there a way to make a class selection scene that will be used when the player starts a new game, that I can somehow code the player selected character class to set specific player stats in the game, instead of just forcing the player to only play as one character class?
For example; the class selection scene would have a selection for a Warrior, Archer, Mage, etc. If the default stats is something like:
var health = 0
var melee_dmg = 0
var ranged_dmg = 0
var splash_dmg = 0
var range = 0
var defence = 0
var speed = 0
Could I potentially have code similar to this to set the values based on what class is selected?
func _CharSelect()
if Warrior:
var health = 5
var melee_dmg = 5
var ranged_dmg = 0
var splash_dmg = 0
var range = 2
var defence = 5
var speed = 2
if Archer:
var health = 3
var melee_dmg = 0
var ranged_dmg = 5
var splash_dmg = 0
var range = 10
var defence = 2
var speed = 5
if Mage:
var health = 2
var melee_dmg = 0
var ranged_dmg = 0
var splash_dmg = 5
var range = 5
var defence = 2
var speed = 5
Any tips, tricks or ideas would be appreciated to make this process easier or to make things work.
You have scenes, and you can instance them, and add them into other scenes.
Given a resource path (a String
that starts with "res://"
, see Data Paths), you can use either load
, preload
, ResourceLoader.load
or ResourceLoader.load_interactive
(see Background Loading and Instancing scenes) to get a PackedScene
. Once you have a PackedScene
you can call on it instance
on it, which will give you a reference to the root node of the instanced scene. And then you just add it to the current scene tree with add_child
.
To reiterate, you start with a resource path, which is a String
. Then you load it, which give you a PackedScene
. And you instance it, which gives you a Node
, and then you can add it to the scene tree with add_child
.
And, of course, if you can add it with add_child
, you can also remove it with remove_child
. On that note, if you remove the Node
that does not free
the node, nor disconnect its signals. queue_free
will do all that. You may also be interested in Node.is_inside_tree
, Object.is_queued_for_deletion
and is_instance_valid
, but I digress.
This means that you can remove the Node
and then add it somewhere else.
And something else you will need to know about is autoloads (singleton).
You can set your autoloads from the project settings -> AutoLoad tab. An autoload can be either a script or an scene. The autoload object will be available from a global variable with the game you set. And it will remain when the scene changes. Thus if you need some information to be available always, even if the scene changes you can put it there…
Are you thinking what I'm thinking? Store what character the player picked in an autoload.
My player scene is a completely separate from the world scene
Good.
as I can just inherent the player scene into multiple world scenes.
I'm not sure what you mean. Anyway, do instance like was describing above.
Is there a way to make a character selection scene
You make a character selection scene, correct.
that will be used when the player starts a new game
So, when the player select new game, it will either take them to the character selection scene (that can be an actual change of scene, or it could be that you instance it within the scene that has the menu).
that I can somehow code the player selected character to spawn in the game
One way to do this is to have a scene for each character, and you are going to remember which one was chosen. You absolutely can load the character scenes to show them in the character selection scene, and just keep the selected one around in an autoload. Or you can just keep the resource path (which, again, is a String
) around. Or it can be stats and textures, or however you prefer to slice it.
You would probably have a routine in the autoload that takes care of changing scene and moving the player character from one scene to the other (you could have placeholders to know where to place the player character, for example Position2D
). And you would call that from wherever you need to change the scene (instead of calling change_scene
/change_scene_to
).
And while you are at it, store any other information you need to keep around (e.g. health, live, ammo, inventory) there, and… Guess where you can put the code for to save and load player progress would be too… That's right, an autoload.
Addendum: You can create a custom resource type.
Create a script and have it extend from resource. Then add all the properties (export var
) you need to define your character there.
Then you can create resources (open the contextual menu of the FileSystem panel with secondary click and select "New Resource…"). Godot will ask you what is the type of the resource, you pick the one you created. Then you can edit its properties in the Inspector panel.
Being a resource, you can load it with load
, preload
, ResourceLoader.load
or ResourceLoader.load_interactive
. Just like the scene. That is because a scene is a type of resource. On that note, you can also save resources with ResourceSaver.save
(note: if you want to save scene see PackedScene.pack
and be aware of owner
).
By the way, using resources like this is a good idea to create - for example - the items for an RPG. You may need hundreds, perhaps thousands, of different kinds of items. It is not worth, nor a good design to create a class for each one if they differ only in data.
You can then have a property (export var
) that you set to the resource you want… Caveat: you won't be able to export a variable of your custom resource type, just of Resource
. Use a setter to filter it (with setget
). See also the proposal Add first-class custom resource support
(you can find there some workarounds).
A simple inventory could be made with an array that has resources.