🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Unit movement

Started by
4 comments, last by pasman 22 years, 10 months ago
Hi, I''m trying to write a RTS gameand i''ve got problems with the units... I''ve managed the collision detection and everything goes well but in some cases, when a unit is colliding, the game suddenly slows down. Here is some part of the code:

procedure TPlayer.move;
var i,dir,a,b,c:integer;
begin
  for i:= 0 to nunits do
    with units <span class="cpp-keyword">do</span>
      begin
        <span class="cpp-keyword">if</span> status=sDead then <span class="cpp-comment">// the unit is dead so no need to move/display</span>
          <span class="cpp-keyword">continue</span>;

        <span class="cpp-keyword">if</span> path.empty then <span class="cpp-comment">// the main destination was reached</span>
          begin
            status:=sStay; <span class="cpp-comment">// set the unit to the status of standing</span>
            <span class="cpp-keyword">continue</span>;
          end;

        <span class="cpp-comment">//we''ve reached a point in the path</span>
        <span class="cpp-keyword">if</span> (coord.x=path.next.x) and (coord.y=path.next.y) then
          begin
           path.popnext;<span class="cpp-comment">//get next destination</span>

           <span class="cpp-comment">//collision with another unit</span>
           a:=getunitindexexcepti(path.next.x,path.next.y,i);<span class="cpp-comment">//returns the index of the unit in a map coord except the curent unit</span>
           b:=getnextunitindex(path.next.x,path.next.y,i);<span class="cpp-comment">//returns the index of the next checkpoint of the unit in a map coord except the curent unit</span>
           c:=getunitindexexcepti(coord.x,coord.y,i);<span class="cpp-comment">//returns &lt;&gt;-1 if there is a unit beside curent unit in the specified cell</span>
           <span class="cpp-keyword">if</span> (c&lt;&gt;-<span class="cpp-number">1</span>) or (a&lt;&gt;-<span class="cpp-number">1</span>) or (b&lt;&gt;-<span class="cpp-number">1</span>) then
             begin
{               <span class="cpp-keyword">if</span> pathcalls&gt;<span class="cpp-number">20</span> then
                 begin
                   status:=sWait;
                   pathcalls:=<span class="cpp-number">0</span>;
                   <span class="cpp-keyword">continue</span>;
                 end;}
               path:=findpath(coord.x,coord.y,endcoord.x,endcoord.y,i);<span class="cpp-comment">//calculates the path of the unit to the destination point</span>
               <span class="cpp-keyword">continue</span>;
             end;
            changedpath:=<span class="cpp-keyword">false</span>;
          end;

        <span class="cpp-keyword">if</span> path.empty then <span class="cpp-comment">// the main destination was reached</span>
          begin
            status:=sStay; <span class="cpp-comment">// set the unit to the status of standing</span>
            <span class="cpp-keyword">continue</span>;
          end;

        dir:=getdir(i); <span class="cpp-comment">//calcs the direction of the unit</span>

        <span class="cpp-keyword">if</span> status=sWait then
          begin
            inc(tfinecoord.x,directionmovement[dir].x*speed);<span class="cpp-comment">//add to the wait fine coordinate</span>
            <span class="cpp-keyword">if</span> (tfinecoord.x mod mainform.map.gettilewidth)=<span class="cpp-number">0</span> then <span class="cpp-comment">// the unit stepped onto a tiles in waiting mode</span>
              status:=smove;
   
            inc(tfinecoord.y,directionmovement[dir].y*speed);
            <span class="cpp-keyword">if</span> (tfinecoord.y mod mainform.map.gettilewidth)=<span class="cpp-number">0</span> then
              status:=smove;
          end
        <span class="cpp-keyword">else</span>
          begin
            inc(finecoord.x,directionmovement[dir].x*speed);<span class="cpp-comment">//add to the fine coordinate in waiting mode</span>
            <span class="cpp-keyword">if</span> (finecoord.x mod mainform.map.gettilewidth)=<span class="cpp-number">0</span> then <span class="cpp-comment">// the unit stepped onto a new tiles in waiting mode</span>
              begin
                inc(coord.x,directionmovement[dir].x);
                finecoord.x:=<span class="cpp-number">0</span>;
              end;
   
            inc(finecoord.y,directionmovement[dir].y*speed);
            <span class="cpp-keyword">if</span> (finecoord.y mod mainform.map.gettilewidth)=<span class="cpp-number">0</span> then
              begin
                inc(coord.y,directionmovement[dir].y);
                finecoord.y:=<span class="cpp-number">0</span>;
              end;
          end;

    end;
