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) ?