Math.sin and Math.cos — The creative coder’s best friend

Written by radarboy3000 | Published 2017/02/05
Tech Story Tags: javascript | programming | creative-coding | art | learning-to-code

TLDRvia the TL;DR App

Welcome to the next installment of Creative Coding Basics. You can see previous tutorials here.

This time I’m going to take you through a handy bit of algebra that creative coders use all the time: Sine and Cosine — in Javascript Math.sin() and Math.cos().

All the code and libraries for these tutorials can be found here: https://github.com/GeorgeGally/creative_coding

If you’ve been following along, do a new git pull to get the latest code.

Sine wave osciallation

Let’s start with Sine waves which are great to build oscillators. Math.sin() will always oscillate between the values of -1, 1. We multiply this by an amplitude variable to get an oscillating wave effect. Instead of adding speed_x to change our particle’s x-value, we increment an angle variable and pass it through Math.sin() like so:

var ctx = createCanvas("canvas1");

var ball = {x: 0,y: h/2,speed_x: random(1),speed_y: random(1),size: random(10, 50),colour: rgb(0),angle: random(360)}

function draw(){ctx.background(255);ball.angle += ball.speed_x;ball.rotation += 2;ball.x = w/2 + Math.cos(radians(ball.angle))*w/2;ctx.fillStyle = ball.colour;ctx.fillEllipse(ball.x, ball.y, ball.size);}

To get the sine wave effect from this tutorial’s header, we use our usual particle code and oscillate our balls’ y position (ie. move it up and down) while moving the ball left and right:

var ctx = createCanvas("canvas1");var number_of_balls = 10;var balls = [];var radius = 200;ctx.lineWidth = 1;ctx.background(0);

// push a ball and it's values into the arrayfor (var i = 0; i < number_of_balls; i++) {addBall(i);}

function addBall(i){var ball = {x: random(w),y: random(h),speed_x: random(1,4),speed_y: random(1,4),amplitude: random(h/10,h/4),size: 2,colour: rgba(255, 0.8),angle_x: random(360),angle_y: random(360)}balls.push(ball);}

function draw(){moveBall();drawBall();}

