Jump to content
  • Advertisement
Sign in to follow this  
lvenonl

Moving sprite around point

This topic is 1523 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

Hello guys,

 

I am trying to rotate a sprite around a specific point on the screen. I managed to do so and here is what I have so far:

 

My Enemy update function:

void Enemy::update()
{
	moveInCircle(&position, 1, 100, 100, 100);

{

My function to move sprite around point:

void moveInCircle(Vector2D* enemyPos, float speed, int centerX, int centerY, int radius)
{
	float speedScale = (0.001 * 2 * PI) / speed;
	float angle = SDL_GetTicks() * speedScale;
	
	enemyPos->SetX(centerX + sin(angle) * radius);
	enemyPos->SetY(centerY + cos(angle) * radius);
}

However, I want to be able to rotate the sprite in a limited angle, instead of just moving ad infinitum and here is where I got stuck, how can I check how many degrees the sprite have moved? Maybe there is a better approach on the function 'moveInCircle' than the one I used?

 

Thanks in advance,

lvenonl

Share this post


Link to post
Share on other sites
Advertisement

Maintain a separate variable for the enemy - e.g., float curAngle. Instead of calculating the angle, calculate a delta-angle.

 

Then:

float speedScale = (0.001 * 2 * PI) / speed;
float angle = SDL_GetTicks() * speedScale;

// determine if the incremented angle will still be within bounds
if( WithinBounds(enemy.curAngle + angle) ) // WithinBounds(float testAngle) function checks whether testAngle is within whatever radian limits you want
{
  enemy.curAngle += angle; // update the current angle
  // set the position based on the angle
  SetX(centerX + sin(angle) * radius);
  SetY(...)
}

If you need to convert radians to degrees: degrees = (360 / 2*PI) * angle-in-radians.

Edited by Buckeye

Share this post


Link to post
Share on other sites

This is similar to what Buckeye said, but you can also do something like this. You can use variable to know when the update should actually move the sprite. When you want it to move, set the variable to the amount of radians you want it to rotate, and then on the moveInCircle function do:

void moveInCircle(Vector2D* enemyPos, float speed, int centerX, int centerY, int radius)
{
        if (radiansToRotate > 0) {
	    float speedScale = (0.001 * 2 * PI) / speed;
	    float angle = SDL_GetTicks() * speedScale;
	
            enemyPos->SetX(centerX + sin(angle) * radius);
	    enemyPos->SetY(centerY + cos(angle) * radius);

            radiansToRotate -= angle;
        }
}

I think something like that should work. Maybe you want to check that the angle you rotate is always less or equal the radians left to rotate, so the rotation stops exactly where you want it. For example, something like this after you compute the angle:

if (angle > radiansToRotate)
    angle = radiansToRotate;

Share this post


Link to post
Share on other sites

Thanks for the answer guys! I appreciate it!

 

I made this modifications:

void moveInCircle(Vector2D* enemyPos, float speed, int centerX, int centerY, int radius, float* currentAngle, float limit)
{
	float speedScale = (0.001 * 2 * PI) / speed;
	float angle = SDL_GetTicks() * speedScale;

	if(*currentAngle + angle < limit)
	{
		*currentAngle += angle;
		enemyPos->SetX(centerX + sin(angle) * radius);
		enemyPos->SetY(centerY + cos(angle) * radius);
	}
}

And in my update function:

if(currentAngle < 360)
{
	moveInCircle(&position, 4, 100, 100, 100, &currentAngle, 360);
}

But the enemy is not completing a full 360º rotation. I think I'm missing something pretty simple and stupid! LOL

Share this post


Link to post
Share on other sites

It stops close to 360? It probably is because you stop the rotation if the angle to rotate will exced the limit, but you never reach the limit. If currentAngle + angle is equal to limit you should also rotate, and if it's more than the limit you should rotate some amount anyway (limit - currentAngle instead of "angle").

Share this post


Link to post
Share on other sites

Actually it stops around 90 degrees away from the 'target'. One strange thing is that printing out the 'currentAngle' value I noticed that at first 'angle' adds around 0.5 to currentAngle, then it starts adding 1, and suddenly it adds 2 every time it passes through the function. I think it's something wrong with the way I'm calculating the 'angle' variable, I just don't know what.

Share this post


Link to post
Share on other sites
SDL_GetTicks returns the number of milliseconds since when SDL was initialized and because of that it's an ever increasing value you get.
 
You need the delta between the current and the last frame.
 

Something like this:

class CTimer{
public:
  CTimer( void ) :
    m_thisFrame( SDL_GetTicks() ),
    m_lastFrame( m_thisFrame )
  {
  };


  void Update( void )
  {
    m_lastFrame = m_thisFrame;
    m_thisFrame = SDL_GetTicks();

    m_dT = ( m_thisFrame - m_lastFrame ) / 1000.0f;
  };


  float getDeltaTime( void ) const
  {
    return( m_dT );
  };


private:
  unsigned long m_thisFrame;
  unsigned long m_lastFrame;


  float m_dT { 0.0f };
}

 

Now call the update-function every frame, and replace your use of "SDL_GetTicks" with "getDeltaTime".

 
Regards
Markus
Edited by Charon

Share this post


Link to post
Share on other sites

Now call the update-function every frame, and replace your use of "SDL_GetTicks" with "getDeltaTime".

 
Regards
Markus

 

 

Now I've got the sprite not moving at all sad.png

I did the same logic you did, except I didn't add a class CTimer, I just added these variables (as floats) to my Enemy update function:

fB = fA;
fA = SDL_GetTicks();
dT = (fA - fB) / 1000.0f;

And modified my moveInCircle function to take dT as an argument

void moveInCircle(Vector2D* enemyPos, float speed, int centerX, int centerY, int radius, float* currentAngle, float limit, float dT)
{
	float speedScale = (0.001 * 2 * PI) / speed;
	float angle = d_t * speedScale;

	std::cout << *currentAngle << "\n";

	if(*currentAngle + angle <= limit)
	{
		*currentAngle += angle;
		enemyPos->SetX(centerX + sin(angle) * radius);
		enemyPos->SetY(centerY + cos(angle) * radius);
	}
}

What am I doing wrong?

Edited by lvenonl

Share this post


Link to post
Share on other sites

Does that even compile? You named the parameter "dT" but you're using the variable "d_t" to get the angle... maybe d_t is some global variable that's always 0?

Share this post


Link to post
Share on other sites

Does that even compile? You named the parameter "dT" but you're using the variable "d_t" to get the angle... maybe d_t is some global variable that's always 0?

 

Nope! I put that underscore there by mistake, on my code it is "dT" hahahaha

I double checked it, tried to do everything all over again, but I still get the sprite not rotating at all

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!