Sine wave movement

Hi, I am currently working on an arcade game for my final assignment this year. I am struggling to get a sine wave movement with the saucer.
Here is the code for it:
1
2
3
4
5
6
7
8
9
void ArcadeGame::spawnSaucer()
{
	Texture* pTexture = getTexture("saucertexture");
	m_pSaucer = new GameObject(pTexture, "saucer");
	m_pSaucer -> setPosition(1000, 300);
	m_pSaucer -> setVelocity(-1, 10 * sin(1 * 3 * PI / 180), sin(1) * OBJECT_DEFAULT_SPEED);
	addGameObject(m_pSaucer);
	m_pSaucer->setSolid(true);	
}


I would highly appreciate it if somebody could help me fix this problem or guide me to the right direction.
Last edited on
I don't really understand your question. For a movement you need some time too. Just a pseudocode for this:

1
2
3
4
5
6
7
8
object.spawn(position);

while(gamerunning)
{
    object.pos.x = object.speed * getElapsedTime();
    object.pos.y = sin(object.speed * getElapsedTime()) * amplitude;
    object.render();
};


the getElapsedTime() return the elapsed time since the program start. You can do the same with frame time, just put object.pos.y += ....
As pandasd mentioned, you can't just set a velocity once and expect it to form a sine wave. A sine wave is a constant change in velocity, so you will need to change your velocity every update.

Though interestingly, you can do this without using sin() at all. Assuming you have a fixed velocity on the X axis, all you need to do to form a sine wave is to add (or subtract) a fixed value to the Y velocity every update.

Some more pseudocode:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void Object::update()  // called once every update
{
    // update the object's position based on its velocity:
    pos += velocity;

    // adjust the velocity by adding or subtracting a fixed value
    //   we'll call this value 'foobar' because I'm too lazy to come up
    //   with a better name.
    //
    // 'centerline' is the Y position which will be the center point of the
    //   sine wave
    if( pos.y < centerline )
        velocity.y += foobar;
    else
        velocity.y -= foobar;
}


The distance between the object's initial position and the 'centerline' determines how 'tall' the sine wave is. 'foobar' determines how 'wide' the sinewave is (smaller values = wider wave)
Thanks for the help
Yeah, both code would work. Just be sure to use frame or elapsed time for the calculations, or your object will move at different speeds on different machine.

1
2
3
4
5
void Object::update(float frametimeInMillis)  // called once every update
{
    pos+=direction*frametimeInMillis*speed;
    ...
};
Last edited on
> Though interestingly, you can do this without using sin() at all.
> Assuming you have a fixed velocity on the X axis,
> all you need to do to form a sine wave is to add (or subtract) a fixed value to the Y velocity every update.

If you want a sin() for the position, then the velocity should be a cos()
Your "add a fixed value every update" is an step function approximation to a linear function.
(that linear function is an approximation to a cos() function)

Then you use that fixed velocity to calculate the next position. So you'll have a piece-wise linear approximation (not smooth)


If we say that the tick is small enough, the velocity is a linear, and the position a quadratic function, that have a sudden change in the curvature when you pass over the centerline.


Quite far from a sine wave, but your the human eye may not be able to tell the difference
Last edited on
How would i get elapsed time to work i have search the web for it and there aren't any useful resources based on the topic of getElapsedTime() ?
Last edited on
For the getElapsedTime, the easy way is simply to have a value to store the time when the program starts, and then return the time since then, like so:
1
2
3
4
5
6
7
8
9
10
#include <chrono>

float getElapsedTime() {
    using namespace std::chrono;
    // Can't remember off the top of my head, but this is initialized with
    // the start of the program rather than first call, right?
    static high_resolution_clock::time_point start = high_resolution_clock::now();

    return duration_cast<duration<float>>(start - high_resolution_clock::now()).count();
}


You can do a similar thing to measure frame rates and the like.
Last edited on
Thank you for the help
Topic archived. No new replies allowed.