function moveBall(){

for (var i = 0; i < balls.length; i++) {var b = balls[i];b.angle_x += b.speed_x;b.angle_y += b.speed_y;// moveb.x = w/2 + Math.sin(radians(b.angle_x/5)) * w/2;b.y = h/2 + Math.sin(radians(b.angle_y)) * b.amplitude;}

}

function drawBall(){for (var i = 0; i < balls.length; i++) {var b = balls[i];ctx.fillStyle = b.colour;ctx.fillEllipse(b.x, b.y, b.size);}}

By oscillating the ball’s x value as well, we can create some interesting effects like this:

Change the ball’s x-speed and to get some interesting effects

The most common thing I use Math.sin() and Math.cos() for is to draw things in circles…

It’s pretty simple. Using our same particles code, we just create an angle variable for the particle and then use Math.cos(angle) to get the x position and Math.sin(angle) to get the y position. We multiply this by our radius and walaa… we have circular movement…

var ctx = createCanvas("canvas1");var number_of_balls = 5;var balls = [];// radius of our circlevar radius = 200;

for (var i = 0; i < number_of_balls; i++) {addBall();}

function addBall(){var ball = {x: 0,y: 0,speed: random(1),size: random(10, 50),colour: rgb(0),angle: random(360)}balls.push(ball);}

function draw(){

ctx.background(245, 1);moveBall();drawBall();}

function moveBall(){

for (var i = 0; i < balls.length; i++) {var b = balls[i];// move the angle to rotate the ballsb.angle += b.speed; // plot the balls x to cos and y to sin b.x = w/2 + Math.cos(radians(b.angle))*radius;b.y = h/2 + Math.sin(radians(b.angle))*radius;}

}

function drawBall(){for (var i = 0; i < balls.length; i++) {var b = balls[i];ctx.fillStyle = b.colour;ctx.fillEllipse(b.x, b.y, b.size);}}

Ok, we have circular movement, now let’s get the balls moving on a circle… Pretty easy, we simply change our draw() function and draw an ellipse twice the size of the radius:

function draw(){ctx.background(245, 1);ctx.fillStyle = "black";ctx.HfillEllipse(w/2, h/2, radius*2);moveBall();drawBall();}

Notice I’m using a new ellipse drawing function I’ve made, HfillEllipse(), this is exactly the same as fillEllipse(), it’s just a higher resolution version, meaning, we get smoother edges. I usually use this for larger circles to make them look better, but be warned, don’t use it for everything or you’ll have performance issues.

And then we’ll also need to alter our moveBalls() function to take into account the individual ball’s size, so that the balls are rolling on the circle… pretty simple to do, we just add half the ball’s size to the radius:

function moveBall(){

for (var i = 0; i < balls.length; i++) {var b = balls[i];// move the angle to rotate the ballsb.angle += b.speed;b.x = w/2 + Math.cos(radians(b.angle))*(radius+b.size/2);b.y = h/2 + Math.sin(radians(b.angle))*(radius+b.size/2);}

}

And boom, we have this…

Balls on a ball!

Say, we wanted to distribute the balls evenly on the circle… we could just use a formula like so:

ball_number/total_number_of_balls * 360;

I’ve made a function for this:

function distributeAngles(me, total) {return me/total * 360;}

Creative coding, is often, just a combination of simple concepts, to make something slightly more complicated. We now have all the tools we need to create something a little more complicated like this:

We have two sets of particles, and out and an inner set. I’ve put these in objects called inners and outers. Note I’ve added an empty array called particles to each object — so we can store our particle

var ctx = createCanvas("canvas1");

// create two objectsvar inners = {count: 3,radius: 220,speed: random(2)/100,particles: []};

var outers = {count: 3,radius: 100,speed: random(-2)/100,particles: []};

And now we can add our particle values. Notice I pass the whole object into the addParticle() function, which makes it easy to access it’s values. We then work out the angle values of the particles using the same method as we did above. Note we don’t really need to work out the x and y values as we’ll do this on each loop iteration later:

for (var i = 0; i < outers.count; i++) {addParticle(i, outers);}

for (var i = 0; i < inners.count; i++) {addParticle(i, inners);}

// pass in the objectfunction addParticle(_i, _object){

var _angle = radians(distributeAngles(i, _object.count));

var particle = {x: 0,y: 0,speed: _object.speed,angle: _angle,radius: _object.radius}

_object.particles.push(particle);

}

Ok, here comes the final part of the puzzle. Notice that each inner particle is connected to every outer particle. So we loop through all the inner particles for each iteration of the outer particles, like so:

// draw and move particles

for (var i=0; i< outers.count; i++) {// move the outer particles

for (var j=0; j< inners.count; j++) {// move inner particle// then connect it to the outer particle}

}

So let’s put it all in a function. Note that we add canvas.width/2 to the x values and canvas.height/2 to the y values. We then draw a line from the inner particle to the outer one:

function drawLines(){

for (var i=0; i< outers.count; i++) {

var outer = outers.particles[i];outer.angle += outer.speed;outer.x = w/2 + Math.cos(outer.angle) * outer.radius;outer.y = h/2 + Math.sin(outer.angle) * outer.radius;

for (var j=0; j< inners.count; j++) {  
  var inner = inners.particles\[j\];  
  **inner.angle += inner.speed;  
  inner.x = w/2 + Math.cos(inner.angle) \* inner.radius;  
  inner.y = h/2 + Math.sin(inner.angle) \* inner.radius;  
  ctx.line(inner.x, inner.y, outer.x, outer.y);**  
}

}

}

And that’s it. We’re done. Happy coding.

As usual the full code is available on my github: https://github.com/GeorgeGally/creative_coding

Follow me on Instagram here: https://www.instagram.com/radarboy3000/

Follow me on Twitter here: https://twitter.com/radarboy_japan

And like my Facebook Page here: https://www.facebook.com/radarboy3000


Published by HackerNoon on 2017/02/05