### Author Topic: Keeping track of character direction  (Read 1356 times)

#### stownshend

• byte
• Posts: 25
##### Keeping track of character direction
« on: September 08, 2011, 02:18:07 am »
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).

Code: [Select]
`private SimpleVector queenDirection;`
And the initialization of the initial direction:

Code: [Select]
`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

Code: [Select]
`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)):

Code: [Select]
` 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:

Code: [Select]
` 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.

#### EgonOlsen

• Posts: 11898
##### Re: Keeping track of character direction
« Reply #1 on: September 08, 2011, 07:55:38 am »
You might want to check out the getRotationMatrix()-method in SimpleVector. Try to feed the direction vector you create into it and use the result as the new rotation matrix for your object.

#### Alexey

• int
• Posts: 50
##### Re: Keeping track of character direction
« Reply #2 on: September 08, 2011, 09:23:44 am »
Hello all! Egon, could you add a method lookAt(SimpleVector) to Object3D, like Camera has?

#### stownshend

• byte
• Posts: 25
##### Re: Keeping track of character direction
« Reply #3 on: September 09, 2011, 06:31:43 am »
Hi Egon,

Thank you very much for the suggestion!

It took a little bit of fiddling but the code and algorithm is ridiculously simple compared to what I was trying to achieve before. It works like a charm, she is facing whatever tile I click without any hassle.

My problem was that I thought you had to do an Object3D.rotateMesh() after setting up a rotation matrix in order to make it do the rotation but it wasn't required. My code:

Code: [Select]
`SimpleVector queenDesiredEyeline = new SimpleVector( destinationX - antQueen.getTransformedCenter().x, 0, destinationZ - antQueen.getTransformedCenter().z).normalize(); Matrix queenRotationMatrix = new Matrix(queenDesiredEyeline.getRotationMatrix()); Log.d("queenDesiredEyeline",queenRotationMatrix.toString()); antQueen.setRotationMatrix(queenRotationMatrix);`