Followers 0

# Need help with 2D oscillation

## 31 posts in this topic

I'm working in XNA but my problem is the math so I posted here.

FYI I am very new to this kind of math and I've been studying hard.  I am to the point where I "think" I can solve this myself but once I try to work it out, I draw a blank.

Simply put, I am wanting sprites to oscillate (sine/cosine?) in a wave-like pattern along their vector.  I've found several options that work with going along in a straight line along the X axis and I believe I understand how those work.  However, my sprites aren't moving straight along the X axis and unfortunately I haven't found anything that is specific to what I'm after.  Their vector can vary in basically any direction.  What I don't know how to do is take the information from their vector and use it to create the oscillation I am after.

Any ideas?

0

##### Share on other sites

You don't provide much detail, but it can be as simple as choosing a 2D point and a direction.

Position2D = sin(angle) * magnitude * vector2DDirection + point2D

Works in any number of dimensions. Pick a magnitude for the maximum displacement from the point. Because sin(angle) will vary from -1 to +1, the position will vary by -magnitude to +magnitude (provided that vector2D is a unit vector) along the direction either "side" of the point.

E.g., a direction vector = ( 0.707, 0.707 ) will result in an oscillation along the 45 degree line through the point.

You could use cos(angle) instead. That will produce the same oscillation, but just be out of phase with a sine based oscillation.

In time-based terms,

P(t) = P0 + L*sin(w*t)*Vdir

w is an angular frequency constant (or variable if you want) in units of radians/sec. t is time. L is the maximum distance from P0. Vdir is a unit direction vector.

Edited by Buckeye
2

##### Share on other sites
For horizontal movement you are probably doing
x = x0 + speed * t
y = y0 + oscillation_amplitude * sin(t * oscillation_frequency)

You can think of this in vector notation as this single equation:
(x,y) = (x0,y0) + (speed,0) * t + (0,1) * oscillation_amplitude * sin(t * oscillation_frequency)

Here (x0,y0) is the initial position, (speed,0) is the velocity and (0,1) is the direction of oscillation, which is perpendicular to the velocity. So to do this in general, you can replace (speed,0) with the arbitrary velocity (v.x,v.y), and (0,1) with a vector that is perpendicular to (v.x,v.y) and has length 1. You can compute a vector perpendicular to (v.x,v.y) as (-v.y,v.x), and you can divide it by its length to make it have length 1; let's call the result (perp.x,perp.y). Then the formula is just
(x,y) = (x0,y0) + (v.x,v.y) * t + (perp.x,perp.y) * oscillation_amplitude * sin(t * oscillation_frequency)
1

##### Share on other sites

This is where it gets fuzzy for me (and also where I am getting used to the terminology).  I'm going to play around with this for a bit and see what I come up with.  Thanks guys for getting me started :).

0

##### Share on other sites

Ok, I've been tinkering with this and unfortunately haven't gotten anywhere.  There are a few things I don't understand.  But I'll start with what I'm trying to do and hopefully it will help.

Essentially what I am doing is having sprites randomly spawn off screen (any side) and having them emerge onscreen, race across the screen, and then leave the screen.

Buckeye, what would the magnitude be?  An integer?  Is the vector2DDirection my sprite's speed?  And what is the point2D?  Is that the "pick a point" you talked about?

Alvaro, I "think" I am close to implementing your final formula but I am stuck on your oscillation_amplitude and oscillation_frequency.  What are those?  Other vectors?

And to both of you, how are you using t (time) in here?  I don't know how to implement that.

Again, thanks for your posts.  I get the feeling that I am on the cusp of understanding this stuff since I am moving from textbook stuff to actual implementation...which makes this all the more frustrating! :)

0

##### Share on other sites
I am using "amplitude" and "frequency" in a very standard manner. These are common words in describing waves and you should have learned about them in high school or middle school. If you don't know what they are, try Wikipedia.

Perhaps you can tell us in detail how you implement oscillation for objects moving along the x axis, so we can see where you are and try to get you from there to where you need to go.
0

##### Share on other sites

What I am trying to understand is how they (amplitude and frequency) are used/implemented in code (specifically the code you posted).

0

##### Share on other sites
What I posted is basically the code: The amplitude multiplies the sine, and the frequency times the time variable goes inside the sine.
0

##### Share on other sites

I am wanting sprites to oscillate (sine/cosine?) in a wave-like pattern along their vector.

But I'll start with what I'm trying to do and hopefully it will help.
Essentially what I am doing is having sprites randomly spawn off screen (any side) and having them emerge onscreen, race across the screen, and then leave the screen.

It's no longer clear what you're asking about, I'm afraid. Oscillating and racing across the screen are two different things.

Maybe the first thing to ask is: do you understand vectors?

Second: Can you describe in clearer terms, or even provide a sketch or picture of the motion you're trying to achieve?

1

##### Share on other sites

What I am trying to understand is how they (amplitude and frequency) are used/implemented in code (specifically the code you posted).

When you're not sure what equation you should be using to describe some motion or are unsure what the variables represent, it's a good habit to do a summary dimensional analysis on the equation, using the simple rules below:

- dimensions multiply and divide as usual

- you cannot add or subtract different dimensions

- transcendental functions are dimensionless

Using this on the equation Alvaro posted, you can see that the frequency (as inverse time, i.e. in Hz) is multiplied with the time variable to give a dimensionless value, the sine of that is dimensionless and is then multiplied with amplitude as a (peak) displacement, giving a result as a measure of displacement, which checks out and is what you wanted. Using the same reasoning you can deduce that the frequency cannot be a vector (unless time is a vector too, which would imply that your x and y coordinates are subject to different times, which is probably not what you want), and so on. As you can see this gives a quick way to check what units a variable should be, whether a physics equation "makes sense", and is also handy to verify that you didn't make an implementation/logic error somewhere.

1

##### Share on other sites

As of right now, my sprites "race across the screen."  What I want to add to that behavior is a wave motion so while they are moving across the screen, they are oscillating (correct term?).  These sprites can come from anywhere offscreen (from any side) and move at any vector.

Alvaro, I asked you if those amplitude and frequency portions were vectors because I get the message "operator * cannot be applied to operands of type 'Microsoft.Xna.Framework.Vector2' and 'double'."  Then you responded by telling me to read Wikipedia.  Then I mentioned I was after how those variables were used in code because you didn't answer how they were used or if they were vectors and you responded with your formula was basically the code.  I appreciate your time but your last two responses haven't cleared up what I asked you about.  If you are responding to clarify your response, you can't expect the person you are talking to to understand that response if it is just a rehash of the original response (IE "What I posted is basically the code") that they didn't understand in the first place and/or still need help on.

This isn't a jab at you but rather an illustration of my ignorance.  I have come a long ways in my efforts to teach myself programming (and I've even had newbie programmers tell me that I am advanced...which makes me feel good!) but there is still so much I have to learn.  The latest area I am trying to learn is how sprites move and the math behind that movement (waves, arcing, gravity, etc.).

Buckeye, I hope my explanation in this post makes it clearer.  I'll post a picture if necessary.  Since I am still learning and getting used to the terminology, I might not be going about it the right way.  That said, I "think" I understand vectors (at least on a basic level) and I have studied them but this is my first foray into the actual application of something that didn't involve straight lines and making the transition from abstract textbook text and application isn't necessarily a smooth one.

Bacterius, most of what you posted I haven't come across before but I'm trying to use it as a jumping off point to tackle my problem.  If it doesn't come together for me, at least it may serve to plant a seed in my mind that I can refer back to later :).  You mentioned something that I asked Alvaro in that the frequency can't be a vector and I can accept that.  What I'm needing help with is how the pieces from that formula come together since my current implementation gives me an error (as mentioned above).

I also mentioned earlier that I am unsure how to implement time in this.  My only real experience with time comes from "pausing" something for a certain number of milliseconds and I don't see how that can help here.

0

##### Share on other sites

Is this what you're trying to simulate?

If so, then Alvaro's equations are the thing to use.

For horizontal movement you are probably doing

x = x0 + speed * t
y = y0 + oscillation_amplitude * sin(t * oscillation_frequency)

x is the position along the red line, y is along the black line.

Oscillation_amplitude is the distance between the red line and the highest (or lowest) position along the black line. You say you have something moving across the screen so you must have some variable that's changing over time. That's "time." Oscillation_frequency is how "fast" the y value moves up and down.

Edited by Buckeye
1

##### Share on other sites

Alvaro, I asked you if those amplitude and frequency portions were vectors because I get the message "operator * cannot be applied to operands of type 'Microsoft.Xna.Framework.Vector2' and 'double'." Then you responded by telling me to read Wikipedia.

How was I supposed to guess that you were getting that error message? Crystal ball? This is the description of the problem that you had given us at the time:

Alvaro, I "think" I am close to implementing your final formula but I am stuck on your oscillation_amplitude and oscillation_frequency. What are those? Other vectors?

If you think that the frequency in my formula could be a vector, it means you didn't understand any of it. That's why I pointed you to Wikipedia.

