Creative Coding

These lecture notes are for the course "Creative Coding" at Hochschule für Gestaltung Offenbach.

Author: Sebastian Kujas

Processing

Processing is a Java Framework/IDE to simplify the process of creative programming. It is tailored to artists, designers and specifically to people that have no experience in programming. It is open source and cross platform compatible, which makes it perfect for an educational environment. The Arduino IDE and workflow is heavily influenced by Processing which makes learning Arduino easier, once you know Processing. Its superb documentation with examples for basically anything makes it easy to learn and tinker with.

Java is an imperative object oriented programming language that is compiled to an intermediate code which is run in a Java Virtual Machine. It is cross platform or better said WORA (Write Once Run Anywhere). Its syntax is based on C/C++ which makes it a good primer for faster creative coding frameworks like openframeworks (https://openframeworks.cc/).

Programming Basics

Programming comes in many different flavors. From textual to visual, from machine code to high level languages. This is an introduction to the key concepts and paradigms.

Paradigms

There are two main paradigms when it comes to programming. Imperative and Declarative. We won't go into very much detail, but remember that Java and C++ belong mainly but not exclusively to the imperative paradigm and that this is the one we will be following.

Imperative means, that we define control flow ourselves and tell the computer exactly how to execute our program. We do this in case of textual programming by writing well defined statements into a file with the help of a text editor. What statements we are allowed to use and how to use them is defined by the programming language syntax. Most programming languages are written like western style text from top left to bottom right. The statements are executed from top to bottom.

Writing Code

So how does such a program look like? Let's look at an example in Java, or more specifically in Processing.

text("hello world", 20, 20);

hello world in Processing

This is actually a complete program in Processing. All it does is, open a window and display "hello world". Let us dissect it and have a closer look at its components.

text( "hello world" , 20 , 20 ) ;
|   | |-----*-----  | |         |
|   | |     |       | |         *-> semicolon
|   | |     |       | *-----------> int argument
|   | |     |       *-------------> comma
|   | |     *---------------------> string argument
|   | *---------------------------> quotes
|   *-----------------------------> round parantheses
*---------------------------------> statement

In this case the statement is a function call. More specifically the text function is called. Inside of the round parantheses are the so called arguments of the function. In this case the text function has three arguments which are of type string and int. A string is a sequence of characters and in most programming languages surrounded by quotes. An int is an integer number. At the end of the line is a semicolon. This is mandatory in some programming languages and defined in the language syntax.

Now you might ask yourself, how can this one line of code generate a window and display text in it? Good question! Just a quick answer before we continue with the basics: text is a function.

Functions

A function is in programming terms a reusable collection of code. That means that somewhere inside of Processing there is a so called function definition which contains more lines of code which are again in most cases function calls.

When a function is called - let's take our little textfunction for example - there are really hundreds, or thousands or even more lines of code executed just to show the window with the text.

The important concept to understand here, is the concept of a function and its arguments. Example time!

void helloWorld() {
    text("hello world", 20, 20);
}

helloWorld();

What do we see here? We see a function definition that creates a function with the name helloWorld. Inside of helloWorld we call our text function from the example above. Everything that is inside of the curly parantheses {} is the body of our function and is executed from top to bottom, when the function is called. Ignore the void for now, it simply defines the return type of the function.

Calling the function is achieved by writing helloWorld();. (To make this work in Processing one would need to put the function call into the draw function. More about that later.) Calling a function means running the code in its body and then returning back to where we called it and continuing with the next line after the function call.

void helloWorld(String myText) {
    text(myText, 20, 20);
}

helloWorld("hello world");

In this example we added one argument to our helloWorld function. This makes it possible to put a text into our function call and relocate the data ("hello world") out of the function body into the function call. What we now achieved is reusability of our helloWorld function.

void helloWorld(String myText) {
    text(myText, 20, 20);
}

helloWorld("hello world");
helloWorld("hallo welt");

The output of this example would first print "hello world" and then "hallo welt".

void helloWorld(String myText, int x, int y) {
    text(myText, x, y);
}

helloWorld("hello world", 20, 20);
helloWorld("hallo welt", 20, 40);

Now we also parametrized the location of the text. We added two more arguments to the function definition, namely x and y with either of them of type int. That means that we can set the position of the text in our function call.

As a sidenote: The colors you see in the examples or in the editor are only decorative. They have no relevance for the execution of the statements and are solely for better readability.

Syntax

Every programming language has a set of rules that define how its code must be written. Syntax is the term which refers to these rules. It tells you which symbols are allowed, where to put parantheses, semicolons, colons and so forth. It tells you how to structure your code, so that the compiler understands what you want to do.

int barWidth = 20;
int lastBar = -1;

void setup() 
{
  size(640, 360);
  colorMode(HSB, height, height, height);  
  noStroke();
  background(0);
}

Where to put parantheses, semicolons and how to define your variables and functions is all called syntax.


Variables and Types

Types

If you need to work with data in your program, you use a variable to store that data in. A variable can hold a value, just like in maths. It also defined almost the same way.

type name = value;

Which kind of value a variable can hold, is defined by its type. The most common data types are shown below.

int coolVariable = 20; // int is for integers
float evenCoolerVariable = 0.256; // float is for floating point numbers
boolean something = true; // boolean is either true or false

char someChar = 'A'; // char is for characters
String someText = "Strings are for text"; // String is for text

Apart from the primitive data types like byte, short, int, long, float, double, boolean and char, there are also non-primitive data types like Strings, Arrays and Classes.

Arrays

Arrays store multiple values in one variable. This has many advantages over storing each value in its own variable. Let alone that this is in many cases not even possible. Take data that is generated during runtime of your program for example.

Basic usage of an array.

int[] numbers = {10,23,35};

print(numbers[2]);

// output: 35

Programmers are a lazy bunch. And they must be, because it is good practice to write code only once and reuse it.

Take this code for example:

int number1 = 1;
int number2 = 20;
int number3 = 25;
int number4 = 123;
int number5 = 5535;

Defining these 5 numbers is really a lot of manual work. And using them later on is even harder. Let's lazy this out to programmer style.

int[] numbers = {1,20,25,123,5535};

This way you declare an Array with values. The rectangular brackets [] tell the compiler that numbers is an array of numbers instead of one single number. The part after the equal sign is the initialization. It tells the compiler which numbers to put into the array, and most important at which index they will be accesible later on. Indexes in arrays always start with 0.

Using a value from an array.

int valueFromArray = numbers[2];
print(valuefromArray);

// output: 25

Reading it aloud: Assign value with index 2 from numbers to valueFromArray and then print it to screen

You could also do it in one line.

print(numbers[2]);

// output: 25

Writing a value to an array.

numbers[3] = 3643;

Easy!

Real world usage of arrays and a peak into the next chapter.

for(int i = 0; i < 5; i++){
    print(numbers[i]);
}

// output: 1202536435535

print would print all numbers from our array numbers without seperator or new line to the screen. Note that 123 at index 3 was overwritten by 3643 above. To understand what for does and how it works continue reading.

Declaring an array without values and writing multiple values to it later.

int[] noNumbersYet = new int[5];

for( int i = 0; i < 5; i++){
    noNumbersYet[i] = i * 10;
}

for(int i = 0; i < 5; i++){
    print(noNumbersYet[i]);
}

// output: 010203040

If you do not know the values of the array upfront, you need to tell the compiler how big your array should be. That is what happens with the new int[5] statement. It tells the compile to reserve 5 times the number of bytes needed for an int in memory for that array. Or easier said, it tells the compiler this array is supposed to store five values. In the first for loop values are assigned to each index of the array. In the second for loop the values are printed.

Scope

Scope in a program defines the lifetime and accessability of variables. It is best explained with some examples.

int[] noNumbersYet = new int[5];

for( int i = 0; i < 5; i++){
    noNumbersYet[i] = i * 10;
}

We have two variables in this example. noNumbersYet and i inside the for loop. noNumbersYet is what is called a global variable. It is defined on the top most level of the program and accessible mostly anywhere. i on the other hand is a local variable to the for loop and only accessible inside the for loop. Understanding how scope works is very important. Later we will also get to know classes and functions and how scope works with those.

Functions

Functions are a great feature for the lazy programmer as they store code that has to be written only once and can then be reused throughout the program.

Processing sketches usually come with two predefined functions.

void setup(){
    // do boring setup things here
    // called once when the sketch starts
}

void draw(){
    // draw fancy graphics here
    // called every frame until the program quits
}

These two functions get called by the code that does all the hard work behind the scenes of Processing. This code is normally not seen by the typical Processing user.

These two functions do not need to stay alone. We can define our own functions and use them inside of the setup or the draw function. Let us think of an extended print function for example.

int i;

void setup(){
    i = 25;
    fancyPrint(i);
}

void draw(){
    i++;
    fancyPrint(i);
}

void fancyPrint(int x){
    print(i);
}