sergeantIndie
Member
GM Version: Game Maker: Studio
Target Platform: PC centric
Download: N/A (considering providing individual links for each video if people are interested)
Links: Complete Tutorial Playlist
Summary:
Turn-Based Strategy is a complex genre, this is the first couple bits of my seventeen video series covering the genre. In these first two videos we create our game grid, let each node know who its neighbors are, and then get a basic cursor up and running.
Tutorial:
The bedrock of the Turn-Based Strategy genre is a big game grid that the action takes place one. This consists of a series of "nodes" which the characters stand on, pathfind with, move between, and target.
In order to get all of this up and running, we need a series of these node objects created in a big grid and we need them to know all of the other nodes that neighbor them!
Start by creating a basic sprite. Just a 32x32 white square with a black border. This is our "Node." I call mine sNode, but anything is fine so long as you're consistent.
Now an object for our nodes. I call mine oNode, but whatever makes you happy.
In here, we need only a simple, single line of code:
I have been informed that directly copy-pasting code may result in an error by placing an invisible character at the end of each line of code. If you try to copy-paste and receive this error, try going to the end of each line and hitting backspace.
oNode Create Event
neighbors = ds_list_create();
This neighbors list will hold on to the instance ids of every adjacent node. This will be the cornerstone of our pathfinding system later on down the road, so it's pretty important. For now, this is the only line of code our Node needs.
Before we go any further, let's create a constant. We're going to be tiling the entire game room with these Nodes so we want one every X pixels, where X is the width and height of our node object.
resources -> define macros
GRID_SIZE = 32
For now, this is all our node object needs. So let's create another object, our game controller which will create our grid of node objects and eventually handle our turn order. I call mine oGame.
First thing we need to do is create an array. In here, we will store the instance IDs of every node in our game grid for ease of reference by other objects.
oGame Create Event
globalvar map;
mapWidth = room_width/GRID_SIZE;
mapHeight = room_height/GRID_SIZE;
//create node!
for(xx = 0; xx < mapWidth; xx += 1){
Alright, map is an array. It will hold on to the instance IDs of every node in our room. We can use that later to reference every node by its grid coordinate as we see it on screen.
mapWidth and mapHeight are how wide and tall our game room is in nodes.
That couple of For loops will tile the entire room in nodes and while it does so, it will store the instance ID of each node in the relevant portion of the map array.
Pretty easy so far. We need more here however.
Earlier we did that neighbors list in the oNode object. Every node needs its neighbors list populated with the instance IDs of every adjacent node! We can accomplish this with another couple for loops.
Now, in the first video I cut off after the first 4 cardinal directions (up, down, left, right) and do the diagonals at the start of the second video. For ease, I'm just going to do all of the neighbors here all at once.
We'll do this in the oGame Create Event right below the other couple For loops.
oGame Create Event
//populate neighbor lists!
for(xx = 0; xx < mapWidth; xx += 1){
}
Great! Now we should have our nodes created, and our neighbors list populated. Our nodes are ready.
But there's really no way to ensure that all of this was done properly! So lets add a little debug feature. We'll add a draw event to our nodes and they'll draw how many neighbors they're tracking on their bellies so we can double-check our work!
oNode Draw Event
draw_self();
draw_text(x + 4, y + 4, string(ds_list_size(neighbors)));
Alright, now run your game and you should be looking at something like this:
Nodes in the center should be tracking 8 neighbors.
Nodes along each border should be tracking 5 neighbors.
Nodes in the corners will be tracking 3 neighbors.
If you've got all that right! Great, our nodes are ready to do cool things like grid-based pathfinding in the future!
But there's a few more steps between here and there. We need a cursor, we need some characters, and some terrain before we get started on pathfinding!
Here's the second video of the series where we implement our basic cursor object:
and finally:
A link to my entire Turn-Based Strategy 101 series
Currently 17 videos and over 8 hours of instruction covering a ground-up framework for the Turn-Based Strategy genre. It should give you all the tools you need to make your own TBS games!
If anyone has any questions or comments, I'm more than happy to help.
Target Platform: PC centric
Download: N/A (considering providing individual links for each video if people are interested)
Links: Complete Tutorial Playlist
Summary:
Turn-Based Strategy is a complex genre, this is the first couple bits of my seventeen video series covering the genre. In these first two videos we create our game grid, let each node know who its neighbors are, and then get a basic cursor up and running.
Tutorial:
The bedrock of the Turn-Based Strategy genre is a big game grid that the action takes place one. This consists of a series of "nodes" which the characters stand on, pathfind with, move between, and target.
In order to get all of this up and running, we need a series of these node objects created in a big grid and we need them to know all of the other nodes that neighbor them!
Start by creating a basic sprite. Just a 32x32 white square with a black border. This is our "Node." I call mine sNode, but anything is fine so long as you're consistent.
Now an object for our nodes. I call mine oNode, but whatever makes you happy.
In here, we need only a simple, single line of code:
I have been informed that directly copy-pasting code may result in an error by placing an invisible character at the end of each line of code. If you try to copy-paste and receive this error, try going to the end of each line and hitting backspace.
oNode Create Event
neighbors = ds_list_create();
This neighbors list will hold on to the instance ids of every adjacent node. This will be the cornerstone of our pathfinding system later on down the road, so it's pretty important. For now, this is the only line of code our Node needs.
Before we go any further, let's create a constant. We're going to be tiling the entire game room with these Nodes so we want one every X pixels, where X is the width and height of our node object.
resources -> define macros
GRID_SIZE = 32
For now, this is all our node object needs. So let's create another object, our game controller which will create our grid of node objects and eventually handle our turn order. I call mine oGame.
First thing we need to do is create an array. In here, we will store the instance IDs of every node in our game grid for ease of reference by other objects.
oGame Create Event
globalvar map;
mapWidth = room_width/GRID_SIZE;
mapHeight = room_height/GRID_SIZE;
//create node!
for(xx = 0; xx < mapWidth; xx += 1){
for(yy = 0; yy < mapHeight; yy += 1){
}map[xx, yy] = instance_create(xx * GRID_SIZE, yy * GRID_SIZE, oNode);
}Alright, map is an array. It will hold on to the instance IDs of every node in our room. We can use that later to reference every node by its grid coordinate as we see it on screen.
mapWidth and mapHeight are how wide and tall our game room is in nodes.
That couple of For loops will tile the entire room in nodes and while it does so, it will store the instance ID of each node in the relevant portion of the map array.
Pretty easy so far. We need more here however.
Earlier we did that neighbors list in the oNode object. Every node needs its neighbors list populated with the instance IDs of every adjacent node! We can accomplish this with another couple for loops.
Now, in the first video I cut off after the first 4 cardinal directions (up, down, left, right) and do the diagonals at the start of the second video. For ease, I'm just going to do all of the neighbors here all at once.
We'll do this in the oGame Create Event right below the other couple For loops.
oGame Create Event
//populate neighbor lists!
for(xx = 0; xx < mapWidth; xx += 1){
for(yy = 0; yy < mapHeight; yy += 1){
node = map[xx, yy];
//add left neighbor
if(xx > 0){
if(xx > 0){
ds_list_add(node.neighbors, map[xx - 1, yy]);
}//add right neighbor
if(xx < mapWidth - 1){
if(xx < mapWidth - 1){
ds_list_add(node.neighbors, map[xx + 1, yy]);
}//add top neighbor
if(yy > 0){
if(yy > 0){
ds_list_add(node.neighbors, map[xx, yy - 1]);
}//add bottom neighbor
if(yy < mapHeight - 1){
if(yy < mapHeight - 1){
ds_list_add(node.neighbors, map[xx, yy + 1]);
}//top left neighbor
if(xx > 0 && yy > 0){
if(xx > 0 && yy > 0){
ds_list_add(node.neighbors, map[xx - 1, yy - 1]);
}//top right neighbor
if(xx < mapWidth - 1 && yy > 0){
if(xx < mapWidth - 1 && yy > 0){
ds_list_add(node.neighbors, map[xx + 1, yy - 1]);
}//bottom left neighbor
if(xx > 0 && yy < mapHeight - 1){
if(xx > 0 && yy < mapHeight - 1){
ds_list_add(node.neighbors, map[xx - 1, yy +1]);
}//bottom right neighbor
if(xx < mapWidth - 1 && yy < mapHeight - 1){
if(xx < mapWidth - 1 && yy < mapHeight - 1){
ds_list_add(node.neighbors, map[xx + 1, yy + 1]);
}}
}
Great! Now we should have our nodes created, and our neighbors list populated. Our nodes are ready.
But there's really no way to ensure that all of this was done properly! So lets add a little debug feature. We'll add a draw event to our nodes and they'll draw how many neighbors they're tracking on their bellies so we can double-check our work!
oNode Draw Event
draw_self();
draw_text(x + 4, y + 4, string(ds_list_size(neighbors)));
Alright, now run your game and you should be looking at something like this:
Nodes in the center should be tracking 8 neighbors.
Nodes along each border should be tracking 5 neighbors.
Nodes in the corners will be tracking 3 neighbors.
If you've got all that right! Great, our nodes are ready to do cool things like grid-based pathfinding in the future!
But there's a few more steps between here and there. We need a cursor, we need some characters, and some terrain before we get started on pathfinding!
Here's the second video of the series where we implement our basic cursor object:
and finally:
A link to my entire Turn-Based Strategy 101 series
Currently 17 videos and over 8 hours of instruction covering a ground-up framework for the Turn-Based Strategy genre. It should give you all the tools you need to make your own TBS games!
If anyone has any questions or comments, I'm more than happy to help.
Last edited: