Sine wave movement

May 4, 2014 at 6:57pm
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 May 4, 2014 at 7:59pm
May 4, 2014 at 8:35pm
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 += ....
May 4, 2014 at 8:45pm
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)
May 4, 2014 at 9:09pm
Thanks for the help
May 4, 2014 at 9:15pm
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 May 5, 2014 at 8:04am
May 4, 2014 at 9:48pm
> 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 May 4, 2014 at 9:53pm
May 5, 2014 at 9:36am
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 May 5, 2014 at 9:37am
May 5, 2014 at 11:40am
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 May 5, 2014 at 11:42am
May 5, 2014 at 12:28pm
Thank you for the help
Topic archived. No new replies allowed.