3
\$\begingroup\$

This is probably best described by image: top row: standing character, moving character on flat ground, moving character on sloped ground; botton row: moving character on multi-sloped ground

I have a character. For floor collision, it uses a single point (the red X). When the character moves, it conforms to the terrain; note how the blue line (its movment per frame) is the same length regardless of the slope.

I have the top three situations working fine. The issue is the bottom one, where the character is crossing over a change in slope. I handle the single-slope case just by rotating the impending movement vector, but obviously that won't work here.

My first instinct was to do something like this:

  1. Measure length to next vertex along first slope.
  2. Subtract length from impending movement vector.
  3. Position impending movement vector at vertex; rotate to match second slope and get resulting position.
  4. Put character at result position.

The problem is that it doesn't seem like this will chain very well if the character has to cross over three or more segments at once (maybe it's moving very fast over round-like terrain).

So basically at this point I'm looking to see if there's an easier solution I'm missing.

\$\endgroup\$
  • 2
    \$\begingroup\$ The short answer is that you have to do the steps you planned in a loop until all the impending movement has been used up. You are on the right track. The only way you could possibly skip this iterative solution is if your terrain was defined by a mathematical function. Then maybe you could do some fancy math with integrals and get your result without iterating. \$\endgroup\$ – Alan Wolfe Jun 7 '15 at 0:41
  • \$\begingroup\$ a solution to having round edges. would be to calculate the radius of a rounded floor. find the angle covered, and factor that into the circumference ot angle ratio. \$\endgroup\$ – HgMerk Jun 7 '15 at 1:50
4
+25
\$\begingroup\$

So what you want is like this?

Like this?

As Stephan says, you have the right idea, just repeat it until you're all out of movement.

 1. Measure length to next vertex along first slope.
while( impending movement vector > length to next vertex )    
{    
 2. Subtract length from impending movement vector.
 3. Position impending movement vector at vertex...
 1. Measure length to next vertex along first slope.    
}
 3.1 ...rotate to match second slope and get resulting position.
 4. Put character at result position.
\$\endgroup\$
1
\$\begingroup\$

You are describing the proper algorithm. If you loop while you have remaining movement left, it wont matter how many segments you have to cross over. All of the calculations you describe are O(1) calculations so performance isn't an issue.

Keep in mind that all terrain is triangles under the hood, so Trig and/or Dot Products may possibly offer some calculation advantages, but still within O(1) domain.

\$\endgroup\$
0
\$\begingroup\$

I guess terrain is 2d from the picture. If it is terrain the {x} axis distance between every vert should be constant. I also condider both players are grounded.

Now lets have such varriables: Player 1 : p1where we have p1.x and p2.x

Player 2 : p2 same as player 1 Let's also say player p1 is before p2 in other words he is behind him vert array: V with lenght n

and {x} spacing between every vertex : s

now what we need to find is a float variable we call: distance

i also consider the terrain start point is at x=0 Algorithm:

First of all we need to determinate the start and end vertex index v_start v_end

Dividing p1,p2 with spacing we can find on which segment does the players stand. as the player 1 is behind player 2 we find that we need to take the front vert from the segment from player 1 and the back vert from player 2. So as finding this we can start calculating the distance.

Notice now we have v_start v_end

Let's say we have function dist whcih finds distance in 2d space

fist of all you must calculate distance between the player 1 and v_start and player 2 and v_end

and then we need to find distance between all segments inbetween verts v_start and v_end

we have:

distance = 0
for(int v = v_start; p<v_end;p++)distance+=dist(verts[v],verts[v+1]);
distance += dist(p1,verts[v_start]);
distance += dist(p2,verts[v_end]);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.