MrDave
Member
GM Version: GMS 1.4 and GMS 2
Target Platform: ALL
Download:
GMS2: http://www.davetech.co.uk/files/complexskilltrees.yyz
GMS1.4: http://www.davetech.co.uk/files/complexskilltrees.gmz (by @Dev_Smithy)
Links: Interactive example and more: http://www.davetech.co.uk/gamemakercomplexskilltrees
Summary:
I wrote a little flexible system to have skill trees where you can have many skills branch off one skill and also re-join together (one to many and many to one relationships). I wanted to do it all with array structures because it was easy edit and maintain huge lists (much larger than the ones I have here)
It could be used for other things like overworld maps, dialogue trees, character progression, level selection etc.
Tutorial:
First lets understand the arrays:
Those three arrays build this skill tree:
Notice how skill 0 and 1 don’t say they are connect to skill 2, They only point towards the skill start object. This is because skill 2 says it is connected to both 0 and 1. When connecting skills you only need to connect them in one direction, you DON’T need both skill 1 to point skill 2 AND skill 2 to point back to skill 1.
The Code:
obj_skillspawner – create:
This is the code that turns your array into individual skill objects, also pre caches where to draw the lines into an array.
obj_skill – create:
Initialise everything obj_skill will use but we will overwrite all of this.
obj_skill – Draw
Draw the lines
obj_skill – Draw End:
Draw the skills
obj_skill – Left Click Released:
The player wants to buy this skill so check to see if they can buy this one and then check all the skills that link to this one to see if they should now be available.
Target Platform: ALL
Download:
GMS2: http://www.davetech.co.uk/files/complexskilltrees.yyz
GMS1.4: http://www.davetech.co.uk/files/complexskilltrees.gmz (by @Dev_Smithy)
Links: Interactive example and more: http://www.davetech.co.uk/gamemakercomplexskilltrees
Summary:
I wrote a little flexible system to have skill trees where you can have many skills branch off one skill and also re-join together (one to many and many to one relationships). I wanted to do it all with array structures because it was easy edit and maintain huge lists (much larger than the ones I have here)
It could be used for other things like overworld maps, dialogue trees, character progression, level selection etc.
Tutorial:
First lets understand the arrays:
Code:
skillname[0] = "Skill0"; // the name of the skill (isnt used)
skillimage[0] = 0; // this is the image that should be used
skillneeds[0,0] = -1; // What skills the player needs to unlock before they can get this one (-1 is always available)
skillx[0] = 230; // x position of this skill on the screen
skilly[0] = 230; // y position of this skill on the screen
skillname[1] = "Skill1";
skillimage[1] = 0;
skillneeds[1,0] = -1; // -1 always available
skillx[1] = 370;
skilly[1] = 230;
skillname[2] = "Skill2";
skillimage[2] = 0;
skillneeds[2,0] = 0; // Link to both skill 0 and skill 1
skillneeds[2,1] = 1;
skillx[2] = 300;
skilly[2] = 160
Notice how skill 0 and 1 don’t say they are connect to skill 2, They only point towards the skill start object. This is because skill 2 says it is connected to both 0 and 1. When connecting skills you only need to connect them in one direction, you DON’T need both skill 1 to point skill 2 AND skill 2 to point back to skill 1.
The Code:
obj_skillspawner – create:
This is the code that turns your array into individual skill objects, also pre caches where to draw the lines into an array.
Code:
for (i=0; i<array_length_1d(skillname); i++) // loop around for each skill
{
var newskill = instance_create_layer(skillx[i], skilly[i],"Instances",obj_skill); // Create an object that will be this skill
newskill.image_index = skillimage[i];
newskill.skillname = skillname[i];
newskill.skillid = i;
show_debug_message("We have made skill " +string(skillname[i]))
// ASSERT – at this point the object skill has been made
with(newskill) { // we now want to pre record all the lines this skill is connected to so we dont have to work it out every time
for (j=0; j<array_length_2d(other.skillneeds,other.i); j+=1) // loop around all the skills I connect to
{
skillneeds[j] = other.skillneeds[other.i,j]
show_debug_message("Skill "+ string(newskill.skillname) + " needs " + string(skillneeds[j]))
if (skillneeds[j] == -1) { // This skill is always available so draw a line to the central object
status = 1;
linetox[0] = obj_skillspawner.x;
linetoy[0] = obj_skillspawner.y;
needcount = 1;
} else { // on the new skill record where its lines should be drawn so we don’t need to look it up every frame
linetox[j] = other.skillx[skillneeds[j]];
linetoy[j] = other.skilly[skillneeds[j]];
needcount++
};
}
}
};
Initialise everything obj_skill will use but we will overwrite all of this.
Code:
image_speed = 0; //Just to stop the skill trying to animate
// Initialise some things we will overwrite in obj_skillspawner
skillname = 0; // We don’t use this but this could be drawn next to or on mouse over to show the player the name of the skill
skillid = 0; // this is the unique id of this skill
skillneeds = -1; // this will be an array holding the unique id of any skill requiered before getting this one
needcount = 0; // this will basically hold array_length_1d(skillneeds) so we dont have to do it every frame
linetox[0] = 0; // this will be an array of where to draw every line coming out of this skill
linetoy[0] = 0;
status = 0; // 0 = unavailable, 1 = available, purchased = 2
Draw the lines
Code:
if (status == 0) { // set the colour of the line (black means they can unlock it, gray is still locked)
draw_set_colour(c_gray)
} else {
draw_set_colour(c_black) // I want all my lines black
}
for (d=0; d<needcount; d++) // loop around all of the lines we have already cached and draw them
{
draw_line_width(x,y,linetox[d],linetoy[d],2)
};
Draw the skills
Code:
switch (status)
{
case 0: // Unavailable
draw_sprite(spr_skills,10,x,y) // image_index 10 is a gray image of the skill so draw this if they cant buy the skill
break;
case 1: // Available
draw_sprite(spr_skills,image_index,x,y) // they can buy the skill so draw it normally
break;
case 2:
draw_sprite(spr_skills,image_index,x,y) // they have bought the skill so draw it normally but ontop draw a box that shows they own it
draw_sprite(spr_available,0,x,y)
break;
}
The player wants to buy this skill so check to see if they can buy this one and then check all the skills that link to this one to see if they should now be available.
Code:
if (status == 1) { // You can only buy this skill if it is available
// add any code here for buying the skill, i.e. you might have to deduct money or skill points
status = 2 // set this skill as being bought
with(obj_skill) { // go through all skills and see if they should now be set to available
// Set skills I link to as available
for (i=0; i<needcount; i++) {
if (skillneeds[i] == other.skillid) {
if (status == 0) { // dont overwrite if they have already bought upgrade
status = 1 // This skill is next to me on the tree and is unavailable so make it available.
}
}
};
// Set skills that link to me as available
for (i=0; i<other.needcount; i++) { // go backwards down the tree
if (other.skillneeds[i] == skillid) {
if (status == 0) { // dont overwrite if they have already bought upgrade
status = 1 // This skill is next to me on the tree and is unavailable so make it available.
}
}
}
}
// add any code here to save the changes
}
Last edited: