Main content
Computer programming
Course: Computer programming > Unit 5
Lesson 7: Oscillations- Oscillation amplitude and period
- Challenge: Rainbow slinky
- Oscillation with angular velocity
- Challenge: Spaceship ride
- Waves
- Challenge: Many waves
- Trig and forces: the pendulum
- Challenge: Pendulum puppet
- Spring forces
- Project: Curling, crawling, circling creatures
© 2023 Khan AcademyTerms of usePrivacy PolicyCookie Notice
Waves
If you’re saying to yourself, “Um, this is all great and everything, but what I really want is to draw a wave onscreen,” well, then, the time has come. The thing is, we’re about 90% there. When we oscillate a single circle up and down according to the sine function, what we are doing is looking at a single point along the x-axis of a wave pattern. With a little panache and a for loop, we can place a whole bunch of these oscillating circles next to each other.
This wavy pattern could be used in the design of the body or appendages of a creature, as well as to simulate a soft surface (such as water).
Here, we’re going to encounter the same questions of amplitude (height of pattern) and period. Instead of period referring to time, however, since we’re looking at the full wave, we can talk about period as the width (in pixels) of a full wave cycle. And just as with simple oscillation, we have the option of computing the wave pattern according to a precise period or simply following the model of angular velocity.
Let’s go with the simpler case, angular velocity. We know we need to start with an angle, an angular velocity, and an amplitude:
var angle = 0;
var angleVel = 0.2;
var amplitude = 100;
Then we’re going to loop through all of the
x
values where we want to draw a point of the wave. Let’s say every 24 pixels for now. In that loop, we’re going to want to do three things:- Calculate
y
location according to amplitude and sine of the angle. - Draw a circle at the (
x
,y
) location. - Increment the angle according to angular velocity.
for (var x = 0; x <= width; x += 24) {
// Calculate y according to amplitude and sine of angle
var y = amplitude * sin(angle);
// Draw a circle at the (x, y) location
ellipse(x, y+height/2, 48, 48);
// Increment the angle according to angular velocity
angle += angleVel;
}
Let’s look at the results with different values for
angleVel
:Notice how, although we’re not precisely computing the period of the wave, the higher the angular velocity, the shorter the period. It’s also worth noting that as the period becomes shorter, it becomes more and more difficult to make out the wave itself as the distance between the individual points increases. One option we have is to use
beginShape()
and endShape()
to connect the points with a line.The above example is static. The wave never changes, never undulates, and that's what we've been building up to. This additional step of animating the wave is a bit tricky. Your first instinct might be to say: “Hey, no problem, we’ll just let angle be a global variable and let it increment from one cycle through
draw()
to another.”While it’s a nice thought, it won't work. If you look at the statically drawn wave, the righthand edge doesn’t match the lefthand; where it ends in one cycle of
draw()
can’t be where it starts in the next. Instead, what we need to do is have a variable dedicated entirely to tracking what value of angle the wave should start with. This angle (which we’ll call startAngle
) increments with its own angular velocity.Here it is, with the start angle incorporated. Try changing the different numbers to see what happens to the oscillating wave.
This "Natural Simulations" course is a derivative of "The Nature of Code" by Daniel Shiffman, used under a Creative Commons Attribution-NonCommercial 3.0 Unported License.
Want to join the conversation?
- Just wondering...can you make real waves with waves?(6 votes)
- I have a basic question.
What is the difference between var draw = function() and draw = function()?
I really want to know, can someone help me?
Thanks!(3 votes)- You use the
var
keyword when you declare a variable that doesn't exist yet.
When you don't use thevar
keyword, then you're using a variable that's already declared.
Sovar draw
declares a new variable called "draw".
Anddraw
simply reuses the variable called "draw" that already exists. If it doesn't exist yet, you will get an error.var draw
is never necessary, because ProcessingJS already declares it for you.
... Why create a new variable when you already have one?(6 votes)
- I'm stuck on step two of the Many waves challenge in putting in the var name for the new wave.(4 votes)
- I still don't get how this works, why do we increase the angle by angleVel and how is it determined? I also don't get what "angle" they are talking about. For example, in the comments for the second program the say "// Calculate the y location according to amplitude and sine of the angle." but the angle of what?(2 votes)
- I created a spin-off to answer your question.
https://www.khanacademy.org/computer-programming/spin-off-of-animating-wave/5866893086867456
If you are not familiar with trigonometry this will surely be confusing. You can learn about it here:
https://www.khanacademy.org/math/trigonometry(2 votes)
- I'm having trouble with my code for the many waves challenge: I keep getting put .update before .draw, and I am. But my waves aren't moving. Please Help.
angleMode = "radians";
var Wave = function(amplitude, period, color) {
this.startAngle = 0;
this.amplitude = amplitude;
this.period = period;
this.color = color;
this.angleVel = (TWO_PI / this.period) * 5;
color= (random(255),random(255),random(255));
};
Wave.prototype.update = function() {
this.startAngle += TWO_PI / this.period;
};
var newWave = new Wave (this.amplitude,this.period, this.color);
var wave= new Wave(this.amplitude+20,this.period+40, this.color+40);
Wave.prototype.draw = function() {
background(252, 252, 252);
var angle = this.startAngle;
fill(this.color);
for (var x = 0; x <= width; x += 24) {
var y = this.amplitude * sin(angle);
ellipse(x, y, 48, 48);
angle += this.angleVel;
}
};
//i am calling update BEFORE draw
draw= function() {
newWave.update();
wave.update();
newWave.draw(30,30,30);
wave.draw(40,40,40);
};(1 vote)- You're trying to use
this.amplitude
,this.period
andthis.color
outside of the object, meaning that they will all evaluate to 'undefined'. Try using actual values there.(3 votes)
- I require assistance with Step One of the next challenge. Someone please help?(1 vote)
- I need help with step two of the next challenge. I have waves, but it won't let me proceed for the same reason as everybody else. I've asked for help a great many times, and nobody has gotten back to me, so please help. What am I doing wrong?
Here's my code:
var Wave = function(amplitude, period, color) {
this.startAngle = 0;
this.amplitude = amplitude;
this.period = period;
this.color = color;
this.angleVel = (TWO_PI / this.period) * 5;
};
Wave.prototype.update = function() {
var newWave = new Wave (this.amplitude,this.period, this.color);
this.startAngle += TWO_PI / this.period;
};
Wave.prototype.draw = function() {
background(252, 252, 252);
var angle = this.startAngle;
fill(this.color);
for (var x = 0; x <= width; x += 5) {
var y = this.amplitude * sin(angle);
ellipse(x, y, 15, 200);
angle += this.angleVel;
}
};
var w = new Wave(156, 337, color(0, 123, 255));
draw = function() {
w.update();
w.draw();
};(1 vote)- By the end of Step 1, we should see two waves like the one we see in this tutorial.(1 vote)
- in the next challenge the red circles disappeared, this is my code
var wave = new Wave(198, 175, color(255, 0, 0, 100));
var lol = new Wave(200, 239, color(36, 25, 179, 100));
translate(0, height/2);
draw = function() {
background(255);
wave.update();
wave.draw();
lol.update();
lol.draw();
};
please help(1 vote) - how do you complete step 2 (next challenge)? Here is my code:
angleMode = "radians";
var Wave = function(amplitude, period, color) {
this.startAngle = 0;
this.amplitude = amplitude;
this.period = period;
this.color = color;
this.angleVel = (TWO_PI / this.period) * 5;
};
Wave.prototype.update = function() {
var newWave = new Wave (this.amplitude,this.period, this.color);
this.startAngle += TWO_PI / this.period;
};
Wave.prototype.draw = function() {
background(252, 252, 252);
var angle = this.startAngle;
fill(this.color);
for (var x = 0; x <= width; x += 24) {
var y = this.amplitude * sin(angle);
ellipse(x, y, 48, 48);
angle += this.angleVel;
}
};(1 vote) - angleMode = "radians";
var Wave = function(amplitude, period, color) {
this.startAngle = 0;
this.amplitude = amplitude;
this.period = period;
this.color = color;
this.angleVel = (TWO_PI / this.period) * 5;
};
Wave.prototype.update = function() {
this.startAngle += TWO_PI / this.period;
};
Wave.prototype.draw = function() {
background(252, 252, 252);
var angle = this.startAngle;
fill(this.color);
for (var x = 0; x <= width; x += 24) {
var y = this.amplitude * sin(angle);
ellipse(x, y, 48, 48);
angle += this.angleVel;
}
};
var wave = new Wave(200, 175, color(255, 0, 0, 100));
translate(0, height/2);
draw = function() {
background(255);
var john = new Wave( , , );
wave.update();
wave.draw();
};
how has no one in this comment section have no idea how to do the second step in Many Waves I know thousands of people have gotten this challenge done but I can't find any that have commented here, so this may just be me rambling on about the fact that I can't complete this challenge(1 vote)- You have to create a second wave. Something like this:
var wave = new Wave(156, 175, color(255, 0, 0, 100));
var wave2 = new Wave(215, 93, color(38, 0, 255, 100));
translate(0, height/2);
draw = function() {
background(255);
wave.update();
wave2.update();
wave.draw();
wave2.draw();
};(1 vote)