0

Using three.js, I'm creating a game with cars that move in a specific direction, depending on their y-rotation. An example would be 90 degrees. I use object.translateZ() to move them forward but I've run into a problem.

I'm using physijs to simulate the cars. Cars that run into each other may change their y-rotation (because of the crash) and I want to find a way for the cars to slowly change their rotation back to the original rotation like they are turning to get back on the road. Without this my city is very chaotic.

Here's the code that I'm already using (this is just part of it):

var targetRotation = 90
var rotation = car.mesh.rotation.y * 180 / Math.PI //to convert to degrees

I want to find a way to slowly change the car's rotation so it's the same as the target rotation.

Any help is appreciated! (but some sort of function would be perfect)

Griffin M.
  • 196
  • 1
  • 17

1 Answers1

2

I've done stuff like this before in other systems (2D, not Three.js), and essentially all you want to do is gradually increment the angle until you reach something close enough to the target angle. Usually this means the float is less than the turning speed you're incrementing by (so you don't "overshoot" the value).

The amount of the increment depends on how quickly you want them to turn.

You also want to check if it's better to increase the angle or decrease (do you turn clockwise or counterclockwise) depending on if you're closer to 360 or 0. This prevents the car from turning the "long way" around. You can find this out by seeing if the difference is greater/less than 180.

We can use the modulus operator to get the "real" angle between -360/360.

var currentAngle = car.mesh.rotation.y * 180 / Math.PI; //car's angle in degrees
var targetAngle = 90; //preferred angle *this time* ;)
var turningSpeed = 1; //one degree per update (wayyy to high for real stuff, usually)
currentAngle = currentAngle % 360; //get the 0-360 remainder
if ( Math.abs(targetAngle - currentAngle) >= turningSpeed) {
  var addto = 0
  if (targetAngle - currentAngle < 0) {
    addto = 360
  }
  if ( targetAngle - currentAngle + addto <= 180 ) { 
    currentAngle += turningSpeed;  
  }
  else {
     currentAngle -= turningSpeed;
  }
}
else { currentAngle = targetAngle; } //we're close enough to just set it
car.mesh.rotation.y = ( currentAngle * Math.PI ) / 180; // back to radians!
Hectate
  • 210
  • 2
  • 9
  • I just noticed a glitch, if the current angle is 0 and the target angle is 90 it goes down to -90, any way to fix that? – Griffin M. Dec 13 '16 at 04:27
  • Yeah I was just thinking about the math and noticed a couple of errors in the turning; I'm mapping out the range right now to examine the formula. Gimme a min... – Hectate Dec 13 '16 at 04:36
  • I suggested an edit that i think works, since your formula couldn't handle when the `currentAngle` is bigger than the `targetAngle`. – Griffin M. Dec 13 '16 at 04:42
  • It wasn't reversing properly. I looked at the values in a spreadsheet to figure out my error, and it can be done with more math and if checks, or just increasing the value. I accepted your edit to reflect the change. – Hectate Dec 13 '16 at 05:20
  • Thanks so much for your work! I suggested another edit to check if the angle is negative or greater than 360. – Griffin M. Dec 13 '16 at 05:27
  • Also, glad to help! – Hectate Dec 13 '16 at 05:29
  • Fixed with an easier way; use the modulus operator. – Hectate Dec 13 '16 at 05:33