If you're seeing this message, it means we're having trouble loading external resources for Khan Academy.

If you're behind a web filter, please make sure that the domains *.kastatic.org and *.kasandbox.org are unblocked.

Remember all this stuff?

location = location + velocity
velocity = velocity + acceleration

The stuff we dedicated almost all of the last two sections to? Well, we can apply exactly the same logic to a rotating object.

angle = angle + angular velocity
angular velocity = angular velocity + angular acceleration

In fact, the above is actually simpler than what we started with because an angle is a scalar quantity—a single number, not a vector!

Using the answer from the previous challenge, let’s say we wanted to rotate a baton in ProcessingJS by some angle. We would have code something like:

translate(width/2, height/2);
rotate(angle);
line(-50, 0, 50, 0);
ellipse(50, 0, 8, 8);
ellipse(-50, 0, 8, 8);

After we add in our principles of motion, we have the program below. The baton starts onscreen with no rotation and then spins faster and faster as the angle of rotation accelerates:

This idea can be incorporated into our Mover object. For example, we can add the properties related to angular motion to our Mover constructor.


var Mover = function(m, x, y) {
    this.position = new PVector(x, y);
    this.mass = m;

    this.angle = 0;
    this.aVelocity = 0;
    this.aAcceleration = 0;

    this.velocity = new PVector(random(-1, 1), random(-1, 1));
    this.acceleration = new PVector(0, 0);
};

And then in update(), we update both the position and angle according to the same algorithm!

Mover.prototype.update = function () {

    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);

    this.aVelocity += this.aAcceleration;
    this.angle += this.aVelocity;

    this.acceleration.mult(0);
};

Of course, for any of this to matter, we also would need to rotate the object when displaying it.

Mover.prototype.display = function () {
    stroke(0, 0, 0);
    fill(175, 175, 175, 200);
    rectMode(CENTER);
    
    // pushMatrix and popMatrix are needed so that the shape rotation
    //  doesn't affect the rest of the world
    pushMatrix();
    // Set the origin at the shape's location
    translate(this.location.x, this.location.y);
    // Rotate by the angle
    rotate(this.angle);
    rect(0, 0, this.mass*16, this.mass*16);
    popMatrix();
};

Now, if we were to actually go ahead and run the above code, we wouldn’t see anything new. This is because the angular acceleration (this.aAcceleration = 0;) is initialized to zero. For the object to rotate, we need to give it an acceleration! Certainly, we could hard-code in a different number:

this.aAcceleration = 0.01;

Here's what a program looks like with the above logic, with a force calculated based on a central attractor:

That's a good start, but we can produce a more interesting result by dynamically assigning an angular acceleration according to forces in the environment - since objects don't usually spin of their own accord! Now, we could head pretty far down this road, trying to model the physics of angular acceleration using the concepts of torque and moment of inertia. That level of simulation is beyond the scope of this course - but we'll still get a bit more complex.

For now, a quick and dirty solution will do. We can produce reasonable results by simply calculating angular acceleration as a function of the object’s acceleration vector. Here’s one such example:

this.aAcceleration = this.acceleration.x;

Yes, this is completely arbitrary. But it does do something. If the object is accelerating to the right, its angular rotation accelerates in a clockwise direction; acceleration to the left results in a counterclockwise rotation. Of course, it’s important to think about scale in this case. The x component of the acceleration vector might be a quantity that’s too large, causing the object to spin in a way that looks ridiculous or unrealistic. So dividing the x component by some value, or perhaps constraining the angular velocity to a reasonable range, could really help. Here’s the entire update() method with these tweaks added.

Mover.prototype.update = function () {
    this.velocity.add(this.acceleration);
    this.position.add(this.velocity);

    
    // Calculate angular acceleration based on horizontal acceleration,
    //  and divide so it's not as strong
    this.aAcceleration = this.acceleration.x / 10.0;
    this.aVelocity += this.aAcceleration;
    
    // Use constrain to ensure velocity doesn't spin out of control
    this.aVelocity = constrain(this.aVelocity, -0.1, 0.1);
    this.angle += this.aVelocity;

    this.acceleration.mult(0);
};

Here's what the program looks like, with those changes incorporated:


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.