I have a character in my game who sits in the middle of a 5x5 grid of tiles. Aesthetically she has a front (where she is looking).
When I click on one of the tiles, I want my character to look at the centre of that tile.
I've currently spent 6 hours or more trying to work this out but I'm failing miserably. I will describe my approach below, but if there is an easier way or a way JPCT-AE can assist me in doing this, that would be great.
My approach:
My character is called the Queen. I've set up a property which is a SimpleVector which represents the direction the Queen is looking. At first she is looking away from the camera so this Vector is set to (0,0,1).
private SimpleVector queenDirection;
And the initialization of the initial direction:
public void onSurfaceCreated(GL10 gl, EGLConfig config)
{
// The Queen is originally facing to 0 degrees.
queenDirection = new SimpleVector(0f,0f,1f);
...
My algorithm is:
- Calculate a vector from the Queen's current position (0,0,0 for now in world space) to the centre of the tile selected. I use the formula vector = destinationX-currentX, destinationY-currentY, destinationZ-currentZ
SimpleVector eyeline = new SimpleVector(
destinationX - queen.getTransformedCenter().x,
0,
destinationZ - queen.getTransformedCenter().z).normalize();
- Then I calculate the angle (in radians) between the Queen's current viewing direction, and this new vector using the formula angle = acos((v1 DOT v2) / (v1.length * v2.length)):
float dotProduct = queenDirection.calcDot(eyeline);
Double temp = (double) dotProduct / ( queenDirection.length() * eyeline.length());
double angle = Math.acos(temp)
... but already I run into problems because (perhaps due to the accuracy of float/double or something else) the dotProduct and therefore "temp" variable which is passed into the arc cosine function is sometimes either slightly higher than 1 (1.00000123) or it's negative - either way the acos function returns NaN because it only accepts parameters between 0 and 1.
The code which actually does the rotation is:
if ( angle > 0.5 )
{
queen.rotateY((float) angle);
queenDirection.x = eyeline.x;
queenDirection.z = eyeline.z;
}
I'm not great at mathematics, but I'll get stuck into if it I have to. My primary question is whether there is an easier way? If not, I'll keep working at this but I wanted to check before I spend another 6 hours at it.
This game is going to have a lot of models who need to turn and face each other often, so I need to have this down before I move on.