The fact that you can't multiply a vector by a double means you are using a language or library that is not very expressive. However, my formulas are not necessarily code: They are Math. The way you multiply a Microsoft.Xna.Framework.Vector2 by a number is by multiplying each component by the number. If you don't have an operator to do it, you can still do the multiplication component by component.

The fact that you don't know what to do with the time variable means we are still not communicating properly. Please, post a piece of code describing how you are doing the movement now, or I am afraid we are not going to get anywhere in this conversation. You have to have time in there somewhere, because "race across the screen" requires changing position as a function of time in some way.

1

##### Share on other sites

The fact that you can't multiply a vector by a double means you are using a language or library that is not very expressive. However, my formulas are not necessarily code: They are Math. The way you multiply a Microsoft.Xna.Framework.Vector2 by a number is by multiplying each component by the number. If you don't have an operator to do it, you can still do the multiplication component by component.

It's probably because in C# (XNA) floats and doubles cannot be implicitly converted to one another, and the framework probably is expecting a float on the other side of the operator and didn't bother providing double overloads. Just making the scalar value a float would fix it. But.. yeah.. that's not really relevant to the problem at hand, and some debugging/research would have provided the solution.

0

##### Share on other sites

Buckeye, yes that is what I am looking to do.  But my trouble comes from my vectors not being in a nice straight line along the X axis.  I give each of my sprites a random vector (within a specific range depending on which side of the screen they are coming from) so the angles of that red line aren't always straight along either the X or Y axes.  So while that code you referred to gave me an idea on how it would work, I don't know how to apply it to situations where the sprite isn't going in a perfectly straight horizontal line.  As I told Alvaro, I "think" I am close to implementing his formula but I am hung up on how to apply the amplitude and frequency as well as how to use the time.  I know that the gameTime is used for movement (after all, I use it when my sprites move in a nice straight line) but I don't know specifically what needs to be done with the time in order to use it in that formula.  I'm sure I can simply pull in the milliseconds but that doesn't seem right.  And thank you for the explanations on amplitude and frequency.  Very helpful for me trying to get my head wrapped around this :).

Alvaro, don't bother responding again.  Snippy comments and thinly-veiled insults are not helpful.  Neither is pointing out that I don't understand something.  If I understood then I would have little need to ask for help.  This may come as a shock to you, but with ignorance being a key component to someone asking a question, it is a very real possibility that ignorance may also play a role in articulating the question and/or situation.  If you want to be helpful, then help the asker get to the core of their problem rather than just referring them somewhere else (which they may have already read).  If you help them better articulate what they need, then they will be able to ask better, more detailed questions and will apply that to future questions.  Everyone is at various stages of learning and it is counter-productive to respond to someone's post to "help" only to respond with quips and answers that leave them none-the-wiser.

Bacterius, I am well aware of research and debugging but I made it clear that I am new to this.  That being said, and as I pointed out to Alvaro, ignorance plays a large role here.  And when it comes to research, if I don't know what to look for (ignorance), then I don't know how to look it up.  I did try to look it up.  I looked up many things before resorting to posting here.  I appreciate your responses but making the assumption that I didn't try to find the answer myself before posting is incorrect.  I am learning how program and with that I have to learn how to solve problems, figure out math, learn terminology, discover available resources and how to use them, learn to debug, and more.  Assuming someone didn't try first carries the connotation of "It's so simple, why don't you just do such-n-such?" when in reality it may be simple to you due to your experience but I haven't reached that point yet.  I am getting there, slowly but surely.  I'm going to see what happens when making the scalar value a float as you mentioned and see what happens.

0

##### Share on other sites

I didn't mean to insult you, so I am sorry if you took it that way.

It's hard to get the tone right on forum posts. If you don't like my style of trying to help, I won't do it again. But I did spend some time trying to give you real help in this thread and you are giving me no credit for it, which is not fair.

0

##### Share on other sites

Your first post was great but it did leave a few things unanswered for me...which is perfectly fine since I was unsure how to ask what I needed and you were working with what you could.  And after all, it was the first tottering steps in our communication.  But I figured I'd give it a go (there is definitely something to be said for making the attempt even when you don't fully understand what is going on).  After some experimenting, I had to ask for clarification.  That is where the incomplete answers (I had to ask about the variables being vectors twice) and comments (could have done without the high school/middle school comment...I've slept a few times since those days and don't remember everything) began.

If you have more input, I'd love to hear it.  However I'd like to mention again that I am very new to this and that it is very possible that I may not know what you assume I know (or should know).  With that thought in mind, I need simple, concise answers to help me reach that "Aha!" moment (and most likely cause me to smack myself in the forehead because I should have seen the solution).

