First Tutorial: Processing and programming basics.
During the course we will be learning how to to write computer programs using the Processing language, its framework and IDE (integrated Development Environment). First we will install Processing:
1. Getting started: Installing Processing.
Download the correct version for your operating system from here:
https://processing.org/download/
-On Windows you will get a zip file. Un-zip it it and drag the folder wherever you want Processing to be installed (like the “Program Files” folder, for example). To run it, click the processing.exe file.
-On Mac OS X, open the zip file and install normally (drag the Processing icon into the “Applications” folder). You can now run it as any other program.
-On Linux, untar the tar archive in your location of choice. Then open the terminal and change the current directory (through the cd command) to the newly untarred directory. Write ./processing on terminal to run (you can always create a small shell script to do this automatically).
Now, to test that Processing is correctly installed, you can go into Sketch->Run and click it. (or click the “play” button on top of the IDE, the small triangle in a circle). A small grey empty rectangle should appear on the side the Processing “IDE”. If it doesn’t you can try to find out what may have got wrong in the troubleshooting page.
Now that the program is properly installed, and before we move on into learning Processing, we can setup a few more things. You can use the default location for saving your sketches or Processing programs, but it may also be convenient to choose a more suitable location in your computer: you can do this in “preferences” (which can be in the “File” menu in Windows, or under the “Processing” menu in OS X, for example).Once here you can tick a few useful boxes for showing errors and warnings, code completion or suggesting import statements:
Hopefully you will have gone through this without much trouble, and now you are ready to start programming. But first a minimal amount of theory about programming:
2. What is programming, basic concepts.
An informal description of a program needs only to recourse to its etymology: derived from the Greek, program means simply to write in advance. The word is made up from the prefix pro-, meaning ahead, forth, forward, as in project, problem or prophecy; and the suffix -gram, meaning that which is written or drawn, originally to scratch or leave a mark, as in diagram, telegram or gramophone. Computer programs are thus instructions inscribed in some material support that will evoke certain operations in a computing agent. Generally (and very informally), any process that can be described as a sequence of well defined steps can be notated as a program. This is what it makes possible to write programs that emulate machines such a typewriter or a telephone, or simulate processes such as flow dynamics or biological growth, for which models exist consisting of such well defined steps and causal relations.
Computer programs consists usually of texts written in a programming language. The type of programming languages that we use today stem from the high-level programming languages that emerged during the late fifties and early sixties. Influenced by formal models of languages like those proposed by Noam Chomsky, they share with natural languages (like spoken or written English or Swedish, for example) their dependance on grammatical and syntactical rules. There are a number of different syntaxes and grammars used in programming, as well as a number of programming paradigms and styles; but despite variations, most programming languages implement the same basic principles, and thus, known one, it is relatively easy to learn any other. The next step will introduce the basic concepts of programming through Processing.
Syntax.
A difference between natural languages -the everyday spoken, signed or written languages- and formal languages (like programming languages) is that the late ones are more strictly formalised; the instructions of programs need to be written strictly following certain rules, or syntax, in order to be interpreted and executed by a computer, while in ordinary language, it is still possible to communicate despite grammatical or syntactical errors. Thus it is very important to pay attention to the syntax . If you checked the “Continuously check for errors” box in the preferences of Processing, the IDE will let you know what it may be missing in your syntax. After all these preliminaries we will write our first (and canonical) line of code. Go to Processing, and write the text bellow:
println("Hello world");
Press the arrow (run) key (or its menu or shortcut alternatives) to execute it. It (surprisingly enough?) prints a line, with the string “Hello world” in the “console” (more about strings later). The console is the default output for text, and very useful for communicating with running programs. Arguably, a small “Hello World” text may not be very exciting. You can try instead writing the following code:
rect(10,20,20,30);
Which draws a rectangle at coordinate X 10 pixels, and coordinate Y 20 pixels,20 pixels wide and 30 pixels high, on the display window. Change the coordinates to see what happens (point 0,0 is placed on the top left corner of the window, with the X positive axis going to the right, and the Y positive axis pointing down).
Now lets analyse this simple code in terms of syntax: both println and rect are functions defined as part of Processing. The syntax is as follows: first comes the name of the function (println or rect); then, and between parenthesis (), the parameters they need (in the case of println a string, in the case of rect 2 coordinates and 2 dimensions); finally, a semicolon “;”. This is the basic syntax convention shared by the C programming language, Java, C++ or Javascript, for example (since Processing is based on Java it follows most of its conventions). There are many predefined functions in processing, which you can check at the processing reference, also accessible in the processing IDE through the “Help” menu.
You should try some of the functions in the Processing reference, particularly those for drawing in 2D, and get familiar using the reference. You can write sequences of functions, one after each other. For example, you can try to write sequences of functions that change the states of the current fill colour ( fill() ), the stroke colour (stroke()), disable the stroke altogether through noStroke() or set background colour through background(). You ca also set the size of the Processing sketch with size(). Useful functions for basic drawing can be found in the reference under the headings “Shape” and “Color”.
This is the code for the simple example above.
Observe also that if you have enabled “Code completion with Ctrl-space” in preferences, if you start typing a function and press Ctrl-space, you will be able to see and choose from a number of suggestions:
After playing for a bit, lets also look at comments before continuing. Computer code becomes often quite cryptic and difficult to understand. Comments exist to add explanations and notes to code. In Processing, as in Java, C, C++, Javascript or C# and other languages sharing similar syntax, these are possible by using “//“ or “/* */“. These symbols tell Processing (or any other compiler or interpreter that translates or executes written code) to ignore the commented text. “//“ means “ignore everything in this line from this point to the right”, and “/* …. */“ means ignore everything between these two signs. Here are some examples of comments:
//this is a comment, of one line
/* this is a comment of many lines */
/* The code below draws a red line, from a point with coordinates 10,10 to a point with coordinates 50,70. */ stroke(255,0,0); //this sets the stroke to be red line(10,10,50,70); //this draws the line
Also, lines of code can be broken. The “;” indicates really the end of a line. For example it is possible to write:
line( 10, 10, 50, 70);
As you may have observed, it is necessary to always end your functions or lines of code with semicolons “;“. This is known as the statement terminator in all these languages, and lets know the program parsing the text (the compiler or interpreter) where the statement ends.
Types.
The functions above could take parameters of types String, for strings of text, or numbers, such as coordinates and dimensions. In the case of rect() the reference says that it can take a number of float values. Float stands for floating point number, a number with a fractional part (commas) up to a certain precision (you can try changing some of the values on your lines, for example instead of 10, you can write 10.35, and see what happens).
Types identify the kind of values that the language can represent and how they behave, particularly in relation to arithmetic or logic operators and functions. The behaviour of types defines for example what may happen when writing “hello” + 35, that is adding a String type to a number, in this case an integer type. The types in processing are the same as the basic types in Java, but generally only a few of them are really used; you can check them under the Data Primitives in the reference. The ones we are going to consider now (and cover most of the basic types) are:
boolean, which is used to represent a true or false value.
int, which is used to represent negative and positive integers (that is, without commas) between the values -2147483648 and 2147483647.
char, an integer type, but generally used to represent single characters, like ‘E’ or ‘#’ (characters in computers correspond to numbers, so when one writes a char ‘b’ in a program it is equivalent to number 98 which is the ascii code for small case b).
float, that represents numbers with commas between -3.40282347E+38 and 3.40282347E+38.
Besides the above basic types, String is used to represent and manipulate strings of text (made of chars), such as “Hello World” above.
Variables.
We have so far seen how how literal values of different types are passed to functions. Programming would be quite limited if this is the only thing we could do. Variables are symbols of a certain type that can store a value. Their type is written first, followed by their name. They can be given any name, and their values are assigned through the “=” assignment operator. Observe that, even if it looks like the mathematical equality sign, its meaning is different; it really means “set a variable (on the left of the operator) to (a value on the right of the operator)”. A few important points about the use of variables are:
- Variables need first to be declared (their type and name stated), before they can be assigned (through the assignment operator) or used in function calls or other statements.
- More than one variable of the same type can be declared and assigned on the same line, if they are separated by comas.
- Before a variable is assigned, it will be initialised to a default value by Processing (zero for int or floats, for example).
Here is a simple example to illustrate variables. (this is not the shortest and best way of writing code to produce these results, it can be written in a much shorter way):
size(200,200); //set the size of the screen //declare a variable called w set it to the width of the display window. float w=200; //same for h and the height of the display window. float h=200; //variables of the same type declared and intialised together. float red=255, green=20, blue=0; float rectWidth; //a variable called rectWidth rectWidth=w/2; //set it to w/5 float posx=0; noStroke(); //draw without outlines from now on fill(red,green,blue); //set the fill colour for all things drawn rect(posx,0,rectWidth,h/2); //now we draw a rectangle //we change the values of the variables... red=30; green=130; blue=255; posx = rectWidth; //set the variable used for the x of the rectangle //and draw again with updated variables fill(red,green,blue); rect(posx,0,rectWidth,h/2);
Try changing the names and values of the variables. Any name is valid, such as “banana” or “foo”, for example…it is however convenient to give variables meaningful names, so the code is readable and easier to understand. Of course if you rename a variable, you have to change its name everywhere it is used.
Variables are really locations in the computer’s memory to which one can give a symbolic name. Besides describing how to treat the variable, the type on the declaration tells the computer how much space in memory it will use for it: for example a “char”, which is used to store one single character or letter, takes 16 bits of memory; an “int” or “float”, uses 32 bits instead (in Processing and Java). Again, variables need to be declared before they are assigned or used. This for example will not work:
x=60; //x is assigned before it has been declared! float x=40; ellipse(x, 10, 20, 20);
But this does:
float x; //x is declared, but not assigned. x=60; ellipse(x, 10, 20, 20);
Here comes another example with a String, which is declared and assigned in the same line. When a variable is given a value for the first time it is said that the variable has been initialised.
String sometext="Hi there"; println(sometext);
Some types can be automatically converted to others, like int to float.
float banana; int pineapple=10; banana=pineapple; println(banana);
They can also be added:
float a=10.36; int b=10; float c=a+b; println(c);
This will also work in Processing, but it will truncate the comma.
float a=10.36; int b=5; b += a; //this is the add assign operator, short for b=b+a; println(b);
Variables of the same type can also be declared and assigned followed by commas, so we can write:
float x=10, y=20, w=40, h=30; rect(x,y,w,h);
Play a bit with the variables, so you understand how they work. You can check the operations that are possible to do with each type in the reference, under “Math” and “Operators”.
Control flow.
Programs would be rather cumbersome if one would need to specify sequences of actions one after the other, without being able to repeat or select which sequences to execute as the program runs. Processing, as most common programming languages, follows an imperative programming paradigm. Their basic characteristic is the use of control flow: a program is just a text defining certain operations statements that the computer reads in a predeterminate sequence and executes accordingly. All programs have usually an entry point, that is, a place in the text from which the computer starts reading and executing it. So far the statements we have seen have been executed by starting at the top of the text and reading one instruction after the other; this order, known as control flow, can be branched and looped.
This is one of the basic differences of programming as a form of notation: music scores for example notate sequences of notes, or written text sequences of phonemes (if they use an alphabet of graphemes such as the Arabic, Hangul or Latin alphabets). These are read sequentially, one after the other. A program, in the other hand, specifies also the order in which it should be read and interpreted, by specifying how and when to repeat, skip and generally jump between different parts of the program. It also specifies, through variables, how to re-write the symbols (the values) that it also reads and interprets. The basic mechanisms for implementing this capacity of a program to read and write itself are relatively simple:
Conditional statements: if, if else.
One of the most basic operations one can think a program would do is to make decisions: if something happens or a condition is fulfilled, execute some part of a program, otherwise, execute another part. This is the basis of conditional statements. Conditional statements evaluate an expression and execute segments of code depending if the expression is true or false. The most common form of conditional statement in Processing is achieved through the use of the if, and else statements(The other forms are in the reference under “Control” and “Conditionals”). The operators used for evaluating expressions, such as the != (inequality), == (equality), < (less than) or > (greater than) result always into a boolean value, one that is either true or false (all operators are in the reference under “Control” and “Relational Operators”). The syntax for a conditional statement is as follows: First comes the statement, and between brackets the expression to be evaluated (for example if a variable is bigger, smaller or equal to other variable or literal value). After that, and between curly brackets {} come the code to be executed if the condition was met. These curly brackets can be placed anywhere after the if statement. For convenience they are often placed on the same line as the if; lines of code between the brackets are usually indented for readability. These are some of the forms conditional statements can take:
if(…){…}
if(…){…}else{…}
if(…){…}else if(…){…}else if(…){…}else{…}
For example:
int a=10; if(a>5){ line (0,0,100,100); //only if a>5, which it obviously is, since we have set it to 10… }
We can also add an else statement:
int b=20; //try out yourself different values of b if(b<3){ //you can also change the condition (equal? larger?…) ellipse(50,50,30,30); }else{ ellipse(30,30,10,10); }
Statements can also be combined through logical operators, such as &&, which means AND, || which means OR, or !, which means NOT. For example:
int a=10; String s="what?"; if(a>3 && s=="what?"){ //AND of comparing 2 ints and 2 Strings fill(255,0,0); //set fill colour to red }else{ fill(0,0,255); //set fill colour to blue } ellipse(50,50,30,30);
An interesting tool in the Processing IDE (and common in many programming environments) is that of debugging. One can turn it on in the Debug menu by choosing “Enable Debugger”. With the Debugger enabled, it is possible to step through the code one step at a time. By inserting “Breakpoints” in relevant lines (by clicking on the line number), it is possible to pause the execution, follow the flow of control, and inspect the values of variables.
Loops:
Besides conditional branching we can also make the control flow go into loops, that is, the program to repeat something until a condition is met. This is often achieved through for or while loops. For loops are very common, used in most cases to repeat a bit of code a certain number of times. The syntax of a while loop is very similar to that of an if statement:
while(…){…}
Within parenthesis an expression is given and the code that follows will be repeated as long as the expression is true. For loops are specially used (though not exclusively) when iterating through something a certain number of times or for a certain number of items (their use will be specially apparent when arrays are introduced in the next tutorial). The syntax of a for loops is as follows: the “for” keyword is followed by a parenthesis, and within the parenthesis there are 3 statements separated by “;“: the first statement initialises (and often also declares) a variable, often used to count the iterations of the loop. the second statements defines a condition necessary for the code in the loop to be executed (in most cases that the counter variable is larger, equal or smaller than a certain value); finally the last statements it is commonly used to modify the counter, by increasing or decreasing it by a number. After the parenthesis, and as with while and if, comes the code to be iterated through between curly brackets {}:
for(… ; … ; … ;){…}
for example:
size(400,400); noStroke(); background(255); int greyColor=255; //check how colors work in the reference! int numSquares=20; int sqSize=300; //initial size of the square int greyDecrement=255/numSquares; int sizeDecrement=sqSize/numSquares; for(int i=0; i < numSquares; i++){ //The for loop fill(greyColor); rect(200-sqSize/2, 200-sqSize/2, sqSize,sqSize); sqSize-=sizeDecrement; //subtract sizeDecrement from sqSize each time greyColor-=greyDecrement; //same for greyColor }
The above for loop declares a variable i, initialises it to 0, and increments it one (with the ++ increment operator) at each iteration of the loop, as long as i is smaller than the variable numSquares. It is also possible to nest loops inside other loops. We can for example modify the previous code to look like this:
size(400,400); noStroke(); background(255); int numSquares=15; int greyDecrement=255/numSquares; int greyColor; for(int j=0; j < 20 ; j++){ //first loop //here we reset values for each iteration greyColor=255; float posX=random(0,400); //random() generates a random float float posY=random(0,400); //between two given limits float sqSize=random(100,300); float sizeDecrement=sqSize/numSquares; for(int i=0; i < numSquares; i++){ //second loop, inside first fill(greyColor); rect(posX-sqSize/2, posY-sqSize/2, sqSize,sqSize); sqSize-=sizeDecrement; greyColor-=greyDecrement; } }
Which will produce this:
Play a bit with the for loops, change the ranges of the values. Things that one may consider are the signs of the values (can they be negative?) their names, or the amount they increment (using the += operator previously mentioned), or having decrementing values. One may use other drawing functions instead of rect, also: you can try to change the squares to circles instead.
Scope
A thing to notice in both the conditional statements and the loops is the use of the curly brackets “{“ and “}” containing a set of code. These brackets, besides defining the beginning and end of a set of code they also define a scope block: variables declared between curly brackets will only be visible, that is, they will only be usable, within the curly brackets they are defined in, and in any other code also between curly brackets inside, but not anywhere outside. For example, you can add this line and the end of the last example:
println("the square size is " + sqSize);
It will give you an error when processing tries to compile the code. Now you can move it within the levels of curly brackets, and see what happens.
The basic setup in Processing.
Before continuing we are going to look at the basic setup of processing. The code above consisted of instructions written directly on the text window; this is valid for simple code that is going to be executed just once, (in Processing also called static mode). Processing has a dynamic mode which consists of two basic functions, in which you will put most of your code: One called setup() , which is called once at the beginning of the program, and the other called draw(), which executes continuously the code inside it. In the setup() we usually initalise variables and call functions that only need to be called once in the program. Typical things to do here is to define the dimensions of the window or the background colour. For example:
/* posX and incrementX need to be declared here at the top level and outside all curly brackets, so they are visible from draw(). They could have been initialised here, instead of in setup(). */ float posX; float incrementX; void setup(){ size(500,100); pixelDensity(displayDensity()); //this is only needed with retina displays... noStroke(); fill(200); //set the fill light grey //initialise posX and incrementX. they could have had any other value... posX = random(0,width); //start anywhere on the screen incrementX = random(-5,5); //start in any direction, with a speed between -5 and 5 } void draw(){ background(255); //this is needed to "clean" the screen //fill(255,255,255,20); //you can use these 2 lines instead of //rect(0,0,width,height); //background(255) and see what happens... fill(0,0,0,255); ellipse (posX,50,10,10 ); //if larger than width OR smaller than 0, change the sign of the direction if(posX > width || posX < 0) { incrementX=-incrementX; } posX += incrementX; //add incrementX to posX }
It is possible to get the position of the mouse in processing with mouseX and mouseY. Can you modify the code above so the ellipse follows the mouse?
Functions and sub-routines
An essential part of programming is the capacity to define functions; this is the equivalent to define concepts or words in a language, and expanding its basic vocabulary. The Processing functions used in the examples above have been defined similarly, to expand the keywords, operators and symbols that make up the basis of the language . The syntax of functions is as follows: first comes the type of the return value, followed by the name of the function, the parameters it takes between brackets, and its body between curly brackets; if a value is returned, the body will require at least one return statement. For example,
int addTwoIntegers(int a,int b){ int c=a+b; return c; }
Defines a function called “addTwoIntegers” that takes two values of type int, a and b, and returns another integer. Some functions don’t return any value, for example:
void printSomething(String sv){ //void means that it does not return any value. println("printed from a completely useless function: " + sv); }
or they don’t take any value
void printSomethingSillier(){ println("this is even more useless."); }
This is a small example of defining and calling a function from within Processing:
int posX=0; int posY=0; int increment=3; int squareSize=5; void setup(){ size(300,300); pixelDensity(displayDensity()); //this is only needed with retina displays... noStroke(); fill(200); //set the fill light grey background(0); } void draw(){ float tone=calculateColorA(posX,posY); fill(tone); //we could have also writen it like this: //fill(calculateColorA(posX,posY)); rect(posX,posY,squareSize,squareSize); posX+=squareSize; //advance posX one square if(posX>width){ //check if posX has reached the full width posX=0; //if it has, set posX to 0 posY+=squareSize; //and increment posY, so it draws the next row if(posY>height){ //if it has reached the bottom right corner: delay(4000); //wait 4 seconds... //reset and starts again background(0); posX=0; posY=0; } } } //This is the definition of the function float calculateColorA(float px, float py){ float newTone; newTone=125*(1+sin((py/67)*px/40)); return newTone; }
This is what it draws:
You can find more tutorials at the Processing website:
http://processing.org/tutorials/
Assignments for next time:
Assignment 1: Change the function in the last example so it produces tones with different functions (for example depending of how far the square is from the centre…).
Assignment 2: Modify the code of the bouncing ball so:
- The initial code works both for the x, and y coordinates, so the circle bounces around the screen.
- The circle follows the position of the mouse on the screen.
- There are more than one circle bouncing around.
Hints:
- You need to add similar code for the y coordinate to that of PosX and incrementX (for example you could have 2 more variables called PosY and incrementY). The call to ellipse() needs also to be changed so it takes your new variable for the y position. You will also need to see that the new y position does not become larger than height or smaller than 0, the same way that the existing code checks for x and the width.
- It is possible to get the position of the mouse on the screen using the variables mouseX and mouseY. You can either use this directly to draw the circle, or otherwise you can calculate the difference between the actual position and the mouse position, and add a fraction of that (it looks more interesting).
Assignment 3: Look at some code from the Processing website, the examples in the Processing IDE (under File->examples), or anywhere else in the internet (that it is easy enough for you to understand) and modify it. Use the chance to look at interesting code and understand it.