Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

diagram

I'm making an isometric game. When the player tries to walk diagonally into a wall I want them to slide smoothly across it, so whatever portion of the movement would be legal is used, and anything in the direction of the normal is thrown away. Walls can be any angle, not just vertical or horizontal, and the player has 360 motion.

I feel like I'm almost there but I can't put the last piece into place.

Update: great news everyone! I have it working. But... I'm a bit confused what I should be normalising and what not. The normal just needs to be a unit vector, right? but then I'm mixing that with my input so I'm normalising that - am I wrong?

By the way, I have also found that I need to push the player 1 pixel in the direction of the normal, so that they don't get stuck on things - works well.

share|improve this question

2 Answers 2

up vote 10 down vote accepted

Just project your vector of motion onto the plane normal and then subtract the result from your vector of motion.

Vector undesiredMotion = normal * (dotProduct(input, normal));
Vector desiredMotion = input - undesiredMotion;

Something like that anyway. Although in your lovely diagram the input seems to be away from the wall so I'm slightly confused.

share|improve this answer
    
sorry he's supposed to be in front of a vertical wall there. terrible drawing –  Iain Sep 23 '10 at 17:49
1  
I'm a bit confused about dot product. Isn't dot product a scalar? –  Iain Sep 23 '10 at 17:54
1  
Yes, but you multiply it by the normal (a vector) to get the vector of your undesired motion. A vector (x,y,z) multiplied by the scalar s gets you the vector (sx,sy,sz). –  Chris Howe Sep 23 '10 at 18:37
    
Done, changed the variables to hopefully match the diagram. :) –  Chris Howe Sep 23 '10 at 20:11
    
@Iain I'm really trying to understand how to use this answer but I can't seem to grasp it. When I create this exact code I get really weird desiredMotion results. Did you ever get this working? –  test Oct 12 at 6:00

While it's straight forward to just remove the component of the motion that is in the direction of the normal, it may suit your gameplay to rotate the motion vector instead. For instance, in a 3rd-person action game, it may be easy to get slightly hung up on walls and other boundaries, so you can make some guesses at what the player intends.

// assume that 'normal' is unit length
Vector GetDesired(Vector input, Vector normal) {
   // tune this to get where you stop when you're running into the wall,
   // vs. bouncing off of it
   static float k_runningIntoWallThreshold = cos(DEG2RAD(45));

   // tune this to "fudge" the "push away" from the wall
   static float k_bounceFudge = 1.1f;

   // normalize input, but keep track of original size
   float inputLength = input.GetLength();
   input.Scale(1.0f / inputLength);

   float dot = DotProduct(input, normal);

   if (dot < 0)
   {
      // we're not running into the wall
      return input;
   }
   else if (dot < k_runningIntoWallThreshold)
   {
      Vector intoWall = normal.Scale(dot);
      intoWall.Scale(k_bounceFudge);

      Vector alongWall = (input - intoWall).Normalize();
      alongWall.Scale(inputLength);

      return alongWall;
   }
   else
   {
      // we ran "straight into the wall"
      return Vector(0, 0, 0);
   }
}
share|improve this answer
    
Nice. But if you scale by a fudge factor does that make you bump along the wall vs sliding along it, or is it just a case of tweaking it? –  Chris Howe Sep 23 '10 at 20:14
    
My thought is that you tweak it to look ok; certainly if it is too big it'll look like you're bouncing but if it's subtle enough it'll just keep you from getting hung up on slight bends in the surface. –  dash-tom-bang Sep 23 '10 at 21:44

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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