0

##### Share on other sites

[deleted] messed up equation.

How 'bout you post some code, rather than having others post things you're not sure of? Be sure to describe each term and what you think that term is used for.

Edited by Buckeye
0

##### Share on other sites

Here is my function for basic, straight-line movement.

// Straight line behavior

private void MoveSprites()

{

for (int i = 0; i < sprites.Count(); i++)

{

// Update position of sprite

sprites[i].SetPosition(sprites[i].GetPosition() +

sprites[i].GetSpeed());

// If the sprite moves off the screen, use it again somewhere else.

if (sprites[i].GetPosition().X > screen.Width + 100 ||

sprites[i].GetPosition().X < -100 ||

sprites[i].GetPosition().Y > screen.Height + 100 ||

sprites[i].GetPosition().Y < -100)

{

switch (rand.Next(4))

{

// TOP

case 0:

sprites[i].SetPosition(

new Vector2(rand.Next(screen.Width), -64));

sprites[i].SetSpeed(

new Vector2(rand.Next(-5, 5), rand.Next(minSpriteSpeed, maxSpriteSpeed)));

break;

// BOTTOM

case 1:

sprites[i].SetPosition(

new Vector2(rand.Next(screen.Width), screen.Height + 64));

sprites[i].SetSpeed(

new Vector2(rand.Next(-5, 5), rand.Next(-maxSpriteSpeed, -minSpriteSpeed)));

break;

// LEFT

case 2:

sprites[i].SetPosition(

new Vector2(-64, rand.Next(screen.Height)));

sprites[i].SetSpeed(

new Vector2(rand.Next(minSpriteSpeed, maxSpriteSpeed), rand.Next(-5, 5)));

break;

// RIGHT

case 3:

sprites[i].SetPosition(

new Vector2(screen.Width + 64, rand.Next(screen.Height)));

sprites[i].SetSpeed(

new Vector2(rand.Next(-maxSpriteSpeed, -minSpriteSpeed), rand.Next(-5, 5)));

break;

}

}

}

}

When a sprite moves off-screen, it is randomly placed on the outside of the screen and given a vector based on which side it is going to be coming from.  Since these vectors are random, I am having a hard time getting the "waves" to work.

Here we have the code to move my sprites:

sprites[i].SetPosition(sprites[i].GetPosition() +

sprites[i].GetSpeed());

Here is one of my attempts:

sprites[i].SetPositionY(sprites[i].GetPosition().Y + (-(float)Math.Cos(sprites[i].GetPosition().X / 100) * 10));

This produces some odd behavior which I actually like and may try to use elsewhere but it isn't what I'm trying to do here.

Here is another attempt based on Alvaro's formula:

sprites[i].SetPosition(sprites[i].GetOriginalPosition() + sprites[i].GetSpeed() * gameTime.ElapsedGameTime.Milliseconds *

-Vector2.Normalize(sprites[i].GetSpeed()) * 5 /* oscillationAmplitude */ * Math.Sin(gameTime.ElapsedGameTime.Milliseconds * 5 /* oscillationFrequency */));

Here you can see my misused attempt at implementing time and the amplitude and frequency.

And here is another attempt based on a suggestion from this thread:

//Position2D = sin(angle) * magnitude * vector2DDirection + point2D