end;
 
</pre></div><!–ENDSCRIPT–> 

OK, so I know the problem is that ''findpath'' is called los of time in some cases up to 100 times 
for &#111;nly &#111;ne unit, but how can i fix it?
Thanks

P.S. : I posted this quastion toseveral topics because I don''t really know where it belongs.  

[Edited by - pasman on March 7, 2006 10:39:49 AM]
Advertisement
quote: Original post by pasman

OK, so I know the problem is that ''findpath'' is called los of time in some cases up to 100 times
for only one unit, but how can i fix it?
Thanks


Rather than post a long chunk of code, why don''t you write out the algorithm that you used to build the code. It will be far easier for anyone to take a look at the problem in that format rather than having to decipher a particular language (even though Pascal is fairly easy to read).

quote: Original post by pasman
P.S. : I posted this quastion toseveral topics because I don''t really know where it belongs.


This forum would be the first place to post (rather than cross posting). If a thread doesn''t belong here, ferretman will happily move it!

Cheers,

Tim
Hi, sorry about that (and the delay) i''ll post now the pseudo code, so hopefully someone could help me.
  for all_the_moving_units_in_the_game    {      if new_waypoint_reached        {  	  get_next_waypoint_from_path	  if (there''s a unit in the next cell) or 	     (the next cell is also the next cell of another unit) or 	     (there''s anoter unit in the current cell) or     	     (the current cell is the next waypoint of another unit)	    {              if too_many_path_calls                {                  set units_status = Wait                  procced_to_next_unit                }              find_new_path              procced_to_next_unit            }        }      if no_more_waypoints      {        set unit_status = Stay         if another_unit_is_waiting_because_of_this_one           find_new_path_for_that_unit and set unit_status = Move        procced_to_next_unit      }	        get_the_heading_of_the_unit      move_in_the_specified_direction    }

Ok, some other info... The findnewpath function considers all the units(current possition) unpassable and also sets the pathcalls for a specified unit. The move procedure uses some ''fine'' coordinates and when that fine coordinate gets to tiles size then we set the actual unit coordinate.
The problem occurs if we have more than 9 units selected. In that case some units are overlapping. Up to 9 units works ok, I guess there is something in the collision detection, everything is based on map coordinates, no ''graphic'' collision detection.
I hope this is more clearly, because i really need to solve his problem soon because my deadline is close and
I really need to make it work fine till than. If you need to se the project you can download it at www.geocities.com/metalpasman/index.html
Thanks

[Edited by - pasman on March 7, 2006 10:58:25 AM]
Every time a path is blocked, you try to recalculate the path for that unit. Does this new path take the previous obstacle into account? If 2 units are trying to get to the same place, what stops them both recalculating their paths every time you enter that loop?
Thanks, but what do you mean when you ask if the previous obstacle into account? The ''find_new_path'', at each call, creates an array of obstacles according to the position of all the units.
To prevent 2 units that are in collision to recalculate the path i could use priorities like in ''Coordinated unit movement'' article (is that a good solution?)
But still, are those collision conditions enough because the units are still overlapping? What other conditions should
i put? Thanks
You recalculate the paths every time some paths cross (ie. 2 units have waypoints in the same place). However, when you recalculate those paths, do you ensure that they don''t cross again? Otherwise you''re gonna find that they keep getting recalculated, keep sharing a waypoint, and so on.

This topic is closed to new replies.

Advertisement