trouble with 2D vector calculations

I am writing a game with directx in which the player can hurl himself off of planets, into space, at which time he will be affected by gravity of other planets and be sucked onto whichever planet he collides with first.

The stored entity position is the position of the centre of the object, to make gravity calculations easier.

The following code is supposed to use the position of the rock and the player to calculate the angle at which to 'attach' the player to the rock. an angle of 0 radians puts the player directly underneath the planet, 1 radian puts him directly on top of the planet. Currently the below code works when the player approaches a planet directly from the top or side, but when coming at an angle the player is attached in the wrong place. It also only works when the player approaches from the right but this will be sorted after I get the angle calculations correct.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

if (m_entityVector[a]->getType() == player)
								if (m_entityVector[b]->getType() == rock)
                                                                {
									D3DXVECTOR2 playerPos = m_entityVector[a]->getPos();
									D3DXVECTOR2 rockPos = m_entityVector[b]->getPos();
									
									int playerWidth = VIS.getFrameWidth(m_entityVector[a]->getID()) * m_entityVector[a]->getScale();
									int rockWidth = VIS.getFrameWidth(m_entityVector[b]->getID()) * m_entityVector[b]->getScale();
									
									// obtain the position of the 'feet' of the item about to be attached
									// by getting a vector going from the item to the rock
									// taking its unit vector and multiplying it by half the width of the item
									D3DXVECTOR2 playerToRock = rockPos - playerPos;
									playerToRock = CUtility::UnitVector(playerToRock);
									playerToRock = playerToRock * (playerWidth/2);
									D3DXVECTOR2 feetPos = playerPos + playerToRock;
									
									// find the position of the top of the rock
									D3DXVECTOR2 topOfRock(rockPos.x, rockPos.y - (rockWidth/2));

									// find the y distance between the 'feet' and the top of the rock
									float yDiff = (feetPos.y - topOfRock.y);

									// divide by the width of the rock giving us a value between 0 and 1
									// by which we multiply pi radians to obtain the angle at which to attach
									float scalar = yDiff/rockWidth;
									m_entityVector[b]->Attach(m_entityVector[a], D3DX_PI + (D3DX_PI*scalar)
                                                                }


I have tested the Attach function and it works exactly as it should.

Please feel free to ask questions if the code is unclear.

Thanks.
quirkyusername wrote:
Please feel free to ask questions if the code is unclear.

Could you move your code a little farther over to the right? I can still see some of it... ;o)
Last edited on
Aww i got excited when I saw I had a reply, very helpful that reply was =P yeah sorry about the text I maybe should've previewed the post
Why are you using only the y difference?
See here to get the angle:
http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm

Or the abridged version: float angle=atan2(ydiff,xdiff);

By the way, shouldn't you be using playerHeight/rockHeight? For me the height is the length along the y axis, so this seems a bit weird.
Some questions:

* What is your coordinate system? Is the angle theta in terms of the entity (the rock in this case)? If this is the case, why does -1 and 1 correspond to the top and bottom of the rock. I would assume it would be -pi and +pi respectively in euclidean coordinates.

* Athar's solution looks correct. Use the arctan function (atan2() in C++) to calculate the angle between the difference between the x and y coordinates of the rock and player (ie: y2 - y1 = y_diff and x2 - x1 = xdiff) The atan2(xdiff, ydiff) will yield the correct angle.

Watch out though.... this is an angle relative to xdiff and ydiff. Depending on your coord. system, you might have to manipulate the angle by adding/subtracting pi.

I can draw you a pic if that wasn't clear enough.
1 - I know very little about maths so that's probably why I only used the y difference, I just figured that if the feet, the part which will be touching the planet, were half way between the top and the bottom of the rock, it should go right on the side of the rock, and if they are at the same level as the top of the rock, it shoud go right on top of the rock. You may be right. Let me make sure you have it clear that the player can only travel around the outside edge of the rock, there is no 3d element to the game. Just one question, will the atan function return an angle in radians or degrees?

2 - In this case the height and width of my textures are the same so it made no difference but you're totally right.

3 - You're totally right cdel 2pi radians corresponds to one full journey around the rock, don't know why I put 0 and 1, I must've been thinking in terms of the scalar that I calculate.



atan2() returns the value in radians.

I'm very interested in your project. Can you tell me more on what development tools and platform you're using, what's the general idea/goal of the project, and what are your thoughts/motivations in completing such a project?

I am leaning towards doing a similar project myself.
I don't really have a goal for the project it's just something to keep me programming during the summer, I'm going into my final year of university this year and don't want to get out of the habit. Im making a win32 application and I got the idea when playing super mario galaxy, in a way it will be similar but in 2d, but it is not yet fully designed so who knows how it will end up.

The thing I find most interesting about it though is that in the way I'm making it, my entities will contain pointers to other entities allowing the environment that an entity exists in to be controlled by the entity which currently holds a pointer to it. For example, when the player is floating around in space it will be updated in the main update loop of the world class, having gravity applied to him, but when he is attached to a planet it will be updated within the update function of that planet, because of course once a player is on a planet it should no longer be pulled by other planets until it is launched back into space.

It may never get completed, but I'm having fun with it. Thanks for the interest and even more for the help =)
Good stuff. When I first read your problem it reminded me of Super Mario Galaxy. Didn't know that was your inspiration haha! good luck
Topic archived. No new replies allowed.