sprites[i].SetPosition((Math.Sin(45) * (5 * sprites[i].GetSpeed()));

Does this help?

0

##### Share on other sites

Here is another attempt based on Alvaro's formula:

sprites[i].SetPosition(sprites[i].GetOriginalPosition() + sprites[i].GetSpeed() * gameTime.ElapsedGameTime.Milliseconds *
-Vector2.Normalize(sprites[i].GetSpeed()) * 5 /* oscillationAmplitude */ * Math.Sin(gameTime.ElapsedGameTime.Milliseconds * 5 /* oscillationFrequency */));

Yeah, that's pretty messed up.

Alvaro posted a general formula:

(x,y) = (x0,y0) + (v.x,v.y) * t + (perp.x,perp.y) * oscillation_amplitude * sin(t * oscillation_frequency)

For (x0,y0) you have GetOriginalPosition(), and that looks ok.

Then for (v.x,v.y) * t you have GetSpeed() * gameTime.ElapsedGameTime.Milliseconds, with a multiplication by -Vector2... Hopefully that's just incorrect coding, and you meant addition, not multiplication.

Stopping there for a moment: does ElapsedGameTime.Milliseconds return the number of milliseconds, or the number of seconds? The variable t should be in seconds, if speed is some-units-per-second. If that function actually returns milliseconds, that's a thousand times faster than seconds. That's basic dimensional analysis.

Does GetSpeed() return a vector or a scalar? As it's called speed, rather than velocity, I suspect that's a scalar. For the v * t term you need a unit vector pointing in the direction the sprite is to travel. Then you would have something like UnitDirectionVector * GetSpeed() * seconds for Alvaro's (v.x,v.y)*t term.

Continuing: for Alvaro's (perp.x,perp.y), as he explained, you need a vector that is perpendicular to the vector (v.x, v.y). When you come up with something for the UnitDirectionVector above, calculate a unit vector perpendicular to it and use it where Alvaro has (perp.x,perp.y).

Not sure what you intended with -Vector2.Normalize(...).

After that, it's not clear what you were trying to code... something depending on speed??

Alvaro has oscillation_amplitude * sin(t * oscillation_frequency), and you have 5 * Math.Sin(gameTime.ElapsedGameTime.Milliseconds * 5) (your comments removed)

That part looks basically okay, except, once again, the same question about milliseconds versus seconds as the time variable. The time throughout needs to be in seconds, not milliseconds.

This all pretty basic math, physics and vector stuff. If you're not familiar with it, I'd strongly suggest you study up on some of the concepts and math to implement basic motion.

Edited by Buckeye
0

##### Share on other sites

Yes, that was a coding error and should have been addition.

That ElapsedGameTime.Milliseconds returns milliseconds.  I changed it to ElapsedGameTime.Seconds.  I had no idea that seconds were needed rather than milliseconds.  Indeed, I just plugged that in to experiment.  I had no idea what exactly belonged there.  It still seems odd to have it simply return seconds.  It might be my ignorance but my gut tells me that something needs to be done to count those seconds rather than just return an arbitrary number of seconds.

I honestly couldn't tell you if GetSpeed() returns a vector or scalar since I'm not sure about the terminology.  Does this help?

public

Vector2 GetSpeed()

{

return m_Speed;

}

What exactly is a UnitDirectionVector that is needed?  You said it is a unit vector pointing in the direction the sprite is to travel.  Would that not be what is determined via the SetSpeed function?  Or am I way off base here?

As far as -Vector2.Normalize, as I understand it, when Alvaro mentioned dividing a vector by its length to give it a length of one, I thought that was normalizing a vector.  So with that thought in mind, I went for the Normalize.

The mention of something depending on speed was my attempt at (perp.x, perp.y).  I didn't know how to go about that or (v.x, v.y) beyond trying to plug in the speed.

I have been studying up on this kind of math but being self-taught at this, I often don't know what to ask or how to ask it.  Or for that matter, what to look up for this sort of thing.  Dealing with the frustration of trying to hunt this stuff down is what caused me to post here.  Sure, it may be basic math if you are used to it but it won't be basic to me until I can get some explanations that tackle what I need head-on rather than just abstract concepts from a textbook (which this post is heading towards :) ).

0

##### Share on other sites

A little tough love here, but, from the quantity and content of your questions, it appears you do, in fact, have to do some studying with regard to basic programming, vectors, dimensional analysis, basic physics, etc.

Googling for things like "equations of motion," "dimensional analysis," "angular motion," etc., should get you started.

I'm not particularly familiar with the language you're programming in, so you'll have to study up a bit on how that works, too. E.g., it appears GetSpeed() returns a Vector2, but you'll have to verify that m_Speed (the return value) fits the bill.

0

##### Share on other sites

I'll look into the phrases you suggested.  I'm going to keep studying but learning alone means I often miss some very basic stuff that would make the rest of it so much easier.  But I'll keep at it...I'm stubborn that way :).

All the code I posted is mine.  So that GetSpeed() function does return a Vector2.  It is from the sprite class I made.

All that aside and since you know what I am trying to do, how would you go about doing that?  If I can figure out all the "pieces" that are needed then I can hopefully alter it to work in XNA.  For example, how would you get the time so you can use it for something like this?  I'm thinking I won't need specific code examples since you said you're not familiar with what I am working in but if I know what needs to be done, then perhaps I can code it myself.

0

##### Share on other sites

how would you go about doing that?

I would do it using Alvaro's equation, as explained in my previous post in which I discussed each of the terms in that formula.

Time is time in seconds. I don't know how to explain it any better than that.

0

##### Share on other sites

I know it is in seconds.  I guess what I am asking is how is "t" calculated before it is plugged into that formula?  I think that might be the last sticking point for me.

0

## Create an account

Register a new account

Followers 0

• 19
• 12
• 23
• 11
• 28