SpaceFace
SpaceFace

Reputation: 1552

Wave vector in 2 dimensions

So I'm trying to make the player shoot a bullet that goes towards the mouse in a wavey pattern. I can get the bullet to move in a wavey pattern (albeit not really how I predicted), but not towards the mouse.

Vector2 BulletFun::sine(Vector2 vec) {
    float w = (2 * PI) / 1000; // Where 1000 is the period
    float waveNum = (2 * PI) / 5; // Where 5 is the wavelength

    Vector2 k(0.0F, waveNum);

    float t = k.dot(vec) - (w * _time);

    float x = 5 * cos(t); // Where 5 is the amplitude
    float y = 5 * sin(t);

    Vector2 result(x, y);

    return result;
}

Right now the speed isn't much of a concern, that shouldn't be too much of a problem once I have this figured out. I do get some angle change, but it seems to be reversed and only 1/8th a circle.

I'm probably miscalculating something somewhere. I just kind of learned about wave vectors.

I've tried a few other things, such as 1 dimensional travelling waves and another thing involving adjusting a normal sine wave by vec. Which had more or less the same result.

Thanks!

EDIT:

vec is the displacement from the player's location to the mouse click location. The return is a new vector that is adjusted to follow a wave pattern, BulletFun::sine is called each time the bullet receives and update.

The setup is something like this:

void Bullet::update() {
    _velocity = BulletFun::sine(_displacement);

    _location.add(_velocity); // add is a property of Tuple
                              // which Vector2 and Point2 inherit
}

Upvotes: 2

Views: 479

Answers (1)

hatboyzero
hatboyzero

Reputation: 1937

In pseudocode, what you need to do is the following:

waveVector = Vector2(travelDistance,amplitude*cos(2*PI*frequency*travelDistance/unitDistance);

cosTheta = directionVector.norm().dot(waveVector.norm());
theta = acos(cosTheta);

waveVector.rotate(theta);
waveVector.translate(originPosition);

That should compute the wave vector in a traditional coordinate frame, and then rotate it to the local coordinate frame of the direction vector (where the direction vector is the local x-axis), and then translate the wave vector relative to your desired origin position of the wave beam or whatever...

This will result in a function very similar to

Vector2
BulletFun::sine(Bullet _bullet, float _amplitude, float _frequency, float _unitDistance)
{
    float displacement = _bullet.getDisplacement();
    float omega = 2.0f * PI * _frequency * _displacement / _unitDistance;

    // Compute the wave coordinate on the traditional, untransformed
    // Cartesian coordinate frame.
    Vector2 wave(_displacement, _amplitude * cos(omega));

    // The dot product of two unit vectors is the cosine of the 
    // angle between them.
    float cosTheta = _bullet.getDirection().normalize().dot(wave.normalize());
    float theta = acos(cosTheta);

    // Translate and rotate the wave coordinate onto
    // the direction vector.
    wave.translate(_bullet.origin());
    wave.rotate(theta);
}

Upvotes: 3

Related Questions