NL / EN

LESSON 4: A CREATURE OF YOUR OWN

INTRODUCTION

In this lesson you will be working on the ‘soul’ of your own creature. We will pick things up where we left them in the last lesson. The steps in this lesson are intended as an example and you are completely free to deviate from the example and really create your own creature.

STEP 1

In this step we will be drawing not 1, but 10 circles. It would not be very convenient if we were to copy and paste our code 10 times. After all, this would mean that if we want to change something, we would have to change it 10 times. Instead what we can do is use a loop. A loop in coding can be compared to a loop in a video. It is a construction in which a piece of code can be executed several times. So let’s use a loop to draw our 10 circles. Initially you won’t see a difference because all 10 circles will be drawn in exactly the same way. We are going to do something to fix that in step 2.

void setup() {
    size(400, 400);
}
 
void draw() {
    background(0);
    stroke(255);
    noFill();

    // this ‘for-loop’ will execute the code within the { and } a number of time (10 in this case)
    for(int i = 0; i < 10; i++){
        float phase = frameCount * 0.015;       // every circle determines their own phase
        float x = sin(phase);                   // and x value
        float radius = map(x, -1, 1, 40, 300);  // we use them for determining a radius
        float lineWidth = map(x, -1, 1, 0, 5);  // and lineWidth
        strokeWeight(lineWidth);    
        
        ellipse(width / 2, height / 2, radius, radius);
    }
}

STEP 2

And now let’s create the differences. To get 10 different circles you can alter the settings for each circle. We could, for instance, change the phase for each circle slightly. A phase (wave) is another term from mathematics. It is used as a unit that indicates the position of a point in motion, so it adds motion to your sketch.


Instead of determining the phase for each separate circle, we are doing it once, before the loop starts. Within the loop we can then raise the value of the phase little by little each time. This will result in a differently drawn circle every time. Instead of drawing 10 circles you could draw 100 or 1000, give it a go. If you do, you will see that the sketch becomes very slow. Therefore you should try to make sure your sketch does not become too slow with every change you make.

void setup() {
    size(400, 400);
}
 
void draw() {
    background(0);
    stroke(255);
    noFill();
    
    // by placing this line outside of the for-loop it will only be calculated once per frame
    // instead of for every circle
    float phase = frameCount * 0.015;
    for(int i = 0; i < 10; i++){
        float x = sin(phase);
        float radius = map(x, -1, 1, 40, 300);
        float lineWidth = map(x, -1, 1, 0, 5);
        strokeWeight(lineWidth);    
        
        ellipse(width / 2, height / 2, radius, radius);
        phase = phase + 0.3;    // now we can add a small value to the phase so the next circle will have a slightly different phase
    }
}

STEP 3

In this step we will be adding colour to our creature. We could activate stroke once before we start drawing, but if we did, all our circles would be the same colour. Let’s use the variable x and the map function to give each circle a different colour, depending on the phase. Try filling in other numbers in map to see what it does to your creature’s colour.

void setup() {
    size(400, 400);
}
 
void draw() {
    background(0);
    stroke(255);
    noFill();
    
    float phase = frameCount * 0.015;
    for(int i = 0; i < 10; i++){
        float x = sin(phase);
        float radius = map(x, -1, 1, 40, 300);
        float lineWidth = map(x, -1, 1, 0, 5);
        
        // determine r, g and b values for color
        float r = map(x, -1, 1, 0, 255);
        float g = map(x, -1, 1, 255, 0);
        float b = map(x, -1, 1, 255, 125);
        stroke(r, g, b);         // set the stroke color
        strokeWeight(lineWidth);    
        
        ellipse(width / 2, height / 2, radius, radius);
        phase = phase + 0.3;
    }
}

STEP 4

The pulsing of the circles is predictable, maybe even a little boring. That’s because we are raising the phase with a set value all the time (in this case, 0.3). Since we are going for creative coding, we can amend this, for instance by using the sine-function again. To do so we can introduce a new variable, phaseAddition, which we recalculate for every frame using the phase’s sine. We then use this phaseAddition to raise the phase every time we draw a circle.


To make the whole thing even more unpredictable and interesting we are raising the phaseAddition itself as well with a small value every time we draw a circle. Try to play around with the numbers in the map function and the value we add in the phaseAddition. You’ll see that minor changes in the numbers can have a major impact on your creature’s movements.

void setup() {
    size(400, 400);
}
 
void draw() {
    background(0);
    stroke(255);
    noFill();
    
    float phase = frameCount * 0.015;
    float phaseAddition = map(sin(phase), -1, 1, 0, 0.25); // determine how much the phase should ‘shift’ for every circle
    for(int i = 0; i < 10; i++){
        float x = sin(phase);
        float radius = map(x, -1, 1, 40, 300);
        float lineWidth = map(x, -1, 1, 0, 5);
        float r = map(x, -1, 1, 0, 255);
        float g = map(x, -1, 1, 255, 0);
        float b = map(x, -1, 1, 255, 125);
        stroke(r, g, b);
        strokeWeight(lineWidth);    
        
        ellipse(width / 2, height / 2, radius, radius);
        phase = phase + phaseAddition;
        phaseAddition += 0.05;  // this helps to create an even more unpredictable result
    }
}

END OF LESSON 4

Great job! This was a tough lesson so well done if you've come this far. In the next lesson we'll take a look at how your creature can interact with the environment.