RTS Project

Posted By: Redeemer

RTS Project - 12/24/10 02:32

Hi all,

It's been a very long time since I've made or attempted to make a game with Gamestudio. But recently I've become interested by the prospect of making a real time strategy game similar to StarCraft or WarCraft.

Just to quiet the naysayers out there, no, I don't plan to make this into a "real" game. It's just a project. I'm not trying to compete with any of the big guys in any way.

Mostly I'm doing this to test my skill. Making FPS games is fun, but it doesn't take much programming to get a simple game rolling.

I've only been working on this project for a few days, but knowing what kind of a project it will be, I wanted to ask for some advice from the experienced users here.

Right now, I only have one question:
1. Pathfinding. How should I get started tackling this monster? Can anyone suggest any articles I should read? Books? I've heard of an "Intense X" plugin that supposedly handles pathfinding, but their site seems to be down and I'm not keen on the idea of wrapping my entire project up in some plugin I'm unfamiliar with.

(Note to mods: I do plan to keep this thread updated with details for those that are interested in this project, so please don't move this)
Posted By: MrGuest

Re: RTS Project - 12/24/10 02:52

This would probably give you a good start grin good luck with the project.
Posted By: Redeemer

Re: RTS Project - 12/24/10 04:03

Thanks for the input, MrGuest! This will be very helpful. But now I have another question for you guys.

For the last few days I've been thinking about creating a simple tile based map format, but I noticed that using ent_create() to spawn multiple map entities in this fashion chews away at the nexus at a ridiculous rate. Can this be changed? And if not, what kind of map format would you suggest I use?

I'm reluctant to build my maps in WED because I want to keep my game grid based and simple, and WED interferes with this idea on a number of levels.
Posted By: EpsiloN

Re: RTS Project - 12/24/10 09:28

If you are using map entities to form your level (tiles) use "tex_share" (dunno in lite-c) to preserve some video memory.
The same thing (I think) can be applied to models , in MED use an "external texture". Not shure about this , but I think it loads it only once , and makes the models smaller (this way they'll use less memory to load).

BTW , if you have problems with FPS with a lot of tiles , dont assign them a function. Use one global function to control/update tiles one by one. A lot of small functions drop the frame rate a lot. Atleast thats what I've experienced in the past laugh

EDIT : Forgot to mention. Again laugh not shure , but I think weaker light calculations also lower the map entity size , wich should decrease memory usage and increase FPS.
Posted By: muffel

Re: RTS Project - 12/24/10 12:21

The article with which i learned A* was this one

I also started a RTS project some time ago, but atm i'm to lazy to implement open and closed lists.

How my levels are build up:
- a wmb with terrain and modells
- texture as a mask for trees
- texture as a mask for nodes

The graph is grid based and is stored in an array ( i use no ents for this )

Perhaps we could exchange our experiences. Till new year i want to implement the pathfinding

muffel
Posted By: Redeemer

Re: RTS Project - 12/24/10 16:19

@EpisloN: Thanks for the tips. I'll see if they fix my problem. laugh

@muffel: Thanks for the link! I'll bookmark it for later.

Quote:
How my levels are build up:
- a wmb with terrain and modells

What do you use to build the terrain? I've played around with MED to do this, but the tools seem insufficient for building terrain that's anything less than chaotic and mountainous. And I'm not a texture artist by any means so it's hard for me to apply any more texture than simple color to my terrains.

On that same note, I've seen numerous references to a Terrain Texture Generator plugin for MED in the manual, but I can't find it. What's that all about?
Posted By: EpsiloN

Re: RTS Project - 12/24/10 17:04

For texture use Multitexturing shader on the terrain to add up to 4 textures , tiled on the whole terrain (find it in the Wiki).
For creating terrains (not randomly) use Photoshop and clouds (or some other method) and manualy form the environment with the paint brush laugh Good idea is to have a tablet...
In case you dont know how to paint terrains , darker to black is lower points , lighter to white is high points when you import a terrain height map. You can even make a terrain in Paint laugh but that'll be very annoying , pixel by pixel.
Posted By: Redeemer

Re: RTS Project - 12/24/10 18:31

Yeah, I understand what a heightmap is. laugh

The trouble with simply painting a terrain in something like Photoshop or MED (using the Magnet tool) is that you end up with a very hilly terrain that doesn't suit an RTS very well. In an RTS, you need lots of level areas to build bases and move your units smoothly.

Traditionally, RTS games only use slopes to move from one plane to another. I want to emulate that kind of terrain in my game.

EDIT: On another note, I've tried adding "tex_share=1" before my level_load statement, but it didn't seem to work. I think it's important to note that I'm loading an empty level, and then I'm adding multiple map entities using for() loops to act as the tiles.

Is there anyway to tell the engine that I will be loading multiple copies of the same map files, and that it need not allocate multiple copies of texture and/or geometry data for each entity?
Posted By: Redeemer

Re: RTS Project - 12/24/10 19:29

Ok, I've decided to go with terrain based levels. To make them, I use MED to create a terrain 128x128 vertices in size, with each polygon sized at 64x64. The standard trooper unit is considered 128x128x128, meaning each polygon is half the size of a trooper.

To keep my terrain simple, I'm making heavy use of the min/max options of the magnet tool.

For fine tweaking though, such as adding perfectly smooth slopes, I would like to be able to do use an image editor. However, MED cannot export HMP files as bitmaps (although it can import them), so I'm stuck there. Does anyone know of a plugin that can export HMP files as BMP files?

EDIT: For the multitexturing shader to work, it seems that I also need the heightmap in an image file (for blending purposes). So I'm doubly screwed if no one can help me. :\
Posted By: MasterQ32

Re: RTS Project - 12/24/10 22:21

my favourite tool for terrains
maybe you get a nice result
http://www.bundysoft.com/L3DT/
Posted By: Redeemer

Re: RTS Project - 12/25/10 02:23

Thanks for the link Richi007, I'll be sure to look into that! laugh

Ok, now I have yet another question!

In my game I want to allow the player to select multiple units through a selection box. I currently use "mouse_dir3d" to c_trace into the 3D world from the camera position and issue orders, select units, etc. However, when the user creates a selection box and lets go of the mouse button, the game needs to "trace through" all of the pixels in the selection box to see if a unit resides there.

Basically the loop looks like this:

Code:
for( x=box_start.x; x<box_end.x; x++ )
   for( y=box_start.y; y<box_end.y; y++ )
   {
      // do some tracing!
   }



My problem is that while mouse_dir3d handles all of the calculations that determine the direction vector for tracing, those calculations aren't made available for me to modify and apply to any pixel on the screen (rather than the one the pointer currently resides on). So how can I "trace into" a pixel on the screen without moving the mouse and using mouse_dir3d?
Posted By: MasterQ32

Re: RTS Project - 12/25/10 02:28

you can use vec_for_screen!
converts your screen coordinates to world coordinates....
Posted By: Redeemer

Re: RTS Project - 12/25/10 03:07

Thanks for the swift reply Richi007! That function will save me a lot of time and effort.

Actually, by the time you had posted your reply, I had almost come up with my own algorithm. It was almost perfect, but there was a severe error in my calculations that was causing mouse clicks on the lower right side of the screen to affect things on the upper left side of the screen, and vice-versa for every other direction I chose.

Oh well, that's just talk. Thanks again, man. wink
Posted By: muffel

Re: RTS Project - 12/25/10 10:27

Although i haven't programmed the box selection yet. I have some ideas how to realize that.
You requier a Collision algorihtm for example sphere to box( or simpler point to box).
You create a box then you loop through all ents and check them against the box
if they are in the box they are selected if not they are unselected.
I believe to use serval c_traces is quite slow and inacurate.

muffel
Posted By: Redeemer

Re: RTS Project - 12/25/10 15:32

You are right. A loop of c_traces is actually quite slow. The only way to get a loop like this running at a good speed is by skipping over multiple pixels. But then it's not very accurate.

Well, apparently the engine knows what pixels are occupied by units, as it uses this information during the rendering phase to draw the units onscreen. Now if I were using my own engine, I would simply create an array of handles for every pixel onscreen during the rendering phase. Then all I would have to do is reference this array during my box loop to see what units occupy what pixels. No calculation required.

Obviously this isn't my engine though, so even if the engine keeps information like this I haven't a clue where or how this information is retained by the engine of if I can even access it.

Pointers, anyone?
Posted By: Saturnus

Re: RTS Project - 12/25/10 15:33

This is pretty much how I once did a selection test:

Code:
// This function is invoked, when the mouse button is released and the
// selection box had been drawn.
// Hint: Alternatively you can use ent_pvs() and omit the if statement.

ENTITY *ent;

for (ent = ent_next(NULL); ent != NULL; ent = ent_next(ent)) {
    if (!(my.eflags & CLIPPED)) {
        VECTOR ent_screen_pos;

        vec_set(&ent_screen_pos, &(ent->x));
        vec_to_screen(&ent_screen_pos, camera);

        if ((ent_screen_pos.x >= minv(selectionbox_from.x, selectionbox_to.x)) &&
            (ent_screen_pos.x <= maxv(selectionbox_from.x, selectionbox_to.x)) &&
            (ent_screen_pos.y >= minv(selectionbox_from.y, selectionbox_to.y)) &&
            (ent_screen_pos.y <= maxv(selectionbox_from.y, selectionbox_to.y)))
        {
                // add entity to selection
        }
    }
}


Posted By: Redeemer

Re: RTS Project - 12/25/10 15:51

Geez, should've thought about vec_to_screen! Man, it's been way too long since I've used Gamestudio.

Thanks man. I'll try applying that method to my own game. laugh

EDIT: Yep, works like a charm. Thanks again, Saturnus.
Posted By: EpsiloN

Re: RTS Project - 12/25/10 20:30

About the terrains... You can still get a smooth terrain (also depends on settings in MED Importing) using Photoshop and Bluring the heightmap. For lowering level of the terrain use (for example) 3 lower pixels than current level (or higher) to make a 'transition' to the lower plane (wich is 4 pixels lower). Thats just an example , but it'll create flat levels with smooth transitions between different layers. And then , you still have the option to surround your level with jagged mountains grin
You can still form the terrain , like in MED or any other model editor , in Photoshop. The difference is that you're not viewing it in 3D , but its enough to shape it by hand with the tools provided.
Posted By: muffel

Re: RTS Project - 12/25/10 21:07

Also thanks to Saturnus works for me also very well.
i should stop thinking to comlicated

muffel
Posted By: Redeemer

Re: RTS Project - 12/25/10 22:41

@EpsiloN: Unfortunately I don't have Photoshop and there's no way I'm going to try downloading it on my connection, so that won't work. :\

Besides, I think I'll be ok without having slopes. It makes the game that much easier to program, since I don't have to deal with path finding between multiple floors. I'll keep the mountains and dips in my terrain, though, to provide obstacles for ground units. Of course I can also make air units that can move over these obstacles without problems. wink

On that same note, unit selection and ordering is working, so now I want to add path finding. I've played around with the scripts MrGuest referenced to me, but I noticed that both their speed and accuracy drops dramatically when there are a lot of nodes in a level.

So I was wondering, what do most game developers do to solve this problem? I'm guessing they precompute the various paths available to the AI before the game even starts, but how is that accomplished?
Posted By: Saturnus

Re: RTS Project - 12/26/10 01:48

The pathfinding script suggested by MrGuest uses a point of visibility graph which isn't reasonable for most strategy games (but for other kind of games, of course). You rather want to use a dense pathfinding grid (basically a two-dimensional matrix).

There are many ways to improve the performance of a pathfinding algorithm:

- In the first place the source code should be of good quality. Try to avoid obvious shortcomings.
- Using appropriate data structures for e.g. the open and the closed list can also improve the speed.
- Use a pathfinding manager that spreads the pathfinding computations over several frames (or something like that).
- Use hierarchical pathfinding for large pathfinding graphs.
- Share computed paths among units.
- Flood fill approach suggested by Damocles: http://www.opserver.de/ubb7/ubbthreads.php?ubb=showflat&Number=313826#Post313826

If your game world is dynamic (ability to construct and destroy buildings, destructable environment and so on) precomputed paths won't help that much, I guess. Perhaps you could cache widely used paths instead, e.g. a path between the enemy's base and the player's base. Depending on the game, you could also experiment with ACO. This might give interesting results!
Posted By: Damocles_

Re: RTS Project - 12/26/10 17:25

With a "floodfill" approach, ou have several advantages:

With the fllodfill I basically mean to generate a topographic map,
startin ftom the target position, where the target has the
lowest count, and all other reachable points in the map
are increasingly "uphill".
You basically fill the whole map, with the target at the
lowest point in the valley.
The pathfinding, does not pre-calculate a path:
its much simpler: the units just move to a neighboring
square that is lower than the current one (going downhill)

Its slower to generate, but it lets you have an unlimited number
of units use the same pathfinding-data to reach this target.
(when you have a group of 10 units, you only need 1
search, instead of 10 with a*)

Also: when something changes on the map, like a unit
blocking the way, you dont need another serach to find
an alternative way. The unit simply uses the next-best
lower-number neighbor.
It works very well, and it fast enough on current computers.

Another thing: you can advance the search to let units
avoid dangerous areas, such as enemy stationry defences.
You do that by adding "hight" value, around the peremiter
of the enemies turrets etc.
You unit will then walk on a path, that walks
around these areas.

-----

for an RTS, a node-based approach such as Intense Pathfinding makes little sense.
An RTS works best on a 2Dimensional gridbased pathfinding map.
(all Blizzard RTS, or the Age of Empires Series use that,
I actually dont know any pure RTS that uses something else)

Posted By: muffel

Re: RTS Project - 12/27/10 17:01

Your "floodfill" approach has one disadvantage.
you have to store at least one value for each node.
Even for the shortest path you need a big graph ( who knows if there is a very high wall between the target or not )
And the more targets you have the more memory it consumes.

For Zombie games it would work out fine thousand of zombies are moving to the target
But for a RTS where are diffrent groups moving to diffrent targetsthe cost are much higher

Can you give some examples where your approach is implemented?


muffel
Posted By: Damocles_

Re: RTS Project - 12/27/10 18:24

It works in a mobile phone RTS, so speed is not an issue.

Also you will not seach for many targets at the same time.
A player will usually click to one targetlocation.
And all units can use this search,

Pathfinding speed in general is not any speedissue anymore.
Only for programmers who dont know how to write efficient code.
Posted By: FBL

Re: RTS Project - 12/28/10 12:44

Speed is more an issue of good algorithms rather than efficient code... or at least should be.

Cryptic code just for speeding up things should be avoided. Instead the algorithm should be rechecked. Maybe it wasn't done the most efficient way.
Posted By: Redeemer

Re: RTS Project - 12/28/10 23:34

Thanks for all the input guys! I haven't been working on the project lately since Christmas has been passing through, but I'll get back to it soon.

Once the pathfinding is done, I want to add different methods of input for the game, including network players and perhaps computer opponents. Then, I will build a small game that uses the system I have built and release it as a demo of my skill. Perhaps someone else can then use the system to build an real game. laugh
Posted By: Redeemer

Re: RTS Project - 12/29/10 22:50

I'm back on the job and I have a few questions.

@Damocles: I understand what you're saying. A floodfill approach would work well in theory, but in my thinking I discovered a few problems with it that you could perhaps shed some light on.

1. Since I'm building an RTS, each unit needs to conduct itself independently and simultaneously of all the other units on the battlefield. However, this would require all of the units to have its own pathfinding graph, otherwise ordering one unit to move somewhere will cause all of the units on the field to move to that destination. But wouldn't this solution cause memory problems with big levels and lots of units?

2. Suppose I order a unit to attack another unit. The unit I ordered should intelligently follow the unit it is attacking until its victim is dead. But wouldn't this require me to constantly recalculate my pathfinding graph so that the unit can avoid obstacles intelligently?

EDIT: I've further contemplated these problems and come up with some other solutions. I would be happy if you could tell me whether they are worth my time, of tell me of something better.

1. To avoid the memory problems, I could keep a "queue" of orders in a linked list. When a player orders a unit, to say, move to a certain location, it adds this order to the "queue" and assigns a pointer to the unit ordered that points to his order on the queue. When the unit(s) have finished executing the order, the order is removed from the queue. This method will allow multiple units to share the same pathfinding information, while simultaneously making sure that only the units that are moving are provided graphs. I believe this would effectively defeat the memory problems, but do you think it would work?

2. I know no real solution for this problem, but I figure I can help defeat part of the problem by only recalculating the unit's graph every few seconds. He won't be moving fast anyway, and I doubt the enemy unit will be either... But in my mind, such a solution seems like it would be prone to failure. What do you think?
Posted By: Damocles_

Re: RTS Project - 12/31/10 11:13

Quote:

1. Since I'm building an RTS, each unit needs to conduct itself independently and simultaneously of all the other units on the battlefield. However, this would require all of the units to have its own pathfinding graph, otherwise ordering one unit to move somewhere will cause all of the units on the field to move to that destination. But wouldn't this solution cause memory problems with big levels and lots of units?


you generate a new Floodfillgrid for each new Pathfind request.
With a 100x100 grid Map each one will take only 20kb Memory.
You make a list of array of maps, and assign it to the units that want to use it.
None used can be freed.
For example: you have a list of arrays, with an id number.
Each unit has one id number stored, of the grid it uses
currently. If the unit needs a new target, it will receive a new id number
of a newly generated grid.

Quote:

2. Suppose I order a unit to attack another unit. The unit I ordered should intelligently follow the unit it is attacking until its victim is dead. But wouldn't this require me to constantly recalculate my pathfinding graph so that the unit can avoid obstacles intelligently?


In most situations, they will not chase each other for long.
You can limit the recalculation of new coordinates to like
every 2 seconds.
You can of course also test if there is a direct path, and
only use a local short-distance follow routine.
(walking to the next square closest to the target)

Quote:

EDIT: I've furth
er contemplated these problems and come up with some other solutions. I would be happy if you could tell me whether they are worth my time, of tell me of something better.

1. To avoid the memory problems, I could keep a "queue" of orders in a linked list. When a player orders a unit, to say, move to a certain location, it adds this order to the "queue" and assigns a pointer to the unit ordered that points to his order on the queue. When the unit(s) have finished executing the order, the order is removed from the queue. This method will allow multiple units to share the same pathfinding information, while simultaneously making sure that only the units that are moving are provided graphs. I believe this would effectively defeat the memory problems, but do you think it would work?


In RTS like Starcraft, the player and AI-commander all use the
unitselection group logic.
The currently selected units share the same pathfinding destination,
and this the same "floodfill" grid. So you only need to generate one for each new targetsearch.


Quote:

2. I know no real solution for this problem, but I figure I can help defeat part of the problem by only recalculating the unit's graph every few seconds. He won't be moving fast anyway, and I doubt the enemy unit will be either... But in my mind, such a solution seems like it would be prone to failure. What do you think?


First realise the simple method (generate a new path
every time the destination changes)
if it affect the performace, make a timedelay for automatic searches.
If it still affects performance, use a direct-walk search.


Also: if the player clicks outsied of the map or on a non passable
area, you can make a floodfill seachrch, assuming the map
has no obstacles. This way the unit will at least walk
towards the clickpoint.
(or you just use a normal direct walk, without pathfinding)
Posted By: Redeemer

Re: RTS Project - 12/31/10 15:31

Once again, thanks for the helpful reply. I can see we're on the same page here.

I'll start integrating these solutions to see how well they turn out.
Posted By: Redeemer

Re: RTS Project - 01/02/11 03:59

Another question:

I need to be able to distribute pointers to my units so they can reference their respective graphs (which are structs of my own design) without manually searching the list. However, I can't use handle() to place pointer handles in the entities skills, because handle() only works for engine objects.

Does anybody know of any workarounds for this?
Posted By: SchokoKeks

Re: RTS Project - 01/02/11 12:10

Since pointers are 32 Bit and skills (aka vars) are also 32 Bit in Gamestudio (at least until a native 64 bit version is released), you can simply store these pointers into skills without converting them to handles.
Here's an example how to save and retrieve with a cast:

Code:
myStruct* pt1; myStruct* pt2;

...

my.skill[0] = pt1;
pt2 = (myStruct*)my.skill[0];


EDIT: of course this also works with engine pointers (including ENTITY*), so there is not need to use handles for this anymore. In general C, this is considered to be a very dangerous method as pointer size can vary between platforms. For 3DGS, I'd say this is a needed hack to overcome platform limitations.
Posted By: Redeemer

Re: RTS Project - 01/02/11 20:22

Thanks SchokoKeks, that works fine. laugh

I didn't think to do that since this method doesn't seem to work for engine objects...
Posted By: Redeemer

Re: RTS Project - 01/03/11 04:07

Hello again laugh

The pathfinding solution presented by Damocles has been coming along very well. My units know how to navigate the graph in eight directions, so a unit can move north/south/west/east and diagonally. They can also find their way around simple obstacles like pits and mountains, since I am taking terrain into account when the graph is built.

But I have encountered a problem in my graph building method. The units can easily lead themselves into corners and pockets in the terrain from which they cannot leave unless the player manually directs them out. This happens because when the terrain is added to the graph, high-cost graph cells are placed next to low-cost graph cells, creating a "trap" which any unit can fall into.

So what I need to do is "smooth out" the graph, averaging high-cost cells with low-cost cells so that the units can "roll around" these traps without being manually directed to do so. But I don't know of any algorithms that can do this.

So what algorithms would you guys suggest to accomplish this?
Posted By: Rackscha

Re: RTS Project - 01/03/11 11:40

I dont understand the problem: If theres is no place in thise bags to get out (for example to arrive the goal point) the Pathdinding should raise the used cost as high as needed to get to the point. At fist in searches for the lowest cost, but if theres no way, it uses the next higher costs etc. Am a bit surprised that your units hang there. Shouldnt happen with a normal a* or djikstra o.O
Posted By: Damocles_

Re: RTS Project - 01/03/11 11:51

When you build the graph correctly, this should not happen.

before the "floodfill" initialize every grid with a very high number. (20000 for example)
The targetpoint has the lowest number (0 for example)

After the floodfill, every gridpoint must then have a neighbor with at least one "lower" count than itself.
If the graph is build correcly you cant get stuck (not finding
a lower neighbor) unless you already reached the target, or
you are on an impassable grid (wich should not be a valid action).
Or if you are on an isolated island. (indicated by you grid
beeing "20000")

Best is if you make a visualization routine, to show
the assigned number of each grid suqare (or a colorvalue)
So you can manually check if the graph is build correctly.

Also: when creating the grid, make the cost of moving diagonally
1.41 times the cost of moving left or right.
(1.4142 -> sqrt(2) )
Posted By: Redeemer

Re: RTS Project - 01/03/11 17:27

Quote:
Am a bit surprised that your units hang there. Shouldnt happen with a normal a* or djikstra o.O

I'm not using A* or Djikstra. wink

I had my doubts you would understand what I am saying, so I created some pictures showing in stages what I do to generate the graph. The highest points are white, and the low points are black (just so we're clear).

Stage 1: The graph is empty. The cost of every cell is zero.


Stage 2: Cells farther from the destination are raised by either their horizontal or vertical distance, whichever is larger. Thus a diamond shaped "bowl" is formed, with the destination at the lowest point:


Stage 3: Terrain is added to the path. Walkable areas aren't added, only obstacles like mountains, pits, etc.


But obviously problems can arise in scenarios like this:

(The green dot is the start point, the red dot is the destination)

Naturally the green dot travels to the northwest as it is the path of least resistance, but the dot will inevitably get caught between the mountain and the terrain around it like a marble.

To fix this without ever having to make the mountains passable, I devised a solution wherein these "pockets" are smoothed out and/or filled in so that the green dot simply "rolls" around them, like this:


I'm pretty sure there are algorithms available that I can use to achieve this, but I'm not sure what they are. So what I was asking in my original post was, "What algorithm would you guys suggest for this?" wink

Quote:
Also: when creating the grid, make the cost of moving diagonally
1.41 times the cost of moving left or right.
(1.4142 -> sqrt(2) )

Excuse my objection/misunderstanding, but why would I want to do this? Isn't it less costly to travel diagonally then in a straight direction? After all, the length of the hypotenuse of a triangle is always less than the sum of the lengths of the other two sides.

EDIT: It doesn't matter if the smoothing algorithm is slow, I can precompute the smoothed "terrain-graph" and overlay it on top of the real pathfinding graph when the graph is being built.
Posted By: Damocles_

Re: RTS Project - 01/04/11 10:56

Ok, you did not actually implement it the way i ment it:

The terrain is not "added" on a later stage, but integral
part of the floodfill search.

Here the actual source of the floodfill i used in Java:
It should be easy to follow when you know C :

Code:
static final int pdimX=120;
    static final int pdimY=60;
    
    final int[][] terrainGrid = new int[STUCTURE_FIELD_SIZEX][STUCTURE_FIELD_SIZEY];

    final int gridFlood[][][]=new int[60][pdimX][pdimY];
    final int floodCurrentID=0; //gets counted up for each new floodfill
    
    //if target is on inaccebible floor, create a curcular floodfill, so units can walk towards it
    
    void floodfill (int targetX,int targetY, int gridId)
    {
    //set the targetzone
    int x=targetX;
    int y=targetY;
    
    //make the floodfillgrid
    //Logger.out("steps:"+generateGrid());
    
    int testvalue=0;  //remove!
    //check if target is on a valid square?

    //create the basegrid
    
    // grid = new int[pdimX][pdimY];
    
    //reset all squares to high count (system copy array faster)
    //System.arraycopy(gridInit, 0, grid, 0, gridInit.length);
    
    for (int ix=0;ix<pdimX;ix++)
    {
        for (int iy=0;iy<pdimY;iy++)
        {
        //grid[ix][iy]=gridInit[ix][iy]; //set to a high value
        gridFlood[gridId][ix][iy]=8192;//set to a high value
        } 
    }
    
    //checkif target is on inaccebile position, do a "no matter what" floodfill,
    //so units can walk toward the destination
    
    boolean dontCareForObstacles=false;
    if(terrainGrid[targetX][targetY]==0) dontCareForObstacles=true;
    
    
    //create the list of currently used squares
    //int worklist[][]=new int[dimX*dimY][2];  //trying a lower dimension reduces the memory use..
    int worklistLenght=0;
    
    //int nextlist[][]=new int[dimX*dimY][2];  //trying a lower dimension reduces the memory use..
    int nextlistLenght=0;
   
    //workarrays
    worklist=new int[pdimX*pdimY][2];
    
       // Logger.out("worklist lenght:"+worklist.length);
        nextlist=new int[pdimX*pdimY][2];
        
    //set the targetpoint to 0
    
    gridFlood[gridId][x][y]=0; //the targetsqare start with the lowest count
    
    //targetnode is the first entry
    worklist[1][0]=x;
    worklist[1][1]=y;
    worklistLenght=1;
    
    
     int testsquare=0;
     int xTemp=0;
     int yTemp=0;
     int xNow=0;
     int yNow=0;
     int countThrough=0;
     
     boolean diagonal=false;
     int walkdist=10; //10 for normal, 14 for diagonal
     
     
     //TODO:
     //when the target is on a building, make this building invisible, right now
     //the trick is to have a little gap in 3x3 buildings, wich is just a workaround
     
    
    //as long as squares active:
    while(worklistLenght>0)
    {
        
        countThrough=1; //start with the first entry
        nextlistLenght=0; //"erase" the nextlist
        
        //for all in the worklist
        while(countThrough<=worklistLenght)
        {
        
        testsquare=0;
        //get the nodes position
        xNow=worklist[countThrough][0];
        yNow=worklist[countThrough][1];
        
        
        
        
        while(testsquare<8)
        {
        testvalue++;//erase
        
        //make that smaller
        //select a neighbor square
        
        xTemp=0;yTemp = 0;
        
        diagonal=false;
        
        //smaller classfile than switch..
        if(testsquare==0) {xTemp = 1;}
        if(testsquare==1) {xTemp = 1;yTemp = 1;diagonal=true;}
        if(testsquare==2) {yTemp = 1;}
        if(testsquare==3) {xTemp = -1;yTemp = 1;diagonal=true;}
        if(testsquare==4) {xTemp = -1;}
        if(testsquare==5) {xTemp = -1;yTemp = -1;diagonal=true;}
        if(testsquare==6) {yTemp = -1;}
        if(testsquare==7) {xTemp = 1;yTemp = -1;diagonal=true;}
        
        
        xTemp=xNow+xTemp;
        yTemp=yNow+yTemp;
        

        //check if neighbor is in valid range
        if((xTemp>-1)&&(xTemp<pdimX)&&(yTemp>-1)&&(yTemp<pdimY))
        {
            //is it a passable tile? (also checking for the buildingblockings)
         // if(basegrid.LayerPathfindingMain[xTemp][yTemp]==0)
            
            if(terrainGrid[xTemp][yTemp]==1 || dontCareForObstacles) //1-> means ist passable here ///could check for Buildingsquares here too
            {
              
            //each square finding a valid neightbor with acount higher then this squares count+1 -> set to thiscount+1 and add to next list
      
             // Logger.out("nextlistLenght:"+nextlistLenght+"   x:"+xNow+"   y:"+yNow+"grid:"+grid[xNow][yNow]+" other:"+grid[xTemp][yTemp]);
            
                //this takes into account that diagonal movement costs more
            walkdist=10;
            if(diagonal) walkdist=14;
                   
            if(gridFlood[gridId][xTemp][yTemp]>(gridFlood[gridId][xNow][yNow]+walkdist))  //neighbor has bigger stepcount than me?
            {
            //mark the neightbor
            gridFlood[gridId][xTemp][yTemp]=(short)(gridFlood[gridId][xNow][yNow]+walkdist);  //set the stepcount to my stepcount plus one
            //TODO: should be a different value for diagonal movement!, to make paths smoother
            
            
            //grid[xTemp][yTemp]+=basegrid.LayerBuildingblocking[xTemp][yTemp]*3; //this can be used to make building "half passable"
            
            //add this neighbor for the next check
            nextlistLenght++;
            nextlist[nextlistLenght][0]=(short)xTemp;
            nextlist[nextlistLenght][1]=(short)yTemp;
            }
              
          }
        }
        
        //choose the next possible neighbor
        testsquare++;
        }
        //test the next node in the worklist
        countThrough++;
    }
    
    //copy the nextlists contents to the current worklist
     //System.arraycopy(nextlist, 0, worklist, 0,nextlistLenght*2); 
 
        worklistLenght=nextlistLenght;
    
        for (int ix=0;ix<=nextlistLenght;ix++)
        {
            worklist[ix][0]=nextlist[ix][0];
            worklist[ix][1]=nextlist[ix][1];
            
        }
     
     
     
    }
    
    
    
    }
 
    
    //create the list of currently used squares
    static int worklist[][]=null;  //trying a lower dimension reduces the memory use..
    static int nextlist[][]=null;  //trying a lower dimension reduces the memory use..


Posted By: muffel

Re: RTS Project - 01/04/11 11:45

Why do you not use a normal floodfill algortihm which is able to change the value which is drawn
WIKI

EDIT: I should actualize the browser window more often

muffel
Posted By: Rackscha

Re: RTS Project - 01/04/11 13:56

@Redeemer but if you use A* or Djikstra, they wouldnt hang there wink
You wouldnt have to "patch" the graph.
Posted By: Redeemer

Re: RTS Project - 01/04/11 18:57

Oh. I understand what I'm supposed to be doing now.

Quote:
Why do you not use a normal floodfill algortihm which is able to change the value which is drawn

That was my problem. I totally misunderstood how I was supposed to generate the graph.

Quote:
but if you use A* or Djikstra, they wouldnt hang there

They also wouldn't hang there if I used the floodfill algorithm properly. tongue

This shouldn't be hard to fix now that I know what I'm doing. Thanks for the input guys. laugh
© 2024 lite-C Forums