Need help with 2D oscillation

Started by
30 comments, last by Waylander 10 years ago

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

Advertisement

Is this what you're trying to simulate?

oscillation.png

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.

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.


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.


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

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

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.

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

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

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.

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.SetPosition(sprites.GetPosition() +

sprites.GetSpeed());

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

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

sprites.GetPosition().X < -100 ||

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

sprites.GetPosition().Y < -100)

{

switch (rand.Next(4))

{

// TOP

case 0:

sprites.SetPosition(

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

sprites.SetSpeed(

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

break;

// BOTTOM

case 1:

sprites.SetPosition(

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

sprites.SetSpeed(

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

break;

// LEFT

case 2:

sprites.SetPosition(

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

sprites.SetSpeed(

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

break;

// RIGHT

case 3:

sprites.SetPosition(

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

sprites.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.SetPosition(sprites.GetPosition() +

sprites.GetSpeed());

Here is one of my attempts:

sprites.SetPositionY(sprites.GetPosition().Y + (-(float)Math.Cos(sprites.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.SetPosition(sprites.GetOriginalPosition() + sprites.GetSpeed() * gameTime.ElapsedGameTime.Milliseconds *

-Vector2.Normalize(sprites.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.SetPosition((Math.Sin(45) * (5 * sprites.GetSpeed()));

Does this help?

Ulfhedhin


Here is another attempt based on Alvaro's formula:

sprites.SetPosition(sprites.GetOriginalPosition() + sprites.GetSpeed() * gameTime.ElapsedGameTime.Milliseconds *
-Vector2.Normalize(sprites.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.

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.

This topic is closed to new replies.

Advertisement