Simple trig problem driving me crazy

Started by
13 comments, last by Catch_0x16 5 years, 9 months ago

Hello folks,

I am fighting with a really simple problem that has been driving me nuts. I'm usually fairly confident with trigonometry and I'm pretty sure the issue here is not the math but in some behavior behind the scenes.

A bit of background - basically I'm developing my own little 2D game engine using C++, in my free-time for fun. I work with game technology and simulation products IRL so for the most part this has been plain sailing. I am using Box2D for physics, and SFML for rendering.

My game at current has a few space ships flying around via keyboard and AI input. These space ships need exhausts! So I'm currently in the process of getting a 'component' system in place, however my problem is that the animated exhaust sprites are not going where I want them to.

When the base GameObject class runs it's update method, it does the following:

  1. Queries the physics object for a position
  2. Converts the physics position to a pixel position (x10 scale factor)
  3. Moves the sprite to the new position
  4. Passes new position to all 'component' objects into their 'UpdateComponent' method
  5. Components move their sprite to the correct position

However the exhaust sprites seem to wander around all over the place, in no way representing where I actually want them to be! This should have been a simple case of:

  • newPosition = (sin(rotationRadians) * offsetX, cos(rotationRadians) * offsetY) + oldPosition

Here is the current code:


void Exhaust::UpdateComponent(const Vec2f & position, float rotationDegrees, float deltaTime)
{
	float angleRad = DEGREES_TO_RADIANS(rotationDegrees);
	float offsetX = sin(angleRad) * mOffset.x;
	float offsetY = cos(angleRad) * mOffset.y;

	sf::Vector2f newPos(position.x + offsetX, position.y + offsetY);

	mSprite->SetRotation(rotationDegrees);
	mSprite->SetPosition(newPos);
	mSprite->Update(deltaTime);

#ifdef _DEBUG
	sf::Vector2f p(position.x, position.y);
	stringstream ss;
	ss << rotationDegrees;
	DebugUtils::DrawCross(p, 8, sf::Color::Green, ss.str());
	DebugUtils::DrawCross(newPos, 8, sf::Color::Green);
	DebugUtils::DrawLine(p, newPos, sf::Color::Green);
	cout << rotationDegrees << endl;

	DebugUtils::DrawSpriteOutline(*mSprite->GetGraphic(), sf::Color::Green);
#endif // _DEBUG
}

 

And here is a gif of it all going wrong! (link below)

Gif of game engine problem

Any help would be much appreciated, even if it is just a thought of where the problem might be originating from!

Thanks!

Advertisement
1 minute ago, Guy Leonard Thomas said:

newPosition = (sin(rotationRadians) * offsetX, cos(rotationRadians) * offsetY) + oldPosition

Shouldn't sin and cos be reversed there? Ie.


newPosition = (cos(rotationRadians) * offsetX, sin(rotationRadians) * offsetY) + oldPosition

 

Hah, Thanks! yeah I think you're right. Problem still persists though sadly.

Still wonky but better!

Anyone else have any ideas what might be causing this?

I haven't dug into this problem but I think you should look into using Transforms.  This is what Transforms do, transform a local coordinate space into another space like the global, camera or viewport space.  You're going to be doing trig everywhere if you don't use transforms and it just seems like there's a super-simple solution already done for you in the library you're already using and you're not using it.

5 minutes ago, gaxio said:

I haven't dug into this problem but I think you should look into using Transforms.  This is what Transforms do, transform a local coordinate space into another space like the global, camera or viewport space.  You're going to be doing trig everywhere if you don't use transforms and it just seems like there's a super-simple solution already done for you in the library you're already using and you're not using it.

This sounds entirely like a good idea, I'll look into transforms, thanks!

The captures don't load for me, but I am wondering why the rotation would be impacting the position. 

I assume mOffset are members, but you aren't setting them with this method that is already taking an offset in.

This math would make since if you passing a rotation and a speed:

Velocity.y=sin(angle)*speed

Velocity.x=cos(angle)*speed

Newpos=oldpos+velocity.

Perhaps we need more context to understand what you are trying to do, but I don't see why you are doing this particular math.

3 minutes ago, Michael LaserBlade Scoggin said:

The captures don't load for me, but I am wondering why the rotation would be impacting the position. 

I assume mOffset are members, but you aren't setting them with this method that is already taking an offset in.

This math would make since if you passing a rotation and a speed:

Velocity.y=sin(angle)*speed

Velocity.x=cos(angle)*speed

Newpos=oldpos+velocity.

Perhaps we need more context to understand what you are trying to do, but I don't see why you are doing this particular math.

Hey mate,

No probs, I should've explained. So basically the offset parameters are supplied via a config file, and describe the offset in pixels, from the centre of the sprite, that the component sprite(s) should be rendered. So for example, the exhaust jet for this particular sprite is at offset (-50,-14) from the center of the sprite.

When the sprite rotates, the sub-sprite should too

Ahh, that is definitely what transform matrices are for. You multiply the hierarchy together to get your final transformation. But without them you want

The math you want is a vector rotation:


 x' = x cos θ − y sin θ
 y' = x sin θ + y cos θ

Where theta is the rotation of the parent.

x' and y' will be rotated versions of x and y. 

You also have to translate by adding your parents position to yours.

There can be a scaling as well.

All of these can be represented as a matrix individualy and multiplied to get to make a 'transform'. 

Order matters. 

It might worth noting that exhaust is the type of thing your ship would 'drop' and only it's spawn would be relative to the ship and it's position would become fixed or at least detached from the ship imeddiately. You could add some drift to it though for a cool effect.

Yeah I feel like I really should've been using transforms from the beginning - didn't know SFML had them! (Didn't look for them to be fair). Oh well silly me :D

Thanks for the input folks, will post a working image once I've fixed it

No problem. I do recommend studying up on vector transforms. Knowing how they work will make it easier to spot what is going on when things aren't quite working.

This topic is closed to new replies.

Advertisement