Moving sprite around point

Started by
8 comments, last by lvenonl 9 years, 6 months ago

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

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.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

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;

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

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").

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.

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

chaos, panic and disorder - my work here is finished


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?

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?

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

This topic is closed to new replies.

Advertisement