TLDR: How would you implement an algorithm that makes an entity rotate until it gets close to a target orientation at which point it slows down the rotation and completely stops the rotation when it hits the matching orientation? Also, what is the simplest way in PlayCanvas to get an entity’s orientation around the Y axis in a scale of (-180 to 180)?
I’m working with objects only moving on a 2D plane. I found this nice algorithm to smoothly match a game object’s orientation with that of another target game object. Here it is in pseudo-code:
1 class Align: 2 # Holds the kinematic data for the character and target 3 character 4 target 5 6 # Holds the max angular acceleration and rotation 7 # of the character 8 maxAngularAcceleration 9 maxRotation 10 11 # Holds the radius for arriving at the target 12 targetRadius 13 speed 14 # Holds the radius for beginning to slow down 15 slowRadius 16 17 # Holds the time over which to achieve target speed 18 timeToTarget = 0.1 19 20 def getSteering(target): 21 22 # Create the structure to hold our output 23 steering = new SteeringOutput() 24 25 # Get the naive direction to the target 26 rotation = target.orientation - 27 character.orientation 28 29 # Map the result to the (-pi, pi) interval 30 rotation = mapToRange(rotation) 31 rotationSize = abs(rotation) 32 33 # Check if we are there, return no steering 34 if rotationSize < targetRadius 35 return None 36 37 # If we are outside the slowRadius, then use 38 # maximum rotation 39 if rotationSize > slowRadius: 40 targetRotation = maxRotation 41 42 # Otherwise calculate a scaled rotation 43 else: 44 targetRotation = 45 maxRotation * rotationSize / slowRadius 46 47 # The final target rotation combines 48 # speed (already in the variable) and direction 49 targetRotation *= rotation / rotationSize 50 51 # Acceleration tries to get to the target rotation 52 steering.angular = 53 targetRotation - character.rotation 54 steering.angular /= timeToTarget 55 56 # Check if the acceleration is too great 57 angularAcceleration = abs(steering.angular) 58 if angularAcceleration > maxAngularAcceleration: 59 steering.angular /= angularAcceleration 60 steering.angular *= maxAngularAcceleration 61 62 # Output the steering 63 steering.linear = 0 64 return steering
The algorithm requires that I be able to calculate the angle around the Y axis for both objects in order to determine the shortest ‘distance’ and direction between both orientations. It is implemented in radians but can easily be done with degrees. I have written a function that takes in a start angle and stop angle and returns the shortest distance between them in positive or negative degrees indicating the direction. The function takes in any positive or negative numbers, and outputs degrees between -180 and 180.
I have been trying to get the entities’ Y axis orientation by doing entity.getRotation().y but I quickly realized that this output is not on a -180 to 180 scale but rather a -90 to 90 scale and is dependant on the rotation value of x (0 or 180) to know the correct half of the circle. This is starting to get complicated.
The algorithm is pretty simple, it basically makes the entity rotate until it gets close to the target orientation at which point it slows down the rotation and stops rotation when it hits the matching orientation. How would you implement this in PlayCanvas? Is there a simpler way, or one that fits more naturally with PlayCanvas, that the one in the proposed algorithm. If not, what is the simplest way to get an entity’s orientation around the Y axis in a scale of (-180 to 180) ?