This is actually my first real tutorial. As you might know im part of the team that developes Starcaft Universe and im responsible for most of the trigger work. Since SCU is a real big RPG and alot of people try to build smaller RPG projects i decided to share some of our knowledge with the community, however some things will for sure be kept secret for now.
Today i wanted to start with a simple tutorial about a custom minimap that works similar to the one in World of Warcraft or other first person RPGs.
Difficulty: Medium (You need some basic trigger knowledge for this tutorial since i dont want to explain each single detail) **
The result will look like this:
1. Creating the library
At first we need to create a new library. Make sure you can see the libraries in your editor (check the "view" tab at the top for options):
Create a new library called "minimap".
For better overview, i like to create several folders within the library containing the variables, actions, functions and triggers.
When your done, it should look similar to this:
2. Creating the variables
Now we need to set up the variables needed for the minimap.
I recommend to use records to manage your variables in a better way. Create a new record called "minimap" and a new variable with type "record" outside the record, also called minimap, and set its record to "minimap". It should look like this:
Now create the following variables in the record:
3. Creating the dialogs
Once we have finally set up all needed variables we can start setting up the dialogs for the minimap. The minimap consists of 3 dialogs. The first one stores the label for the region name, the second one is the main panel which basically is just the border for the minimap image, and the third dialog actually stores the minimap image, causing it to be cut off at the edges when its moved. (Since dialog items of a dialog can never fill more space than the dialog itself)
Since we want it to be a library, we need to make sure that its flexible and easy to use. Because of that we will set up the dialogs in a custom action and give the user a few parameters to customize the minimap for his needs.
The user will be able to enter the anchor, the offset and the size of the minimap, and also has to enter his values for map size and map image size (since each map has a different size and so does the map image, for sure).
TLDR: The minimap should be usable in EACH map with a few simple clicks and without recoding stuff later on.
Create a new action and set it up as following:
I think i dont need to explain too much right here, actually we are just creating a few dialogs and attaching them to each other, it shoulnd be a big deal if you have basic trigger knowledge. The trick right here is basically to use a second dialog within the main panel that is invisible and stores the map image to make it cut off at the edges.
4. Creating a few simple actions
Ok, now we have our minimap dialogs set up. However we need 3 more very simple actions to make it usable.
First off, we need to be able to show/hide the minimap for specfic players. We could just use the default action blizzard gives us "Show/Hide Dialog", but since the minimap consits of more than one dialog it makes sense to write a custom action for it since it would be pain in the ass to have 3 lines of code everytime you want to show/hide the minimap and it could also cause bugs (for example when forgetting to show the hidden 3rd dialog).
So, we just create a new action that should look like this:
It just shows/hides all the panels of the minimap for a specific player. The local variable "pg" makes the action a little bit faster since it doesnt need to convert a player to a player group 3 times (what would be the case if we would do it in the show/hide dialog action itself).
Secondly, we need an action that sets the region name label, since we want the minimap to show the name of the region the player is currently in. For sure we could just directly modify the text of the label later, but keep in mind that its a library and should be easy to use. Also we wanna make everything except the custom actions internal to make sure the library doesnt add dozents of variables and triggers to the scroll lists of the gui (more about that later).
Set it up likes this:
Finally, we need one more action to set the minimap hero, since the minimap should follow a specific unit later:
5. Making the minimap work
OK, so we are nearly done now, except one thing: The minimap doesnt work.
The minimap should do the following things:
1) Make the player arrow match the hero facing
2) Move the minimap image to the right position to match up the heros position ingame
To achieve this goal we create a new trigger, thats initially NOT turned on (its turned on at the end of the "init minimap" action to make sure its not active when not using the minimap at all, to save performance).
Set the trigger up as follows:
First off, we need to use a periodic event for sure. If you want to save performance you might decrease the amount of executions per second. If you use
"Timer - Every 0.0 seconds of Real Time" it will execute 16 times a second (thats the current limit of sc2), however i dont think the trigger costs to much performance at all so its alright to use the minimum interval, since it makes it look smoother.
What it basically does now is it loops through all players (make sure to use ACTIVE PLAYERS to save performance, since it will only pick the players that are currently playing) and updates the minimap for the picked player.
First it changes the rotation of the player arrow dialog item image of the minimap. The exact formula is different for each dialog item since each arrow might have a different default rotation (in this example we need to add 135 degrees at the end to make it fit). The first part, "360 - hero facing", needs to be used for each dialog item to match the hero facing, its not enough to simply set it to the hero facing since it rotates in the opposite direction.
The more complex part is the moving of the map image.
To understand how it works i have to point out some things first:
1. When the hero is standing at the buttom left edge of the map with size 128x128, his position (x,y) will be 0,0. At the top right its 128,128. Center would be 64,64.
2. The map image dialog item is anchored at the center of the hidden map image panel dialog.
So, that basically means if the hero is standing at the bottom left edge of the map the map image dialog item needs to be moved so that the bottom left edge of it is located at the center of the dialog.
That means that each time we move the map image dialog item we have to add a fixed amount to the offset to make it fit. This value depends on the size of the map image file. Since its anchored at the center we always have to add <map image size> devided by 2 to the offset to move the bottom left corner to the center. However, if we want to move a dialog item to the right side we have to INCREASE the x offset, if we want to move it up we have to DECREASE the y offset, what actually means we must differ between x and y offset.
However we have to keep in mind that the hero position on the map for sure moves the map image. Lets say the hero moves from point 0,0 to 10,10. If the map image size would be 1:1 the size of the map, we could just add 10 to the y offset and substract 10 from the x offset. But since the map image can (or better: WILL) have a different size we need to calculate the size factor first, by deviding the map image size by the map size and THEN multiplying this value with the current hero offset.
Sounds complex but actually its kinda simple.
Example: The map is 64x64 and the map image is 128x128. If the hero moves from 0,0 to 10,10 we have to change the offset of the map image by 20 since its twice the size of the map. So you can say: hero offset * (map image size / map size).
This is actually the reason why we had to save all the values from the "init minimap" action into variables within the record, because right now we need to access them since each map and map image can have different size.
You can see the exact formulas in the trigger above.
All calculations are done as reals to avoid losing accuracy.
6. A few words on libraries
If you create libraries like this one, make sure to make all functions, trigger, actions and variables internal, except for the ones that should be accessable by the user later. For the minimap, the user should just be able to use the 4 custom actions but not have access to the minimap record variables or the update trigger. This makes 1) the library more secure and 2) removes all the unneeded stuff from the gui function lists (for example when the user types "minimap" in the search window of his trigger editor he WONT find the minimap record, because its internal and can just be used by the library itself).
7. How to use the minimap library in my map / How to set it up
If you want to use the library in your map, you just have to follow this 6 steps:
1. Extract the map image. Open up the terrain editor and click on "Data" -> "Export map image" at the top. I recommend to make the map image at least 4 times bigger than the map itself cause otherwise it will look like very far away in the minimap, moving slow and with less detail.
2. Import the map image using the import manager.
3. Import the minimap library.
4. Set up the minimap by using the "init minimap" action provided by the library, make sure to enter the correct values for map size and map image size since otherwise the minimap wont match the heros position in the game.
5. Set up the minimap hero for each player using "set minimap hero" action and show the minimap for each player with the "show/hide minimap action" (both provided by the library).
6. Use the "set minimap region" action to set the region label text of the minimap.
7. Enjoy!
8. Final Words
Please note that this is just a very basic example of a minimap. You could for example add a world map showing all players and work with dialog styles to make it look much cooler. I just wanted to give a basic idea how it works and i hope it has helped some people to understand the mechanics of a custom RPG minimap.
Wow, awesome tutorial. It opened my eyes not only for a great way of implementing a minimap, but also for the possibilities using libraries. Reminds me of "Classes" in Python!
Wasn't there a way to move and resize the actual SC2 minimap using layout files? You could just move it to your desired position, create an arrow ping and attach it to the players unit.
I admit I didn't give this much though, maybe there are some limitations on using the built-in minimap that justify remaking it completely with triggers.
Actually the build in minimap works totally different than this RPG minimap.
The build in minimap always shows the entire map and all units on it, while the RPG minimap basically just shows a small area around the hero and moves with the hero. Also it shows more details like doodads and you can customize it in any way you like.
...The build in minimap always shows the entire map and all units on it...
To my knowledge this simply isn't true. You can make the minimap only view a certain region with a single trigger I believe. You may well be doing other things but I think you'd be better off working with the built in minimap personally. Unless you are doing something clever like rotation?
Never heard of that actually and couldnt find anything in the triggers.
Also you will always miss the details of the custom map image (the default minimap is very low detail).
Additionally you can for sure make the minimap rotate instead of the arrow if you like to, like i said you have all freedom.
For me personally its always better to create smth from scratch and have full control over it instead of using some real messy solutions with the default ui.
it's one of those things that they have hidden away a bit:
Camera - Set the camera bounds for (All players) to Arena 1 (Do adjust the minimap)
I do agree you have more freedom, but the trouble is, you are not making a map in your engine, by using the built in functions you are undoubtedly going to use less resources. So for me personally, I prefer to slave away trying to make the built in functions work rather than straight away adding more and more clutter to a map which could ultimately end up lagging or slowing things down for players.
But I will agree if you can rotate you map and have more detail that you have no other choice and it's a nicely made solution as well of course!
You know that that action limits your camera bounds, too, right? :)
I dont think everyone using a custom minimap wants to limit the camera bounds, too.
About the resources, the minimap actually doesnt really cost much performance, since its only the one periodic trigger that does kinda simple calculations and moves a dialog item.
I am having a problem with the formula in my Diablo map it doesn't so exactly where you are its close in town but the farther east you go on the map the farther away the image is from the character my map size is 256x256 and my image size is 953x964 I'm not sure if anyone else has this problem i also made a little map 64x64 and image size 1024x1024 it is off as well i would like some help with this asap cause i would like to release my map with a working minimap
I must be doing something stupid (wouldnt be surprised -- never worked with a library before) but when I try and make the action pictured in step 3, when I go to do the first action -- "set minimap map size x = map size x" -- I'm not able to choose from those variables. I already defined them int he record "Minimap" and in the same action's Parameters, but they just arent there...
Edit: it also won't let me save the map! Says theres a syntax error: " lib1_gv_minimap;"
It's the variable, not the record. It looks exactly like the picture, but says (No Value), though I dont think that's wrong either because whenever I click on that, it won't open a window to let me assign it
Edit again: figured it out. Thanks for the tutorial -- helps a ton!
How do you get rid of the white space on the edges of the image? It keeps the player's arrow in the middle of the screen even when youre on the edge of the map, so it just shows white space where it has no image. If there's no (easy) way to make it not show that space at all, is it at least possible to make it black instead of white?
Recently i got a bunch of PMs full of questions about this tutorial..
I already answered the same questions a couple of times , so it would be great if you could post your questions in this thread instead, so other people can learn from your mistakes or answer your questions directly. :)
OK, after publishing my map 20x. I have narrowed down an issue i am having. Whenever I add the imported image to the "initi minimap" action, when i try to enter the lobby of my map it just sits at "Streaming Data".
When I test the map through the editor everything works fine.
What is the problem here? Is there additional steps I need to take to use imported images in published maps?
I have the minimap working perfectly except for the problem with my above comment, and I would prefer if the map rotated around the arrow instead of the arrow rotating in the minimap. Been trying to fix both these issues all day but it is time for sleep.
On the rotating issue, I cannot figure out how to change the rotation point of the dialog image. I can make the image rotate on any single point on the map, but i cant make that center rotation follow my unit.
I was able to make a pretty cool feature where a object thats on the minimap, instead of disappearing from the minimap when i walk too far from the object, its icon will hug/circle the boarder of the minimap. That way i can make my way back to it even when it is out of range.
Can you create a minimap directly after the beginning of the game? I have a random terrain generator with deformator and cliffs, so I would like to create a minimap for this new terrain.
Rollback Post to RevisionRollBack
To post a comment, please login or register a new account.
Hey guys!
This is actually my first real tutorial. As you might know im part of the team that developes Starcaft Universe and im responsible for most of the trigger work. Since SCU is a real big RPG and alot of people try to build smaller RPG projects i decided to share some of our knowledge with the community, however some things will for sure be kept secret for now.
Today i wanted to start with a simple tutorial about a custom minimap that works similar to the one in World of Warcraft or other first person RPGs.
Difficulty: Medium (You need some basic trigger knowledge for this tutorial since i dont want to explain each single detail) **
The result will look like this:
1. Creating the library
At first we need to create a new library. Make sure you can see the libraries in your editor (check the "view" tab at the top for options):
Create a new library called "minimap".
For better overview, i like to create several folders within the library containing the variables, actions, functions and triggers.
When your done, it should look similar to this:
2. Creating the variables
Now we need to set up the variables needed for the minimap.
I recommend to use records to manage your variables in a better way. Create a new record called "minimap" and a new variable with type "record" outside the record, also called minimap, and set its record to "minimap". It should look like this:
Now create the following variables in the record:
3. Creating the dialogs
Once we have finally set up all needed variables we can start setting up the dialogs for the minimap. The minimap consists of 3 dialogs. The first one stores the label for the region name, the second one is the main panel which basically is just the border for the minimap image, and the third dialog actually stores the minimap image, causing it to be cut off at the edges when its moved. (Since dialog items of a dialog can never fill more space than the dialog itself)
Since we want it to be a library, we need to make sure that its flexible and easy to use. Because of that we will set up the dialogs in a custom action and give the user a few parameters to customize the minimap for his needs.
The user will be able to enter the anchor, the offset and the size of the minimap, and also has to enter his values for map size and map image size (since each map has a different size and so does the map image, for sure).
TLDR: The minimap should be usable in EACH map with a few simple clicks and without recoding stuff later on.
Create a new action and set it up as following:
I think i dont need to explain too much right here, actually we are just creating a few dialogs and attaching them to each other, it shoulnd be a big deal if you have basic trigger knowledge. The trick right here is basically to use a second dialog within the main panel that is invisible and stores the map image to make it cut off at the edges.
4. Creating a few simple actions
Ok, now we have our minimap dialogs set up. However we need 3 more very simple actions to make it usable.
First off, we need to be able to show/hide the minimap for specfic players. We could just use the default action blizzard gives us "Show/Hide Dialog", but since the minimap consits of more than one dialog it makes sense to write a custom action for it since it would be pain in the ass to have 3 lines of code everytime you want to show/hide the minimap and it could also cause bugs (for example when forgetting to show the hidden 3rd dialog).
So, we just create a new action that should look like this:
It just shows/hides all the panels of the minimap for a specific player. The local variable "pg" makes the action a little bit faster since it doesnt need to convert a player to a player group 3 times (what would be the case if we would do it in the show/hide dialog action itself).
Secondly, we need an action that sets the region name label, since we want the minimap to show the name of the region the player is currently in. For sure we could just directly modify the text of the label later, but keep in mind that its a library and should be easy to use. Also we wanna make everything except the custom actions internal to make sure the library doesnt add dozents of variables and triggers to the scroll lists of the gui (more about that later).
Set it up likes this:
Finally, we need one more action to set the minimap hero, since the minimap should follow a specific unit later:
5. Making the minimap work
OK, so we are nearly done now, except one thing: The minimap doesnt work.
The minimap should do the following things:
1) Make the player arrow match the hero facing
2) Move the minimap image to the right position to match up the heros position ingame
To achieve this goal we create a new trigger, thats initially NOT turned on (its turned on at the end of the "init minimap" action to make sure its not active when not using the minimap at all, to save performance).
Set the trigger up as follows:
First off, we need to use a periodic event for sure. If you want to save performance you might decrease the amount of executions per second. If you use
"Timer - Every 0.0 seconds of Real Time" it will execute 16 times a second (thats the current limit of sc2), however i dont think the trigger costs to much performance at all so its alright to use the minimum interval, since it makes it look smoother.
What it basically does now is it loops through all players (make sure to use ACTIVE PLAYERS to save performance, since it will only pick the players that are currently playing) and updates the minimap for the picked player.
First it changes the rotation of the player arrow dialog item image of the minimap. The exact formula is different for each dialog item since each arrow might have a different default rotation (in this example we need to add 135 degrees at the end to make it fit). The first part, "360 - hero facing", needs to be used for each dialog item to match the hero facing, its not enough to simply set it to the hero facing since it rotates in the opposite direction.
The more complex part is the moving of the map image.
To understand how it works i have to point out some things first:
1. When the hero is standing at the buttom left edge of the map with size 128x128, his position (x,y) will be 0,0. At the top right its 128,128. Center would be 64,64.
2. The map image dialog item is anchored at the center of the hidden map image panel dialog.
So, that basically means if the hero is standing at the bottom left edge of the map the map image dialog item needs to be moved so that the bottom left edge of it is located at the center of the dialog.
That means that each time we move the map image dialog item we have to add a fixed amount to the offset to make it fit. This value depends on the size of the map image file. Since its anchored at the center we always have to add <map image size> devided by 2 to the offset to move the bottom left corner to the center. However, if we want to move a dialog item to the right side we have to INCREASE the x offset, if we want to move it up we have to DECREASE the y offset, what actually means we must differ between x and y offset.
However we have to keep in mind that the hero position on the map for sure moves the map image. Lets say the hero moves from point 0,0 to 10,10. If the map image size would be 1:1 the size of the map, we could just add 10 to the y offset and substract 10 from the x offset. But since the map image can (or better: WILL) have a different size we need to calculate the size factor first, by deviding the map image size by the map size and THEN multiplying this value with the current hero offset.
Sounds complex but actually its kinda simple.
Example: The map is 64x64 and the map image is 128x128. If the hero moves from 0,0 to 10,10 we have to change the offset of the map image by 20 since its twice the size of the map. So you can say: hero offset * (map image size / map size).
This is actually the reason why we had to save all the values from the "init minimap" action into variables within the record, because right now we need to access them since each map and map image can have different size.
You can see the exact formulas in the trigger above.
All calculations are done as reals to avoid losing accuracy.
6. A few words on libraries
If you create libraries like this one, make sure to make all functions, trigger, actions and variables internal, except for the ones that should be accessable by the user later. For the minimap, the user should just be able to use the 4 custom actions but not have access to the minimap record variables or the update trigger. This makes 1) the library more secure and 2) removes all the unneeded stuff from the gui function lists (for example when the user types "minimap" in the search window of his trigger editor he WONT find the minimap record, because its internal and can just be used by the library itself).
7. How to use the minimap library in my map / How to set it up
If you want to use the library in your map, you just have to follow this 6 steps:
1. Extract the map image. Open up the terrain editor and click on "Data" -> "Export map image" at the top. I recommend to make the map image at least 4 times bigger than the map itself cause otherwise it will look like very far away in the minimap, moving slow and with less detail.
2. Import the map image using the import manager.
3. Import the minimap library.
4. Set up the minimap by using the "init minimap" action provided by the library, make sure to enter the correct values for map size and map image size since otherwise the minimap wont match the heros position in the game.
5. Set up the minimap hero for each player using "set minimap hero" action and show the minimap for each player with the "show/hide minimap action" (both provided by the library).
6. Use the "set minimap region" action to set the region label text of the minimap.
7. Enjoy!
8. Final Words
Please note that this is just a very basic example of a minimap. You could for example add a world map showing all players and work with dialog styles to make it look much cooler. I just wanted to give a basic idea how it works and i hope it has helped some people to understand the mechanics of a custom RPG minimap.
Great tutorial! People always ask for how to do these, and I'm glad somebody has answered :D
Wow, awesome tutorial. It opened my eyes not only for a great way of implementing a minimap, but also for the possibilities using libraries. Reminds me of "Classes" in Python!
Thanks!
Wasn't there a way to move and resize the actual SC2 minimap using layout files? You could just move it to your desired position, create an arrow ping and attach it to the players unit.
I admit I didn't give this much though, maybe there are some limitations on using the built-in minimap that justify remaking it completely with triggers.
@Tolkfan: Go
Actually the build in minimap works totally different than this RPG minimap.
The build in minimap always shows the entire map and all units on it, while the RPG minimap basically just shows a small area around the hero and moves with the hero. Also it shows more details like doodads and you can customize it in any way you like.
@Mille25: Go
To my knowledge this simply isn't true. You can make the minimap only view a certain region with a single trigger I believe. You may well be doing other things but I think you'd be better off working with the built in minimap personally. Unless you are doing something clever like rotation?
@xil_theMINISTER: Go
Never heard of that actually and couldnt find anything in the triggers.
Also you will always miss the details of the custom map image (the default minimap is very low detail).
Additionally you can for sure make the minimap rotate instead of the arrow if you like to, like i said you have all freedom.
For me personally its always better to create smth from scratch and have full control over it instead of using some real messy solutions with the default ui.
@Mille25: Go
it's one of those things that they have hidden away a bit:
Camera - Set the camera bounds for (All players) to Arena 1 (Do adjust the minimap)
I do agree you have more freedom, but the trouble is, you are not making a map in your engine, by using the built in functions you are undoubtedly going to use less resources. So for me personally, I prefer to slave away trying to make the built in functions work rather than straight away adding more and more clutter to a map which could ultimately end up lagging or slowing things down for players.
But I will agree if you can rotate you map and have more detail that you have no other choice and it's a nicely made solution as well of course!
@xil_theMINISTER: Go
You know that that action limits your camera bounds, too, right? :)
I dont think everyone using a custom minimap wants to limit the camera bounds, too.
About the resources, the minimap actually doesnt really cost much performance, since its only the one periodic trigger that does kinda simple calculations and moves a dialog item.
I am having a problem with the formula in my Diablo map it doesn't so exactly where you are its close in town but the farther east you go on the map the farther away the image is from the character my map size is 256x256 and my image size is 953x964 I'm not sure if anyone else has this problem i also made a little map 64x64 and image size 1024x1024 it is off as well i would like some help with this asap cause i would like to release my map with a working minimap
EDIT: figure it out created a new formula that takes the offset the map editor gives with maps that are 256x256
I must be doing something stupid (wouldnt be surprised -- never worked with a library before) but when I try and make the action pictured in step 3, when I go to do the first action -- "set minimap map size x = map size x" -- I'm not able to choose from those variables. I already defined them int he record "Minimap" and in the same action's Parameters, but they just arent there...
Edit: it also won't let me save the map! Says theres a syntax error: " lib1_gv_minimap;"
It's the variable, not the record. It looks exactly like the picture, but says (No Value), though I dont think that's wrong either because whenever I click on that, it won't open a window to let me assign it
Edit again: figured it out. Thanks for the tutorial -- helps a ton!
How do you get rid of the white space on the edges of the image? It keeps the player's arrow in the middle of the screen even when youre on the edge of the map, so it just shows white space where it has no image. If there's no (easy) way to make it not show that space at all, is it at least possible to make it black instead of white?
Recently i got a bunch of PMs full of questions about this tutorial..
I already answered the same questions a couple of times , so it would be great if you could post your questions in this thread instead, so other people can learn from your mistakes or answer your questions directly. :)
@ctccromer: Go
Simply tint the image behind the map image black instead of white.
Nevermind i messed some lines up.
Is there a way to add the position of other players units on the map?
Yes. Instead of just creating 1 arrow create one per player, and then move all arrows to the linked players position.
OK, after publishing my map 20x. I have narrowed down an issue i am having. Whenever I add the imported image to the "initi minimap" action, when i try to enter the lobby of my map it just sits at "Streaming Data".
When I test the map through the editor everything works fine.
What is the problem here? Is there additional steps I need to take to use imported images in published maps?
This minimap tutorial as taught me a lot btw.
I have the minimap working perfectly except for the problem with my above comment, and I would prefer if the map rotated around the arrow instead of the arrow rotating in the minimap. Been trying to fix both these issues all day but it is time for sleep.
On the rotating issue, I cannot figure out how to change the rotation point of the dialog image. I can make the image rotate on any single point on the map, but i cant make that center rotation follow my unit.
I was able to make a pretty cool feature where a object thats on the minimap, instead of disappearing from the minimap when i walk too far from the object, its icon will hug/circle the boarder of the minimap. That way i can make my way back to it even when it is out of range.
Can you create a minimap directly after the beginning of the game? I have a random terrain generator with deformator and cliffs, so I would like to create a minimap for this new terrain.