213. Turning to face an object in 2D
Something like this question came up on the Codea forum. If you are at (x1,y1), and an object (perhaps an enemy) is at (x2,y2), how do you figure out how to rotate a sprite to face that object? What if your sprite is drawn sideways to start with?
You could start with trigonometry, but there is a function built into Codea to calculate this for you.
To do this, we need to put the positions into vec2, eg
OurPos = vec2(x1,y1)
EnemyPos = vec2(x2,y2)
Then we can calculate the angle between them with
angle=math.deg(vec2(0,1):angleBetween(EnemyPos-OurPos))
There is a full code example at the bottom if you’d like to try it, but here is the explanation.
How it works
We are at the point OurPos, and want to rotate to face EnemyPos.
We start by calculating which direction we want to look, by subtracting OurPos from EnemyPos (ie telling us which way we have to move from OurPos to get to enemyPos).
Now we need to turn that direction into a rotation in degrees.
Before we can do that, we need to know which way we are facing before rotating. If we are rotating a sprite that has been drawn facing up the screen, then it is facing the direction (0,1) [I could have written this as (0,3), (0,1.65) etc, all that matters is that x=0 and y is positive, which tells us the direction points vertically up the screen].
So we want to rotate from a direction of (0,1) to a direction equal to the difference between OurPos and enemyPos. And this is exactly what the angleBetween function does, as shown in the formula at the top, and in the code example below. Note we have to convert to degrees afterwards, because angleBetween produces an answer in radians.
What is really nice is that it works for all angles from 0 to 360 without any adjustment, and it allows for the fact that positive rotations are anti clockwise in Codea.
Allowing for different sprite angles
This works for sprites which are drawn facing up the screen. But suppose you have a sprite which is drawn facing to the right? You can handle this a couple of ways. One is to simply add 90 degrees to the formula above, so it rotates the sprite to face up the screen before doing the calculations. Or you can realise that your sprite drawing is facing in the direction (1,0), ie towards +x, and alter the formula at top to
angle=math.deg(vec2(1,0):angleBetween(EnemyPos-OurPos))
So it is quite easy to allow for different starting angles for your sprite.
Code example
A red dot moves across the screen at the top, and the spaceship turns to face it. Touch the screen to change the position of the spaceship.
function setup() --make the enemy move left and right at top of screen enemy=vec2(100,HEIGHT-100) tween(10,enemy,{x=WIDTH-100,HEIGHT-50}, { easing = tween.easing.linear,loop = tween.loop.pingpong }) pos=vec2(300,200) --our starting position end function draw() background(50) fill(255,0,0) ellipse(enemy.x,enemy.y,50) --draw enemy --calculate angle to enemy local a=math.deg(vec2(0,1):angleBetween(enemy-pos)) --draw ourselves as a spaceship translate(pos.x,pos.y) rotate(a) sprite("Space Art:Red Ship",0,0) end --touch anywhere on screen to change our own position function touched(t) pos=vec2(t.x,t.y) end
Trackbacks & Pingbacks