Sign in to follow this  

Left/Right based off angle + rotation

This topic is 4074 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all, I am having a serious brain fart momment here. I am working on a 2D tutorial for an upcoming chapter and I know im doing things way harder then they have to be. I for the life of me though, cant figure out the simple thing im missing :( Its a 2D game, where the AI needs to determine which way to turn. My inputs for the AI in this case are a total rotation in degrees where 0 = up (toward y=0) and 179 = down. I also have the angle between the ai sprite and the player sprite. The angle has a value in degrees as such: 0-90 = top left 91-180 = top right 0 - neg 90 = bottom left neg 91 to neg 180 = bottom right So I have the current rotation of the computer sprite ( from 0 - 359 degrees ), and the angle I need to rotate towards. Granted, I have it working, its just im sitting at around 20 lines of code to do so ( basically a test for each of the four possible quadrants, then a test within a quadrant for left or right ). I just know that it can be done most likely in one or two lines of code and im way going overboard. Can someone see what im missing here? EDIT: Forgot to mention... the outputs consist of basically turnleft, turnright, or do nothing. There is no state between updates ( in other words, I have no idea what move I did last update ) and this is by design.

Share this post


Link to post
Share on other sites
Does 'tutorial for an upcoming chapter' mean homework of some sort? If so I don't want to give a complete answer, but in general these sorts of problems are better expressed in terms of coordinate systems.

Consider that each object has a local coordinate system with a forward vector and a side vector (which is x and which is y is up to you). If you then transform the target into the local space of the object, you have all the information you need to drive the AI (especially for a simple 'turn left, turn right, or do nothing' scheme).

So in short, construct the local system for your object from its angle, transform the target position into this coordinate system, and then go from there.

Share this post


Link to post
Share on other sites
No, upcoming chapter is refering to sample code for the 5th chapter in the free XNA book I am writing. I have it working, I just think my implementation is far more complex than it needs to be. Its alot harder writing code for complete beginners... I never expected it to be as difficult as it has been. Not only making something functional, but educational and easily read is lots of work. Plus, writing code you know thousands of others will see makes you doubly paranoid :)

I have a coordinate system ( standard cartesian coordinates ), and I have a direction vector for each sprite. However, what I am working on now is a very simple AI system that controls the game the same way a player does... for example, while the player is to the left, I want controlState->MoveLeft = true.

The problem is, I cant simply move the sprite in the direction of the other player, as the sprites implement yaw ( pivoting around their center ). The coordinates I defined earlier arent the world coordinates, they are the position of the players sprite relative to the computer sprite. I suppose I also have the x,y coordinates, current rotation and direction vector of each sprite to work with, but in this case, I think I only really need to care about those two values ( currentRotation of ai sprite, and current offset angle of players sprite to the computer sprite ).

Hope that makes sense.

This might make my situation a bit clearer:

Vector2 playerPosition = _player.position;
Vector2 cpuPosition = _computer.position;

int distance = (int)(Math.Sqrt(Math.Pow(cpuPosition.X - playerPosition.X, 2.0) + Math.Pow(cpuPosition.Y - playerPosition.Y, 2.0)));
float angle = MathHelper.ToDegrees(((float)(Math.Atan2(cpuPosition.Y - playerPosition.Y, cpuPosition.X - playerPosition.X - MathHelper.PiOver2))));
float currentRotation = MathHelper.ToDegrees(_computer.currentRotation);
if (currentRotation < 0)
{
currentRotation = 360 - currentRotation;
}
// Angle values work as follows relative to the cpu sprite
// 0 - 90 Top left
// 91 - 180 Top right
// - 0 to - 90 bottom left
// -91 to -180 bottom right


The code that follows is a sequence of 8 if statements. My brain tells me I can figure out if I need to go left or right at this point in just one line of code, or perhaps two... but that single line of code isnt coming to me :(

EDIT: Oh and "MoveLeft" is kinda a misnomer... what I really mean is continue rotating left. The sprites move forward based on their velocity elsewhere. The MoveLeft command actually controls yaw rotation and cycling through a bitmap series ( aka, graphically updating the amount the plane is banked )

Share this post


Link to post
Share on other sites
Sorry about misconstruing this as a homework problem - it's just that the mods discourage answering homework-related questions here, so if the nature of the question isn't clear from the post, it's usually best to err on the safe side.

Anyway, I still think you're barking up the wrong tree here. I'll try to sketch out some pseudocode:
// The object's forward vector (assuming the object is oriented along
// the x axis in local space):
vector2 forward(cos(angle),sin(angle));

// The object's side vector:
vector2 side(-forward.y,forward.x);

// The coordinates of the target in the object's local space
vector2 diff = target - position;
vector2 local_target(dot(diff,forward),dot(diff,side));

// Turn:
if (local_target.y < 0) {
TurnRight();
} else if (local_target.y > 0) {
TurnLeft();
}
In practice you'll want to apply a tolerance to the direction test; otherwise, the object may 'jitter' back and forth as it approaches the target.

The above is not guaranteed to be error-free, but it should be close, and I really think it's a better way to express the problem than your current method. But YMMV.

Share this post


Link to post
Share on other sites
You're right, I was making things way more complicated then they had to be. Your pseudo code worked perfectly ( oh, and btw, translated almost exactly to real code, very impressive pseudo code!!!!! :D ). Thanks alot, I knew I was over engineering there.

Oh, to show how close you were... heres the final code


Vector2 playerPosition = _player.position;
Vector2 cpuPosition = _computer.position;

Vector2 forward = _computer.direction;
Vector2 side = new Vector2(-forward.Y, forward.X);
Vector2 diff = playerPosition - cpuPosition;
Vector2 localTarget = new Vector2(Vector2.Dot(diff, forward), Vector2.Dot(diff, side));
if (localTarget.Y < 0)
controlState.MoveLeft = true;
if (localTarget.Y > 0)
controlState.MoveRight = true;



Almost line for line identical!

Thanks again.

Share this post


Link to post
Share on other sites

This topic is 4074 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this