• Create Account

# Need help with 2D oscillation

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

31 replies to this topic

### #1Ulfhedhin  Members   -  Reputation: 136

Like
0Likes
Like

Posted 25 March 2014 - 04:49 PM

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?

Ulfhedhin

### #2Buckeye  GDNet+   -  Reputation: 10734

Like
2Likes
Like

Posted 25 March 2014 - 05:22 PM

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, 25 March 2014 - 05:33 PM.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #3Álvaro  Crossbones+   -  Reputation: 18617

Like
1Likes
Like

Posted 25 March 2014 - 06:23 PM

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)

### #4Ulfhedhin  Members   -  Reputation: 136

Like
0Likes
Like

Posted 25 March 2014 - 08:29 PM

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 .

Ulfhedhin

### #5Ulfhedhin  Members   -  Reputation: 136

Like
0Likes
Like

Posted 26 March 2014 - 07:25 PM

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!

Ulfhedhin

### #6Álvaro  Crossbones+   -  Reputation: 18617

Like
0Likes
Like

Posted 26 March 2014 - 08:17 PM

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.

### #7Ulfhedhin  Members   -  Reputation: 136

Like
0Likes
Like

Posted 26 March 2014 - 09:01 PM

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

Ulfhedhin

### #8Álvaro  Crossbones+   -  Reputation: 18617

Like
0Likes
Like

Posted 26 March 2014 - 09:27 PM

What I posted is basically the code: The amplitude multiplies the sine, and the frequency times the time variable goes inside the sine.

### #9Buckeye  GDNet+   -  Reputation: 10734

Like
1Likes
Like

Posted 26 March 2014 - 09:46 PM

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?

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #10Bacterius  Crossbones+   -  Reputation: 12841

Like
1Likes
Like

Posted 26 March 2014 - 10:06 PM

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.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

### #11Ulfhedhin  Members   -  Reputation: 136

Like
0Likes
Like

Posted 27 March 2014 - 05:39 AM

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.

Ulfhedhin

### #12Buckeye  GDNet+   -  Reputation: 10734

Like
1Likes
Like

Posted 27 March 2014 - 06:16 AM

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, 27 March 2014 - 06:24 AM.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #13Álvaro  Crossbones+   -  Reputation: 18617

Like
1Likes
Like

Posted 27 March 2014 - 07:28 AM

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.

### #14Bacterius  Crossbones+   -  Reputation: 12841

Like
0Likes
Like

Posted 27 March 2014 - 07:35 AM

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.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

### #15Ulfhedhin  Members   -  Reputation: 136

Like
0Likes
Like

Posted 27 March 2014 - 09:04 AM

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.

Ulfhedhin

### #16Álvaro  Crossbones+   -  Reputation: 18617

Like
0Likes
Like

Posted 27 March 2014 - 10:18 AM

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.

### #17Ulfhedhin  Members   -  Reputation: 136

Like
0Likes
Like

Posted 27 March 2014 - 11:53 AM

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).

Ulfhedhin

### #18Buckeye  GDNet+   -  Reputation: 10734

Like
0Likes
Like

Posted 27 March 2014 - 03:05 PM

[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, 27 March 2014 - 03:10 PM.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

### #19Ulfhedhin  Members   -  Reputation: 136

Like
0Likes
Like

Posted 27 March 2014 - 06:18 PM

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?

Ulfhedhin

### #20Buckeye  GDNet+   -  Reputation: 10734

Like
0Likes
Like

Posted 27 March 2014 - 07:09 PM

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, 27 March 2014 - 07:23 PM.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Old topic!

Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS