NL / EN

LESSON 5: INTERACTION & IMPULSES

INTRODUCTION

So far our assumption has been that your character is alone and is not receiving any outside stimuli. In this lesson we will see how we can respond to stimuli. As soon as you let your character out in the big world, a variable agitation will be available. This variable will always have a value between 0 and 1. The value of agitation is influenced, among other things, by the presence of other characters: if there are many other characters around, agitation will have a higher value than when your character is all by himself. This will have a wonderful visual effect when more and more characters are released into the environment.

STEP 1

To allow your character to respond to this outside stimulus you have to add two things: the function setAgitation and the variable agitation. This function will be called upon when there is a new value and you can then save this value in the variable agitation. Because your character has not been released into the environment this function will not be called upon automatically. So to be able to test the agitation we have to activate this function ourselves.


One way of doing this is to use the variable mouseX. You mustn’t forget to remove this line again before you finally upload your character, because then the agitation will be set by the environment automatically. This sketch looks the same as the last one, because we are not yet using the agitation to make your character draw differently.

// variable to save the agitation
float agitation = 0;
 
void setup() {
    size(400, 400);
}
 
// this function will be called by the environment
void setAgitation(float newAgitation) {
    agitation = newAgitation;
}
 
void draw() {
    background(0);
    stroke(255);
    noFill();
    
    // only for testing: use the horizontal mouse position to control the agitation
    setAgitation(map(mouseX, 0, width, 0, 1));
    
    float phase = frameCount * 0.015;
    float phaseAddition = map(sin(phase), -1, 1, 0, 0.25);
    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;
    }
}

STEP 2

We can now use agitation to vary things like the width of the circles. In this example we are using the random function to adapt the width of the circles in an unpredictable way in every frame.

float agitation = 0;
 
void setup() {
    size(400, 400);
}
 
void setAgitation(float newAgitation) {
    agitation = newAgitation;
}
 
void draw() {
    background(0);
    stroke(255);
    noFill();
    
    setAgitation(map(mouseX, 0, width, 0, 1));
    
    float phase = frameCount * 0.025;
    float phaseAddition = map(sin(phase), -1, 1, 0, 0.75);
    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);
        
        // use agitation to change the lineWidth randomly
        float lineWidthAddition = random(map(agitation, 0, 1, 0, 25));
        strokeWeight(lineWidth + lineWidthAddition);    
        
        ellipse(width / 2, height / 2, radius, radius);
        phase = phase + phaseAddition;
        phaseAddition += 0.1;
    }
}

STEP 3

We can use agitation for all kinds of things. As a final example we will make sure your character is completely white when agitation equals 0 and that it takes on a colour when agitation equals 1. To achieve this we are using the function lerp, a function that can be used for so-called linear interpolation. This means we can mix, so to speak, the 2 numbers. In our case, we want all three colour components (r, g and b) to interpolate between 255 (white) and the colour value we have set earlier. lerp looks like this:

float a = 100;
float b = 200;
float interpolated = lerp(a, b, 0.5)

In this short example we are interpolating (i.e. estimating a value between two known values) between the values of a and b. The number 0.5 indicates that we want to end up exactly in the middle, and the result will therefore be 150. Imagine filling in the value 0 instead of 0.5, then the result would be 100, and for a value of 1 the result is 200. For this value we want to use agitation:


float agitation = 0;
 
void setup() {
    size(400, 400);
}
 
void setAgitation(float newAgitation) {
    agitation = newAgitation;
}
 
void draw() {
    background(0);
    stroke(255);
    noFill();
    
    setAgitation(map(mouseX, 0, width, 0, 1));
    
    float phase = frameCount * 0.025;
    float phaseAddition = map(sin(phase), -1, 1, 0, 0.75);
    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);
        
        // use the lerp function to interpolate between white and colored depending on agitation
        r = lerp(255, r, agitation);
        g = lerp(255, g, agitation);
        b = lerp(255, b, agitation);
        stroke(r, g, b);
        
        float lineWidthAddition = random(map(agitation, 0, 1, 0, 25));
        strokeWeight(lineWidth + lineWidthAddition);    
        
        ellipse(width / 2, height / 2, radius, radius);
        phase = phase + phaseAddition;
        phaseAddition += 0.1;
    }
}

END OF LESSON 5

Congratulations! This was the last lesson where you actually learn how to code. In the next lesson we'll take a look at how to put your code on GitHub and upload your creature into the environment.