5
\$\begingroup\$

I'm working on a 2d game and am looking to make a sprite move horizontally across the screen in XNA while oscillating vertically (basically I want the movement to look like a sin wave). Currently for movement I'm using two vectors, one for speed and one for direction. My update function for sprites just contains this:

Position += direction * speed * (float)t.ElapsedGameTime.TotalSeconds;

How could I utilize this setup to create the desired movement? I'm assuming I'd call Math.Sin or Math.Cos, but I'm unsure of where to start to make this sort of thing happened. My attempt looked like this:

    public override void Update(GameTime t)
    {
        double msElapsed = t.TotalGameTime.Milliseconds;
        mDirection.Y = (float)Math.Sin(msElapsed);
        if (mDirection.Y >= 0)
            mSpeed.Y = moveSpeed;
        else
            mSpeed.Y = -moveSpeed;
        base.Update(t, mSpeed, mDirection);
    }

moveSpeed is just some constant positive integer. With this, the sprite simply just continuously moves downward until it's off screen. Can anyone give me some info on what I'm doing wrong here? I've never tried something like this so if I'm doing things completely wrong, let me know!

\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

You need to move the sprite relative to a center point. To do this, create an offset and alter the position of Y with that offset.

If your Y doesn't move, you can just store your Y:

float center = Position.Y;
float offset = 0; //The offset to add to your Y
float radius = 5; //Whatever you want your radius to be

Then, in your update function, you can offset your Y by a specific amount:

double msElapsed = t.TotalGameTime.Milliseconds;    
offset = (float)Math.Sin(msElapsed) * radius;   
Position.Y = center + offset;
\$\endgroup\$
6
  • \$\begingroup\$ This works great! Thanks a lot. It looks a little crazy right now because the frame rate is so fast, but I can work on that to make it smooth. \$\endgroup\$ Commented Mar 2, 2011 at 4:34
  • 1
    \$\begingroup\$ You should not use msElapsed as the input to the sin function class. Instead, use an angle that you increment and then multiply by msElapsed time => Math.sin(angle*msElapsed), that way no matter the frame rate the oscillation will be smooth. \$\endgroup\$
    – dotminic
    Commented Mar 2, 2011 at 5:33
  • \$\begingroup\$ Would I just increment the angle by 1 every time the update function is called? When I try that, it just stays jittery. And is the angle just an integer? \$\endgroup\$ Commented Mar 2, 2011 at 6:38
  • \$\begingroup\$ The angle would be a float and the bigger the incrementation, the faster the movement. For example, this increments an angle I use to rotate a camera arround an object in a 3D world: this->_phi += .34f * dt; where dt is the same as msElapsed. \$\endgroup\$
    – dotminic
    Commented Mar 2, 2011 at 14:16
  • 1
    \$\begingroup\$ I suggest: sinValue += gameTime.ElapsedGameTime.TotalSeconds * Math.PI * speed; offset = (float)Math.Sin(sinValue); It makes calculating the speed pretty easy, since sin will oscillate every 2*Math.PI \$\endgroup\$ Commented Mar 2, 2011 at 16:45
2
\$\begingroup\$

If this is the kind of motion you are trying to get, all you need to do is something like this:

[pseudo clode]
float center_y = position.y;
float raduis = 10.0f;
float angle = 0.0f;

void update( float elapsedTime )
{
    // you can use different speeds for the X and Y positions
    // to adjust the wave as you need.
    position.x += speed * elapsedTime;
    position.y = center_y + Math.Sin(angle) * radius;
    angle += speed * elapsedTime;
}

Essentially, what the sine function does is return a float point value in range [-1,1] based on the input angle (in radians). You can then scale that result by the radius, in the example, I scale the value by 5 given me a value in the range [-5, 5], and then all you need to do is add that value to the Y position you want the sprite to oscillate around.

You can also think of the "speed" variable as the frequency of the wave in this line:

angle += speed * elapsedTime;

The higher the speed the faster the oscillation will be. Note however that this isn't physically accurate, to make waves and have control of amplitude, frequency and other parameters is a little more "complicated".

Hope this helps.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .