Minimap and Tile mapping (Prototype RTS for iPad)
edit: please read lower comments for newer versions and information. This project is growing!
I thought I would share this! It's the beginning of my new RTS (real time strategy) game project, but right now it's mainly the foundational GUI stuff and only 90 lines long. So I thought I would share it, because it's easy to learn from.
In this example, there are two grids. They're identical, except for size, as one is the 'minimap' grid. When you click on the minimap, it controls motion on the larger grid. There is a blue ball bouncing around on the grid for now, to show the concept that units will naturally stick with their landscape even as the controller moves around.
There's also a small beginning of unit selection controls. When you don't click on the minimap, and you're clicking on the real map, you can drag your finger and it makes a square. I plan on combining that with a hittest on touch_ended to select units.
The script is designed to be easily tweaked. The variable self.grid_count can add more grids to the map. And the variable self.map_size changes the size of the maps grids. Right now it's in beta test mode so I wanted a scene I can see without clicking (lazy)
Nice! Will the RTS be something like Command & Conquer: Generals?
I hope it is Sebastian! And thanks Eliskan for this code. I'm going to see if this can finally teach me the scene module.
@Sebastian - Yeah that is the idea, something like C&C or Age of Empires.
Several major features are beginning. Terrain tiles are now included (which currently are 60x60 but the sprites are designed for blending so I need to write an algorithm for that - it will look MUCH nicer when finished).. also drag and drop works on selecting the ball.
I did a tricky solution for the problem I was having with lag. Instead of drawing 10000x rectangles each frame, I spliced all the images of the map together BEFORE it began. So I only draw 1 image for minimap and 1 for main map. That's why the new script takes a while to begin.
Stage 3: https://gist.github.com/anonymous/c8f2c575bd5fd6fa3041 (update: fixed some glitches and redundant codes)
IF THIS SCRIPT HAS A TIMEOUT ERROR: Go to line 89 and decrease grid_count. 25 is about the limit for my iPad2, at 26 I will get a timeout. It may be lower on other devices. To fix the timeout error, I may make the map before the draw loop begins but after the user is warned through print that it will load.
For fun graphical changes, alter the choice on line 51. Less choices mean more consistant maps. The current choices are ALL the ones that blend properly right now.
This step was a beast. Most of the work is tile mapping. You will notice tiles now blend in with eachother, for example if two water tiles are next to eachother they form a puddle. This really was more complex than I expected. My coding in this section is sub-par but I think I can turn it all into simplified functions that will lessen code length by a good amount.
The other new addition aside from tile mapping is the get_node function, a pretty simple function that is used to show which node the circle is on.
The game will take several moments to load. Like before it's designed for iPad.
Great work @eliskan!
Thank you :)
I am all the way to Stage 3:
Unfortunately, yes it's now two files. I had to clear space in the main file, it was just too many functions. Both files need to be in the same folder, and a_RTS_Core.py needs to be the same name or you need to edit the import in a_rts_3
The new additions? Where to start!!! Well, I got A* pathfinding implemented. This is a much more efficient variation of the A* algorithm I have used in the past. It's incredibly efficient and short, and you'll find the actual A* pathfinding algorithm in the a_RTS_Core.py file.
The units all walk around, chosing a random new node whenever they reach the end of their path. One lucky unit at the start of the array gets his path illuminated with orange squares so you can see what the aStar pathfinding is doing. I have it construct its path every time the unit steps on a new node. This is because I plan on having objects like walls and buildings be implemented, and that means the path may become obstructed while the unit is traversing it. To account for that I am just planning ahead, though this does result in more lag than the alternative (call the path once, and follow it from then on out)
To push the limits of the pathfinder, I have 40 units on the map. You will notice a very stop-start type lag at the beginning. This is a result of all 40 units calling the aStar() function at the exact same moment. This won't be a problem in the actual game, since all units won't spawn at the exact same instant (the beginning) and thus won't share the EXACT same moment for aStar.
Will be working on trying to implement min heap into the aStar so it's even more optimized.
Also tweaked selection rules. Now you can select individual units by clicking them once, or select multiple ones. They will stop walking when selected.
This is the beginning of real units and selection controls, as well as pathfinding. Woot.
TODO: Shorten my coding a lot, and begin adding unit interactions. Any help shortening some of those obnoxious loops would be great.
Not sure why I never said this before, but....
Two things I've noticed about the program:
- In order to run, <pre>from urllib import urlopen</pre> needs to be added to the top of the core.
- After selecting units, they do not go to where you tell them. Granted, now that I re-read your posts, they aren't supposed to do that... I guess it is only one thing then.
That being said, the programs are still amazingly awesome.
And some one said that python wasn't good for games (some article I read)!
Ahh interesting, I never had that urllib problem so far.
Yeah unit control is what I am working on currently. Being able to direct units and construct buildings with them, etc. Implementing aStar was the tricky part.
Now all I need to do is have the game store which units are selected and be able to change their target_path to a new path when the player directs them somewhere. Should be pretty easy.
Another bug you may notice with the tilemapping is that the furthest rightmost tiles have graphical glitches. I will probably need to refactor the entire section that sets up tile graphics because it's an ugly smelly mess, and I'm dreading that, so I am just letting it slide for now while I work on the more enjoyable aspects of the code.
Yes, I had noticed the graphical bug (I only saw it in the top right corner, but I didn't look much).i do know what it is like to dread a certain rewrite ("I need more ideas! Anything instead of shortening that code!!!"). I was planning on reading the tile mapping code in detail (I want to know how it is done) so I'll let you know if I find any short cuts!
As for the game storing units, wouldn't a tuple be good? Or is it list, I get it confused. Just make a class that creates a new list after each click (that way you can have multiple commands) and then have a command delete said list once the troops arrive at the given point. Or could you just have each unit that is selected store their own location data? as in, if I tell A, B, and D to go to point $, then each of them has their "GPS" set to point $. But if you then, mid trip, told C and D to go to point £, they would each set their own "GPS" to point £. I hope that makes sense...
Actually that's almost exactly how it works.
Right now, when a unit reaches the end of their path, I have them automatically create a new path. But when unit controls are implemented, they will walk to their path and wait or resort to their default behaviors (soldiers for example would fight their enemies). Since every unit stores its current path, it's very easy to change that on the fly and give them a new path.
Once I get it working, when it selects units and gives them a command, all of them will update their unit path accordingly. They may also have goals or waypoints so you can give them multiple commands at once (IE walk here then walk here).
I am at the fun stage of design where I get to decide how resources and tech trees are handled. The ideas are pouring in! I am thinking of treating all units as basically the same, however they will all have their own individual stats that they upgrade by what they do. So if you sent a unit to war and it survived, it would become a better soldier. But we'll see, maybe I am jumping the gun thinking ahead too far haha
I'm glad that I was not only understandable, but also I was right!
Since we're on the topic of thinking far ahead and I'm learning how to use the pickle module, would a save/load function be practical/added? If you press the save button, a function pickles all of the variables. The reverse happens when you press the load button. (I'm sure this is how saving works most of the time.) I've done something like that (need to shorten it) and the snake game uses it for the high score.
Saving would definitely be a fun thing to implement into the game. But there is a TON of data that would need to be saved... It may be more prudent simply to save the current level, so a player can pick off at the beginning of the level they stopped on. But I don't even have levels begun and that's going to be a problem, due to the lag in making the graphics tiles for the minimap.
It's definitely something I am interested in!
If you are trying to learn how I did that map tiling, it's kind of annoying and very brute force. Every node is graphically split into nine parts. I go through each of these nine parts and check its neighbors. Depending on what the neighbors are determines what tile used in that section. Then we go through this process for every node on the map. The reason that the far right nodes don't work is because they are trying to match themselves to nonexistant nodes further in the array. This produces an error, which I just 'patched' using a try: except: statement. The far left nodes, in contrast, are searching through negative indexes of the array, so they're technically matched to the far right side.
It's confusing and annoying and I'm slightly ashamed how brute-force the algorithm for that section is. Like I said, it warrents a complete rewrite.
I did a small update, because you were so interested in getting units to walk where you tell them :) So this update does just that. After selecting units, you can tell them to walk anywhere.
Pretty minor update but it shows how useful aStar is going to be once the game design is working!
Doesn't need to update RTS_Core so use the one I posted in my last post (with the urllib addition)
Whoops double post sorry
I know it's been forever since you posted this, but I hope you're still working on it! It's a super cool engine, at least, and I'm impressed at how fast it runs!