Você está na página 1de 200

An Introduction To Programming With Processing

This publication is released under a Creative Commons Attribution-


NonCommercial-NoDerivs 3.0 License. CC BY-NC-ND 2011

You are free to share, and redistribute this publication in whole, but not in part
under the following conditions.
The person identified as the author in the following terms is also known as
Lyndon Daniels and is the owner of the domain name
http://www.lyndondaniels.com
Classified works of the author and a classified work of the author will include
all content and redistributions of the content, that the author has created and is
licensed to the author by de facto or de jure.
This publication refers to the document you are currently reading in it's entirety
and is also a classified work of the author.
1. This publication and all redistributions of this publication must remain as
is, and not in any way be modified.
2. All redistributions of the source code and related material, including but
not limited to the images associated with this publication, that are not
licensed under other terms or are not classified works of the author, also
fall under the same license of this publication.
3. Attribution must be given to the author for all redistributions of the
classified works of the author.
4. Acceptable attribution for redistributions of this publication must associate
the publication/s duplicated as being a classified work of the author.
5. This publication is only to be redistributed digitally and not to be
redistributed in any other format including, but not limited, to print.
6. No capital or commercial profit, monetary or other, is to be gained from
this publication or redistributions of this publication without the author's
consent. This includes, but is not limited to selling and/or trading this
publication or any redistributions.
7. All redistributions of this publication are to be released under the same
license that this publication is released under.
8. The author solely reserves the right to change this agreement at any time.

For additional information regrading this license please see


http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode

2
An Introduction To Programming With Processing

Table of Contents
About this Guide......................................................................................................7
Hardware and Software Theory...............................................................................7
What is programming?...................................................................................7
How does programming relate to hardware and software?.....................................8
Abstraction.............................................................................................................10
Speed............................................................................................................11
Efficiency.....................................................................................................12
Disambiguation............................................................................................14
The Unique Qualities of a Programming Language..............................................17
Lower Level Languages and Higher Level Languages.........................................20
An Analysis of a Computer Program.....................................................................22
Commands....................................................................................................22
Expressions...................................................................................................23
A Scalable Software Development Model.............................................................25
1. Plan...........................................................................................................25
2. Research...................................................................................................26
3. Mockup Designs.......................................................................................27
4. Data Acquisition: Sourcing the data needed for your project.................28
5. Filter.........................................................................................................29
6. Clustering and Data Mining.....................................................................29
7. Parsing......................................................................................................32
8. Determining Flow of Control through Stepwise Refinement..................32
9. Implement, Test and Document. Repeat...................................................34
10. Deliver....................................................................................................35
Why Learn Programming using Processing?.........................................................36
Code for Artists............................................................................................36
Java Based....................................................................................................36
Open Source.................................................................................................37
PDE..............................................................................................................38
Source Code Editor.............................................................................39
Build Automation Tools......................................................................40
Compiler and /or Interpreter...............................................................41
Debugger.............................................................................................42
Active Online Community...........................................................................43
Hello Processing....................................................................................................44
Install Processing..........................................................................................44

3
An Introduction To Programming With Processing

Sketches........................................................................................................44
Hello World Program 1.0.......................................................................................45
The println() function...................................................................................46
Syntax and Syntax Errors.............................................................................48
Logical Errors...............................................................................................49
Display Window...........................................................................................49
The size() function. ......................................................................................50
Standardized Coding Practices.....................................................................51
Comments...........................................................................................51
White Space........................................................................................52
Program Notes....................................................................................53
Visual Representations of Code ............................................................................54
The Cartesian Graph and the Processing Coordinate System......................54
Hello Display Window: Hello World 1.1 ....................................................55
The text() function........................................................................................55
Program Notes..............................................................................................56
Formatting Text............................................................................................58
Color...................................................................................................59
Drawing........................................................................................................62
2D Primitives......................................................................................62
The Origin of an ellipse......................................................................63
Aliasing...............................................................................................67
Smile.............................................................................................................67
Angles in Processing...........................................................................67
Editing the smile.................................................................................70
Adding Eyes.................................................................................................73
Drawing Irregular Shapes.............................................................................74
Order, order!........................................................................................79
Finishing the sketch......................................................................................79
Programming Paradigms.....................................................................81
Datatyping Categories.........................................................................82
Primitive Datatypes...................................................................83
Processing's API Datatypes.......................................................83
User Defined Complex Datatypes.............................................84
PImage................................................................................................85
The Design and Layout Program...........................................................................87
Program Notes for Interface01.pde..............................................................87

4
An Introduction To Programming With Processing

The PDE Tools menu..........................................................................87


Beyond Static Sketches and on to Active mode....................................................91
Methods, functions and their contexts..........................................................92
The setup() function...............................................................................................94
The draw() function...............................................................................................96
Experimentation.....................................................................................................97
Datatyping............................................................................................................102
Variables.....................................................................................................102
Variable Scope..................................................................................105
Interacting with images........................................................................................108
Friction simulation......................................................................................110
Variable naming conventions............................................................112
Planning and Pre-Debugging......................................................................113
Implementing a Programmatic Solution.....................................................115
Constraining Values..........................................................................116
Branching.............................................................................................................119
The if() structure.........................................................................................119
Relational Operators...................................................................................121
Comparison................................................................................................122
Extending the if() structure with else.........................................................125
Extending the if() construct with if else if else..........................................126
Logical Operators.......................................................................................127
Interface Controls: Setting up a Slider.................................................................130
User Defined Functions.......................................................................................131
Creating a user defined function................................................................135
Datatyping a function .......................................................................135
Determining a range..........................................................................135
Returning data from a function.........................................................139
Dragging the slider button................................................................141
Setting up regional constraints..........................................................143
Finishing the slider............................................................................144
Mapping Values................................................................................145
The mystery shape maker....................................................................................150
Arrays...................................................................................................................150
Program Notes..................................................................................154
Dynamic assignment for elements in an Array..........................................157
Iterations..............................................................................................................160

5
An Introduction To Programming With Processing

Transforms...........................................................................................................164
Transforming Coordinate Space.................................................................165
A Convenient Animation System...............................................................166
pushMatrix() and popMatrix()....................................................................170
What is the Transformation Matrix............................................................175
A Programmatic Solution For Rotating Wheels.........................................176
An Introduction to 3D in Processing...................................................................179
3D Primitives..............................................................................................180
Guess My Number Game....................................................................................183
Object Oriented Programming.............................................................................184
The concept of a class................................................................................185
The Blueprint Analogy...............................................................................186
Why use Object Oriented Programming....................................................188
Creating a Class..........................................................................................188
A Button Class.....................................................................................................191
Class Name.......................................................................................191
Fields.................................................................................................192
Constructor........................................................................................192
Methods.............................................................................................194
Object Instantiation....................................................................................194
Working with external data..................................................................................197
Attribution............................................................................................................200
Images........................................................................................................200

6
An Introduction To Programming With Processing

About this Guide


Introduction to Programming with Processing is a guide to creating interactive
software with the programming language, Processing. The main focus of the
documentation is to give the reader an understanding of the programming
language, Processing and also to give the reader the knowledge to apply an
understanding gained from reading this documentation to learning other similar
high level programming languages.

Hardware and Software Theory

What is programming?
A software program is a set of instructions issued to a computer via source code.
Source code is data that usually resembles a text document which is typed in a
specific programming language that is somewhere between a language that
computers can process efficiently and humans can understand. The task of
creating source code is known as programming.

Human readable source code on the left and machine code on the right.
Although source code does not make sense at first glance to someone new to
programming, when compared to it's equivalent in machine code it definitely looks more
appealing.

Hardware and Software Theory 7


An Introduction To Programming With Processing

How does programming relate to hardware


and software?
Before we get into the process of creating software programs, lets first examine
the relationship between a software program and a computer.

One of the fundamental functions of a computer is it's ability to control electrical


energy and ultimately transform that energy into another form of energy such as
light, sound or motion. We use software to communicate with a computer, which
will determine the various paths that the electrical energy will take, in order to
achieve the goal we have stipulated through programming.

Computers are designed to react to electrical energy, this energy can be of a high
or low voltage and forms the basic premise of all the complex interactions that
exists between humans and computers. These high and low voltages of electrical
energy are relayed within the circuitry of a computer in very short intervals that
allow us to distinguish one from the other and will eventually be sequenced
together to form a protocol for communicating with computers.

This protocol of communication we represent with two numerical digits a 1 and a


0, which to a computer equates to a high and a low voltage. We refer to this form
of representation as Binary Code. Of course, this representation means nothing to
a computer as it is only reacting to the electrical energy that is being relayed
within it's circuitry. But to us using a 1 and 0 as a form of representation creates a
means for every simple to complex interaction we have with computers through
software.

By combining various sequences of 1's and 0's (and ultimately sequences of high
and low voltages) followed by more sequences of 1's and 0's arranged in similar
or different patterns the effect of a continuous flow of energy is created that
results in light or sound or one of the many other capabilities of a computer. The
fact that this flow of electrical energy is broken up into smaller chunks means that
each chunk can be made up of a different sequence of 1's and 0's which could be
used to create the impression of a change or variation which could finally be
perceived as an image moving in an animation or the diaphragm of a speaker
vibrating at different amplitudes which, for example, we ultimately perceive as
the sound of our favorite track.

How does programming relate to hardware and software? 8


An Introduction To Programming With Processing

Although useful, representing data in this way can become quite cumbersome and
error prone. If developing software meant having to learn endless sequences of
binary code, becoming a programmer would be a very daunting task. This is,
however, not the case as we can use a 1 and a 0 to represent a high and a low
voltage we can use a sequence of 1's and 0's to represent more complex ideas
such as a larger number like 155 which can be translated into binary as 10011011.
This form of representation can furthermore be extended to include typographic
characters, which in themselves can be strung together in sequences to create
words, which can in themselves be strung together to issue commands to a
computer through programming. We refer to this process as abstraction.

Programming in it's simplest form is the process of creating and modifying a


series of 1's and 0's that influences the path of the electrical current, by means of
abstraction.
At some point everything that a computer processes (including our own
interactions with it) has to exist in binary code representations. However, it's
important to remember that binary code is simply just a human representation, for
determining a sequence of high and low voltages, that we use to make the
complexities that occur within a computer more understandable to us.
As I mentioned earlier, a computer does not really care about what form of
representation we use, however this process of representing data certainly does
make it a lot easier to communicate with computers.

We interface with computers via software which allows us to work in an individual


capacity, whenever applicable, in fields that would previously have required teams of
people working together.

How does programming relate to hardware and software? 9


An Introduction To Programming With Processing

Abstraction
Representing the abstract concept of something like data in the form of high and
low voltages with a series of 1's and 0's can be quite useful, but still very difficult
to read and understand. Imagine having to memorize all of those sequences in
order to be an efficient programmer. It would take exorbitant amounts of time to
create the simplest of software programs. Fortunately the process of representing
human-relevant concepts to a computer does not stop at binary code. Since we
know that a certain sequence of 1's and 0's on a certain type of machine such as
the sequence 00110101 can be used to represent the number 53 why not make
the sequence 01001000 and 01101001 represent the characters h and i
put together to make the word hi. This is exactly what software developers do,
the process of taking a complex set of data and representing it in a more human-
readable format is known as abstraction. As you can image this makes it a lot
simpler to communicate with a computer, so instead of typing 01001000
01101001 we can simply type hi and thanks to the process of abstraction our
computer knows what to display even though it's reading a sequence of high and
low voltages at the simplest level.

Abstraction is great because it makes the process of communicating with


computers easier, so you might be thinking to yourself why then is programming
and source code so cryptic and far removed from a common natural spoken
human language such as English? Surely, if we can abstract complex data why not
keep on abstracting concepts to computers until it can understand a human
specific language like plain and simple English?

For example if we wanted to draw a circle on a computer screen why can't we just
say to a computer:

Computer, could you please draw a circle that has a diameter of


55 pixels and who's center is somewhere close to the top left of
my screen, thanks?

Instead we communicate with our computers like this:

ellipse(56, 46, 55, 55);

There are three main issues to consider here speed, efficiency and disambiguation.

Abstraction 10
An Introduction To Programming With Processing

Speed
One of the main reasons we cannot continue to abstract our communications with
computers to the point where everyday English is used, is due to the speed at
which data can be processed.
As we abstract data in order to make it more human-readable that same data
becomes less machine-readable, and in order for a machine to be able to make
anything useful out of that data it must first convert that data into a machine-
readable format.
All of this abstracting and un-abstracting requires valuable system resources and
energy, system resources and energy that could be used more effectively
elsewhere. Subsequently as we move further away from machine code we require
faster more powerful computers to process the data we create.

It's estimated that under certain circumstances a consumer grade Intel Core i7 3.3
GHz processor can preform 147,600 Million instructions per second, and if
you've ever used one of these processors you'll probably also note that even with
all of that processing power there are certain situations where your computer can
still lag!
This does not necessarily have anything to do with the processor specifically but
simply due to the massive amounts of data that an average modern day computer
is expected to cope with. To put this into perspective consider that 40 years ago in
order to send a man to the moon computers with a clock speed of 0.043MHz and
64Kbyte of RAM were required to run software ranging about 6MB in size, by
today's standards a single modern day home computer could be about 77 million
times more powerful than the computers used to launch a space shuttle, navigate
it to the moon and safely return it to earth such as the Apollo Guidance Computer.
In retrospect the modern day needs we place on our computers can be somewhat
demanding.

Abstraction 11
An Introduction To Programming With Processing

The Apollo Guidance Computer used on Apollo 11 on the left and the NASA Manned
Spacecraft Center on the right. Technology from the 1960's.

Efficiency
Like any natural language, computer languages are built around their
environments. Human cultures have developed languages as a means of
communicating their perceptions of internal, conceptual and external
environments. However what exists in one environment might not be a part of
another. Subsequently, a string of words might be used to describe something that
is uncommon to one environment, whereas in another culture where that thing is
common a single word might be used to describe it.
For example a visitor traveling to Japan in the late 1800's might describe a
specific mode of transport as:

A human-powered two wheeled cart, that seats one or two people


reserved for the social elite.

However a person familiar with this mode of transport might have a specific name
for it, such as:

Rickshaw

Abstraction 12
An Introduction To Programming With Processing

Rickshaws are not a common sight in modern times but where a regular mode of
transport in Japan, in the 1800's

Obviously if you are living in an environment where such things are common
using a single word that can effectively describe a whole sentence can be a more
efficient means of communication.

Computer languages are similar in this way, each language is developed to run
efficiently under certain conditions and circumstances yet the same language may
perform less efficiently under a different set of circumstances.
What qualifies as an optimal environment for a computer's programming
language is something that the developer of that language will have to define. An
environment in this sense could be an operating system, the world wide web, a
network, or a combination of these environments. This could also be a large
contributing factor, possibly explaining why there are so many different computer
languages currently in existence each with it's efficiency optimizations for
specific environments.

Currently Wikipedia lists approximately 661 popular computer languages and this
number is constantly growing compared to it's listing of 540 currently spoken
languages (not including their derivatives). Of course there have been many more
spoken languages throughout human history, The Cambridge Encyclopaedia of

Abstraction 13
An Introduction To Programming With Processing

Language estimates this number to be between 3000 to 10000, but then again
what actually qualifies as a language is a whole other topic for discussion in itself.
Computer languages share in this ambiguity. Throughout the comparatively short
history of computer languages, which can arguably be traced as far back as the
first programmable computer, the Z1 invented by Germany's Konrad Zuse in
1938, programmers have seen languages raise to popularity and become virtually
obsolete, one such language is LISP. LISP was in many ways synonymous with
Artificial Intelligence (AI) from the mid 1950's till the early 1970's but gradually
gave way to a dwindling numbers of devotees, who where lured by new
programming paradigms such as object oriented programming and other higher
level programming language concepts, which we will explore in greater detail
later. Although this language never really died, some would say it became
somewhat antiquated. Nonetheless, LISP started to regain popularity in the mid
1990's in a new implementation currently known as Common LISP. Determining
whether a programming language closely based on a previous programming
language should be considered a new language that is able to stand on it's own,
can be a difficult distinction to make and can add considerably to the ambiguity
around what defines and distinguishes one computer language from another.
Processing too, has been subject to this topic of debate as it's roots in the
programming language Java have seen it referred to as a library for Java while
others identify it as stand-alone programming language.

Regardless of whether a programming language derived from another can stand


on it's own or not one of the key factors that determine it's popularity, and
ultimately contributes to a following of devotees that develop and maintain the
language, is the language's ability to achieve a balance of being fast enough for a
computer to process but easy enough for a human to read. It is this balance that
currently determines the efficiency of a computer's programming language.

Disambiguation
Computers tend to be very literal. They accept specific instructions more readily
than vague descriptions of what you are hoping to achieve with their help. Such
that a statement like the above mentioned, and repeated below:

... draw a circle that has a diameter of 55 pixels and who's


center is somewhere close to the top left of my screen...

Abstraction 14
An Introduction To Programming With Processing

would not be as effective as the statement:

ellipse(56, 46, 55, 55);

The first statement although a perfectly acceptable command issued in English,


would fail dismally when translated directly into computer-speak for several
reasons relating to the ambiguity associated with it.

Firstly the longer a command tends to be the more prone it is to incorporating an


erroneous syntax. Computers are very specific about the type of syntax you use to
communicate with them. Syntax in terms of the English definition is the particular
arrangements of words making up a sentence. In computer terms, syntax has a
very similar meaning but is even more relevant and specific in it's
implementation. Words must follow a particular sequence within the context of a
command issued to a computer determined by the language you are currently
programming in, and may not be rearranged into various discourses simply
because you find them to be more meaningful.

Computers have truly amazing mathematical capabilities and predictably


congruent mediocre social skills. Subsequently concepts such as circles and
squares which are simply mathematical concepts abstracted for human
convenience have little or no relevance to a computer. For example if you were to
consider that a circle, as per another description, could be an ellipse with
equidistant radii to each point encompassing it's edge; or technically speaking a
square is actually a rectangle with it's height equal to it's width. Descriptive
abstractions such as these for human convenience are in fact very inconvenient
for a computer, and as a result in Processing we refer to a circle and an ellipse
using Processing specific syntax that removes the ambiguity and abstraction for
the convenience of a spoken language and groups them into the same context.
Subsequently if we want to describe a circle we refer to it as an ellipse with equal
dimensions in height and width or more specifically:

ellipse(56,46,55,55);

Finally I'm sure that if computers had a sense of humour, they would find our
former description of the location of our circle somewhere close to the top
left of my screen to be somewhat uninformed and laughable, not to mention
words such as somewhere and my which might condition a response

Abstraction 15
An Introduction To Programming With Processing

equivalent to that of an existential dilemma for a computer. If you supply a


computer program with specific screen positions in terms of x, y and z and
dimensions in terms of width, height and depth either communicated explicitly or
implicitly through an expression (which is something we will discuss in more
detail later) you will find your programs to have more predictable and efficient
results and would help to remove ambiguities that could lead to errors. Screen
space and dimensions are concepts we will be dealing with in more detail in later
chapters. Of course there are times when randomness and unpredictability are
desirable qualities in a program, in which case no other resources available to
man can produce a series of unpredictable results more efficiently than computers.
This is a testament to why people devotedly invest in computers to provide the
sequence of random digits that could potentially make casinos loose millions
upon millions to gambling patrons.

Computers, and subsequently software are used in various fields of medical technologies
where predictability is of the utmost importance. Gambling machines also use software
but in contrast to medical software predictability in the application of the software, is an
undesirable effect for the machine owners.

Abstraction 16
An Introduction To Programming With Processing

The Unique Qualities of a Programming


Language
At the simplest level a programming language should be Turing complete. Turing
complete refers to a set of data manipulation rules that, can simulate a Turing
machine. This begs the question to be asked, who is Turing and what is his
machine?

Alan Turing was a British mathematician that is heralded as the father of


computer science. He lived from 1912 to 1954 when he died at the age of 41.
Turing is responsible for creating the Turing machine which is a theoretical device
that operates with a strip of tape imprinted with an infinite array of symbols, the
machine is able to read a symbol and alter the symbol and the symbol in turn
affects the behavior of the machine. The tape that the symbols are printed on
represent memory and it can move back and fourth so that any symbol can be read
by the machine and altered by it, additionally at any given time a symbol is
affecting the state of that machine.

Turing referred to this machine as an "a(utomatic)-machine" and it forms the


fundamental logic of all computer algorithms. This principle is still used in
modern computers. A programming language that is Turing complete complies
with this logic, and will subsequently be able to run on all computers based on the
Turing machine. What this simply means is that programming languages will
need to be able to run on a basic computer system that at the very least has a
Central Processing Unit (CPU) that is based on the Turing machine, which
includes all known operational computer models.

Quantum computing models are commonly based on the quantum Turing machine
also known as the Universal Quantum Computer, and even these models can be
related back to the classical Turing machine. Quantum computing models are
theoretical models of how a quantum computer could work once the technology
can be implemented, in much the same way that the Turing machine was a
theoretical model of today's modern computer before it's current implementation.

The Unique Qualities of a Programming Language 17


An Introduction To Programming With Processing

Alan Turing (1912 - 1954) is heralded as the father of computer science

What about speed, efficiency and dis-ambiguity, are these not also amongst the
unique qualities of a programming language?

Simply put, no they are merely guidelines that programmers may or may not
adapt into the computer languages they develop. However, most useful
programming languages will in some form or another adapt these standards into
their design. There is another form of computer language development that does
not comply with these standards, but the languages that develop from this field do
still comply with Turing completeness, as without this design implementation it
would not be possible to run the language on a computer modern or old.

This field of computer science is referred to as esoteric programming languages.


Esoteric programming languages usually are not designed to be useful for real-
world programming situations but are usually more popular among hackers that
develop these language to test the boundaries of computer programming language
design.
A relatively well known example of an esoteric programming language is the
language known as brainfuck . Brainfuck is known as a Turing-tarpit language as
it still qualifies as a Turing complete language even though the entire language
consists of only 8 commands and no operands. We'll be discussing what exactly a
command is shortly and what an operand is a bit later, but needless to say this is a
language that is still functional with a bare minimum of interfacing protocols. An
example of a hello world program (yet another concept we will get to a bit
later), which is a program that simply prints the words hello world to the screen
in brainfuck code follows:

The Unique Qualities of a Programming Language 18


An Introduction To Programming With Processing

++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>+
+.<<+++++++++++++++.>.+++.------.--------.>+.>.

LOLCODE is another example of an esoteric programing language that is based


on the text within lolcats images. Lolcats are images of cats that circulate the
Internet, often in cute and whimsical representations. These images are
accompanied with text that is generally idiosyncratic and grammatically incorrect
with the intent to contribute humour to the image.

An example of a typical lolcat image

An example of a Hello World program in LOLCODE follows:

HAI
CAN HAS STDIO?
VISIBLE "HAI WORLD!"
KTHXBYE

As you can see the language uses what is typically termed as lol-speak as an
integral part of it's syntax and keywording.

The Unique Qualities of a Programming Language 19


An Introduction To Programming With Processing

Lower Level Languages and Higher Level


Languages
Generally speaking higher level programming languages are closer to human
spoken languages and lower level programming languages are closer to machine
code, or binary. However this classification might not always be so clear. C++ is
one language that some might argue challenge this programming language stereo
type. C++ is a programming language that has all the features that one would
expect from a higher level language such as an easy to read syntax, object
oriented programming and extensive collections of libraries to add to the
language's capabilities but also has other features that are not commonly found in
higher level languages such as memory management, user defined operator
overloading, six different integer datatypes and a plethora of compilers to choose
from. As a result many refer to C++ as a mid-level programming language.

For Processing this distinction is currently not so difficult to make. Processing is a


high level language, meaning it has an easy to read syntax, supports modern day
programming concepts such as Object Oriented Programming, has it's own IDE
(Integrated Development Environment something we will become more familiar
with throughout this guide) and fundamentally it abstracts a lot of machine
specific interactions for us making the code more readable for humans.

However, it's worth considering that the terms higher and lower level
programming languages are relative to the time period in which they are used. For
example when the programming language C (that C++ is based on) was first
introduced in the early 1970's it was considered to be a high level language as it
supported such features as expression evaluation and datatyping, both of which
are programming concepts common to most modern day programming languages.
As technology progresses, new concepts become common place and rapidly
replace older more cumbersome programming designs, till we get to the point
where there are far less people that would refer to an older language such as C as
being a high level language and a lot more people that would refer to it as a low
level language, lacking modern abstractions and less direct hardware interactions.
Processing might one day, also be subjected to such a topic of discussion.

Lower Level Languages and Higher Level Languages 20


An Introduction To Programming With Processing

Following is the C version of a Hello World Program:


#include <stdio.h>
int main(void)
{
printf("hello, world\n");
return 0;
}

The level of abstraction that is needed in order for a language to qualify as a


higher level programming language does not come without it's penalties. Lower
level languages, because they are conceptually closer to machine code are
considered to produce more efficient machine readable code, of course this is
largely dependent on the programmer creating the code. As mentioned before the
greater the level of abstraction of the code, the more stress that is placed on the
machine interpreting the code, and subsequently more system resources are
required. As a result of this cycle higher level programming languages generally
cannot run on systems where resources are limited. Initially, this might not seem
like such a big issue to you, but have you ever considered the amount of
technology running on limited resources like a television, fridge, GPS, mobile
phone, remote-controlled air-conditioner, electronic toys, media players and the
list goes on...? In fact if you were to think about it there are not many devices like
computer workstations, laptops or computer servers that are designed to have
their resources, available to the software that runs on these machines, extended.
Yet, even these machines have their limitations.
Ultimately software, whether it is designed with a high level or low level
programming language, should always take into consideration the possible
limitations of available system resources.

Lower Level Languages and Higher Level Languages 21


An Introduction To Programming With Processing

An Analysis of a Computer Program


As we are already aware Binary is a conceptual model that people have invented
to represent the workings of a machine. Binary resultantly forms the basis of all
software because as mentioned earlier no matter what programming language you
use that code must be translated into a machine readable format before it can be
interpreted by a machine, the product of this translation is usually represented as
binary code.
Computer Software is conceptual and intangible as opposed to hardware which is
tangible such as a motherboard, a CPU, an optical drive or a monitor. As a result
the word software is intentionally used to contrast the term hardware.
Programming is a means of creating software and a computer program is a type of
software. Specifically, a program is a set of instructions issued to a computer in a
programming language, such as Processing. These instructions are usually made
up of one or many statements. Depending on what language you are programming
in statements can consist of several different parts, such as
expressions
commands
assignments
comparisons.
Statements can also be made up of many other parts not mentioned here, but for
now we are most interested in two of these components making up a statement,
commands and expressions, the rest we will get to later.

Commands
If you were to compare a statement in computer programming to a sentence in a
natural language, a computer programming statement could be considered to be
somewhat imperative. For example the following sentence in a natural language:

Run, as fast as you can!

This would be an imperative statement in English issued to the implied subject. In


extending this comparison, a verb in an imperatively spoken sentence would have

An Analysis of a Computer Program 22


An Introduction To Programming With Processing

the same purpose as a command in a programming language. A command in a


programming language usually implies a directive issued to a computer, in other
words it's a means of telling a computer to do something. In Processing we often
use functions to tell a computer what to do, a function in this sense is a type of
command. Functions are the building blocks of Processing programs, as you will
come to see. Additionally many functions in Processing accept parameters, which
modify how the function is interpreted the by program.
If we were to extend on our previous example and apply this programmatically,
the word Run in the sentence would be a function and as fast as you can!
would be representative of a parameter.

Expressions
Expressions in computer programming languages can consist of single or multiple
different types of data such as numbers, typographic characters and many other
types of data that can be interpreted in various ways according to rules established
by the language you are programming in. The process of how this expressional
data is interpreted is known as evaluation and is similar to the term as it is used in
mathematics. For example 3 + 2 is an expression that evaluates to 5.
Mathematical operators such as +, -, *, etc. work in Processing, as you would
probably expect them to. As the term implies the programmatic mathematical
operator is often interchangeable with the standard classical mathematical
operator in Processing. For example the statement in Processing:

println(5+3);

Consists of two parts, first the function println() which accepts a parameter. In this
case the second part of the statement, the parameter, is an expression and the
expression is 5+3 which evaluates to 8.
One of the basic features of Processing is it's ability to act as a calculator when
computing values separated by mathematical operators such as + (plus), - (minus),
* (multiply), / (divide) and % (modulus). But this inherent ability of Processing
extends a lot further than simply evaluating numerical expressions, as expressions
amongst other types of data can also consist of other typographic characters that
can be evaluated. For example the statement:

println(h + i);

An Analysis of a Computer Program 23


An Introduction To Programming With Processing

This statement evaluates to hi. Using a mathematical operator in this way is


known as operator overloading and is an inherent quality of Processing that
comes from it being a C based programming language. Operator overloading is a
common feature in higher level languages and simply refers to the level of
abstraction built into a higher or mid level programming language that allows us
to use the same operator in more ways than one. For example the plus sign can be
used to add numbers or other typographic characters, but not numbers and
characters at the same time without the use of a process known as typecasting
(which we will cover in more detail later).
What makes operator overloading so useful is that we often don't need to be
aware of it, because the way that the operator is used will be determined by the
context in which the programmer has used it and this is something that the
program converting our human readable code into a version that is more machine
readable will handle for us.

An example of operator overloading and typecasting in Processing's PDE

An Analysis of a Computer Program 24


An Introduction To Programming With Processing

A Scalable Software Development Model


Programming is only one of the steps required in the process of developing
software. Establishing a scalable model for software development will help you
determine what the requirements of the project are before programming begins.
As you start developing larger programs this development model can be scaled to
help you allocate your time appropriately to the various needs of your project, and
ultimately contribute to more realistic deliverables within a predictable time-
frame. The idea behind a scalable software development model is that it can be
adapted to suit any project large or small. Although certain areas might require
more focus than others dependent on the project you are working on, having an
established software development model can contribute to a progressive workflow
that does not stagnate when difficulties within a project are encountered.

1. Plan

What are the goals for the project?


How would you ideally like to implement these goals?
Have there been similar projects undertaken by yourself or others, if so is
it possible to obtain those implementations?

Asking yourself similar questions following this line of thought can help you
visualize the steps, leading to your goals, that need to be taken well before
programming begins.
This process of visualization contributes to creating a conceptual sketch of the
project as a whole and in it's completed form. This idea can then serve as a means
of deconstructing the main concept into smaller workable objectives.
Planning your project through conceptual visualization should be supplemented
with a few rough ideas jotted down on a piece of paper. It's not uncommon to
spend days and sometimes longer periods of time conceptualizing a project before
considering trying to implement any of these ideas.
Depending on the complexity of your project, you may have to further refine the
process of breaking down the smaller tasks into even smaller tasks until you reach
a task or set of tasks that are achievable in the short term. Often these short-term
objectives will not necessarily relate directly to programming but rather to a set of
questions that need to be answered before the implementation of the project can

A Scalable Software Development Model 25


An Introduction To Programming With Processing

begin. These questions that you derive from planning your project will form the
basis for the research that follows planning.

Examples of an abstraction, followed by a deconstruction and finally a technical


overview of a project plan.

2. Research

Addressing the details of how you see your project being implemented should
bring certain technical questions to your attention. Questions such as,
What is the target system you would like your software to run on?
Will my software require additional resources such as plug-ins?
Can the software also be distributed for both online and offline usage?

These are amongst many questions that you might not be able to answer in your
own capacity. The Internet is a seemingly endless resource of information and
probably your best bet when it comes to answering these and many other
technical questions you can think of.
Research might also reveal that the code you are interested in creating might
already exist. If the code is distributed under a license that permits you to reuse it,
then by all means you are encouraged to do so. It is often said that up to 80
percent of a programmers time is spent maintaining already developed code. What
this means is that generally developers will spend a comparatively small amount
of their time developing their own code from scratch and far more time adapting
and modifying already existing code to suit the needs of their projects.

A Scalable Software Development Model 26


An Introduction To Programming With Processing

Finally researching your project can also reveal useful sources for data
acquisition, which will be particularly helpful in the fourth phase of your
development model.

The various sites on the Internet have vast resources of reusable code

3. Mockup Designs

Once you have answered the questions you had about implementing your project
consider returning to the notes you created during the first phase of Project
Planning. With the new information you have derived through your research,
refine your ideas into graphical representations of your program.
By now you should have a clearer idea of what your end product should look like.
Avoid prematurely designing your project only to realize your goals where not
realistic given a particular time-frame or some other design flaw, following this
development model in the predetermined order will help avoid such a situation.
Use the mockup design phase of software development to start drawing out
conceptual sketches of your program, in the form of schematic diagrams that
outline the program's flow of control (which we will discuss in more detail in Step
8) and map out the user experience you hope to achieve.
If your software is visually oriented you may wish to create more detailed and
specific designs of your application, for example by designing an interface for a
data visualization program or designing a theme for an online game. Consider
how your designs can contribute to making the user's experience more immersive.
The design phase of software development can also help to identify and even
solve how programmatic implementations of visualizing data might be addressed
through various programming methodologies.

A Scalable Software Development Model 27


An Introduction To Programming With Processing

Mockup Designs should include some rudimentary visualizations of the final project and
schematic diagrams detailing the program's flow of control.

4. Data Acquisition: Sourcing the data needed


for your project.

Obtain all the data you need to create your software, this data could include
statistical information from books, tabulated data from a website, printed lists of
sales from business owners or even screen-scraped data.
Screen-scraping data is a technique that has been in use for many years and is
used to acquire data from new and old computers alike. In modern times one of
it's most common implementations involves the process of acquiring data that is
in no particular standardized format and commonly sourced from from an html
page of a website. The idea of screen-scraping is that data exists remotely from
the program you are creating, in a format that your program cannot process. As a
result you may need to write another program that serves as an in between
application converting the remote data from an undesirable format to the desired
format of the main software program you are developing.
Screen-scraping is a technique of data acquisition that is differentiated from
parsing, as the data that is being acquired is not intended for another software
program but often intended to be read by a human. Parsing data is something that
happens much later in the software development process and relies on proper data
acquisition. Parsing data is something we will discuss in more detail during the
seventh phase of the software development model.

A Scalable Software Development Model 28


An Introduction To Programming With Processing

Acquired data might be in the form of a spreadsheet, a text document, images and many
other different formats that might not, even at this stage, be digital.

5. Filter

Filtering data is simply the process of removing all components of your data that
are not necessary for the proper functioning of the main program. If your data is
in a Processing friendly format such as tabulated data, a multi-line text file, a
comma separated value text file or other similar format the process of filtering
data could be as simple as selecting those components (including spaces and new
line characters in a text file) and deleting them. However, if your data is not in a
Processing friendly format you might have to spend quite a bit of time filtering
out data that is not relevant to your program.

6. Clustering and Data Mining

Data mining is the process of identifying patterns within the data you have
acquired. The purpose of doing this is to place the relationships that exist between
the various aspects of your data in a more mathematical context that can
ultimately be used programmatically (in the program you are developing).
Data mining can be done manually or it could be automated. When dealing with a
small data set with a high ratio of inconsistent data types, manual data mining
could be more effective and save you some time.
For example, lets take a hypothetical situation where the owner of a small caf
has asked you to determine what items a customer is likely to purchase together.

A Scalable Software Development Model 29


An Introduction To Programming With Processing

The data set you have acquired consists of all the items customers have purchased
in the store over the past year. From that data you could determine that goods can
be divided up into food, drinks, magazines, stationary etc, and then into even
smaller groups like fruit, vegetables, soft-drinks etc. Identifying these groups
would be the first step of data mining and is a process also known as clustering. If
the caf has a large variety of items to choose from the clusters making up the
data could resultantly be numerous, yet the data set as a whole is actually quite
small, only consisting of a single year of purchased items.
In contrast a more established caf that has been operating for several years
proposes the same question to you. In the case of the smaller caf groupings of
purchased items would yield a lower probability of repeating in a shorter period
of time. In contrast the more established caf has a better chance of the same
groups of items being purchased together over a longer period of time.
In the former case manually mining this data set could be more effective because
of the lower probability of the same items being purchased together in a relatively
short space of time. In this scenario the majority of your time would be spent on
clustering and populating the resultant groups after eliminating the majority of
items purchased in that year because they will not fall into any cluster.
However in the case of the established caf although there may be just as many
clusters the values that these clusters are populated with have a higher probability
of being repeated, it might therefore be more efficient to have a computer
program count, cluster and mine the data.
Regardless of whether you choose to manually mine your data or have a software
program do the work for you, you should have a set of data at the end of the
process that can be manipulated programmatically.

A Scalable Software Development Model 30


An Introduction To Programming With Processing

Raw Data

Manual Clustering

Digital Results

The process of getting external data into a program, via clustering and data mining.

A Scalable Software Development Model 31


An Introduction To Programming With Processing

7. Parsing

The process of transferring data from one computer program to another program
that requires the data in a specific format that is different to the original format, is
referred to as parsing data. The program that converts the original data to an
acceptable format for the main software program to process is referred to as a
parser. Parsing in Processing should return a set of data that your main program
can read directly in a text file, a spreadsheet or other such data format that does
not require any further levels of un-abstraction.
Sometimes, the decision to write a parser might not be an easy choice to make.
Weigh up the amount of time you think it will take to manually convert the data
(as illustrated in the above diagram) compared to the amount of time it will take
you to develop a parser, along with it's overall usefulness (as a parser can
sometimes end up being specific to one application) and try to make an informed
decision based on these factors before jumping head first into the task at hand.

8. Determining Flow of Control through


Stepwise Refinement

A program's flow of control refers to the order in which statements are run within
in a program. The results of these statements can ultimately determine how a user
interacts with the program by means of various branches of code structures within
your program that the program determines whether to execute or not based on the
choices the user has made through interactions with the program.
Branching is an important part of a programs flow of control as it allows your
program to determine, through a logical decision, what path to take within your
program's code based on various circumstances you have defined for the user.
Planning the program's flow of control allows us to address what we would
ultimately want our users experience of the program to be, and the best place to
start with this process would be to write out a list. This list should contain a set of
instructions that determine how you would like the program to work and
ultimately describe a user's experience of interacting with the program. Once you
have this information remove unnecessary clutter from the list and identify the
key points, keep it concise and short. Once you have this list keep refining it until
you have something resembling a step by step process of the tasks the program
will eventually perform.

A Scalable Software Development Model 32


An Introduction To Programming With Processing

An example of such a list for a guess my number game follows:


1. Start the game and generate a random number.
2. Render the space scene interface including a slider,
spaceship and a panel to show user's guesses which are
either too high or too low.
3. Click and drag the slider and a number is displayed
indicating the users current guess.
4. When the slider is released the user's guess is made
5. If the guess is the same as the random generated number,
show the win screen.
6. If the guess is too high, tell the user the guess is too
high and increment the number of user's guesses.
7. If the guess is too low, tell the user the guess is too low
and increment the number of user's guesses.
8. If the user has not guessed the number within five tries,
show the lose screen.

Your list at this stage should start to read more like a program rather than a
paragraph written in a natural language. This resemblance is no coincidence and
forms the basis for the process programmers use for developing what is known as
pseudo code. Pseudo Code is somewhere between a programming language and a
natural language and forms the basis for stepwise refinement. During stepwise
refinement rewrite your list so that it resembles something closer to the code of
your program each time the pseudo code is refined.
A Pseudo code example for a guess my number game might look something like
this:

choose a random number between 1 and 100


set the number of user guesses to 1
get the user's guess
while the user's guess is not equal to the random number and less
than 5 guesses
if the guess is too high
tell user guess too high
increment user guesses
else if the guess is too low
tell the user guess too low
increment user guesses
if the number of guesses is 5 or greater user has lost
else if the guess is equal to the random number
user has won

A Scalable Software Development Model 33


An Introduction To Programming With Processing

9. Implement, Test and Document. Repeat.

Implementation is the phase of software development where the actual source


code is created, by means of programming.
As the code is created it should be constantly tested. This helps to identify bugs in
the program during current implementation or that could occur in the future
development of the software.
While implementing and testing a program it is important to document the steps
taken to achieve the goals of the project. This could either be done in a
comprehensive form of external documentation but should always include
documentation within the code itself in the form of comments and multi-line
comments.
This phase is repeatable and should be constantly updated by the recursive nature
of it's design which should eventually lead to a erroneous free implementation of
the software.

Comments in Processing start with the // characters and multi-line comments in


Processing start with the /* characters and end with the characters */

A Scalable Software Development Model 34


An Introduction To Programming With Processing

10. Deliver

Once the software has been thoroughly tested it should be delivered. Delivery
could involve something as simple as uploading the software to a website, or as
complex a task as marketing and selling the software. However you deliver your
software, you should always accommodate for the delivery phase of the project
uncovering unforeseen bugs and errors in the software as users test it on systems
that differentiate substantially from that of the systems it was tested and
developed on. As a result maintenance is a crucial part of delivery and an
appropriate time-frame should always be allocated for it within software
development. In some dire situations an entire redesign of the software might be
deemed necessary during the delivery phase, in this case allocating a specific
time-frame for software maintenance might not be adequate to accommodate the
requirements of the development of the software.

There are various options for publishing your software, once it is complete.

A Scalable Software Development Model 35


An Introduction To Programming With Processing

Why Learn Programming using Processing?


Processing covers a lot of ground as it is a great way to learn programming for the
novice and for the experienced programmer it provides a fast and efficient
approach to developing advanced applications.

Code for Artists


Processing is built with the intent to be a tool for creating visual and interactive
representations of code. This means that it is not as generic in it's application such
as a programming language like C++ which can be used for engineering,
mathematics, scientific applications and even games development but which also
has it's limitations as it is generally not used to create online applications that
might appear on a website. Processing is built for specific fields of interest and as
a result less coding is needed in Processing than might be required in more
generic programming languages when developing programs that are suited for the
Processing environment, such as data visualization, interactive online
applications, animation and many other similar fields. This is not to say that
Processing is limited to one particular genre of application, but merely to say that
Processing provides a set of tools that make the process of creating certain types
of applications easier.
Processing has developed since 2001 initially as an extension to the Java
programming language, then into a prototyping tool and now into it's current
implementation of being a fully developed programming language that continues
to develop in fields such as microprocessor programming and physical computing
where it has gained much recognition.

Java Based
Processing was originally developed as an extension to the Programming
language, Java and it's roots in Java are still evident today even though Processing
is a language on it's own. Processing's relationship with Java has many benefits,
the two languages share a similar syntax except that Processing can make visual
representations of your code easier to create than Java can (which is more generic
in it's scope of application). Java shares a lot of similarities with the programming
language C (from which it was originally developed) and Java is also one of the
most popular languages currently in use. If you are familiar with Java or C++
(which is also closely based on C) learning Processing should come quite
naturally to you.

Why Learn Programming using Processing? 36


An Introduction To Programming With Processing

The Java programming language is a popular language for software development and is
almost entirely open source.

C++ is a widely implemented language, as it is available on many popular platforms

Open Source
The Processing PDE (which is used to develop Processing code and is something
we will discuss in more detail later) is Open Source Software and it is released
under the GNU General Public License.
You've probably heard the term open source before and are aware that it relates
to something free, but are you aware that the term free as it is used in the
context of open source does not necessarily have anything to do with money or
the absence thereof?
The term free within the context of open source refers more to a philosophy or
methodology rather than a monetary reference and as such is akin to the term
freedom. However as the idea of open source has expanded in modern day
society it is often come to be synonymous with something that is also free of
monetarily related costs. Processing is no exception to this, it does not require a
costly software license such as proprietary software vendors require for the usage
of their products. Anybody can use Processing and the PDE, modify it,
redistribute it and the GNU General Public License ensures that the Processing
PDE will always remain free.

What about the content you create with Processing does that also have to be
free and open source?

Why Learn Programming using Processing? 37


An Introduction To Programming With Processing

The answer to this question is, and will remain to be, no. The content you create
with Processing belongs to you, the creator, and you are free to do with it
whatever you please. If you wish to sell the software or code that you produce
with Processing it is your right to do so. If, however, you do not wish to sell your
work and wish to distribute it freely as open source code there are various options
available to you to protect you and your work.
Amongst these licences is the GNU General Public Licence which protects the
rights of developers of computer programs that wish to ensure that the software
they develop remains free, including all derivatives that are made from the
original software program.
Another such licence is the Creative Commons Licence, this licence allows
creators of media to reserve some rights of their work (if they choose to) and still
legally allows the copying, redistribution and modification of such media if the
author chooses to exercise these rights. Wikipedia is an example of a large scale
organization that licenses it's contents under a Creative Commons Licence and
Linux is an example of popular software that is licensed under the GNU General
Public Licence.

The GNU GPL 3 logo as started by the Free Software Foundation on the left and a
Creative Commons logo on the right both of these trademarks have become synonymous
with the term copyleft.

PDE

An IDE is an acronym for Integrated Development Environment, it refers to a


software application that is used to develop code for a computer programming
language. Processing has it's own IDE called the PDE or Processing Development
Environment.

Why Learn Programming using Processing? 38


An Introduction To Programming With Processing

The PDE is a popular tool for developing Processing sketches, but another popular IDE,
Ellipse is also quite readily used too.

Of course all code is simply text, so why can't we call any text editor an IDE? An
IDE such as the PDE generally has several special characteristics that separate it
from other software applications.
1. Source Code Editor
2. Build Automation Tools
3. Compiler and/or Interpreter
4. Debugger

Source Code Editor


A source code editor is a textual editor within an IDE. The Source Code editor in
an IDE is designed specifically for programming purposes and not for word-
processing, so generally text formatting capabilities such as bold, italicizing
characters or directly editing characters colors is not permitted within source code
editors.

Why Learn Programming using Processing? 39


An Introduction To Programming With Processing

The source code editor within the PDE allows you to type code, and access
Processing's API.

Modern day source code editors use color codes to distinguish different types of
data, this is referred to as syntax highlighting and it helps to make code more
human-readable.

Build Automation Tools


Programming can involve many repetitive tasks, build automation tools help
programmers perform these repetitive tasks by use of tools built into the IDE.
They might include the IDE's ability to convert source code to machine readable
code with the click of a single button (the button being the build automation tool)
or the ability to export your source code to multiple platforms with a menu
selection. In the PDE several build automation tools for creating Processing
applications can be found under the Tools and Sketch menus. More generic build
automation tools can also be found in the other menu's in the PDE, such as File,
Edit and Help Menus.

Some of Processing's build automation tools. Processing's build automation toolset can
also be extended by downloading tools from processing.org/reference/tools/

Why Learn Programming using Processing? 40


An Introduction To Programming With Processing

Compiler and /or Interpreter


Most modern day IDE's have a compiler and/or interpreter, as this is the feature
within an IDE that enables the conversion of source code to machine readable
code. It is in this feature that our code is given a meaning for a computer to
implement and for us to observe, interact with and experience in what ever it's
intended form of implementation.
You might be wondering at this point what exactly is the difference between a
compiler and an interpreter?
The terms stem from a Compiled Language and an Interpreted Language. As
mentioned before in order for a computer to make any sense of our source code it
needs to convert this code into a machine readable format, this process of
conversion is referred to as compiling. The process is specific because the code
must be fed into a compiler in a specific language and then be compiled into
another language which is no longer human-readable but machine readable and
specific to a particular platform. A compiler is said to perform this task on the
entirety of the source code once so that when the program is compiled there is no
more conversion or compilation that needs to be performed there after.
An interpreter differs in the sense that the source code is not compiled into a
specific machine readable format. So how does the code run on a machine? The
code is passed to an interpreter (which is another software application) that runs
the code. The interpreter then determines how the code should be run
continuously translating the code from a higher level to a machine readable level
each time the code needs to be executed.
Of course at some point in order for the code to be run on a computer it has to
exist in a machine readable format regardless of whether it's compiled or
interpreted, so theoretically the difference between the two methods is not
inherently specific to the language you are creating the code with, but rather more
to do with how a language is implemented. What this means is that any language
could be interpreted or compiled it's how the code that you create is implemented,
that determines whether that code will be compiled or interpreted.
Processing compiles it's applications known as sketches to Java bytecode, this
code is then sent to a Java Virtual Machine (JVM) where it is either interpreted
via the JVM instruction set or compiled using a Just In Time (JIT) compiler. As a
result a Processing sketch can run on any Java enabled machine and it is
estimated that there are currently over 4.5 billion Java-enabled machines. Java is
often said to be an interpreted language.

Why Learn Programming using Processing? 41


An Introduction To Programming With Processing

Processing compiles your Sketches to Java Bytecode and uses the Display Window
(foreground) for testing and development.

Debugger
A debugger in the context of an IDE is software that examines code either as a
part of the compilation process or before compilation or interpretation in order to
reduce the number of bugs within a program. The term bug in relation to
computer programming is used to describe an error, fault or some means of a
computer program acting in an unexpected or unintended way. The process of
debugging a program is intended to identify these bugs and in some cases assist
the programmer in rectifying them. In the PDE the debugging console consists of
the Message and Text Area and can be found below the text editor and is used
generally for debugging one's own program or allowing the PDE to determine
bugs within a program.
Message Area

Text Area

The debugging console is made up of the Message and Text Area and can be used
to identify bugs and track the associated values of program variables which can be
useful in identifying logical errors.

Why Learn Programming using Processing? 42


An Introduction To Programming With Processing

Active Online Community


Processing is not a stagnant language it is very much alive and growing. The
Language's development is rapid but not so rapid that it becomes difficult to keep
up with. A lot of this development can be attributed to the active community that
support the project by contributing libraries and their own source code.
If you are in need of any help with programming in Processing, want to keep up
to date with it's development or just simply want to play around with programs
made with Processing online then I recommend you visit
http://www.processing.org
The forums are really easy to use and you are encouraged to ask questions, as
there seems to be many people out there that are keen on helping you develop
your software.
The latest version of Processing can be downloaded at
http://processing.org/download

The trademark image of processing.org

Why Learn Programming using Processing? 43


An Introduction To Programming With Processing

Hello Processing
Now that we have an idea of what programming is and how we will be using the
PDE to create our own code in Processing lets start coding!

Install Processing
Once you have downloaded Processing, depending on your platform you might
need to install it or just simply uncompress/unzip the package to a location on
your hard disk drive and run it from there. Open the processing root folder inside
which you will find an executable file called processing, double click this file to
start the PDE and you are ready to start programming with Processing.
If however you are unable to run the PDE check that you have permission to
execute/run the processing file and that Java or more specifically the JRE (Java
Runtime Environment) is properly installed.
It is recommended that you use the version of Java that is available from Sun
Microsystems (a subsidiary of Oracle), alternative open source versions of the
JRE and Java Development Kit (JDK) such as OpenJDK do exist but are currently
not recommended with Processing, however this might change at some point in
the future, see the Processing website for updates.
You can get the latest version of Java from http://www.java.com/getjava

Sketches
A program created in Processing is known as a sketch. Processing sketches are
stored in a folder called the sketchbook folder. Being able to identify the location
of this folder will be useful particularly when adding external data to a sketch. To
identify the location of the sketchbook folder within the PDE click:

File Preferences Sketchbook location

In the Preferences dialogue box the sketchbook folder can be identified under the
heading Sketchbook location or changed by clicking the Browse button and
navigating to and choosing a new location under the same heading.
All Sketches you create should be stored within your sketchbook folder.

Hello Processing 44
An Introduction To Programming With Processing

Hello World Program 1.0


Programming can be simple or very complex depending on what you are hoping
to achieve. Since this is our introduction to programming we'll be following
programming tradition and starting with a simple Hello World program. A Hello
World program sounds a lot more complicated than it actually is, as the purpose
of the program is simply to print the words hello world to a display. That
display in our case is going to be the Text Area of the debugging console in the
PDE. The purpose of the Hello World 1.0 program is not as much to impress
but rather to get a firm grasp on the key points that make a successful program,
then to later expand on this understanding.
If you have not already done so open the PDE and start a new sketch. You can do
this by clicking:
File New
Save the sketch in your sketchbook folder by clicking:
File Save As...
Give the sketch a unique name that you will remember.
In the text editor of the PDE create the Hello World 1.0 program by typing the
following text exactly as it appears below:

println("Hello World");

Press the Run button in the PDE which looks like a play button, or ctrl-r on
your keyboard. The PDE checks, compiles and executes (runs) your program. If
all has gone well you should get a result similar the following image.

The typical Hello World program is many a programmers first attempt at coding.

Hello World Program 1.0 45


An Introduction To Programming With Processing

If your console window has the phrase Hello World printed in it,
congratulations you've successfully completed the Hello World 1.0 program!
Like I said earlier, don't expect to be impressed right away, building a more useful
program is going to take a little more practice. Nonetheless let's have a look at
what is going on here. Firstly you'll notice that the text editor has formatted the
text we input in different colors. The colors denote specific meanings in
Processing, for example in our Hello World 1.0 program:

Orange Orange is used to identify a keyword.

Black Black identifies syntax formatting characters such as


parenthesis and a statement terminator.

Blue Blue identifies a string of data.

IDE's such as the PDE that use syntax highlighting make code more human
readable and once you get familiar with what the colors represent you'll find
yourself separating the code you are reading into smaller manageable chunks by
identifying the colors that serve specific functions.
We refer to the sentence typed in the text editor as a statement. Statements are
easy to identify because they always end with a semi-colon and not with a period
(like in English). Our entire Hello World 1.0 program consists of only one
statement which in itself consists of only one command (or function as is the
preferred terminology in Processing).
Processing is a case sensitive language so it is very important that when you type
a function you do not mix it's casing because println() and printLn() will not yield
the same results, in fact the latter will cause an error.

The println() function


println() is a special type of command known as a function.
Sometimes a function is also referred to as a subroutine so how the term is used
from one language to another may vary but regardless of what you call it the
purpose of a function is generally the same in any programming language, a
portion of code (usually a single word followed immediately with parenthesis)
that exists within a larger body of code (in our case this could be the sketch we
are creating) and performs a specific task within the context of the program but is
also independent of the program.

Hello World Program 1.0 46


An Introduction To Programming With Processing

What this means is that we have not defined the function println() we are simply
using it as it has been defined by the people that developed Processing. In other
words we have not told the computer what to do when it comes across println() in
our Hello World 1.0 program. This means that the main body defining how
println() acts in our program is not defined within our program but exists
independently of our program, somewhere else on your computer's hard disk drive
which would typically be where you installed Processing. If we were to take
another look at the Hello World 1.0 program, we can see the function println() is
telling the computer, that the sketch is running on, to print whatever is inside it's
parenthesis. We refer to data we input into a function through it's parenthesis as a
parameter. Some other higher level languages might refer to parameters as
arguments, but Processing adheres closer to C style code by using the term
parameter as an input for functions and the term argument is used to describe
what happens to a parameters through evaluation (which is something we discuss
in more detail later). The parameters our println() function accepts in this case is
the string of characters that make up the words Hello World.
There are two points worth noting here, firstly we have input data into the
println() function by using it's parameter options and secondly it has returned data
back to us, that being what it has printed to the Text Area. When a function is used
in this way we are said to be calling a function. Functions are the building blocks
of Processing and we will be using them regularly and even creating our own.

The process of calling a function visualized.

Hello World Program 1.0 47


An Introduction To Programming With Processing

Syntax and Syntax Errors


The arrangement of components within a statement is exceptionally important in
programming. Unlike in natural languages, where sentences can be structured in
several different configurations and still have the same meaning. In programming
a specific syntax exists for all languages and must be adhered to or your
compiler/interpreter might throw an exception or a syntax error. Syntax errors are
generally quite common when you first start programming, it is easy to forget to
place a semi-colon at the end of a statement or close parenthesis that have been
left hanging open. Errors like these are often easy to debug, particularly when
using the PDE. For example, if we were to make a mistake in our Hello World 1.0
program and forget to close the open parenthesis, when trying to run the sketch
we could get an error looking something like this...

Syntax errors are common when one first starts programming, but with the help of the
debugging console they can be relatively easy to identify.

As you can see debugging the program in this case is really quite simple, in fact
the PDE tells us exactly where the error is. In larger programs however it might
not be so obvious where the problem lies, although the PDE will try to help you in
tracking down a bug where ever it can. Some useful pointers to remember when
constructing statements in Processing follow, these pointers could help in
avoiding syntax errors.
Always end statements with a semi-colon.
All parenthesis (), brackets [] and braces {} that are opened with their
corresponding left characters must be closed with the right version of the
same character. None of these sets are interchangeable, but some of these
sets are nestable eg (code(code)code), {code(code)code}.
A String of literal characters (such as hello world) must exist between
double quotes. Single quotes are reserved for the char data type (discussed
later).
Look it up in the Processing reference when you are uncertain, which can
be accessed online at http://processing.org/reference/ or from the PDE, for
offline viewing, click :
Help Reference

Hello World Program 1.0 48


An Introduction To Programming With Processing

Of course there are many other points worth noting on syntax and program
structure but we will get to these in due time, for now there's no need to get ahead
of ourselves.

Logical Errors
Logical errors are errors that do not cause the program to halt, crash or throw an
error but will cause the program to act in an unexpected manner or produce
unintended results. Logical errors can therefore be difficult to track down and
rectify because the PDE does not indicate the specific location of an error.
Keeping track of your data through documentation and organizing it into small
manageable chunks can be one method of avoiding logical errors. If your program
seems to have a logical error you might have to use the println() function to track
the values you were hoping to have your program return to you, we'll take a closer
look at this technique when we start creating our own sketches.

Display Window
In our Hello World 1.0 program after pressing the Run button you will notice that
a new smaller window was created. This is the Display Window and because
Processing is a visually oriented language it automatically creates this window
which you will usually use to draw to.

The default Display Window has dimensions 100 pixels in width by 100 pixels in height
and it is automatically created when we run a sketch.

Hello World Program 1.0 49


An Introduction To Programming With Processing

The size() function.


The size() function allows you to specify the dimensions of the Display Window
in pixels. You use the size() function by supplying two parameters to it, a width
value which defines the horizontal dimension of the Display Window and a height
value which defines the vertical dimension of the Display Window. Just like the
println() function, parameters for the size() function are entered between the
function's parenthesis. For example if we wanted the dimension of the Display
Window to be 640 pixels across by 480 pixels down we would type:

size(640,480);

Note that because we have just entered a statement telling Processing how big we
want the Display Window to be we must terminate this statement with a semi-
colon. You might also have noted that the two values 640 and 480 are separated
with a comma. Do not try to separate parameter values such as these with a semi-
colon because the statement is incomplete at that point and you are therefore
attempting to terminate it prematurely. This will most commonly result in a
syntax error or even worse in a logical error in some cases.
Parenthesis following a function's name is usually reserved for parameters
relating to the function and these parameters are most commonly separated by
commas. This is pretty easy to remember because in English you generally list
items by separating them with a comma in Processing and many other higher
level languages you separate parameter values for a function with a comma.
The two values 640 and 480 have been listed in this particular order because
when Processing accepts parameters of dimensional type like X and Y or width
and height in 2 dimensions, or X, Y and Z or width, height and depth in 3
dimensions it will generally accept values in the order X or width first, Y or
height second and Z or depth third. This is with the exception of a trigonometric
function called atan2() in which Y is read first followed by X due to the special
circumstances of how this function works. Incidentally many other programming
languages besides Processing accept parameters in that particular order for the
atan2() function and in the standard format of X, Y, Z or width, height, depth for
most other functions. Below the first statement type the second statement so that
your code now reads:

println("Hello World");
size(640,480);

Hello World Program 1.0 50


An Introduction To Programming With Processing

Standardized Coding Practices


Standardized coding practices establish a consistency between different software
languages. The use of comments and white space (the space between the
characters making up your code) form an important part of formatting your code
to comply with these standards. If you do not use standardized coding practices
your software may or may not throw an exception or an error, but you can be
certain that there are many people that will take exception. Whether your code is
intended to be used by yourself or by others standardized coding practices can
contribute to the readability of your code and as a result it best to avoid trying to
invent your own.

Comments
Comments are lines of information inserted between code that informs a person
reading the code of it's purpose and intent. Comments are completely ignored by
the software executing the code such as the PDE and they should be written in
plain and simple English or, what ever your chosen natural language. Consider
that the comments you write might not always be for your personal understanding
but for another person reading your code and therefore should reflect a clear and
impartial explanation of your code.
Commenting your code becomes particularly useful for code that you have not
revisited over a long period of time. Regardless of whether you wrote the code or
not, trying to understand what revisited code is supposed to do after long periods
of time becomes a cumbersome process when it is not commented properly.
Comments in Processing and many other higher level languages (particularly
those that are C based) are indicated with two forward slashes:

// for a single-line comment

Comments that are more than one line long are called multi-line comments in
some programming languages and documentation comments in Processing. They
are indicated by starting the comment with:

/** typing the multi-line comment


...
...
and ending it with */

Hello World Program 1.0 51


An Introduction To Programming With Processing

White Space
White space is also sometimes referred to as negative space and is the space
between the characters of text that make up the lines of your source code text file.
For example a space, tab or enter/break are all referred to as white space.
Processing unlike other programming languages (such as Python) completely
ignore white space, just like it ignores comments. Programming languages that
ignore white space and allow the programmer to decide how to format their own
code are known as free form languages.
However, just because Processing ignores white space doesn't mean you should,
as using consistent spacing and formatting within your code can make it easier to
read. For example:

println("Hello World");size(640,480);

Although the above code is valid the same program rewritten with proper
formatting can be easier to read (especially when you are in a rush or just glazing
over it), for example:

println("Hello World");
size(640,480);

You can probably imagine how unreadable code could quickly become when
creating more complex programs with hundreds of statements.
Let's revisit our Hello World 1.0 program and retype it taking standardized coding
practices into consideration.

/**
* Hello World 1.0 Program
* by Lyndon Daniels.
* 11/01/2011
* This example program demonstrates how to
* create a Hello World Program in Processing.
*/

//Determine the size of the Display window


size(640,480);

//Print characters to the console


println("Hello World");

Hello World Program 1.0 52


An Introduction To Programming With Processing

Program Notes
Firstly you'll notice that every line in the documentation comment except the first
and last lines of this comment start with an asterisk *. This is not necessary but,
it does make the code look somewhat nicer and many programmers adopt this
fashion of multi-line commenting so I've included it in this program. To
Processing such niceties make absolutely no difference, but to us it makes the
code a little easier to read.
It is standardized coding practice to include the following information in the
documentation comment.

Name of the program,


The programmers name,
The date on which the program was released,
A brief description of what the program does.

Secondly it's worth noting that the order in which the statements are executed (or
run) has changed. Code written in this way resembles a procedural programming
style meaning that the code is executed one line after the next starting at the top of
the document and working down. As a result it makes more sense to define the
size of the Display Window before any other code is run. Although in this sketch
using this particular order for the two statements is not entirely necessary, it is still
a standard practice amongst many Processing programmers to include the size()
function at the beginning of a program and not at the end. This is also a more
logical approach to writing code in terms of how programs are structured within
Processing. At a later stage you will see that when using the setup() function
starting with the size() function, before any other functions following setup(), is
mandatory.

Hello World Program 1.0 53


An Introduction To Programming With Processing

Visual Representations of Code

The Cartesian Graph and the Processing


Coordinate System
As mentioned earlier the Display Window's dimensions are determined within the
size() function via the parameters that it accepts. Those dimensions are measured
in pixels. Later, when we start drawing to the Display Window we need to tell
Processing where exactly we are attempting to draw to within the Display
Window, this information we supply to Processing in the form of X and Y
coordinates when dealing with a 2D sketch and X, Y and Z coordinates when
dealing with a 3D sketch. As a result you can think of the Display Window as
being a piece of graph paper with invisible lines.

A point located at
(120,80)

The Display Window can be divided up into a grid.

The origin of the Display Window is in the top left hand corner and being the
origin it's coordinates will be (0,0) meaning zero X and zero Y respectively. The
type of grid layout represented in the above image might look familiar to you,
that's because it's based on the Cartesian graph system. This is the name for the
type of graph layout we use in Processing and many other programming
languages that allow us to create and place components of a program (such as
graphical elements) within an area such as the Display Window. Although the
name might sound very grandiloquent it's application is actually quite simple, and
resembles the workings of most common graph layouts used in some of the
simplest forms of mathematics. The main difference between the programmatic

Visual Representations of Code 54


An Introduction To Programming With Processing

version of the Cartesian graph and the mathematical version of the Cartesian
graph is that in the programmatic version the positive Y axis runs downwards not
upwards as is usually the case in the mathematical representation of this graph.
This actually does not change anything about how the graph system is used, if you
find this to be a bit odd you can think of it as if we were looking at a piece of
graph paper rotated 180 degrees around the x axis so we're looking at the back of
the graph paper and as a result everything drawn on the paper now appears upside
down. As you can imagine nothing drawn on the graph paper has changed just the
way we are looking at it is different.
Understanding how the Cartesian graph system is applied in programming is a lot
easier when we have an example to work with, so lets add to our Hello World 1.0
program by making use of the Display Window in our updated sketch.

Hello Display Window: Hello World 1.1


In the revised version of our Hello World Program we will start using the Display
Window, firstly to display the original character set Hello World then to display
a few shapes too.

The text() function


The text() function is the first function we will use to draw to the Display
Window. The text() function accepts parameters in various formats of which the
simplest format is:

text(data, x, y);

For the data parameter in our sketch we will use a string of characters that spell
the phrase Hello World and as you've probably already guessed the X and Y
parameters tell Processing where in the Display Window we would like to draw
the text in terms of X and Y coordinates relative to the Cartesian graph
(superimposed on top of the Display Window, with a bit of imagination).
So let's give it a try, add the following statement to the bottom your Hello World
1.0 sketch and Run it to see the results. If you already have a sketch running you
can press the Stop button (next to the Run button) to stop the currently
running sketch, pressing the Run button again will include any changes you
have made to your sketch:

text(Hello World, width/2, height/2);

Visual Representations of Code 55


An Introduction To Programming With Processing

Using the Display Window gives you immediate feedback for testing your code.

Program Notes
You'll notice that the sketch is now making use of the Display Window, which is
the first step towards creating visual representations of your code. We used the
string of text Hello World in the data parameter. This kind of string is known as
a literal string because it does not require any further processing, within the
program you are creating, to output it's final form of representation, kind of like
the concept of what you see is what you get. The term string, in general, refers
to a list of characters that when grouped together form the contents of a single
string, for example in our case we have a literal string which consists of several
characters 'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o' ...etc.
The X and Y parameters are however, looking a little different particularly if you
were expecting them to be numbers. In fact they are representations of numbers in
the sense that instead of inputting a specific number for the X and Y parameters,
we used an expression and in this case the expression evaluates to a number. It is
this number that Processing reads and accepts as the parameter. But what exactly
do the expressions mean and what do they do?
Amongst the many things that Processing is, it is also a very sophisticated
calculator. It has the ability to calculate very complex mathematical formulae and
also is able to do very simple mathematical calculations too.

width/2

The above expression is asking Processing to get the width of the Display
Window and divide (/) it by 2. As you can see Processing has formatted the word
width in blue by use of syntax highlighting, this should immediately indicate to us

Visual Representations of Code 56


An Introduction To Programming With Processing

that we are not using an arbitrary word but in fact a special word known as a
keyword. Keyword is a generic term we use to describe words that have a
specific meaning for the language we are using that word in. As a result keywords
within Processing do not appear formatted in black. A list of keywords and other
features making up the Processing language can be found in the Processing
Reference (mentioned earlier). The keyword width is a special type of data known
as a system variable. Basically the width system variable stores information set by
the first parameter in the size() function, and as you are aware the first parameter
in the size() function determines the width of the Display Window. In our
program we set the size() function to read:

size(640,480);

How this relates to the width system variable is that every time Processing sees
the keyword width it replaces it with whatever we set the width value to be in the
size() function. In this case since we set the width to 640 the text statement as
Processing reads it would look like this:

text(Hello World, 640/2, 480/2);

The height system variable has the same effect but relates to the second parameter
of the size() function.
So the question is why did we not just simply type the values 640 and 480 instead
of using the keywords width and height respectively? Even further still why didn't
we just type the values 320 for the width parameter and 240 for the height
parameter of the text() function, so that it looks like this:

text("Hello World", 320, 240);

Although this is a perfectly valid methodology, it is not very versatile. Currently


there is not too much maintenance involved in updating the code if we were to
decide that the Display Window needs to be smaller, however when it comes to
creating the rest of the sketch which is going to involve drawing shapes to the
Display Window of which each shape will need to have it's own set of
coordinates, if we had typed in a specific value for each X and Y position or width
and height parameter, updating the code to reflect the change of dimensions to the
Display Window would mean changing each statement where we input specific
X, Y, width or height values. That could mean a lot of extra and unnecessary

Visual Representations of Code 57


An Introduction To Programming With Processing

work. By using an expression with the keywords width and height we can place
whatever we are drawing relative to a position determined by the size() function.
So all we need to do is update the size() function and those expressions that use
the width and height system variables will also update to reflect these changes.
This is a programming methodology that is used often to create versatile and
scalable programmatic interfaces and is referred to as implicit programming.
Although it might not seem entirely obvious to you at this point why it is a
recommended methodology it should become more clear as we explore
programming through the introductory Hello World 1.1 and 1.2 programs.

Formatting Text
You might have noticed that the text is supposed to be in the center of the Display
Window but looks more like it's leaning to the right hand side of the window.
Processing allows us to align text relative to the coordinates we specified for the
text() function's X and Y parameters. The relative positions are LEFT, RIGHT or
CENTER. I have typed them in upper case because that is the format that
Processing accepts them in, when entered as a parameter for the textAlign()
function. So let's fix the text alignment so that it is in the center of the Display
Window, add the following line of code directly above the text statement:

textAlign(CENTER);

If you were to re-run the sketch, the updated version should have the text directly
in the center of the Display Window. As we are using a procedural programming
style to create this sketch, Processing needs statements input in a particular order.
We'll discuss procedural programming and other programming paradigms in
more detail a bit later, but for now it's worth noting the emphasis on the order that
statements are placed in. Placing the textAlign() function before the text()
function ensures that the textAlign() function is run before the text() function
thereby ensuring that by the time Processing gets to drawing the text in the
Display Window it already knows that the parameters that relate to the text's
coordinates within the text() function refer to the CENTER of the text.

Visual Representations of Code 58


An Introduction To Programming With Processing

Text box Text box

Text box is drawn textAlign(CENTER)


relative to this point centers the text to
this point

The point indicated in the illustration is determined by the text() function's X and Y
parameters. As you can see this point does not move when using textAlign() the text's
alignment to this point is what changes.

Next we'll have a look at the size of the text. Currently it looks like the text is
drowning in a sea of greyness, we're going make the text a little bigger in an
attempt to place more visual emphasis on it, within the composition. The
textSize() function allows us to set the size of text in pixels. Size is input as a
number which is a parameter of the textSize() function.
Add the following statement before the text statement:

textSize(24);

Now we're starting to get somewhere, although white text on a grey background
does not exactly jump out at you. So in keeping with one of the main
processing.org color schemes we're going to use a black background with light
blue text, we'll address these requirements as we examine how to use color in
Processing.

Color
Color in Processing can be input in several different formats such as RGB (Red,
Green, Blue), HSB (Hue, Saturation, Brightness) or Hexadecimal notation. RGB
is the default color mode but this can be changed with the colorMode() function.
Lets have a look at how to change the background color. Add the following
statement to your sketch directly after the size() statement:

background(0,0,0);

Visual Representations of Code 59


An Introduction To Programming With Processing

The background() function accepts up to three parameters, in our case the first
parameter is the Red value followed by the Green value and finally the Blue
value. As we want a black background all of these values are set to 0, the
minimum value for the current color mode of RGB. The maximum value for these
parameters is 255, this gives you a total of 256 different color values for each
color (remember 0 is also a value). If we wanted a white background we would
enter 255 for each of the three parameters of the background() function. Later we
will have a look at a shorthand version for displaying greyscale colors such as
black, white and various levels of grey.
Now onto the color of the text. The textAlign() and textSize() functions set
parameters not just for the text currently displayed but for all text that is created
thereafter. Until these functions are used again and their parameters are changed
they will remain in Processing's memory and effect all text that is drawn to the
Display Window following their execution.
The fill() function acts in a similar fashion, it accepts color values and will effect
everything that is drawn to the Display Window that has a fill after the function is
evoked. We will have a look at how to modify this behaviour a bit later, for now
lets focus on getting the text to display in a light blue.
In the PDE click:
Tools Color Selector

The Color Selector is accessible within the PDE from the tools menu

The Color Selector dialogue box is useful for finding the specific HSB, RGB or
Hexadecimal color values of a color. In our case the RGB values for the light blue
I'm looking for are R 191, G 233 and B 255. I can now use these values in my
sketch. Before the text() statement add the following statement:

fill(191, 233, 255);

Visual Representations of Code 60


An Introduction To Programming With Processing

This statement sets the color of the text to light blue color.
Before we continue drawing shapes, lets make a few adjustments to the horizontal
position of the text so that we can have some space to draw a smiley face in the
center of the Display Window. Once again we're not going to input a specific
number into the Y parameter of the text() function, instead we're going to use an
expression so that we can have Processing do the work for us just in case we feel
like changing the dimensions of the sketch once it's complete.
Basically we want to keep most of the text's characteristics as is, but just place it
closer towards the bottom of the Display Window about three quarters of the way
down. We know that the height system variable contains the height of the Display
Window and that dividing it by 2 will return a value that is half the size of the
Display Window's height. As a result we can deduce by use of some simple
mathematics that dividing the height value by 4 will give us a value that is a
quarter of the height of the Display Window. If we then multiply this value by 3
we will have a value that is three quarters in length of the height of the Display
Window. So our expression would look like this:

(height/4)*3

What this reads as is height divided by four then multiplied by three. Just like in
mathematics anything within parenthesis is evaluated before that which is outside
of parenthesis. So the expression height/4 is first evaluated, the answer of this
expression is then multiplied by 3.
Modify your text statement to look like this:

text("Hello World", width/2, (height/4)*3);

Now we can ensure that whatever the height of our Display Window may be,
Processing will always place our text three quarters of the length down the Y axis
of the Display Window.

Visual Representations of Code 61


An Introduction To Programming With Processing

The new Hello World Program in Processing.

Drawing
Processing is a language that was made to create visual representations of your
code really easily, and as a result the developers of Processing have provided us
with pre-configured functions for drawing primitive shapes much like you would
expect in a drawing program. Shapes such as rectangles, ellipses and triangles
amongst others are known as 2D primitives and can easily be drawn to the
Display Window with a simple keyword. We'll start by drawing an ellipse.

2D Primitives
Drawing an ellipse in Processing is easy you just use the ellipse() function that
accepts parameters in the following order:

ellipse(x, y, width, height);

As you might have already guessed the X and Y parameters indicate where the
ellipse is to be drawn on the coordinate system, and the width and height
parameters indicate the width and height of the ellipse. Please note that the terms
width and height in this context have nothing to do with the system variables
width and height which store information relating to the width and height of the
Display Window. To draw an ellipse in the Display Window add the following
statement to the end of your program:

ellipse(width/2, height/2, 100, 100);

Visual Representations of Code 62


An Introduction To Programming With Processing

Once again to find the center of the Display Window I have used the expressions
width/2 and height/2 this returns the X and Y coordinates respectively that will be
the center of the ellipse. Technically a circle is an ellipse with an equal width and
height, which is why we have input 100 for both the width and height parameters
of the ellipse() function. I've also chosen to enter explicit values for the ellipse's
width and height parameters, as I don't want the dimensions of the ellipse to
change even if I do decide to change the dimensions of the Display Window.
Using this hybrid style of mixing implicit programming and explicit programming
can sometimes lead to logical errors, so you should always be certain of what you
are doing when using this approach to programming.

The Origin of an ellipse


Processing provides several different methods for drawing an ellipse which
modify what the X and Y parameters of the ellipse() function refer to. These
parameters of the ellipse() function are used to determine the position of what is
known as the origin of the ellipse. The function ellipseMode() is used to change
where the ellipse is drawn with relation to it's origin as specified by the X and Y
parameters of the ellipse() function. This relationship will determine where the
ellipse is drawn within the Display Window and works in a similar fashion to that
of the text() and textAlign() functions.
The function ellipseMode() accepts the parameters CENTER, RADIUS,
CORNER, or CORNERS. Using the CENTER parameter tells Processing to use
the X and Y parameters of the ellipse() function to determine the center of the
ellipse as it's origin. The CENTER parameter for ellipseMode() is the default
mode, and is subsequently why we are choosing not to add the statement to our
sketch. If you did want to use the CENTER creation mode for drawing ellipses
after having overridden this setting with one of the other modes, apply the
following statement to your sketch before using the ellipse() function:

ellipseMode(CENTER);

Remember Processing is case sensitive so don't forget to type this parameter in


upper-case.

Visual Representations of Code 63


An Introduction To Programming With Processing

Drawing an ellipse with the CENTER parameter of ellipseMode()

The CORNER parameter for the ellipseMode() function allows you to create an
ellipse by specifying the X and Y parameters of the ellipse() function as the top
left hand corner of an imaginary bounding box that surrounds the ellipse. In other
words the X and Y parameters of the ellipse() function are used to determine the
top left-hand corner of the bounding box from where the width and height
parameters of the ellipse() function are used to extend to the maximum width and
height of the ellipse.

Drawing an ellipse with the CORNER parameter of ellipseMode()

To use this creation method for ellipses type the following code:

ellipseMode(CORNER);

At this point you might be wondering what the purpose of functions such as
textAlign() and ellipseMode() are since we can simply place an element of a
sketch, such as an ellipse, where ever we want in the Display Window using the
function to draw the element's X and Y parameters.

Visual Representations of Code 64


An Introduction To Programming With Processing

However, providing a means of placing an element within the Display Window is


only part of the reason why we have such functions. One of the main reasons is
that these functions (without modifying the position of the element we are
placing) allow us to think differently about how we will align and place other
elements relative to that element in question. For example if we wanted to place
two ellipses next to each other with their edges touching, using either the
CORNER or CENTER parameter options would require changing the way we
think about placing the second ellipse in relation to the first depending on which
parameter option we chose. Let's use the CENTER option first to illustrate this
situation.

width/2
Ellipse 1 Ellipse 2

In the above diagram the method used to determine the origin of the second
ellipse is to divide the width of the first ellipse by two, then add this value to
whatever half the width of the second ellipse is. This calculation would return a
value that would equate to the X parameter of the second ellipse. The Y parameter
of the second ellipse would be the same as that of the first ellipse.

width
Ellipse 1 Ellipse 2

When using the CORNER option in order to determine the second ellipse's origin
we would simply need to know the width of the first ellipse and add this value to
the X coordinate of the second ellipse. This calculation although different from
the previously mentioned example would yet again return a value that would
equate to the X parameter of the second ellipse. The Y parameter of both ellipses
is the same.
As you can see although the visual results are the same, that is two ellipses with
their edges touching at the same places, how we solve the problem is different
depending on how the origin of an element is determined.
The relationship between the placement of one element with that of another is

Visual Representations of Code 65


An Introduction To Programming With Processing

something we will address often in programming especially when using an


implicit methodology, fortunately it is also something that becomes easier to
visualize with practice.
It's time to save the sketch if you haven't already done so. In the PDE click
File Save As...

Change the name of your sketch to something more meaningful and save it.
Processing will create a new folder in your sketchbook folder with the name of
your sketch, in this folder Processing will save a .pde file which is the source code
file we are currently working on. It's also worth noting that if you have added any
additional files to your sketch such as images or other external resources
Processing will also copy the those files to a folder called data, which will be a
subdirectory of your sketch's folder. In the PDE saving a file with a different
name is akin to creating a new sketch. This is something to be aware of as you can
inadvertently increase the amount of data on your hard disk drive by duplicating
sketches with different names if you are unaware of this feature. Adding external
content to a sketch is something we will get into a bit later when we start adding
images to the sketch. The sketch should currently look something like this:

/**
*Hello World 1.2 Program
*by Lyndon Daniels.
*This example program demonstrates how to
*create a Hello World Program in Processing.
*/

//setup of the Display Window


size(640,480);
background(0,0,0);

//Print characters to the console


println("Hello World");

//Render and format text


textAlign(CENTER);
textSize(24);
fill(191,233,255);
text("Hello World", width/2, (height/4)*3);

//Drawing the face


ellipse(width/2, height/2, 100, 100);

Visual Representations of Code 66


An Introduction To Programming With Processing

Aliasing
You might have noticed that the ellipse is looking a bit pixelated and not very
smooth this effect is known as aliasing and is often counteracted with the effect of
anti-aliasing which creates the impression of a smoother looking rendering.
Fortunately in Processing we have a function that is made exactly for the purpose
of making the contents of a sketch look smoother. Add the following statement to
the first part of the sketch just after the size() function:

smooth();

The smooth() function does not accept any parameters but still requires
parenthesis, it's also worth noting that although using the smooth() function will
make your geometry appear smoother it might come at the expense of slowing
down the rate at which your sketch runs. By default a Processing sketch will try to
update itself 60 times in one second (if a function such as draw() is used), this
allows for smooth looking motion and almost instantaneous interactive results.
We are creating what is known as a static sketch which does not involve any
interactivity or animation, so using the smooth() function in this situation should
not greatly influence the sketches performance.

Smile
The ellipse needs a smile in order to make it into a smiley face. We will use an arc
to draw the smile, the main reason we are using an arc is firstly to introduce the
arc() function but more importantly it's an opportunity to explore working with
angles in Processing.

Angles in Processing
In mathematics angles are usually measured in either degrees or radians,
Processing and many other programming languages generally accept both units of
measurements but prefer the latter. One of the main reasons most programming
languages prefer measuring angles in radians is because radians work well with
the value known as PI (pronounced py rhymes with try) which can be
represented in mathematical notation as . PI is a number that has the
approximate value 3.1415927 (calculated to seven decimal places). The actual
number that PI represents in programming is not quite as important as it's
mathematical equivalent, subsequently we will generally never need to remember

Visual Representations of Code 67


An Introduction To Programming With Processing

what this number is in programming but rather what the language we are choosing
to use it in, represents it as. In Processing the value of is represented by the
mathematical constant PI. To Processing and many other programming languages
a constant is a value that does not change, as a result it makes sense for the
Processing representation of pi to be a constant. Pi has always been the same
value long before Archimedes approximated it's value in the 200's BC as it's
implication in the construction of many architectural wonders of human ingenuity
from as far back as the Egyptian pyramids and even further back in human history
suggests, and it's highly unlikely that pi could be used to represent any other
value. So what does it mean?
Pi is the ratio of the circumference of a circle to it's diameter, and pi radians is
also equal to approximately 180 degrees. Pi can be expressed mathematically as:

= C/d

Where C is the circumference of a circle and d is the diameter of a circle.


So how do we use this information about pi to work with radians and degrees?
Well we already know that pi radians is equal to 180 degrees so that means twice
pi radians (or you might be more familiar with the mathematical notation 2r) is
equal to a full revolution or 360 degrees, or as the value is referred to in
Processing TWO_PI. Processing also has other mathematical constants to
represent pi in other useful quantities such as HALF_PI which is approximately
equivalent to 90 degrees and finally QUARTER_PI. But what about all the other
infinite angles how do we reference these values in Processing? You could either
type them out explicitly as radians or if you know their approximate equivalent in
degrees you can use a formula to convert the value from degrees to radians:

radians = (/180)*angle in degrees

For example if we had the angle 270 degrees and we needed this in radians so that
we could use it in our Processing sketch we could either use the mathematical
constants Processing provides us with and type the following expression:

PI + HALF_PI

This expression would return the equivalent of 270 degrees in radians. Or we


could use the above mentioned formula and type the following expression, which
would also return the equivalent of 270 degrees in radians:

Visual Representations of Code 68


An Introduction To Programming With Processing

(PI/180)270

Remember that because there is no mathematical operator between 270 and the
right closing parenthesis character the value of what is in parenthesis must be
multiplied by 270, this will return the equivalent of 270 degrees in radians.

However there is a simpler method of converting degrees to radians in Processing,


and that is to use the radians() function. If you know the value of the angle in
degrees and want to convert it to radians you can simply use the known value as a
parameter of the radians() function and Processing will use the above mentioned
formula to calculate the equivalent value in radians for you. For example:

radians(270);

This will convert 270 degrees to it's equivalent in radians. One of the main
reasons why angles in Processing are converted to radians is because all
trigonometric functions that require angles as an input accept these values in
radians.

Getting the hang of working with radians at first might be a little tricky if you are used to
degrees, but if you think of them in terms of pi they can be a lot easier to work with.

The arc() function in processing accepts six parameters in the format

arc(x, y, width, height, start, stop)

Visual Representations of Code 69


An Introduction To Programming With Processing

You are already familiar with the first four parameters X and Y determine the
origin of the arc and this can be further controlled with the ellipseMode()
function. The width and height parameters represent the dimensions of the arc in
much the same way that these parameters, determine the dimensions of an ellipse.
The last two parameters you might not be familiar with, the start and stop
parameters determine the beginning and ending angles of the arc. For example,
we are attempting to draw a half circle to represent a smile which, as you know,
can be expressed with angles between 0 and 180 degrees. Secondly, because we
want our smile to resemble the shape of a horseshoe pointing upwards we will
start it at 0 and end it at PI (which is approximately 180 degrees). This means that
the arc will be drawn between the start and stop parameters and the other
parameters are used to determine the dimensions of the arc and the arc's position.
Add the following statement to your sketch following the ellipse statement:

arc(width/2, height/2, 50, 50, 0, PI);

A Smile on the Hello World Program.

Editing the smile


Our smile drawn with the arc() function looks fine but needs a bit of work.
Although you cannot see it the arc actually has a fill. In order to see the fill we
will first have to remove or hide the ellipse, but we're happy with the way the
ellipse looks so instead of deleting the statement or cutting it to the clipboard we'll
comment it out. Commenting out a statement or a group of statements is the
process of adding comment tokens to the statement/s that cause the statement/s to
be ignored by the compiler. Comment tokens in Processing are two forward
slashes // as mentioned previously. The easiest way to comment out the ellipse
statement is simply to place the comment tokens at the start of the statement so it
looks like this:

Visual Representations of Code 70


An Introduction To Programming With Processing

//ellipse(width/2, height/2, 100, 100);

You might have also noticed that when you comment out a statement, syntax
highlighting causes the statement to turn grey. This means we can now run the
program and Processing will no longer draw our ellipse, until we uncomment the
statement by deleting the comment tokens. To comment out a block of code
select the lines of code you wish to comment out and in the PDE click:

Edit Comment/Uncomment

This will toggle your selection between a commented state and a standard block
of non-commented code. Commenting and uncommenting is just simply a
convenient and easy way of testing or debugging a program by including and
excluding statements easily without having to retype out a statement that has been
deleted or using an operating system's clipboard.

Commenting out the ellipse statement reveals that the arc is drawn with a fill.

To remove the fill we will use the noFill() function. So between the ellipse
commented statement and before the arc statement add the following code:

noFill();

The order in which commands are issued to Processing is very important.


Functions such as rectMode() and noFill() not only effect the command that
directly follows them (such as the arc statement being effected by the noFill()
function) but they also effect all statements that follow there after that rely on
these special functions. So what that means is that if we were to place the noFill()
function before an uncommented ellipse statement followed by the arc statement
both the ellipse and the arc would have no fill. This is obviously not what we
want, we only want the arc to be without a fill and subsequently run the ellipse()
function before noFill().

Visual Representations of Code 71


An Introduction To Programming With Processing

If you were to run the sketch at this point it might look as though the noFill()
command has removed the arc completely from the Display Window, but this is
not the case. In Processing 2D primitives such as triangles, arcs, quads, ellipses
and rectangles are actually made up of both a fill and a stroke. We've already seen
that the fill can be controlled with the noFill() function, the fill() function and that
Processing's default setting is to draw all 2D primitives with a fill.
The stroke is the outline that surrounds all 2D primitives and looks like a line of
various inclinations, dimensions and weights. The stroke can also be turned off
with a function similar to the noFill() function, as you might have guessed it's
noStroke().
To turn the stroke or fill back on or to simply edit an existing stroke or fill we use
the stroke() or fill() functions. Both of these functions accept parameters in the
form of a grayscale color, an RGB value or a RGBA value by default. You can
also control how Processing accepts parameters for these two functions with the
colorMode() function. We'll be changing our black stroke (which seems to have
disappeared, because it's camouflaged into the black background) to a red smile.
Add the following statement after the noFill statement:

stroke(255,0,0);

The stroke() function can be used in a similar way fill() is used but for editing the
color of lines.

This statement simply informs Processing that any strokes that are drawn after
this statement is run will consist of a color that is fully red, with no green and no
blue in other words (255, 0, 0). Now we have a smile floating above our text, so
we're going to uncomment the ellipse statement and when we run the sketch our
smile is restored to it's elliptical face.
The smile is looking a little too high up on the face so we're going to move it

Visual Representations of Code 72


An Introduction To Programming With Processing

down, this is easy because we already have the style of the smile so we just need
to offset it's y position. To do this we are going to edit the arc() function once
more to the following state:

arc(width/2, height/2 + 10, 50, 50, 0, PI);

Notice that because we are using an inverted Cartesian graph adding 10 to the
arc's current y value actually moves the arc down, inversely if we subtracted 10
we would move the smile up. At first getting used to this system might be a little
tricky, but it's certainly worth noting because this type of graph system is used in
many graphics based software packages.

Adding Eyes
What's a smiley face without eyes. Add the following code to your sketch after
the previous arc statement:

stroke(0,0,0);
fill(0,255,0);
ellipse(width/2-15, height/2-15, 20, 30);
ellipse(width/2+15, height/2-15, 20, 30);

As we changed the stroke to red in our previous statement to draw the smile, we
need to change it back to black in order to draw the strokes encompassing the
eyes so we add the second stroke statement to our program to change the stroke
color back to black. Having also turned the fill off for the arc statement we need
to turn it back on for the eyes and set it to green, we can conveniently achieve
both of these tasks with stroke() and fill() function calls.
Let's take a look at the X and Y parameters of the ellipse functions that actually
draw the eyes and how the expressions used in these statements have been
modified. For the eye on the left's X parameter 15 has been subtracted, and for the
eye on the right's X parameter 15 has been added.
When working with expressions like this it's important to remember that certain
mathematical operators have precedence over others. For example * and / have
precedence over + and -, this means that the expression width/2-15 is actually
being evaluated like so (width/2)-15. This effect is known as operator
precedence. Finally the Y positions of the ellipses have been offset by subtracting
15 and rendered less circular in form and more oval-shaped by making their
height's greater than their widths.

Visual Representations of Code 73


An Introduction To Programming With Processing

Drawing Irregular Shapes


Fortunately we are not limited to drawing only 2D primitives in Processing, but
we can in fact draw any 2D shape that we can imagine. In order to draw irregular
or non-primitive 2D shapes we use two main functions, beginShape() and
endShape() issued in that particular order, in conjunction with several calls to
another function called vertex(). We're going to start off by experimenting with
this feature by drawing a speech bubble surrounding the Hello World text in our
sketch.
The beginShape() function tells Processing to start recording the following set of
points that are about to be issued until the endShape() function tells Processing to
stop recording. Between these two functions we are going to supply Processing
with a set of special X and Y coordinates that will be parameters in a call to the
vertex() function. The vertex() function accepts parameters in various formats of
which we are most interested in the X and Y parameter format, which will be used
to determine where (in terms of X and Y) the point (or vertex) to which the
function is referring to will be placed. By adding the following statements in the
particular order listed below we will be able to draw a speech bubble:
beginShape();
//Start the shape in the middle of the Display Window's x axis

vertex(width/2, (height/4)*3-35);
vertex(width/2-70, (height/4)*3-35);
vertex(width/2-80, (height/4)*3-25);
vertex(width/2-80, (height/4)*3+5);
vertex(width/2-70, (height/4)*3+15);

//The following statement marks the point where the shape


//starts to mirror itself

vertex(width/2, (height/4)*3+15);

//Notice how the X parameters are mirrored from this point, The Y
//parameters do not change from their mirrored counterparts

vertex(width/2+70, (height/4)*3+15);
vertex(width/2+80, (height/4)*3+5);
vertex(width/2+80, (height/4)*3-25);
vertex(width/2+70, (height/4)*3-35);

Visual Representations of Code 74


An Introduction To Programming With Processing

//this is the arrowhead that points out of the


//speech bubble towards the smiley face

vertex(width/2 + 50, (height/4)*3-35);


vertex(width/2 + 40, (height/4)*3-55);
vertex(width/2 + 30, (height/4)*3-35);

//the end of the shape is the same as


//the beginning

vertex(width/2, (height/4)*3-35);

endShape();

Although at first this might appear to be a little confusing and a lot of typing,
upon closer inspection you may notice that it is in fact repetitious and more of
copy, paste and modify effort. So lets have a look at what's going on here.

Each vertex position can be mapped to a vertex() in the code.

In the above illustration we can see that beginShape() has started recording the
various points that make up the irregular shape of the speech bubble, which we
subsequently define for the beginShape() and endShape() functions one vertex at
a time. The first vertex is located along the center of the Display Window's X axis
followed by the Y parameter for this vertex which is 35 pixels above the center of
the text that says Hello World. Of course we could just as easily have typed in
the values explicitly such as:

vertex(320, 325);

Visual Representations of Code 75


An Introduction To Programming With Processing

But using this method of explicit programming does not leave much room for
changes and could subsequently lead to the extremely time consuming task of
changing each explicitly determined point in your program manually, if it is
deemed that such a change is necessary at a later stage.
From the next vertex on we can use the Display Window's width and height
system variables and the text's X and Y position as a starting point from which we
can place every vertex that follows relative to the position of the previous vertex
and in relation to the other elements making up the program.
Using this method of implicit programming also makes it easier for us to mirror
the coordinates of the irregularly shaped speech bubble across the center of it's
own Y axis. As you will notice once we get to the vertex marked as the point
where the shape starts to mirror itself it's just a simple question of copying and
pasting the previous code excluding the first vertex statement, changing the
negative values associated with the vertices' X parameters to positive values, and
reversing the order of the statements in a mirrored fashion.

Using an implicit style of programming can also make patterns in your code easier to
identify.

This can save quite a bit of time as it is not necessary to work out the specific
coordinate of each vertex individually all we need to know is half of the
coordinates that make up the shape and since we are mirroring the shape on the X
axis we simply change the negative values associated with X to positive values.
Once we have all the vertices mirrored on the right hand side (excluding the last
vertex) we can then start to plot the points of the arrow head of the speech bubble
that points to the smiley face implying that it's saying Hello World.

Visual Representations of Code 76


An Introduction To Programming With Processing

This part of the shape is pretty straight forward because we already know that we
will need three points to make the triangular shape of the arrowhead and we
already know the Y positions of two of these points because they will be at the
same height of the first and last vertices of the speech bubble. So it's just a case of
simple trail and error to determine what looks best in adding the remaining
parameters to the next three vertex() functions. Once that's complete we can close
the shape by placing the last vertex at the same location of the first vertex.
Finally to end the shape you must use the endShape() function.
You might have noticed that the image on page 75 has a speech bubble with a
thick blue outline around it. This is due to the strokeWeight() function, and it
controls how thick or thin a stroke is rendered. It accepts a number as a parameter,
I don't recommend setting this number too high as you might find it causing
undesirable effects on your sketch. The higher the number the thicker the stroke.
Add the following statement before the statements that draw the speech bubble:

strokeWeight(8);

You might remember that in order to have a black outline around the face's eyes
the stroke() function had to be set to an RGB value of 0,0,0 (or black), so
although the strokeWeight() function has done it's job by increasing the thickness
of the stroke surrounding the speech bubble, the effects of it might not be so
obvious. Changing the stroke and fill colors are functions that you might need to
run several times within a single sketch to achieve the desired result which is
precisely what we are about to do. Add the following statement before the
previous statement:

stroke(50,127,255);

This changes the stroke color for the speech bubble to a little bit of red, about 50
percent green and full blue. In order to change the fill color of the speech bubble
to white you must add the fill() function before the drawing of the speech bubble.
A statement to determine the speech bubble's fill color as white would look like
either one of the following two fill statements:

fill(255,255,255);
//or
fill(255);

Visual Representations of Code 77


An Introduction To Programming With Processing

Either option is perfectly acceptable, the latter is used for determining a greyscale
value from 0 (which is black) to 255 (which is white). When dealing with
greyscale values, including black and white, the latter is the more widely adopted
method as only one parameter is needed as opposed to three parameters used to
determine RGB color values.

The Stroke Caps are over lapping on the first and last vertex of the speech bubble
in the current version of the Sketch.

The section of the speech bubble where the first and last vertices of the shape
overlap has a slight blemish caused by the default stroke caps setting. Stroke Caps
determine how the end of a stroke is drawn for example is it round or flat, and
they become most evident when dealing with heavily weighted strokes such as the
stroke surrounding the speech bubble. Fortunately we have a function in
Processing for controlling how stroke caps are drawn, as you might have guessed
the function is called strokeCap() and it accepts the parameters ROUND,
SQUARE or PROJECT.

Different types of stroke caps in Processing, which are very similar in effect to that of a
vector illustration package.

Remember that Processing is case sensitive so you must type the parameter's
name with the correct casing. ROUND is the default parameter that causes strokes
in Processing to have a beveled end, SQUARE will end the stroke with a flat end
and PROJECT will tend to render the end of the stroke slightly past it's destined
coordinates, like ROUND but with a flat end. We are going to use SQUARE to
fix the speech bubble. Add the following statement after the strokeWeight()
function call:

strokeCap(SQUARE);

Visual Representations of Code 78


An Introduction To Programming With Processing

Order, order!
We now have a speech bubble, but where's our text gone to? If you added the
statement to draw the irregular shape to the end of your sketch, Processing would
have drawn the speech bubble over your text. Your text is still there just
underneath the speech bubble, obviously this is not the desired effect. So we are
going to reorder things in our sketch, with some simple cut and paste commands.
Cut the three statements that relate to rendering text to the Display Window
textAlign(), textSize() and text() to the end of the sketch so that they are run after
the speech bubble is drawn. If you were to run the sketch at this point your text
will still appear to be missing, but in fact is still there it's just that because it's
been drawn after the speech bubble it's also been effected by the fill() function
issued to change the speech bubble's fill to white. White text on a white
background isn't very legible so we'll change the text to another color, I'm going
to make my text the same color as the speech bubble outline by adding the
following statement before the text is drawn and after the speech bubble is
rendered:

fill(50,127,255);

Finishing the sketch

To add the final touches to the Hello World 1.2 Program we're going to get
Processing to display an image for the sketches background instead of the black
background. This exercise will also be our first introduction to the programming
paradigm known as Object Oriented Programming and the concept of data
typing.
The first thing we need to do is set our sketch up to accept external data in the
form of an image. With the PDE still open, via your computer's operating system
open a file browser and locate the file named smileBkg.png. From your file
browser click and drag the image file into the sketch you are currently working on
in the PDE.
When you have dropped the file to the sketch Processing, will confirm this in the
debugging area by printing the phrase One file added to the sketch. If you get
this message you are ready to start using the image in your sketch.

Visual Representations of Code 79


An Introduction To Programming With Processing

Adding an Image to a Sketch in Processing is easy, just click and drag it into the PDE.

The simplest way to use external data, such as an image, in your Processing
sketch is to ensure that the data exists in a folder called data, which must be a
subdirectory of the location where your sketch is saved. For example, we set up
Processing to store all sketches in folder called Sketchbook, stored within this
folder will be the sketches we create with the PDE. I've called my Hello World
1.2 Program smile so within the Sketchbook folder is another folder called
smile and within the smile folder is the file smile.pde (which is my Hello World
sketch) and another folder called data. When we dropped the image into the
PDE Processing automatically created the data folder, and placed a copy of the
smileBkg.png file in it. If you would like to view the contents of this folder you
can access it from the PDE by clicking:

Sketch Show Sketch Folder

Or simply navigating to the folder with your operating system's file browser.
When transporting your Processing sketches from one computer to another you
must always retain this directory structure of having your data folder as a
subdirectory of the location where your processing sketch resides, which should
always have the extension .pde.

Visual Representations of Code 80


An Introduction To Programming With Processing

Programming Paradigms
A programming paradigm is a fundamental style of programming, the term is
often confused with programming methodology which is a style of addressing a
problem within a program. But perhaps a better way to understand what a
programming paradigm is, would be to look at some examples of it.
Many modern day software languages offer at least two fundamental
programming paradigms, most commonly amongst these two choices are the
Objected Oriented Programming Model and the Procedural Programming Model
(Procedural programming is also sometimes referred to as imperative
programming). Like the name implies imperative programming is a programing
paradigm that is used to determine a set of commands and/or steps a computer
program must take in order to reach a desired state. It's worth knowing that the
Object oriented programming model is often contrasted to the procedural
programming model because of the fundamental differences (which we are about
to discuss) that separate these programming paradigms.
Procedural Programming can be summarized as a style of programming where the
program is tailored to suite the data as opposed to Object Oriented Programming
which is more akin to a style of programming where the data is tailored to suite
the program. So what exactly does that mean?
As mentioned earlier, programs are made up of statements and one of the things
statements are made up of, is commands. As you might recall a command in
programming, much like in a natural language, is used to communicate a
directive. In this way procedural programming is a list of statements telling a
computer what to do. At this point you could be thinking Isn't that the purpose of
all programming i.e. telling a computer what to do, so how then does procedural
programming differ from any other programming paradigms?
In one way or another we use programming to represent data, whatever that data
may be the amount of tea compared to the amount of coffee consumed over the
past ten years world wide, determining the choices a character has in a game then
choosing to act on those choices or something as simple as representing a set of
alpha numeric characters on a screen that spells your name. Whatever way you
look at it creating a program requires data. In procedural programming we use the
tools provided to us by the language we are programming in to break down that
data into smaller data types that the language predetermines for us and then use
those representations to create a program that ultimately represents the larger
original data set programmatically. This can be contrasted to object oriented
programming where we use the tools provided to us by the language we are

Visual Representations of Code 81


An Introduction To Programming With Processing

programming in to create our own data types for which we determine their
meanings and use these new data types to create a program that ultimately
represents our original data set.
Either way you look at it the results of both procedural and object oriented
programming can produce software that is modular in design, meaning that
components of the data that can be represented with either one of these paradigms
can be dynamic or changing, or even completely non-existent. Designing software
that does not have to be rewritten each time the data that it represents changes or
is removed from the main program entirely, is a challenge regardless of which
programming paradigm you might use and it is this key feature of software design
that determines how modular the main program is.
Object Oriented Programming since it's earliest inceptions in the late 1950's
programming language LISP has consistently seen various implementations on
the concept of modularity amongst other features such as encapsulation (which
we will discuss in more detail later), contributing to it's modern day popularity. As
software development needs have become more demanding and larger data
structures are required for abstractions, Object Oriented Programming due to it's
inherent ability to represent complex data structures, modularly has grown in
popularity to meet the needs of software developers creating these sophisticated
programs. That is however not to say that procedural programming lacks
sophistication. To summarize programming paradigms in a utilitarian sense,
people tend to address problems in different ways, programming paradigms
accommodate for these shifts in thought and conceptualization.

Datatyping Categories
Organizing the data that we represent in a program can be a difficult task unless
you have some sort of system that can be applied at a higher level to abstract the
complex interactions that a machine must facilitate in order to make the data we
interact with more accessible to us. Datatypes make the process of organizing the
various forms of data that exist in our programs more accessible and categorically
meaningful to us. What qualifies as a data type varies from one programming
language to another and also forms the basis of what differentiates the two main
programming paradigms we have been discussing, Procedural Programming and
Object Oriented Programming.
In Processing there are three main categories of data types that we will be dealing
with Primitive datatypes, Processing's API datatypes and User Defined Complex
datatypes.

Visual Representations of Code 82


An Introduction To Programming With Processing

Primitive Datatypes
Primitive datatypes form the building blocks of all the different types of data
accessible within Processing. As a result these datatypes are immutable, meaning
that we cannot modify their definitions by use of Processing.

int

Numbers can be represented as Primitive datatypes and most commonly fall into
the primitive datatype categories of int or float. An int data type is an abbreviation
of the word integer and is used to create categories of numbers within a program
that represent whole values such as 0, 1, -58, 6000000 and so on. In Processing an
int can range in value anywhere between 2,147,483,647 to -2,147,483,648.

float

A float (or floating point number) is a data type used to categorize numbers that
have a decimal point. Numbers such as 1.5, 3.0, -56.91 and even numbers such as
3.40282347E+38 in SI (the International System of Units) notation qualify to be a
float primitive datatype.

char

Typographic characters such as A, b, 5, @ etc can also be stored as primitive data


types by use of the char datatype which is an abbreviation for the term character.
However, storing a sequence of typographic characters as a single unit requires a
different datatype that is more complex than a primitive.

Processing's API Datatypes


In order to make languages fit more specifically to an environment certain
repetitive tasks are often automated by the developers of the language's API. The
acronym API stands for Application Programming Interface and it refers to the
means by which you communicate with a program. Although you are creating
programs (known as sketches) with Processing, Processing in itself is also a
software program. We have been communicating with Processing through the
PDE, and within the PDE we have been typing statements instructing Processing
what we would like it to do with the data we have supplied it with. Those
instructions such as functions, tokens, arithmetic operators etc that we are using to
communicate with Processing are all defined within Processing's API.

Visual Representations of Code 83


An Introduction To Programming With Processing

Processing's API Datatypes are special datatypes defined within the Processing
API that may or may not be found in other languages, but will make fulfilling the
requirements of creating sketches (including data visualizations, end-user
interactions and many other features commonly found in sketches) easier and less
repetitive for the programmer by abstracting base-level computational
interactions.
The PImage datatype is an example of a Processing specific API Datatype that
makes the task of using images within a sketch much simpler for the programmer.
The String data type is a Processing non-specific API Datatype, meaning that
although this datatype is common to many different programming languages it is
not a primitive datatype as it uses characteristics of both int and char datatypes,
this makes it more complex than a primitive datatype. Processing's API Datatypes
are usually quite easy to identify as the keyword used to invoke them usually
starts with an upper-case character, this is a common standardized programming
practice that is used to identify Classes which are the fundamental building blocks
of Object Oriented Programming and are an inherent quality of Processing's API
design.

User Defined Complex Datatypes


In procedural based programming the programmer is supplied with a
predetermined set of datatypes that can be used to communicate with other
features of the programming language's API. As a result no matter what data the
programmer is representing, that data must be tailored to suit those datatypes.
This differs from an Object Oriented approach to programming, in that the
programmer tailors the program to suit the data being represented. In other words
with Object Oriented Programming the programmer creates custom definitions
known as Classes by combining various primitive datatypes and predetermined
complex datatypes of the programming language's API, with functions and
directives to give the Class definition and meaning. These custom definitions (or
Classes) are the basis from which datatypes that fall into the category of being
User Defined Complex Datatypes originate. They are complex simply because
they are often made up of more than one type of data. The most common of these
datatypes is the Software Object or simply an Object, which is a copy or instance
of a class. These datatypes can be used throughout a program in a manner that is
akin to any other datatype. In other words to use a class in a program we must
first create an instance of it, this instance is what we refer to as an object how the
term Object Oriented Programming evolved.

Visual Representations of Code 84


An Introduction To Programming With Processing

PImage
The PImage Class defines useful information about the image we are loading into
our sketch and allows us access to this information without having to understand
how it has extracted this information from the image, such as it's width, height or
how many pixels make up the image and what color each pixel is. This is one of
the benefits of Object Oriented Programming, being able to abstract complex
code by referencing it with a single keyword, the name of the object.
We are going to create a new software object from the PImage class, and we will
give this new object a name. It is important that the name that we assign to the
new object is unique so that when ever we want to use that object we can refer to
it by it's name and Processing will know exactly which object we are referring to.
Amongst the prerequisites of using an image file as a background in Processing is
that the image must be in either gif, jpg, png or tga format and must have the
same dimensions as the sketch in which it will be displayed. If you have had a
look at the smileBkg.png file you might have noticed that the dimensions do not
match that of our current sketch. However, we are in luck because we have been
using an implicit style of programming to specify the X and Y parameters within
our sketch so changing the dimensions of our sketch at this late stage in the
programming process is actually not going to be problematic. If, on the other
hand, we had used an explicit style of programming we would have a problem as
all of our had work to keep the graphical components of our sketch in the center
of the display window and aligned with each other would now be lost and fixing it
would mean having to go through every statement where X and Y coordinates
where used and changing them to accommodate for the new sketch size.
Since we are loading our image as a background we are going to add the
following statements before the background statement near the top of the sketch.
To create or as it is referred to in OOP-speak, instantiate a new object from the
PImage class add the following statement before the background statement:

PImage img;

This statement tells Processing that we want to create a new software object
which has all the properties of the PImage datatype and we would like to call this
new object img. Our new software object has inherited the properties of the
PImage class which allows us to access information about the image we would
like to associate with the object named img (which we have instantiated from the
PImage class), without having to know how it goes about accessing this

Visual Representations of Code 85


An Introduction To Programming With Processing

information. However, what our new object does not know yet is what image we
would like to use in our sketch and refer to as img, in other words what image do
we want to associate with the img object? Add the following statement after the
previous PImage statement in order to associate the image smileBkg.png with the
img object:

img = loadImage("smileBkg.png");

This statement tells Processing the name and location of the image file we would
like to use and refer to as img throughout the rest of our sketch. Because the
image file has already been dropped into our sketch Processing has placed a copy
of the file in our data folder. Processing will expect to find whatever image files
we are using in our sketch in this folder. The loadImage() function can also accept
a URL as a parameter if you wanted to load an image that is not located locally on
the same station that your sketch is running from.
Now that we have the image loaded into our sketch we need to tell Processing
what we would like to do with and, where we want to place it and finally to draw
the image to the Display Window.
To display the image in our sketch we're going to modify the background
statement and Processing will now render the image to the Display Window when
we run the sketch. Modify the background statement to read:

background(img);

This statement simply tells Processing that we would like to use the object named
img as a background. Later we will have a look at compositing images on top of
each other in addition to using them as backgrounds.

To briefly recap on the steps we took to load an image into our sketch
1. Drop the image into the PDE
2. Instantiate a new software object from the PImage Class
3. Load the image file into the new software object
4. Instruct Processing to display the image through it's identifier (name).

Visual Representations of Code 86


An Introduction To Programming With Processing

The completed Hello World 1.2 Program

The Design and Layout Program

Using what we've learned thus far from this guide, you should be able to construct
a program that sketches a prototype for an interface to an online portfolio
similar to the interface01.pde sketch.

Program Notes for Interface01.pde

The PDE Tools menu


Under the Tools menu in the PDE are additional build automation tools and other
tools that members of the community have contributed to Processing. More tools
can be downloaded to add to the functionality of Processing by downloading and
installing the necessary files from http://www.processing.org/reference/tools/
A useful tool that comes with the PDE is the Create Font tool. This tool allows
you to package any font you'd like to use in your sketch so that users accessing
your sketch do not have to have that font installed on their computers in order for
the sketch to display correctly. To use the Create Font tool in the PDE click:

Tools Create Font..

The Design and Layout Program 87


An Introduction To Programming With Processing

The Create Font tool can be used to ensure that font's you have used in your sketch will
display correctly on other users' systems regardless of whether they have the same fonts
installed on their systems or not.

The Create font dialogue box appears in which you can scroll down to and select
the font you would like to package with your sketch. Choose a size you would
like to have the font displayed at by specifying a numerical value in the size field
(values are in pixels). The size value determines the size of the characters of the
font that will be exported as bitmaps, and although you can change what size you
would like to display a font as in your sketch even after it's been exported it is
recommended that you use the font in your sketch at the same size that you
exported it as for best results. Up-scaling a font is not recommended and as a
result if you do plan on using the font in different sizes it is best to use the Create
Font tool to export the font at the largest size and use Processing font() function to
down-scale the font only when necassary.
When you are happy with your selection click ok and Processing will create a
file with the extension .vlw in your sketch's data folder, it is important that you
know the exact name of this file as you will need to load it just like you loaded an
image into Processing by using the PFont class and instantiating an object from it.
To use the font in your sketch, you will need to follow a procedure very similar to
that of loading and displaying images. Start by creating a new object that will
serve as the container for your font, by adding the following statement:

PFont myFont;

The Design and Layout Program 88


An Introduction To Programming With Processing

PFont is a special data type in Processing used for storing fonts, in a similar way
that PImage works with images. myfont is the name we have chosen to create an
object that inherits the qualities of the PFont class. Next you will need to load the
font into your sketch, to do so add the following statement:

myFont = loadFont("FancyFont-Bold-42.vlw");

The loadFont() function accepts one parameter that is the name of the font,
including it's extension, enclosed within double quotes. We will then need to
specify what font we would like to use to display text in our sketch, because you
are permitted to use more than one type of font in a sketch the next statement tells
Processing which font it is you would like to render the text that follows this
statement:

textFont(myFont,42);

The textFont() function accepts two parameters, the name of the PFont object you
have created (which is myFont in this case) and the size at which you would like
the text that follows to be rendered at. All the calls to the text() function (which is
used to render text within a sketch) that follow this statement will use the
parameters set in textFont() for rendering text, until textFont() is called again with
a different set of parameters. Finally you can draw the text to the Display Window
with the text() function:

text("Welcome to my\nProcessing Portfolio", width/2, height/2);

You might notice something strange about the literal string parameter for the
text() function. Between the words my and Processing are the characters \n.
This is known as an escape character and escape characters are not rendered
within a sketch. Escape characters are used to format text before they are drawn to
the screen. In my Interface01 sketch there is a break between Welcome to my
and Processing Portfolio, this is because the \n is known as a new line escape
character and has the function of inserting a break between characters. This
prevents having to use the text() function twice, first to render the text Welcome
to my then adjust the Y parameter in the next call to text() to render the rest of
the sentence. Using a short-cut like this can save your program some overhead,
but also comes with the expense of making your code look a little less readable,
particularly if you have never seen an escape character before.

The Design and Layout Program 89


An Introduction To Programming With Processing

Another place where a short-cut has been used in the Interface01 program is in
the statement where multiple instances of the PImage class have been created as
holders for images that will be used throughout the rest of the sketch. The
following statement demonstrates this:

PImage mGoat, banner, bkg, button;

The long version of this code would look like this:

PImage mGoat;
PImage banner;
PImage bkg;
PImage button;

As you can see using a shortcut in this way can save you quite a bit of typing and
can actually make your code even easier to read.

The Completed Design and Layout Program

The Design and Layout Program 90


An Introduction To Programming With Processing

Beyond Static Sketches and on to Active


mode
Static sketches are mainly used for testing basic programs that do not incorporate
interactivity or are used to output and image file or sequence such as a .png or
.pdf. The majority of programs produced with Processing are made using active
mode. Active mode requires two fundamental additions to a sketch, the setup()
and draw() functions.
setup() and draw() provide a new structure to sketches and allow for the
initialization of a code block within setup() and the repetition of the code block
within the draw() structure. Code blocks within the setup() and draw() functions
are always cradled between braces, so they are easy to identify. The structure of
an active mode sketch generally follows the pattern identified in the example
below:

void setup(){
code...// This code block will run only once,
// at the start of the sketch.

}
void draw(){
code...// This code block with run repeatedly,
// throughout the duration of the sketch.

}

A typical active mode sketch structure with the setup() and draw() code blocks
highlighted

Beyond Static Sketches and on to Active mode 91


An Introduction To Programming With Processing

Up until now our sketches have not been interactive or included animation. The
use of the active mode structure, by means of the setup() and draw() functions,
allows us to truly access the powerful features that programming offers to
developers and extend our sketches with interactivity, animation, logic and a host
of other features that we will explore.
First, we'll start by having a look at how setup() and draw() change our sketches
by making them more dynamic.

Methods, functions and their contexts


Before we start using the setup() and draw() functions let's first examine the
context in which they exist within Processing. setup() and draw() are also
sometimes, albeit less accurately, referred to as methods. A method is simply
another way of saying function, but more specifically it refers to the function of a
class. As you might remember, classes form the building blocks of object oriented
programming and can be packaged into groups consisting of many classes which
we refer to as Libraries. From Libraries we can access classes, from which we
can instantiate objects that we use in our programs. But before using a particular
library we would first need to tell Processing to import that library for usage
within our sketch, by using the import keyword. This differs from using a class
built into Processing's API where we do not need to use the import keyword, for
example we could instantiate an object from the PImage class and call it img like
in our Hello World program, without using the import keyword, like in the
following code fragment:

PImage img;

One of the methods, that works, in a sense, just like a typical function would of
our main program, of img could be to resize the width and height of the image
that we have associated with the img object for example:

img.resize(50,100);

This statement would resize the width and height of the image associated with the
img object to 50 and 100 respectively. In this sense the resize() keyword used in
relation to the img object would be a method of the img object. Just like a
function, a method's definition can also exist independently of the main program
and in this case it does, as the resize method is defined within the PImage class

Beyond Static Sketches and on to Active mode 92


An Introduction To Programming With Processing

which as you are aware is not defined within our sketch but exits as a part of
Processing's API. So as you can see the term method is very similar to that of
function in terms of the purpose they both serve. However, it is important that the
terms are not used interchangeably as they can lead to ambiguity and confusion.
As I have mentioned before Processing is a language on it's own and not just a
library consisting of classes for Java. If it was, referring to setup() and draw() as
methods would be perfectly acceptable because they would be methods of a class
defined within the Processing library for Java. Although Processing can be used in
this context we are not using Processing as a library for Java we are using
Processing as a language that is independent of Java until implementation, this is
relevant because although Processing relies on Java currently for it's
implementation theoretically there is nothing stopping Processing from being
implemented within other environments. Within this context Processing is a
language and not exclusively a library for Java. What that means is that, setup()
and draw() within this definition cannot accurately be discribed as methods of a
class that has been instantiated but rather as functions of a programing language.
This concept can be extended even further because setup() and draw() are such
fundamentally important functions within Processing, that they could be placed in
a category of their own and described as structural defining functions, because
they alter the structure of a program so dramatically.

93
An Introduction To Programming With Processing

The setup() function


Let's have a look at how the setup() function works and how it alters the structure
of a program. Code that is cradled between the braces{} of the setup() function
forms the code block of the setup() function and determines it's structure. This
code will run only once, throughout the duration of the sketches life-cycle.
Meaning that from the time the sketch is started to the point when you close the
Display Window, exit the web page the sketch was running on, close the
application the sketch was running through or do whatever is needed to end the
sketch, the code block within the setup() function is never repeated until that
sketch is run again. So how does that make the sketch more dynamic? Well in
fact, when compared to the draw() function the setup() function does not
contribute to significantly making the sketch more dynamic, but it does contribute
to allowing the sketch to become dynamic. Having said that, let's examine what it
means in more depth.
In programming the term dynamic is often used to describe the changing effects
of a program. If we where to contrast this definition with our previous example of
the interface01 program, we would see that this program is not dynamic. From the
time that the sketch starts to the point when the sketch is terminated, the program
does not change. However if we where to add animation to the images, or make
the buttons of the interface clickable, then the program would be dynamic.
So how does the setup() function contribute to this?
One of setup()'s main forms of contribution to active mode sketches is in
something we call assignment. Assignment is actually not a new concept to us as
we have already used it several times in our previous sketches and is often
invoked in many programming languages with an equals sign = which, in
programming, is referred to as an assignment operator. For example, we have
previously used assignment in the following context, when loading an image into
a sketch in preparation for it to be rendered:

img = loadImage(myBitmap.png);

The purpose of assignment is to make whatever is on the left side of the operator,
equal the value that is on the right side of the assignment operator. In this way
assignment can be a relatively straight forward or complex procedure. For
example if we have a simple value such as a number or typographic character on
the right of the assignment operator, the assignment of that value to whatever
exists on the left is relatively straightforward because we're just simply telling

The setup() function 94


An Introduction To Programming With Processing

Processing to make whatever is on the left of the assignment operator be the same
as that which is on the right and then store those values in the computer's memory.
However if we have an expression, a command or both on the right of the
assignment operator the task of assignment can become more complex not only
for Processing but also for us to keep track of.
In the previous example we are assigning the value of the bitmap image that
exists in our data folder called myBitmap.png to the img object, by using the
loadImage() function.
But, what exactly is going on in this assignment statement, as the computer that is
running the sketch sees it?
Firstly the computer running the sketch must process the call to the function
loadImage() this requires processing power and secondly the computer having
realized what the loadImage() function requires after processing it, now accepts
the parameter myBitmap.png.
In order for it to accept this parameter it has to allocate a certain amount of it's
memory to load the image. Computers have a limited amount of memory and the
larger the bitmap image's size (in terms of kilobytes, megabytes, etc.) the more
physical memory they require to be loaded into a sketch. As a result the computer
must try to allocate memory that has not already been assigned to another value
and does not request more memory than is necessary. All of this work performed
by the computer is performed without us having to know anything about the steps
it must take to display the image in our sketch.
As you can see, although this assignment statement was relatively easy for us to
create, the steps that our computers must take in order to make what we are
requesting possible is actually not so straightforward.
The setup() function can be very useful in a situation such as this, because the
previous statement is so resource insensitive it is not the kind of statement we
would like to have repeated throughout the duration of our running program.
Doing this will simply cause a bottleneck effect on the resources of the computer
running the sketch and ultimately cause the sketch's performance to drop, as the
computer struggles to keep up with our requests.
The setup() function as a result will run only once throughout the duration of a
program, and is designed to keep system performance at optimal speeds so that
our sketches can run more efficiently with the code that does need to be repeated
such as that of the draw() function.

The setup() function 95


An Introduction To Programming With Processing

The draw() function


The draw() function differs substantially from the setup() function in that it is
designed to repeat the code block associated with it and cradled between it's
braces. The ability to repeat code and have it update itself in the process is a key
feature in creating dynamic content. For example when creating interactive
programs it is quite useful to know the position of the users mouse, so that you
can use this information to determine whether the user is hovering over a button, a
scroll bar, an image or other interactive interface feature. As the user is likely to
move the mouse around several times while the program is running, the mouse's
position will change regularly. Knowing the mouses current X and Y position and
being able to compare it with a previous X and Y position can tell us something
like which direction the user is moving their mouse in, how far the mouse has
moved and how fast the mouse is moving, this information can be used to
enhance the interactive quality of the application.

Using the setup() and draw() functions in Processing is actually quite easy, and in
the following example we'll use them for the purpose of getting the user's mouse
position in terms of X and Y coordinates and then use the println() function to
print these values to the debugging console.

Enter the following code and run it. Don't be alarmed when Processing starts to
print line after line of information to the console, this is actually the desired effect.
Move your mouse around in the Display Window to see the values update in the
console view then close the Display Window when you are done:

void setup(){
//setup the size of the sketch
size(510,300);
}
void draw(){
//print the mouse positional data
println("The Mouse's X position is " + mouseX +
" The Mouse's Y position is " + mouseY );
}

The draw() function 96


An Introduction To Programming With Processing

The Mouse's X and Y position is updated every 60th of a second and printed to
the console

Experimentation
The setup() function must always precede the draw() function, and is used to
define the initial properties of the sketch such as the size of the sketch. The size()
function when used within an active mode sketch must always follow the setup()
function before any other statements. If we had images to display in our sketch
assigning them to object variables would generally be done within the setup()
structure, we'll have a look at this technique a little later.
The draw() function repeats once every 60th of a second by default, but this
behaviour can be changed with the frameRate() function which would be called
within the setup() structure too.
Within the println() function you might have noticed something a little different,
two new commands, mouseX and mouseY are system variables in Processing that
store the X and Y position of the mouse when it is over the window the sketch is
running in. When used within a sketch they simply return a number that is either
the respective X or Y coordinate of the user's mouse. It is also worth noting that it
is necessary for the println() function to be repeated within the draw() structure
because whenever the user moves the mouse within the Display Window a new
value for the mouse's X and Y position replaces the old value for the previous
position of the user's mouse. If this command was within the setup() function
Processing would only print the mouse's X and Y values once and not again.

Experimentation 97
An Introduction To Programming With Processing

Although this is perfectly valid code it, is not very useful to us because if the user
has moved the mouse since the start of the program (when setup() ran for the first
and only time) the current position of the user's mouse would not have been
updated thereafter. The statement to update the mouse's X and Y position would
not have been repeated so according to the sketch the X and Y position of the
mouse would be the same as when the program first started, this is obviously not
the case if the user has moved the mouse.

The repetitious nature of an active mode sketch

The mouseX and mouseY system variables are important keywords in


determining the interactive nature of many sketches so lets attempt to use them in
another way that is more directly related to the visualization nature of sketches.
Add the following statement before the println() statement:

line(0,0, mouseX, mouseY);

The mouseX and mouseY system variables can be used to add interactivity to a sketch

Experimentation 98
An Introduction To Programming With Processing

After running the sketch you should be able to recreate an image within the
Display Window like the preceding image. The line() function is used to draw a
straight line in Processing and accepts four parameters in the form of the starting
point of the line's X and Y coordinates and the end point of the line in terms of X
and Y coordinates. In our sketch we made the starting point of the line the origin
of the sketch, that is (0, 0) or zero X and zero Y and we made the end point of our
line equal whatever the mouse's current X and Y values are. There are infinite
ways of using the mouseX and mouseY system variables to create interesting and
interactive qualities within a sketch, and they don't always have to relate to
positional data as in our previous statement. For example, if we wanted to use the
mouse's X value to determine the greyness of the line we could add the following
statement to effect the strokes color, which we will add before the line()
statement:

stroke(mouseX/2);

Remember that the stroke() function used in this way with only one parameter
accepts values between 0 to 255 which relates to the greyness of the following
strokes that are drawn. So because the size of our sketch is 510 pixels across our
mouse's X position will, in the context of this sketch, return a value between 0
and 510 for the mouseX system variable, as any value greater than this would
mean that the mouse is no longer positioned over the sketch. Bearing this
information in mind we can use what we know about the width of the sketch and
divide this value by 2 so that we never receive a value greater than 510/2 or 255
which is white, when input as a parameter of the stroke() function. This is a very
simple example of mapping one value to another but Processing conveniently
provides us with a more sophisticated method of mapping values by use of the
map() function which we will look at in more detail later.

By linking one value to another we can start to create some interesting effects, within our
sketch

Experimentation 99
An Introduction To Programming With Processing

Try experimenting with the mouseX and mouseY system variables until you are
comfortable with them as we will be using them quite regularly in our following
sketches. For example try combining the previous sketch with an ellipse that
attaches itself to your mouse and has an interactive transparency feature.

More interactivity can be added to this sketch example quite easily

fill(50, 60, 127, ??/2); //Here's a hint...


ellipse(??, ??, 50,50); //and another.

As you might remember, the order in which commands are issued in many
programming languages is really quite important. So when Processing reads your
code it is important that commands are issued to Processing in the correct order,
for example we would not want to have a command that updates the color of an
ellipse's fill after the ellipse has been drawn to the Display Window. We are
already aware of this from our static mode sketches, however in active mode even
if you do have a fill() command after an ellipse() command to update that ellipse's
fill your results sometimes might be more forgiving.
As active mode requires that the code within the draw() structure is repeated there
remains a history from one execution of this code to the next. What that means is,
even though the fill() command is issued after the ellipse() command when the
program repeats the next time around Processing will remembers what the value
of the fill was set to in the previous execution and updates your ellipse in the
current cycle to match that command of the previous execution. Currently this
might not seem like a big issue to you because you are ultimately getting the
results that you want, but this is at the expense of creating ambiguity within your
program. This could also lead to possible errors later in the programs
development cycle, and is therefore not a recommended methodology for several
reasons.
Firstly, it is not clear within the order of such a program why the fill() command
is being called. Whereas if the fill() is issued before ellipse() it is clear that it is

Experimentation 100
An Introduction To Programming With Processing

meant to effect the color of the fill of the next ellipse that is drawn to the Display
Window.
Secondly, if there are other values depending on your ellipse's fill being a
particular color at that point in time, and these values precede the fill() command
these values will always be calculating their results based on the color of the
ellipse's previous fill color and not the current color for that particular cycle. This
color only becomes evident the next time the program repeats, and by then the
visual representation of the fill will no longer match the values that are used in
calculations preceding it. This could lead to inaccurate calculations such as
division by zero which could cause your program to halt or even worse to crash.
Needles to say that although you can get the results you are hoping to achieve by
structuring your program in a manner that contradicts appropriate ordering, you
might in effect be causing yourself more problems in the long run than necessary.

Always consider how the ordering of your commands and structure of your
program can be improved.

Ordering statements appropriately can contribute significantly to the readability of your


code.

Experimentation 101
An Introduction To Programming With Processing

Datatyping
You might have noticed something else that's new about the active mode structure
of a sketch, that being the usage of the void keyword preceding both the setup()
and draw() functions. The keyword void is used for defining functions that do not
return a value, all other user defined functions must return a value of a certain
type of data. The setup() and draw() functions differ significantly from their roots
in the C/C++ main() function in that they are not intended to return a value of any
type of data to the main program, the mandatory usage of the void keyword
ensures this. We'll have a look at user defined functions in more detail later.
The process of assigning a type to data is known as datatyping. There are many
different types of data within Processing we have already had a look at some of
the categories that the different types of data within Processing can be broken
down into, but what exactly are these different types of data and how do they
assist us in programming?
One of the datatypes we're already familiar with is the PImage datatype. We know
that if we want to use a bitmap image in our sketch we must first assign it to the
object we instantiated from PImage. That new object that we have then created
has inherited all of the properties of the PImage datatype amongst which is the
ability to resize the image, get information about the pixels that make up the
image and what the alpha and color values of each pixel making up the image is.
We did not have to tell Processing what a pixel is or how we would like to use it,
these definitions already exist predetermined within the PImage class and other
Processing API features, and will resemble a body of code that exists somewhere
on your computer (probably in the location you installed the PDE). Now that we
have a new object instantiated from the PImage class it has inherited all of the
properties that define that particular type of data, in other words the new object
we have created has been datatyped as PImage.
But in order to understand what is really going on here we need to look a little
deeper...

Variables
Variables are common to most programming languages as they provide us with a
means of storing data within the memory of a computer without having to know
the process the computer has taken to store that data and where exactly within the
computers memory that data has been stored. This provides us with a convenient
method for accessing data, without having to understand the complexities of

Datatyping 102
An Introduction To Programming With Processing

manual memory management as might be the case in lower level languages. Lets
have a look at how variables play a part in helping us store data.
Using variables is pretty straight forward and can be thought of as a two step
process, 1.) Declaration and 2.) Assignment.
The second step we are already familiar with, which could imply that you might
have already used variables in your previous sketches, and this is in fact correct.
You have used both steps of variable creation in your previous programs as
variable assignment relies on declaration.
Declaration is the process of giving the data you are representing in your program
a name, and is a process that involves datatyping (preformed by the programmer)
and memory allocation (performed automatically in most higher level languages).
So lets have a look at a declaration in the following statement:

PImage img;

This is known as a form of variable declaration, you might at this point be


thinking I thought this is supposed to be object instantiation (as it has previously
been referred to)? You'd be right on both counts in this particular case because
there are in fact two different things going on here. Firstly the PImage class
defines all objects that are instantiated from it, by whatever code that makes up
it's class body, and because PImage is specific to Processing's API and not
something that exists readily within other programming languages referring to the
preceding statement as object instantiation reveals the underlying structure of
what is going on in Processing when compared with other programing languages.
However, since PImage is a class defined within Processing's API and can be used
for datatyping the preceding statement can also be viewed as declarative, as such
img can be referred to as an object variable. In contrast lets have a look at a
simpler declaration that does not involve a Processing specific datatype, which
can make the process of defining variables easier to grasp:

int myVar;

The keyword int in this statement is used to datatype a variable with the
properties of type integer.
Integers are primitive datatypes that must be whole numbers, such as 0, 5, -1,
2430 and so on. They cannot have a decimal value. All we are doing at this stage
is giving the variable a name, that being myVar, we have not given the variable a
value yet the value would effectively be an integer, and associating the variable

Datatyping 103
An Introduction To Programming With Processing

with a value is specifically what assignment is for.


In the above statement we have declared a variable called myVar and datatyped it
as an int. So when we want to use the variable and the data associated with it in
our program we can simply refer to it by it's name for example:

println(myVar);

However this is getting ahead of ourselves a little, as you might remember one of
the main reasons we use variables is so that we can associate data with them
through the process of assignment. In the previous example we have declared a
variable but not given it a value, so lets restructure the example to be more
meaningful:

int myVar; //Declaration


myVar = 5; //Assignment
println(myVar); //Prints 5

In the second line of the above code listing we have used assignment to associate
the numerical integer value of 5 with our variable, and in the third line we have
put the variable to work by getting println() to read it's value back to us. You
might also notice that variables are never placed between double quotes, like the
literal strings we have been using with the println() function up till now.
What makes variables so special is that we can get them to store any value that is
valid to it's datatype, change this value then re-use it in another statement with the
new value, without the help of variables a simple task like this would be very
impractical. This is particularly useful as we never have to know what address the
variable we are using has in memory, Processing takes care of that for us.
Here's an example of the changing (or variable) nature of a variable:

int x; //declaration
x = 5; //assignment x is now 5
x = x + x; //assignment expression x is now 10
println(x); //Prints 10

The value you assign to a variable can be changed when ever you instruct your
program to do so, often through use of the assignment operator. As a result in the
previous example although we started with the variable we called x having a
value of 5 assigned to it in the second statement, in the next line we added it's
current value of 5 to itself then reassigned that new value of 5 + 5 (on the right of

Datatyping 104
An Introduction To Programming With Processing

the assignment operator) back to itself (on the left of the assignment operator),
making x equal 10. Using this simple method we have represented two different
values of 5 and 10 with only one variable, x. That does not mean that x could be
either 5 or 10 it simply means that at the start of the program x was 5 and by the
end of the program x ended up being 10. By having one variable that can be used
to represent many different values we can save on memory as, at any given time,
that variable can only have one value associated with it, meaning that if a new
value is assigned to it like in our previous example that new value will replace the
old one and so on. Not only does this make our program run more efficiently but
it also makes keeping track of the representations of the different data in your
program more manageable.

Variable Scope
An important aspect of working with variables is that they can be accessed at
various places in your program so that the values associated with them can be
referenced (in their original form) or changed and then referenced. For example
you can reference a variable in one statement, run a couple of other statements
then choose to reference the original variable again even with all the code
separating the the first reference from the second, Processing will still remember
what the variable you are referring to is.
But not every variable is accessible from every place within a program. Variable
scope refers to the enclosing range within a program that a variable can be
accessed. For example variables defined within the setup() function are not
accessible to the rest of the program, which is why setup() is best suited for
assignment in terms of dynamic programming. As such there is a scope in which
variables can be defined such that they are accessible from every place within a
sketch, we call this the global variable scope.

Erroneous code is produced from a lack of considering variable scope

Datatyping 105
An Introduction To Programming With Processing

As you can see in the previous image x cannot be accessed from within draw()
because it has been initialized within the setup() function. Initialization is the
process of combining variable declaration and assignment into one statement.
Take the following declaration and assignment statements for example:

int x; //declaration
x = 20; //assignment

or the statements could be combined in one statement and written as such:

int x = 20; //initialization is both declaration and assignment

Although the latter statement might save you some time in terms of typing, it is
something you should be careful of doing when taking variable scope into
consideration, as when this method of initialization is used within setup() it is
going to create variables that are not accessible (and therefore cannot be
referenced) from outside of the setup() structure.
The proper way to address this issue would be to declare the variable outside of
both draw() and setup(). Generally it is not a good idea to declare a variable more
than once because this could cause unnecessary overhead on your program, as
such, declaring variables within the draw() structure is best avoided whenever
possible. Nonetheless, declaring variables within the draw() structure sometimes
cannot be avoided and as a result is considered to be valid code.
Each time you use a datatyping keyword for variable declaration Processing
thinks you are trying to create a new variable, and does not perceive the statement
as updating the already existing variable with the same name.
Programming like this tends to look ambiguous and difficult to read. However, as
already mentioned, there are times when declaring a variable within draw() is
unavoidable, or in some cases can even contribute to the readability of your code.
Basically, what this boils down to is that where you choose to declare your
variables is your choice, but there are also certain rules in place that if you are
aware of, can make this decision somewhat easier for you.
Lets restructure the previous example using a more readable format that takes
variable scope into consideration:

Datatyping 106
An Introduction To Programming With Processing

int x; //declare variable only once in global


//variable scope

void setup(){ //assign a starting value to the


x = 20; //variable. Note: accessible within
} //setup()structure

void draw(){ //access the variable from elsewhere in


println(x); //the program. Note: also accessible
} //within draw() structure

By declaring a variable outside of the setup() and draw() structures we have


created a global variable. A global variable can be accessed from both the setup()
and draw() structures, it is said to have a greater scope than a variable that is
defined within the setup() or draw() structures. Within setup() the variable has
been given a starting value, remember that the variable already exists before the
program reaches setup(), so setup() is not being used to create or declare the
variable only for assignment. By the time the program gets to draw the new value
associated with the variable is the value that the println() function reads each time
it repeats. It's also worth noting again that only the code block within the draw()
function is repeated.

Datatyping 107
An Introduction To Programming With Processing

Interacting with images


We're going to use what we've learned to have an image in a sketch react to our
mouse's Y position, making the image move up and down accordingly. You might
have seen this effect when viewing so called high resolution images that are
larger than the window they are begin displayed in, on an online image gallery.
Locate the image named doorsClosed.png and drag it into your sketch. We can
then start by rendering the image at the origin with the following code:
//declare global variables
PImage doors;

void setup(){
//size() always first in setup
size(800,600);
//use setup() for assignment wherever possible
doors = loadImage("doorsClosed.png");
}

void draw(){
//draw the image
image(doors,0, 0);
}

When loading images into an active mode sketch, it's important that you declare
the images object variable name outside of both setup() and draw(). This makes
the object accessible as a global variable so that it is now within the scope of both
setup() and draw(), this is important because we will need to access the new
object variable from within both structures. It is advisable to use assignment in
the setup() structure so that the image is loaded into the new object variable only
once, placing the loadImage() function, within an assignment statement, for the
new object inside the setup() structure, ensures this.
Finally once we have set the image up for rendering we can use the image()
function, as usual, to display the image in the sketch. It's worth noting that
because the image is static, it is not possible to see that the image is in fact being
redrawn to the Display Window approximately 60 times per second, when the
sketch is run and although this might sound like a lot of excessive usage of system
resources, most modern day computers should be able to handle this framerate for
one image with relative ease. However, we will take a look at how to reduce the
amount of times Processing cycles through the draw() structure per second, when

Interacting with images 108


An Introduction To Programming With Processing

we use start using the frameRate() function, a little later.


Making the image follow the mouse's Y position is actually quite easy, modify the
image statement to read:

image(doors, 0, mouseY);

Now when you run the sketch your image will start to move up and down in the
Display Window because the value that the image() function is reading for it's Y
parameter is the system variable mouseY. As you might recall mouseY stores the
mouse's current Y position. If your mouse has moved, the new Y position of your
mouse will replace the previous value that was stored in the mouseY system
variable of the previous run-cycle, and as a result the image will be drawn in a
new position.
But why does the image appear to be streaking across the Display Window?

S treaking

The streaking effect

We have told Processing to repeatedly draw the image by placing the image()
function within the draw() structure, as a result the streaking effect is actually
caused by the ghosting of the previous image having been drawn to the Display
Window and not being erased before the image is redrawn in a new position for
the current frame. To fix this effect we need to tell Processing to first clear the
Display Window before drawing the image again in the current position. We can
do this quite easily by adding the background() function before the image
statement, thereby clearing the Display Window of the the image's previous
rendering. Add the following statement before the image() statement in the draw()
structure:

background(0);

Interacting with images 109


An Introduction To Programming With Processing

Now when you run the sketch it should act in a more predictable fashion. I've
chosen black as a background color but you can choose any color. There are
however several areas that can be improved on,
firstly the way in which the image moves in relation to the mouse is not
very interesting to interact with. It would seem that the image appears to
be stuck to the mouse.
In order to fix this we will make the image lag slightly behind the mouse
and then slowly catch up to the position of the mouse by creating a new
variable that we can use to control the speed at which the image moves.
This will create the impression of the image's movement being affected by
friction.
Secondly because the image's origin is it's top left hand corner, when we
move the mouse down we tend to expose the background above the image,
so we'll also make the image react to the mouse's Y position in relation to
the center of the image and not it's top left hand corner. This reduces the
possibility of exposing the background and makes the image more of a
focal point.
Finally we will constrain how far the image can move along the Y axis so
as to completely eliminate the possibility of exposing the background.

Friction simulation
Friction is the force that resists the relative motion of something else (like an
object, a gas, a liquid, etc), and is the effect that we will be attempting to simulate
(in a simplified form) in this sketch. By moving the mouse up and down within
the Display Window the image should try to follow the mouse and slow down as
it approaches the mouse, this will create the impression of friction.
We'll start by creating three new variables. Add the following statements at the
top of the sketch, below the PImage statement:

float yPos; //declaration related to image Y position


float difY; //declaration related to difference between
//mouse and image's Y position
int frict = 30; //initialization, friction. high values make
//image move slower

Interacting with images 110


An Introduction To Programming With Processing

The float keyword is used for declaring floating point variables. Floating point
values are numbers that have a fractional part, that is to say they are numbers with
a decimal value such as 1.0, -2.9865, 10000.423, 0.0000001 and so on. Floating
point numbers will tend to require more memory for storage so if you can get
away with representing the number data as type int and not compromising the
integrity of your program you should consider doing so.
We are using the float datatype in this program because we will be using division
in one of our expressions. This is important because true division will always
return a number with a decimal value, if you were to use an int instead of a float
or double depending on the programming language you are using, you risk having
datatype conversion errors or truncated integers returned. As a result when you
use division in your expressions always consider whether representing that data
with an int is a good idea or not.
The three variables yPos, difY and frict are going to be used to represent three
different values of which only one will remain constant throughout the duration
that the program is running. The only variable that will remain constant is the frict
variable. As a result the frict variable has been initialized through a declaration
and assignment statement outside of both setup() and draw() structures. This
value will control how fast or slow we would like the image to move towards the
mouse.
Creating a variable such as this within the global variable scope, will give us
access to the variable within both setup() and draw() thereby allowing us to tweak
the value associated with the variable and have it update throughout the program.
This will save us some unnecessary work in the long run. When the sketch is
complete setting the frict value high will cause the image to appear to have more
resistance when moving towards the position of the mouse ultimately making the
image move slower, and setting this value low (but not to zero, because division
by zero is not permitted in mathematics, as is the case in programming) will cause
the image to appear to have no resistance and move almost immediately to the Y
position of the mouse.
The variable yPos will be used to store the Y position of the image and also
update the Y position of the image, and the variable difY will be used to store the
difference between the mouse's Y position and the center of the image. Both of
these variables will need to be updated regularly for each of the cycles of the
draw() function, this is because each time the user moves the mouse the position
of the image must change as a result of difY now being less or more depending on
whether the mouse is closer or further from the images center.

Interacting with images 111


An Introduction To Programming With Processing

Variable naming conventions


Before proceeding, it's worth noting a convention used for naming the variables in
this program. There are several rules (depending on what language you are
programming in) that determine what a valid variable name is. Generally, you'll
find that many popular higher level languages share these similarities regarding
valid variable declaration:

1. Variable names can only contain alphanumeric characters and underscores


(that is _, a to z, A to Z and/or 0 to 9). Spaces cannot be
used in variable names.
2. Variable names cannot start with numbers.
3. Variable names should be descriptive but not verbose, for example yPos
as opposed to Y_Position_Of_The_Image.
4. Use consistent casing. Variable names generally do not start with an
upper-case character. This convention is reserved for Classes. In the
previous example I've used a mixture of both upper-case and lower-case
characters to name my variables such as yPos which is intended to be an
abbreviation for y Position or difY which is an abbreviation for the
difference in Y positions.
Some programmers might use different conventions including underscores
because to them this might look more readable y_pos or dif_y. Either of
these conventions is perfectly valid. But you should determine which
convention you are using, and stick with it throughout your program.
Changing from one naming convention to another can often make a
program confusing and less readable.
5. Your variable names should be self-documenting, that is to say they
should be descriptive about their purpose without having to include
additional comments explaining their purpose. This point is with the
exception of intentionally, explicitly documented code, which is generally
a convention used for teaching programming.
6. Variables that are typed in all upper-case characters are often referred to as
constants. Their value is not supposed to change. This is simply a naming
convention and there is nothing stopping you from changing the value of a
constant in many higher level languages, although this is not
recommended. So beware when using this naming convention as it could
lead to confusion if not used properly.

Interacting with images 112


An Introduction To Programming With Processing

Planning and Pre-Debugging


We'll start by making an assignment within the setup() structure that sets the yPos
value to the center of the Display Window. This has not effected the position of
the image yet, because we have not linked the yPos variable to the image yet. Add
the following statement at the end of the setup() structure, before it's closed
braces:

yPos = height/2;

If we wanted to make sure that yPos is returning the value we are expecting it to
return then we could add a println() statement within the draw() structure to test it.
The statement would look like this:

println(yPos);

If the program was run at this stage it should print a value that is representative of
the center of the Display Window's height. Using this method of tracking
variables is a common technique for debugging a program and provides an easy
and convenient method of understanding how the program is changing and
updating values internally. When you are happy that the program is returning the
results you were expecting you can simply comment out the println() statement
and resist deleting the statement until the program is fully completed, tested,
documented and functional.

In order to render the image at the correct position we need to:

Determine what the Y position of the users mouse is (mouseY) and from this
value subtract the sum of the Y position of the image (yPos) and half of it's height
(doors.height/2). The latter value (yPos + doors.height/2) describes the position of
the image with relation to it's center.

Interacting with images 113


An Introduction To Programming With Processing

The image's movement will react to the mouse's relative position to the images center.

Once we have the mouseY (yPos + doors.height/2) value we will assign it to


difY, then in the following statement we'll divide difY by the frict variable. This is
important because we're then going to take that value (that is the answer of difY
divided by frict) and add it to the yPos variable, meaning that if the value of difY
was initially returned as 90 dividing it by frict would return a value of 3 (because
90/30 = 3) which is subsequently the value that we add to the image's current Y
position to cause it to move down by a value of 3 (plus moves down the Y axis
minus is moves up the Y axis). On the other hand if difY returned a value of -90,
this would mean that the users mouse is above the center of the image and the
value of -3 would be added to the images Y position causing the image to move
up by 3.

As the mouse's Y position is less than the center of the image, the image is forced to
move up.

Interacting with images 114


An Introduction To Programming With Processing

Then we're going to assign the sum of those values (yPos + difY/drag) back to the
yPos variable.
Finally we will use this value to determine the position that the image is currently
rendered at.
The results of this method is that the image will start moving fast towards the
mouse then get slower as it approaches the mouse.

Implementing a Programmatic Solution


To summarize we are dividing the difference between the mouse's Y position and
the center of the image with the frict value, then adding this value to the images
current position. We can express this programmatically with the following two
statements, which you can add to your sketch before the image statement:

difY = mouseY - (yPos + doors.height/2);


yPos += difY/drag;

In the second statement we use a technique known as augmented assignment


which is the process of condensing a statement that uses the common technique of
using a variable in an expression, then assigning the value of the expression back
to the same variable. For example the statement:

x = x + 5;

Can be expressed in augmented assignment form as:

x+=5;

Both statements evaluate to the same answer, the latter is a more commonly used
method for this type of statement, as this kind of statement is so commonly
implemented in programming. Some other examples of augmented assignment
follow:

x = x -5;
//Can be expressed in augmented assignment form as:
x-=5;

x = x * 7;
//Can be expressed in augmented assignment form as:
x*=7;

Interacting with images 115


An Introduction To Programming With Processing

/= and %= can also be used in augmented assignment. As you can see the
following statement used in our sketch is an example of augmented assignment:

yPos += difY/drag;
//Can also be expressed as:
yPos = yPos + difY/drag;

At this point if you were to run the sketch, your image still would not move in
relation to the two statements you just added to your sketch. However if you were
to add a println() statement for the yPos variable you would see the numbers
indicating that the code is working. It's always a good idea to test an
implementation before fully integrating it into your program when ever possible,
with the println() function.
In order to create a link between these two statements and the Y position of the
image we would need to place the variable yPos into the Y parameter field of the
the image() function. However, if we where to do this our image would continue
to move beyond it's boundaries and display the sketches background. Fortunately
we have a function in Processing that allows us to stop values from getting too
high or too low.

Constraining Values
The constrain() function works by clamping a value between a range that you
specify. It accepts three parameters, the first parameter is the value that you want
to constrain and in our case this would be the variable yPos. The next parameter is
the minimum value of the range you would like the value constrained between
and the final parameter is the maximum value for the range that the value yPos
will be constrained between.
Modify the image() statement to match the following code fragment, and
complete your sketch:

image(doors,0, constrain(yPos, height- doors.height, 0));

At first this statement could look a little intimidating, but in fact you already
know what's going on in most of the statement and it's only the Y parameter of the
image() function that is somewhat different.
As you are aware the image() function accepts three parameters, firstly the object
variable containing the image (i.e. doors), secondly the value of the X position
you would like the image rendered at and finally the image's Y position.

Interacting with images 116


An Introduction To Programming With Processing

This statement is in the draw() structure and as a result will be repeated


throughout the program's run-cycle, this means that every time the user moves the
mouse the difY variable will change and as a result so too will the yPos variable.
It is therefore necessary for this statement to be within the draw() structure, or
these changes will never be seen. The Y parameter of the image() function accepts
an expression in this example, the expression consisting of the constrain()
function:

constrain(yPos, height - doors.height, 0)

This expression when evaluated, returns the value of the image() function's Y
parameter. The constrain() function clamps the yPos value so that the image is
never raised above the value returned from height doors.height and never
lowered below 0, this will be the point where the image's origin matches the
Display Window's origin.

The area which the image's motion is constrained to, exists above and outside of what is
visible within the Display Window.

Of course if you think this example could be easier to read, you're probably right.
For example you could declare a global variable to which you assign the previous
expression to within the draw() structure. The additional overhead that such an
action would create in this example is minimal, for example:

Interacting with images 117


An Introduction To Programming With Processing

...
float imageY;

void setup(){
...
doors = loadImage("doorsClosed.png");
...
}

void draw(){

imageY = constrain(yPos, height- doors.height, 0);
image(doors,0, imageY);
}

However in order to demonstrate how expressions can be used as parameters in


code, this example uses the former method which does not accommodate for the
imageY variable. Nonetheless if you would like to see how this example can be
implemented you can examine the comments in the imageScroll.pde file.

Interacting with images 118


An Introduction To Programming With Processing

Branching
When we write a program we generally don't want the script to do the same thing
every time we use it. Often, what we want is a script that is versatile in it's
application. Excluding this versatility would make the interactive software we
create predictable and boring. We therefore use certain built-in structures that help
us control the way in which our programs run, allowing us to skip blocks of code
and execute other blocks of code before others in a non-linear way. This can be
done in a dynamic and changing sequence based on the users input, the logic of
the program, the time of day or whatever other characteristic we choose to model
into a program. The process of creating this dynamic ordering that determines the
programs flow of control is what is referred to as branching.
Branching is also referred to as conditional programing and is the process of
creating code that has the ability to choose a certain path based on a set of
conditions stipulated in the program but which can also be influenced by
conditions outside of the program, such as a user interaction. The conditional
statement is syntactically a single statement made up of multiple branching
statements. What determines the course of action that the program follows is a
boolean value of true or false (which we will discuss in more detail later) returned
from a comparison within the structure of a conditional statement.

The if() structure


The if() structure can also be referred to as an if statement because although, the
statement is in practice made up of multiple statements the structure of the if
statement is treated like a single statement during compilation and/or
interpretation.
if statements must always have a conditional to qualify as an if statement. An
example of the structure of an if statement follows:

conditional
if(expression1){
do statements if() statement
} structure
keyword

Branching 119
An Introduction To Programming With Processing

Multiple if statements can be used within the same program and even within the
same structural function such as draw(). They are identified by the if keyword
followed by parenthesis containing a conditional. The conditional for an if()
statement will always return a value that is true or false through the process of
evaluation which can be based on a comparison expression. We'll have a look at
the process of comparison a bit later, for now we'll focus on the boolean datatype.
Data that can either be true or false is a primitive datatype known as a boolean.
Just like all primitive data types booleans can be declared with a keyword
followed by a variable name.
The expression within the conditional of an if() statement must, through the
process of evaluation, return a boolean value of either true or false in Processing,
in order for the program to continue. In other programming languages the
conditional can also evaluate to a 1 or a 0, with 1 being representative of true and
0 being representative of false. The language's compiler/interpreter will then
convert the 0 or 1 to a boolean equivalent value through a process known as type
casting. Processing, however, requires that the conditional evaluate to a boolean
value of true or false, so that automatic type casting can be avoided. As you are
aware 1 and 0 are of type int in Processing and the Processing does not
automatically convert them to boolean values. In the event of your conditional
evaluating to an int or datatype other than a boolean you will receive a cannot
convert datatype error. Later we will have a look at how to use Processing's in-
built ability to prevent automatic type casting to our advantage. Although
automatic type casting is favored in some programming languages it is usually an
inherent legacy feature of a lower level language that a current higher level
language is based on. In Processing type casting must be done explicitly with a
type casting function.

Type casting errors

If we were to declare a boolean variable and use it in an if statement, it might look


something like this:

Branching 120
An Introduction To Programming With Processing

boolean myValue = true; //initialization

if(myValue){ //if conditional returns true


run these statements //statements within if() structure
} //are run

...then run these statements //if conditional is false entire if


//structure is skipped

In the previous code listing we have used initialization to declare a variable of


type boolean and assign the value of true to it. We then used the new variable in
an if() statement conditional (the part between parenthesis following the if
keyword). An if statement works by evaluating the expression within it's
conditional, if the conditional evaluates to true the code delimited within the if()
statements braces will be run. However if the conditional evaluates and a value of
false is returned, it will skip the code within the if() statement's braces and
proceed to the statements that follows, for example:

boolean myValue = false; //variable initialized to


//false

if(myValue){ //conditional evaluates to


don't run these statements //false
}

...run these statements //entire if() structure is


//skipped

Using this method of programming we have allowed our program to make a


decision based on certain conditions, in a real world situation the conditions the
program would evaluate would usually be dynamic for example a user interaction
or some other dynamic feature.

Relational Operators
Writing if() statements becomes really interesting when more than one expression
is used in the conditional. Up until now we have only used a single expression as
a condition.

Branching 121
An Introduction To Programming With Processing

Using a single expression within a conditional

In the previous image the highlighted area indicates a single expression for the
conditional in the form of a variable called myBooleanVar which has been
datatyped as a boolean, in this case the variable has been assigned the value of
true, therefore the conditional evaluates to true. This simplistic approach to using
if statements can be useful in some situations but, the ability to use comparison
within a conditional statement extends it's usefulness much further.

Comparison
A comparison requires at least two entities (which are most commonly numerical
values and/or expressions in Processing, but can extend into strings in some other
programming languages) and a relational operator (also known as a comparison
operator in other programming languages). Comparisons included within a
conditional, just like the previous expressions we've been working with, must also
evaluate to a value of either true or false. Comparisons simply instruct the
program to evaluate the two expressions on either side of the relational operator
and compare the results of the two expressions with each other and from this
comparison return a boolean of either true or false. Relational operators include:
< less than
> greater than
== equality
<= is less than or equal to
>= is greater than or equal to
!= inequality

Let's have a look at how we can use the a relational operator to compare two
values.

Branching 122
An Introduction To Programming With Processing

(5>1)

This is a conditional extracted from an if() statement, it consists of a single


comparison. The comparison returns a value of true and would be read as five
is greater than one. The next example demonstrates a comparison that returns a
value of false:

(5<1)

This comparison is read as five is less than one. This is not true and the
program will return a value of false. Comparisons are not limited to simple int's
and can be used to evaluate the relationship between complex expressions.
Following is an example of a conditional code fragment comparing two
expressions:

(mouseY > height/2)

The Y position of the mouse is compared with the system variable, height when it
is divided by two, which as you know is the middle of the Display Window's
height. A conditional such as this can be more useful in terms of creating dynamic
content because when placed within the draw() structure the value that is returned
each time the code is repeated may or may not be the same as the previous return
value, depending on whether the user's mouse is in the bottom half of the Display
Window or not.
Lets have a look at how we can use this code fragment in a sketch. Try running
the following code. Start by hovering your mouse over the top of the Display
window then moving it to the bottom of the Display Window and watch what the
console prints.

void setup() {
size(300,300);
}

void draw() {
if( mouseY >= height/2){
println("Mouse is in the bottom half of the sketch");
println(mouseY);
}
println("Mouse could be in either half");
}

Branching 123
An Introduction To Programming With Processing

The program starts, as always, by running the code within the setup() structure
then moves onto draw(). Within draw() it runs the if() statement which instructs
the program to check whether the mouse's Y position is greater than or equal to
the height of the Display Window divided by 2. For example in our sketch the Y
parameter of the size function within setup() is 300 so if the user has placed the
mouse at a Y position that is anywhere between 150 and 300 then the conditional
will return a value of true as these values are all greater than or equal to 150 (i.e.
height/2). It's also worth noting that the relational operator that has been used in
this comparison is the >= (greater than or equal to) operator, which means that the
value that is returned on the right side of the operator is included within the range
of values (as the minimum value in this range) that will cause the conditional to
evaluate to true. What this means is that if you want a value of false returned the
mouse must be within the range of 0 to 149.
If the conditional returns a value of true meaning that the mouseY system variable
has a current value of 150 or anything between 150 to 300, the program then runs
the code delimited within the if() structure, which in this case tells Processing to
print "Mouse is in the bottom half of the sketch" and then print the value of the
mouseY system variable. The program then moves on to the rest of the code
within the draw() structure. This tells the program to print "Mouse could be in
either half", as this statement exists outside of the if() structure, it will be
evaluated regardless of whether the if()'s conditional is returned as true or false.

if() structures can increase the amount of options that can be programmed into a sketch.

Branching 124
An Introduction To Programming With Processing

The program then loops back to the beginning of the draw() function and goes
through the code within the draw() structure again as it has reached the end of the
draw() structure at this point. If the users mouse is not within the bottom half of
the Display Window this time the comparison conditional will return a value of
false, the program will then skip the code delimited within the if() structure that
tells it to print "Mouse is in the bottom half of the sketch" and move onto the rest
of the code within the draw() structure that once again tells it to print "Mouse
could be in either half".

As you can see branching provides us with a very easy way of changing the
behavior of our program by including variables within a comparison that in
themselves are dynamic.

Extending the if() structure with else


In our previous example, we where able to run statements based on whether the
mouse was in the bottom half of the Display Window. However, If we change the
conditional by substituting a less than or equal to relational operator instead of a
greater than or equal to relational operator (as in the original example):

(mouseY <= height/2)

We could get Processing to run a set of statements based on whether the mouse is
in the upper half of the Display Window. But what if we wanted Processing to run
a specific set of statements when the mouse is in the upper half of the Display
Window and a different set of statements when the mouse is in the bottom half of
the Display Window?
Using an if statement by itself to fulfill this purpose would not be possible, but
fortunately we can extend the if() statement into an if() structure with the else
keyword.
Use of the else keyword within an if() structure ensures that even if the
conditional returns a value of false that the code that follows else (which is still
within the if() structure) will be run, before the program exits the if() structure and
moves on to the rest of the statements making up the program. This can
effectively provide us with a fail safe method of ensuring that code is run within
an if() structure before the program exits the structure. For example if we wanted
our sketch to tell us whether the mouse is specifically in the upper or lower half of
the Display Window we would modify the previous sketch to look like this:

Branching 125
An Introduction To Programming With Processing

void setup() {
size(300,300);
}

void draw() {
if( mouseY >= height/2){
println("Mouse is in the bottom half of the sketch");
println(mouseY);
}else{
println("Mouse is in the upper half of the sketch");
println(mouseY);
}
println("Mouse could be in either half");
}

Notice that as soon as you start the sketch and if your mouse is not hovering over
the Display Window, Processing will read the mouseX and mouseY system
variables as being 0 and 0. As a result the first branch of the if() structure is
skipped because the conditional evaluates to false (0 is less than 150) and the
second branch is immediately run, that being the else code block. Once you start
moving your mouse around in the Display Window you will see the println()
statements execute depending on which half of the Display Window the mouse is
in.

Extending the if() construct with if else if else


There are many times when you will require more than the two branches that an if
else structure will permit, and in that case you can use the process of nesting
multiple if else structures within others to form an if() construct. For example, in
our previous sketch when our program started and our mouse was not hovering
over the Display Window, Processing rightfully skipped the first if() code block or
more generically and appropriately named control structure and went to the else
structure. However we could capture this unique possibility of the mouse having
an X and Y value both equating to 0 in a condition and associate it with it's own
control structure. An if else if else construct enables us to capture as many
possibilities as we can conceive and associate them with their own unique control
structures. An example of the pattern that an if else if else construct follows, is
listed on the next page:

Branching 126
An Introduction To Programming With Processing

if(condition){
...statements
}else
if(condition){
..statements
}else{
...statements
}

As you can see nesting if else constructs within each other is pretty easy, but
when typed in the previous format they can be a bit difficult to read. As a result
they are generally written in the following format, remember that because
Processing is a free form programming language you are free to format the
statements as you wish, however certain formats might be easier to read than
others, for example the traditional format for an if else if else construct follows:

if (condition){
...statements
}else if(condition){
...statements
}else{
...statements
}

There are no limits to how many if else structures you can nest within an if else
construct, but bear in mind that nesting too many if else structures within others
can make it difficult to follow and keep track of what is going on in your code.
Processing and many other higher level languages have structures such as
switch() that might serve your purposes better, if you want your program to be
able to branch between a possibility of three or more control structures.

Logical Operators
Logical operators allow us to to extend our conditionals by creating a means of
comparing one relational expression with another. They come in the format of:

&& logical AND


|| logical OR
! logical NOT

Branching 127
An Introduction To Programming With Processing

These operators can be used within a conditional to return a value of true or false
based on the context in which they are used, for example logical AND will return
a value of true only when both expressions on either side of it evaluates to true
and can be used as in the following examples:

(5>3 && 3>1) //Returned as True, because both


//expressions are true

(5>3 && 3<1) //Returned as False, because the


//expression in the right is false

logical OR returns a value of true if at least one of the expressions on either side
of it is true, for example:

(5>3 || 3>1) //Returned as True, because both


//expressions are true

(5>3 || 3<1) //Returned as True, because the


//expression on the left is true

(5<3 || 3<1) //Returned as False, because both


//expressions are false

logical NOT (also traditionally referred to as bang) works in a somewhat


different manner to that of it's counterparts. It will return a value that is the
opposite of the expression it is evaluating. For example if an expression such as
x>1 evaluates to true, then !(x>1) will evaluate to false. However, be cautious of
how you choose to use this operator as you can often express the meaning of your
code in another format that might be easier to read, for example:

if (!(x>1))
...
//can also be expressed as,
if (x<=1)
...

However the logical NOT operator can be useful, for toggling the boolean value
of an expression when that expression is required in several places in a certain
state and only once in the opposite state. For example:

Branching 128
An Introduction To Programming With Processing

boolean x = true;
ellipseMode(CORNER);
if (x) {
rect(25, 25, 50, 50);
}else{
ellipse(25, 25, 50, 50);
}
if (!x) {
rect(25, 25, 50, 50);
}else{
ellipse(25, 25, 50, 50);
}
println(x); //x still has the value of true associated with it

Now that we have an understanding of the context in which branching exists, the
following example of slider.pde will demonstrate a usage for it amongst other
programming features within a typical sketch.

Branching 129
An Introduction To Programming With Processing

Interface Controls: Setting up a Slider


In the following sketch use what we have learned to create a slider that can return
a numerical value, which we will map to the tinting of an image.
The best place to start with a program is always doing what your are already most
familiar with so lets start by loading all the images into the sketch:

PImage img;
PImage sliderBk;
PImage sliderFd;
int margin = 50;

void setup(){
size(800,600);
img = loadImage("tunnel.png");
sliderBk = loadImage("sliderBk.png");
sliderFd = loadImage("sliderFd.png");
}
void draw(){
background(0);
image(img,0,0);
image(sliderBk, width/2 sliderBk.width/2, margin);
image(sliderFd, width/2 sliderBk.width/2, margin);
}

Starting a sketch in this way is enables us to see a template of the sketch, and
provides us with foundation on which to build. After adding the previous code
you should have a sketch that looks something like the following image.

The template from which the sketch will evolve.

Interface Controls: Setting up a Slider 130


An Introduction To Programming With Processing

User Defined Functions


Now that we have a template we can start modifying it, to include interactivity.
One of the fundamental components of this sketch is the slider, as the whole idea
of changing the color of an image is going to be based on the user's interaction
with the slider. As a result we're going to start by setting up the button of the
slider, first. The button we will be setting up in this sketch is going to be
determined by a range. This range will encompass the clickable area of the button,
and because our button is part of a slider the range should automatically be able to
adjust itself to accommodate for the button moving around the area that it can be
dragged within, by the user.

S lider Button

Area in which slider button can be dragged


As detecting the location of the button is a fundamental requirement for this
sketch and is something that needs to work throughout the duration that the sketch
is running, we are going to create a user defined function that will take care of this
requirement for us.
Up until now we have been using Processing's built-in functions, which can
suffice for many different situations but you will occasionally come across a
situation in programming when the language you are coding in does not provide
the functionality you need built directly into it's API. This is not a reflection on
the language's inability to perform in a certain situation, but rather an intentional
quality built into a programming language's design where paradoxically it's
limitations, in terms of built-in functionality, can actually extend the languages
capabilities. What this means in terms of Processing is we have a set of functions
already provided for us, these functions already have definitions associated with
them, by creating user defined functions we take these predetermined functions
and combine them into new forms of useful, reusable and compact code. This not
only allows us to extend the languages capabilities into fields that perhaps even
the developers of the language never imagined but also to create our own
definitions which suite the specific needs of our own applications in a more
practical sense.

User Defined Functions 131


An Introduction To Programming With Processing

Perhaps at this point you are wondering why all programming languages do not
share the same set of functions? Many useful, popular programming languages do
in fact share many of the same functions we find in Processing, but might be
referred to as directives, commands or subroutines amongst other terms
depending on which language you are programming in.
Besides the functions that are common amongst many different programming
languages each programming language will have certain features (perhaps in the
form of functions or some other built in API feature) that will tailor that language
to the environment it is best suited, as defined by it's developers and possibly
extended in definition by a community, as is the case with Processing. This
feature-set that contributes significantly to defining the language's functionality, is
intentionally maintained within the languages definition or philosophy as this
makes the feature-set easier to contextualize and thereby easier to learn for the
programmer using the language, creates an abstraction of commonly used
resources within an environment and can significantly improve the language's
performance when a user's program is implemented within the context of that
philosophy, definition or environment. For example, if you wanted to write your
own class for loading and displaying images within a Processing sketch, there is
nothing stopping you from doing that, however the PImage class is maintained as
a part of Processing's feature-set specifically for those reasons (i.e. loading and
displaying images) and as a result is optimized to run as efficiently as possible for
the loading and displaying of images. Subsequently the possibility of you gaining
any form of performance increase from creating your own class using
Processing's built-in functions to serve the same purpose as the PImage class is,
unlikely. As a result it's worth considering whether writing your own class or user
defined function is applicable or not before setting out to do so.
In our case we are creating a user defined function because it will make our code
easier to read and not reduce the performance of the application, as our function
will contribute to making our program running more efficiently than having the
function definition within the draw() structure causing the computer running the
sketch to process the function definition line by line every time the draw()
structure repeats. With a user defined function we can avoid this by loading the
function's definition into memory and calling the definition with a simple function
call, as we have been doing with built-in functions.

User Defined Functions 132


An Introduction To Programming With Processing

As we are using Processing's built-in functions, within the environment that they
are intended for and best suited to, we will be enhancing the quality of our sketch
with our user defined function rather than trying to work against the context that
Processing is best suited.
However, this is not to say that it is not possible to extend a programming
language beyond the definition or philosophy of it's environment, but if that is
your intention then you would more than likely consider abstracting a far greater
degree of the languages built-in features within a library consisting of multiple
classes.

The definitions for user defined functions must exist outside of both setup() and
draw() structures if they are to have a greater scope. Our function definition will
reside at the bottom of the sketch and contain three main characteristics.

1. Our function should always know whether the user's mouse is over the
slider button or not.
2. If the user's mouse is over the slider change the cursor to a hand icon
indicating that the button is clickable to the user.
3. Return a value of true or false to the main program, depending on whether
the mouse is over the slider button or not.

Although the process of creating a user defined function might seem new to you,
it is in fact not really all that different to how we have been using the setup() and
draw() function's structures. Bearing this in mind, our user defined functions are
going to follow a very similar structure to that of setup() and draw(), for example
expressed generically:

datatype functionName(){
...function definition
}

Then within the context of draw():

void draw(){
..statements defining draw() structure
}

User Defined Functions 133


An Introduction To Programming With Processing

Now as a user defined function, applicable to our sketch:

boolean myFunction(){
...statements defining myFunction
}

As you can see, not a lot has changed in terms of how a user defined function is
structured in comparison to the previous example using draw(). The fundamental
difference is that statements delimited within the braces associated with draw()
define it's structure and not the function, as the definition of the draw() function
exists outside of the sketch we are creating and is something that the developers
of Processing have determined. In contrast statements delimited within a user
defined function form a function definition, within it's braces.
In order to use the function we will then need to include a call to the function
from within our main program. This is very similar to the method used to call
built-in functions such as rect(), ellipse(), println() and many other functions we
have already used.
Let's revise our previous example to demonstrate the process of defining a
function then calling it from within the draw() structure:

void setup(){
...statements
}
void draw(){
...statements
myFunction();
}
boolean myFunction(){
...statements defining myFunction
}

From this example you can see that a call to a user defined function is as simple
as a call to a built-in function. This has the added benefits of making the code
easier to read and removes the function definition from the body of the draw()
structure. Now we can reuse the function as many times as we would like within
our main program by simply evoking it via it's name, compare this to typing out
every statement within it's definition in the main program every time we wanted
to instruct the program to do what the user defined function does.
Now that we have an understanding of how the function will fit into the program,
lets have a look at creating it's definition.

User Defined Functions 134


An Introduction To Programming With Processing

Creating a user defined function

Datatyping a function
The first line of a function definition must be used to declare the function, and as
you are aware declaration in Processing means giving the function (variable or
other entity) a name and datatyping it. Some programming languages might refer
to the first line of a user defined function as a function header. Naming a function
is a very similar process to that of naming a variable as you will see in the
following code fragment forming the first line of our user defined function:

boolean overButton()

The parenthesis following the function name are used to contain declarative
parameters. These parameters will be defined within the function body, in our
case this function does not accept any parameters so we leave the parenthesis
empty. As you have been using functions that accept parameters user defined
functions can also be created to accept parameters that you define.
In comparison to setup() or draw() our function is being datatyped as a boolean,
all functions must return a datatype or use the void keyword like setup() and
draw(). As void does not return any data it is subsequently not classed as a
datatype within Processing (and traditionally in C/C++) but as a structural
element, this differs to other higher level languages (some of which are closely
tied to Processing such as Arduino) that do consider void as a datatype.
Nonetheless our function is going to return data of type boolean, which will be
used to determine whether the user's mouse is over the slider button or not.

Determining a range
In order to calculate whether the mouse is over the slider button or not we will
have to determine the range in which the slider button is located. We already
know where the slider button is in terms of X and Y because these are values
determined by parameters if the image() function used to draw the image. We can
use this information, along with the width and height object variables to work out
the slider button's range.

User Defined Functions 135


An Introduction To Programming With Processing

Determining the range of the button as the area covered in diagonal stripes.

In the previous image if A and B where variables the image() function to render
the slider button could be rewritten as:

image(sliderFd, A, B);

This method of expressing the X and Y parameters as variables is particularly


useful to us because, we would like the slider button to be able to slide along
the X axis, this means the value of A would need to be dynamic.
As the slider button only moves along the X axis the variable B will not change,
however this value is used in more than one situation, firstly to determine the Y
position of the image that will form the area along which the slider button can be
dragged referred to as sliderBk (short for slider background), secondly to
determine the Y position of the slider button referred to as sliderFd (short for
slider foreground) and thirdly referenced within the range we will set up shortly to
determine the clickable area of the button. As a result this value has been declared
as a variable of type int and named margin. This way if at a later stage we decide
to move the entire slider down in order to make room for other graphical elements
above it then all we need to do is update the value associated with margin, instead
of having to find and change an explicit value scattered throughout the source
code.
The value described as A in the previous image requires a more meaningful name,
something that is self documenting. As a result this value has been named
buttonXPos, declared as a variable in the global region and datatyped as an int:

int buttonXPos;

Eventually we'd like to replace the X parameter for the image() function rendering
sliderFd in the X position determined by buttonXPos. As we are aware what the
variable buttonXPos is going to represent we're going to set it up with a
temporary value within our sketch to test our user defined function. So we're

User Defined Functions 136


An Introduction To Programming With Processing

going to add a temporary statement for testing and debugging purposes to the
draw() function which assigns a value to buttonXPos and then changes the
image() function of which sliderFd is associated with to reflect this assignment
statement. Once the buttonXPos variable is declared in global space, you can edit
the draw() structure to include the first command and update the appropriate
image command:
...
//temp for debugging
buttonXPos = width/2 - sliderBk.width/2;
...
image(sliderFd,buttonXPos ,margin);

Once we are sure that our function is working we will return to the temporary
statement that we adding for debugging and testing purposes and include the
buttonXPos variable assignment statement within an if() structure.
We are now ready to proceed with setting up our function. To briefly recap our
function has been declared as type boolean and given the name overButton(),
setting up the range will occur within a conditional consisting of multiple
comparisons and will look like this:
boolean overButton(){
if (mouseX >= buttonXPos && mouseX <= buttonXPos +
sliderFd.width && mouseY >= margin && mouseY <= margin +
sliderFd.height)
{

Although this conditional might look a little confusing at first, when broken down
into the four distinctive elements that it is comprised of it tends too make a lot
more sense. So lets have a look at what each comparison is calculating and how
these four different expressions put together will either return a value of true or
false, which will ultimately determine whether the following code block of the if()
structure is run or not.

Comparison 1: mouseX >= buttonXPos

This checks if the mouse is anywhere in the highlighted area of the following
image. If the mouse is then a value of true is returned and Processing will
continue to evaluate the rest of the conditional.

User Defined Functions 137


An Introduction To Programming With Processing

Comparison 2: mouseX <= buttonXPos + sliderFd.width

This comparison is only evaluated if the previous comparison evaluated to true


because a logical AND operator (&&) separates the two comparisons and as you
are aware in order for a logical AND operator to return a value of true all
expressions within the conditional must evaluate to true. So if one of these
comparisons making up this compound conditional (as it is sometimes referred to
as) evaluates to false, there is no need for Processing to continue to evaluate the
rest of the conditional as the value of the conditional will invariably equate to
false. This particular comparison will only return a value of false if the mouse's X
value is less than the right edge of the slider button.

Comparison 3:mouseY >= margin

Once again this comparison is only evaluated if the previous comparison was true
because both comparisons are separated with &&. This comparison returns a
value of true only if the mouse is below the top of the slider button.

User Defined Functions 138


An Introduction To Programming With Processing

Comparison 4: mouseY <= margin + sliderFd.height

Another && precedes this comparison which will finally only return true and
determine if the entire compound conditional evaluates to true if the mouse's Y
value is less than the bottom of the slider button.

Now that we have the range setup we're going to tell Processing what to do when
the conditional evaluates to true or false.

Returning data from a function


Every function declared in a sketch that does not use void, must return data
matching the type that the function has been datatyped as. In our example the user
defined function we are creating has been datatyped as a boolean and as a result
we need a means of returning boolean data back to the program in a useful way.
This boolean value that is returned back to the program, is what we will use in our
main program to let us know that when the value returned from the function is
true that the mouse is over the button and when the value is returned as false we
can safely conclude from this information that the mouse is not hovering over the
button.
First we are going to declare another variable in the global scope and datatype it
as a boolean, add the following global variable to your sketch:

boolean mouseOverButton;

Now we'll use this variable in our user defined function to return a boolean back
to the main program.

User Defined Functions 139


An Introduction To Programming With Processing

boolean overButton(){
if (mouseX >= buttonXPos && mouseX <= buttonXPos +
sliderFd.width && mouseY >= margin && mouseY <= margin +
sliderFd.height){
mouseOverButton = true;
cursor(HAND);
//Returns true back to main program
return mouseOverButton;
}else{
mouseOverButton = false;
cursor(ARROW);
//Returns false back to main program
return mouseOverButton;
}
}

Returning data back to the main program is actually really easy and is simply a
means of using the return keyword followed by the data you want to return which
must match the same type as that of the function. Basically, our function is
checking in the conditional if the mouse is within the range defined therein, if it is
then it sets the mouseOverButton variable which has been declared in global
space and datatyped as boolean to true with a simple assignment statement. We
then use the cursor() function to change the mouse icon from the default ARROW
to a HAND. This function also accepts parameters CROSS, MOVE, TEXT, WAIT
and can also accept a PImage as a parameter. Now when the cursor is over the
slider button it will change to a hand icon, giving the user a visual clue that they
are hovering over a clickable element. If we where to leave the function at this
point and not add an else structure, Processing would give us an error when trying
to compile this sketch. This is because every user defined function must return
data of it's specific type, meaning that in our case when the mouse is not over the
slider button and we did not have an else structure capturing this possibility at that
point our function would not be returning any data back to the main program.
This is why it is important that we add an else structure to this if() structure, so
that we can set the mouseOverButton variable to false, and subsequently return
the correct data back to the main program. This also gives us an opportunity to
change the cursor back to an arrow, indicating to the user that their mouse is no
longer over a clickable element.

User Defined Functions 140


An Introduction To Programming With Processing

Our function declaration and definition is now complete and we can use it in our
main program. Calls to user defined functions are as easy as calls to Processing's
API functions. Add the following statement to the draw() structure.

overButton();

Now Processing will run the function at every frame and set the
mouseOverButton variable within the overButton() function to true or false
appropriately, update the cursor and return the correct value datatyped back to our
main program, which we will soon put to use.

Dragging the slider button


mouseDragged() is a built-in Processing function that provides a structure to
which we can add statements each time the mouse is dragged. A dragging
operation qualifies as a user clicking and dragging a mouse button anywhere in
the Display Window, when this happens the mouseDragged() function will be
called once, and it's structure will be executed. As a result because the
mouseDragged() function is not called repeatedly for each frame that the mouse is
being dragged, we will use the mouseDragged() function to set a variable called
buttonDrag to true indicating that the mouse is currently being dragged, this
variable will then be used in the draw() structure, within an if() statement which
causes the slider button to follow the mouse when the buttonDrag variable is true
and remain stationary when it is false. When the user releases the mouse we will
use a call to the mouseReleased() built-in Processing function (which structurally
works in a similar way to the mouseDragged() function) to set the variable,
buttonDrag to false within the mouseReleased() structure. What this means is that
when the if() statement in draw() checks the status of this variable it will now be
returned as false causing the slider button to remain stationary. In other words, we
already have a function that tells us if the mouse is over the button or not, we will
now add two more functions that will tell us whether the user's mouse is
attempting to drag the button and whether it has been released.
Mouse related functions usually follow the end of the draw() structure and should
not be mixed amongst user defined functions.
We'll start by declaring the buttonDrag boolean in global space:

boolean buttonDrag;

User Defined Functions 141


An Introduction To Programming With Processing

We will then use the buttonDrag variable within a mouseDragged() function.


remember to place all mouse related functions together and not between user
defined functions:

void mouseDragged(){
if (mouseOverButton){
buttonDrag = true;
}
}

This simple function is run once the user clicks a mouse button and starts to drag,
then the function will check if the mouse is over the slider button as
mouseOverButton is returned to our main program via our overButton() user
defined function. If the mouse is over the slider button and the user has clicked
and dragged in the Display Window, then we can safely conclude that the user is
trying to click and drag the slider button. As a result we set the buttonDrag
variable to true. Now we can use this variable in our main program to update the
position of the button slider in the draw() structure.
Firstly we will start by commenting out the following statement as it is no longer
needed for testing, as we are ready to implement the actual code:

//buttonXPos = width/2 sliderBk.width/2;

The following statement will replace it:

if(buttonDrag){
buttonXPos = mouseX - sliderFd.width/2;
}

This if() statement will form the basis of the program's control flow used to
control the movement of the slider button. If you were to run the script at this
stage you might notice that although you can now click and drag the button, there
are a few new issues that need tending to:

1. The slider button now starts at the 0 X position, and subsequently needs to
be constrained to the region that the sliderBd object covers.
2. When the button is dragged it can be dragged well beyond the sliderBd
region, so this operation also requires constraints.
3. Once the button is released it continues to follow the mouse.

User Defined Functions 142


An Introduction To Programming With Processing

Setting up regional constraints


As we have seen from previous examples the constrain() function can be used to
setup a maximum and minimum value that can be used to determine the limits of
another value. This provides a convenient solution for working with the
buttonXPos value of which we'd like it's minimum value mapped to the left edge
of the sliderBd object and it's maximum value mapped to the right edge of the
sliderBd object minus the width of the slider button (sliderFd). We need to minus
the width of the slider button (sliderFd) because the top left hand corner of the
slider button image is the point that will be able to move to the maximum value
specified in the constrain() function, as a result of using the default setting for
imageMode() which is CORNER. If this point was matched to the right edge of
sliderBd the results would look like the following image:
s liderBd.width S liderFd CORNER

The slider button is dragged too far right

As you can see the slider button has gone too far past the right edge of the
sliderBd image, subtracting the sliderFd's width from the right edge of sliderBd
will solve this.
Modify the if() statement to include the following else clause:

else{
buttonXPos = constrain(buttonXPos, width/2 -
sliderBk.width/2, width/2 + sliderBk.width/2 -
sliderFd.width);
}

The minimum value for the constrain() function is the center of the Display
Window minus half of the width of the slider background image (sliderBd).
The maximum value for the constrain function is the center of the Display
Window plus half of the width of the slider background image (sliderBd) minus
sliderFd's width.

User Defined Functions 143


An Introduction To Programming With Processing

The values that will be used in the constrain() function to determine the slider button's
draggable area

With this information in mind finishing the if() structure is just a matter of copy
and paste with one minor modification. Although the modification is minor it's
addition to the sketch will be what finally gives the user the results they were
looking for. The value we are constraining in this case is going to be mouseX. The
following if() statement demonstrates this:

if(buttonDrag){
buttonXPos = constrain(mouseX - sliderFd.width/2, width/2 -
sliderBk.width/2, width/2 + sliderBk.width/2 -
sliderFd.width);
}else{
buttonXPos = constrain(buttonXPos, width/2 -
sliderBk.width/2, width/2 + sliderBk.width/2 -
sliderFd.width);
}

Finishing the slider


The third issue with the slider is to get it to stop dragging once the mouse has
been released. For this we're going to use the mouseReleased() function. The
mouseReleased() function should be placed directly below the mouseDragged()
function for the purpose of readability. However to Processing it does not make a
difference if the function is before or after mouseDragged().

User Defined Functions 144


An Introduction To Programming With Processing

The mouseReleased() function is pretty simple, all it does is run the function once
every time the mouse button is released in the Display Window. In our case the
function will check if buttonDrag is set to true, if it is then we can be sure that the
slider button is being dragged. As the function is run when the mouse has been
released, we can be certain that the user no longer wants to drag the button, as a
result the function then sets the buttonDrag variable back to false. This means that
the conditional using this variable in the draw() structure will evaluate to false, so
that mouseX will no longer be used to determine the value of buttonXPos. The
mouseReleased() function should look like the following code listing:

void mouseReleased(){
if(buttonDrag){
buttonDrag = false;
}
}

Mapping Values
Now that we have the slider moving correctly we can use the values of
buttonXPos and map them to any values that we choose, for example we could
map the range of values that buttonXPos returns to the amount we would like an
image to scale on it's X axis, how far or fast an image moves across the screen, or
just about anything that can accept a range of values as an input. We're going to
map the buttonXPos range to the tint of an image, making the image appear to
fade in from black. Mapping one range of values to another is done with the
map() function. The map() function accepts parameters in the following format:

map(mValue, oldLow, oldHigh, newLow, newHigh);

The parameter mValue is the value that you will be mapping to the new range, in
our case this is buttonXPos. The parameters oldLow and oldHigh are the
minimum and maximum values of the range you would like to map to the new
range, in other words these values are the furtherest left we can drag the slider
button (oldLow) or expressed within the context of our program:

width/2 - sliderBk.width/2

User Defined Functions 145


An Introduction To Programming With Processing

The oldHigh value is the maximum value of the original range, and in the context
of our program:

width/2 + sliderBk.width/2 sliderFd.width

You might have noticed, by now that these two values are the exact expressions
we used to determine the minimum and maximum values for the constrain()
function assigned to buttonXPos, this is no coincidence. These two values
determined the maximum range of the sliders movement and this is the exact
range we are mapping to a new range. The new range will be represented by the
two parameters newLow and newHigh and in our case these are two simple
numbers 0 and 255 respectively. As we are mapping the slider button's movement
to the tinting of an image via the tint() function we will be using the single value
that is returned from the map() function which will be between the newLow and
newHigh parameters in order to create the impression of the image fading in from
black. In the context of the actual values, 0 to 255 represent the range of values
that the tint() function uses to tint the image with various levels of gray. For
example the value 0 has the effect of making an image appear as fully gray (or
black) and 255 has the effect of making an image appear with no gray and no
black tint.
With the slider button's values converted to the correct range of values, all that is
left to do is link the new values to the image. In order to do this we will start by
declaring a new variable in the global scope. Add the following variable to your
sketch:

float imgTint;

As you can see this variable is datatyped as float, this is because the map()
function returns floats. Remember that this does not mean that the parameters
themselves have to be floats, nonetheless it is worth noting that in order to
perform true division if the parameters you supply Processing with for the map()
function are of type int Processing will typecast them to floats for the purpose of
the map() function. What this means is that once those values have been evaluated
by the map() function, the answer will be returned as a float. Since this is the
variable that we will assign the return value of the map() function to, and as just
stated this value will be a float it makes sense to datatype this variable as a float.
If we try to use another datatype, such as an int, we will get a type miss-match
error.

User Defined Functions 146


An Introduction To Programming With Processing

With our new variable, imgTint, we will use assignment in the if() structure we
created earlier within the draw() function, to determine it's value as the slider is
dragged. Add the following statement to the if() structure, directly under the
assignment statement for buttonXPos:

imgTint = map(buttonXPos, width/2 - sliderBk.width/2, width/2 +


sliderBk.width/2 - sliderFd.width, 0, 255);

In the previous statement we use the map() function to determine the value of the
imgTint variable. Now that we have a place to store this value we can associate it
with the tint() function. Which we will do before the image() function to render
img. We do this by adding the following statement:

tint(imgTint);

This statement must precede the statement telling Processing to render the img
object. If you were to run the sketch at this point you might notice that everything
is working, but not quite as expected. The answer to this problem is order. If you
look at the current sketch it runs like so.

draw()

If the slider button is being dragged


Update variables

Else leave everything as it is

render the images

end draw()

Although this method might be somewhat functional, it's not very intuitive. What
this means is that when the user drags the slider the user should be able to see the
results of their actions in realtime (another way of saying immediately or
something very close to that) and when the user releases the mouse button, the
values should stay as the user set them and not jump around to seemingly
incorrect values. As a result we need to make sure that the images are being
rendered for all possible situations using the correct values, which in our case is

User Defined Functions 147


An Introduction To Programming With Processing

only two different branches. So we are going to restructure our code to


accommodate for a more intuitively designed interface.

draw()

If the slider button is being dragged


Update variables
render the images

Else leave everything as it is


render the images
end draw()

How this new structure is implemented in our program will follow this pattern:

buttonXPos //update variable


imgTint //update variable
tint() //set the tint value
img //render main image now effected by tint
noTint() //Turn tint off so slider images are not
//effected by it
sliderBk //render slider background image
sliderFd //render slider button image

This is the order within the first control structure of the if else structure the second
control structure will follow the same order. For a full listing of the code it's best
to look at the sketch itself which is named slider.pde.

Finally to end off the example I've added another image to the sketch which I've
associated with the object called star and mapped it's Y movement to the slider.
Like I said the mapping of one value with a range to another range can lead to an
infinite array of possibilities, and is largely the premise on which more complex
applications are built upon. Why not try your own custom mappings you'll soon
come to realize that with this simple function, the sky is definitely not the limit.

User Defined Functions 148


An Introduction To Programming With Processing

The final slider.pde sketch

User Defined Functions 149


An Introduction To Programming With Processing

The mystery shape maker


In this next sketch we will discover two new fundamental programming concepts
arrays and iterations, learn how to work with random numbers and try out a new
datatype called color. The mystery shape maker is a sketch that allows the user to
make several clicks in the Display Window, and by capturing and storing the
coordinates of each click constructs a new shape for the user in a randomly
generated color. The shapes can be as simple or complex as you want, as you
determine how many times the user gets to click in the Display Window before
the mystery shape is drawn.

Some of the shapes that can be created with the mystery shape maker

Arrays
Arrays are used to store data, but unlike the other data storage types we have been
using (such as variables) arrays have the ability to store more than just a single
value. Arrays can store multiple values of the same datatype in much the same
way that an ordinary list (such as a grocery list) consists of multiple elements
related to the topic of the list. In fact, this analogy is so true to the nature of arrays
that every component making up an array is referred to as an element. This
analogy can be extended ever further, as with a list each element in that list can
have a number associated with it, in an array each element has a number
associated with it too. We refer to these numbers as indices (in plural) or simply
an index number in singular form.

Arrays 150
An Introduction To Programming With Processing

An everyday list:

My Shopping List //name of the list


1. Tea //element1
2. Soy-Milk //element2
3. Vegan Cookie //element3

An Array in Processing:

int[] myArray = {20, 30, 40};


//name of array is myArray[] and it is datatyped as an int, so it
//can store integer values
//element 1 is 20, and has an index value of 0
//element 2 is 30, and has an index value of 1
//element 3 is 40, and has an index value of 2

Index values for arrays start at 0 and can go as high as the number of elements in
an array minus 1, for example if an array has 15 elements, the index value of the
last element in the array is 14.

Element No. 1 Element No.3


has an index has an index
value of 0 value of 2

int[] myArray = {20, 30, 40};

Element No.2
has an index
value of 1

Understandably at first this system of numbering might seem a bit strange, so in


order to simplify things you can think of an index number as a means of referring
to an element within an array without having to know what it's value is. This
concept should not be new to you as it does not differentiate very much from that
which defines a variable, the main difference being that instead of using a variable
name we are now using an index number within an array to reference that specific
value. The syntax for referencing an element within an array follows:

Arrays 151
An Introduction To Programming With Processing

int[] myArray = {20, 30, 40}; //initialize array


myArray[0]; //reference array element with
//index number 0, which has a value
//of 20.

We can also use an array in a program in a similar way that we would use a
variable, for example:

Index Number 0 1 2

int[] myArray = {20, 30, 40}; //initialize array


int x = myArray[0] + myArray[2]; //sets x to 20 + 40 i.e. 60

Using an array in this format can be very similar to the way in which variables are
used, and the comparison can extend further than the previous expressional
example into initialization and assignment. As you can see in the previous
example the array was initialized through both declaration and assignment in one
statement in a similar way that variables use initialization, in the first line of the
previous example.
As arrays have multiple elements assigning values to the elements of an array
cannot be through a simple reference to the arrays name, as Processing would not
know which element is to inherit the value on the right of the assignment operator.
As a result the process of assigning values to elements of an array after
declaration or initialization must also include the index number of the element
you wish to assign a value to, on the left hand side of the assignment operator. For
example:

int[] myArray = {20, 30, 40}; //initialize array


myArray[2] = 10; //element 3 was 40 now has a value
//of 10

With all the similarities between variables and array elements you might be
wondering what the purpose of an array is? Unlike variables storing one value
followed by another value of the same type within the same variable, the array
does not have to replace the previous value in order to store a new value. For
example, what if I wanted to store the X position of the mouse when the user
clicks in the Display Window. This would be easy enough, I'd just create a
variable and assign it the value of the mouseX system variable. This is fine if all I
need to know is the current X position of the mouse when the user clicks.

Arrays 152
An Introduction To Programming With Processing

However, what if I need to know the previous X coordinate of the mouse, or the
one before that and so on. Retrieving this information with a simple variable
would not be possible because each time the user clicks the mouse the current
value of mouseX replaces the previous value.

int mXPos; //declare variable to store mouse X


//position

if(userClicked){ //hypothetical conditional to test if


//user has clicked in the Display Window
mXPos = mouseX; //sets variable to current X position of
//mouse
}

//user moves the mouse around and clicks again

if(userClicked){ //hypothetical conditional repeats to


//test if user has clicked
mXPos = mouseX; //replaces the previous value for mXPos
//with the new X position of the mouse,
//and the previous value of mXPos can no
//longer be retrieved.
}

With arrays this information becomes accessible to us. By using the elements of
an array we can store the first X coordinate of the mouse at index 0, the second
coordinate at index 1, the third at index 2 and so on. We can store all of this
information without having to create a new variable for each value, which would
make keeping track of all the variables very confusing and difficult. By using an
array we can store all the data related to the X coordinates of the mouse under a
single entity. Lets have a look at an example of this in a sketch.

Arrays 153
An Introduction To Programming With Processing

int[] myArray = new int[4]; //declare array with four


//elements
int clicks; //counts the number of clicks

void draw() { //makes the program repeat


}

void mouseClicked(){
if(clicks<4){ //check that the user has not
//clicked more than 4 times.
myArray[clicks] = mouseX; //Sets the mouse X coord to
//the index number in an
//array that matches the
//amount of times the user
//has clicked.
println(myArray[0]); //print the value of the
//first x coordinate
println(myArray[1]); //print the value of the
//second x coordinate
println(myArray[2]); //print the value of the
//third x coordinate
println(myArray[3]); //print the value of the last
//x coordinate
clicks++; //increment the click value
//by 1
}
}

Program Notes
In the first line of the sketch we declare an array with four elements. When using
this technique to create a new array we must indicate the datatype of the array and
use brackets[] to tell Processing that we are about to create an array (and not just
simply declare a variable). We must then name the array and use the assignment
operator to populate the array with the new elements (which do not have values
assigned to them as of yet). We do this by use of the new keyword, followed by
the datatype of the new elements which must match the array's datatype and
finally, brackets indicating how many of these new elements will populate the
array.

int[] myArray = new int[4];

Arrays 154
An Introduction To Programming With Processing

Next the variable clicks is declared, this variable will be used to count how many
times the user has clicked in the Display Window. The draw() function is then
initiated in order to keep the program running, and prevent the sketch from
turning to static mode.
The mouseClicked() function consists of a simple if() statement. The conditional
of the if() statement is executed when the user clicks a mouse button within the
Display Window. The conditional checks if the clicks variable is less than four,
which is the amount of elements in the array. If this is the first time the mouse has
been clicked, clicks will equal a value of 0 as it has not been assigned a value
through initialization, it has only been declared. As a result the following
statement is run:

myArray[clicks] = mouseX;

This is the statement that assigns a value to each element in the array. If this is the
first time clicks has been used in the comparison it will also be the first time the
user has clicked in the Display Window and therefore clicks will have a value of
0, as a result the preceding statement can be translated and explicitly expressed
as:

myArray[0] = mouseX;

This means the element with the index number 0 is assigned the value of
whatever the mouse's X coordinate was at the time the user clicked a mouse
button. The next four println() statements print the value of each of the four
elements in the array. As only the first element has a value at this point in time, it
will be the only element that is non-zero until the user clicks again (up to three
more times).

clicks++;

In a similar way that we used augmented assignment to shorten an expression that


is commonly used in programming, we have used an increment operator in the
previous example to shorten this statement. The increment operator works by
adding 1 to the current value of the particular variable it is used with, then
assigning this new value back to the original variable. This is a common method
of getting a program to count for you as each time the variable is used with the
increment operator it will return a value that is one more than it's previous value.

Arrays 155
An Introduction To Programming With Processing

Writing this statement without the increment operator would look like this:

clicks = clicks + 1;

As you can see using an increment operator can make your code easier to read
and save you some keystrokes.
The decrement operator (which is two minus signs --) works in a similar way to
the increment operator except that it subtracts 1 from the variable's current value
before reassigning the new value back to the original variable.

The result of this statement is that the clicks variable will now be one more than
it's previous value by the time the program repeats. For example the clicks
variable was initially 0, but at the end of the if() statement the clicks variable will
have a value of 1. This is important because the next time the user clicks a mouse
button the comparison will be working with different values. For example on the
first click the comparison can be expressed as (0<4), on the second click the
comparison can be expressed as (1<4) and so on. This continues until after the
fourth click, as the fourth click will equate to (3<4). At the end of the if()
statement on the fourth click the variable clicks is incremented to 4, this means on
the fifth click the conditional can be expressed as (4<4), this is false and the if()
statement is no longer executed.
If we did not include the if() statement which serves the main purpose of counting
the amount of clicks, the sketch would still have run but on the fifth click we
would be trying to assign a value to an element in the array that does not exist, as
a result Processing would have given us an Array Index Out of Bounds
exception. You cannot add elements to an array like this, there is however a
method of getting around this restriction, which we will have a look at in our
mystery shape maker sketch.
It's worth noting the print out that appears in the text area every time the user's
mouse is clicked for the first four times within the Display Window. What is most
notable about this, is that the current position of the users mouse's X position is
printed along with all the other X positions that the user's mouse was in when the
user clicked up to three more times previously in the Display Window. All of
these values are now assigned to elements in an array and we now have the option
to use those values in a more complex program, by accessing them through their
index numbers.

Arrays 156
An Introduction To Programming With Processing

Dynamic assignment for elements in an Array


For the mystery shape maker sketch we are going to use two arrays, one will store
the mouse's X positional values and the other will store the mouse's Y positional
values, each time the user clicks in the Display Window. As there is no way of
knowing exactly where the user is going to click in the Display Window we will
need to populate these arrays with the aforementioned values, dynamically. This
means each element of the array must have values assigned that relate to the
values of the user's mouse X and Y positional data while the program is running
and the user has clicked in the Display Window. We then need to make sure those
values are not overwritten but stored in memory and can be accessed through their
index numbers of the arrays they are associated with. Finally when the user has
clicked the last point contributing to the mysterious shape the conditional that was
evaluating to true and subsequently assigning positional data to the elements in
the array, will now evaluate to false as the number of clicks increases in value.
We will then use the beginShape() and endShape() functions and combine each
one of the two arrays' corresponding elements into a coordinate for the vertex()
function, which will be embedded within a loop that cycles through the two arrays
extracting the information from them and subsequently drawing the mystery
shape.
Although this might sound like a handful, you already know how to create two
thirds of this program. Nonetheless, lets recap on these fundamental programming
topics as they will more than likely prove to be a useful asset in many a sketch.

First we are going to start by declaring and/or initializing the following global
variables:

int points = 6; //number of points


int clicks; //click counter
int[] numx = new int[points]; //array for mouse x
//coordinates
int[] numy = new int[points]; //array for mouse y
//coordinates

//generate a random color for the shape's fill


color randCol = color(random(256), random(256), random(256));

Arrays 157
An Introduction To Programming With Processing

The points variable will be a number that we can change before running the
sketch so that we can make our shape consist of as many or few points as we like,
this number should not be negative.
The clicks variable will be used to store the amount of times the user has clicked
in the Display Window, it will also be an operand within the conditional that
populates the array.
Then we move onto declaring the arrays that will store the X and Y coordinates of
the user's clicks. Notice how the number of elements in this array has been
defined as the variable points. As points is of type int it can be placed within the
array's declaration brackets. The preceding statement relating to the declaration of
the numx array can be translated and explicitly expressed as:

int[] numx = new int[6];

It is worth noting that in the actual sketch we have not used a numerical constant
but rather a variable to determine how many elements will populate the array, this
is because if we decided to use more or less points making up the mystery shape,
it would be easier to implement this change by means of modifying the
initialization statement for the points variable rather than having to change
numerical values scattered throughout the sketch, such as in a statement
resembling the previous example.

The final variable we have created within the global space is called randCol and
has been datatyped as color. The color datatype is used to store color values, in
our case we are using the format of:

color varName = color(R, G, B);

Where color is the keyword used to declare variables of type color, varName is
the name of the variable, and the assignment operator is used to assign a color
value in R (red), G (green) and B (blue) values. RGB values range from 0 to 255
each. Note the expression used for each of the R, G and B values:

random(256)

random() is a built-in Processing function that is used to return a random number,


that is between 0 and the number specified, but not including the specified
number. As a result the parameter 256 is used so that Processing will include

Arrays 158
An Introduction To Programming With Processing

values between 0 up to and including 255. random() also accepts parameters in


the form of:

random(Low, High);

Where Low is the minimum number in the possible range of random numbers and
High is one more than the maximum number in the range. If you assign the
random() function to a float Processing will return random floats.

The next step is to setup the setup() and draw() functions as per usual, then add
the following if() statement to the draw() function:

if (clicks<points){
numx[clicks] = mouseX;
numy[clicks] = mouseY;
}

There's not really anything new about this if() statement, so we'll just run through
it briefly. First the conditional checks if the amount of times the user has clicked
is less than the amount of elements in the arrays. Using this method creates an
error catching scenario, as opposed to if the user was allowed to click repeatedly
beyond the number of elements in the arrays which would result in the amount of
elements that the program would attempt to store in the arrays exceeding the
amount of elements that can be stored in the arrays. This would cause an Array
Index Out of Bounds exception.
We can then use the clicks variable in the if() structure to determine which
element in the array is assigned the corresponding mouse X or mouse Y value.

void mouseClicked(){
clicks++;
}

Outside of the draw() function we setup a simple mouseClicked() function, which


works in a very similar way to the mouseReleased() function. The difference
being that the mouseClicked() function does not wait for the mouse to be released
before running the code that makes up it's structure, it executes the code within
it's associated braces as soon as the mouse is clicked within the Display Window.
The purpose of the mouseClicked() function is simply to increment the clicks
variable, which it does so within the function's only code block.

Arrays 159
An Introduction To Programming With Processing

Iterations
Processing has two main types of iterations the for() structure and the while()
structure. The while() structure can be thought of as a simplified version of the
for() structure. We will be focusing on the for structure.
The for() structure is used to iterate a value, that is to change a value by means of
a recurring pattern. for() structures are also referred to as for() loops in some
programming languages, whatever you call them they usually will be structured
according to the following protocol.

for(init; test; update){


...statements
}

The main differences that separate one languages implementation of for loops
from that of another, will generally not be anything structural but rather syntactic.
For example some programming languages use comma's to separate init, test and
update Processing uses a semi-colon implying that each is a statement on it's own.

The term init in the previous example is used to describe initialization. In


a for() loop iteration init is used to declare a temporary variable that will
usually be used in the iterations structure, test and update.
test is used to describe a conditional, which like a normal conditional will
evaluate to true or false. If the conditional evaluates to true the for()
structure will run, if the conditional evaluates to false the entire for()
loop's structure is skipped and Processing will continue to the statement/s
that follow the for() structure in the sketch.
update is used to describe an expression that will determine how the value
of the variable in the conditional is being changed. The value of the
variable being evaluated in the conditional must change, by means of the
update, or the loop will go on forever which will eventually cause your
sketch and Processing to crash. For example an increment statement is
often used in update to increment the value of the variable initialized in
init and evaluated in the conditional test.

In programming it is common to use a for() loop iteration to get your program to


count for you, as per the following example:

Iterations 160
An Introduction To Programming With Processing

for (int i = 0; i < 10; i++){


println(i);
}
//prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 one digit at a time

The previous example used a for() loop iteration to count from 0 to 9, lets have a
look at how it did this. First we need to use the for keyword to indicate to
Processing that we are about to create a for() loop iteration. A for loop iteration
relies on three statements init, test and update within parenthesis so that they are
specifically associated with the for() loop iteration structure. As you can see the
three statements are separated with semi-colons, this is unique to a for() loop
iteration in Processing and clearly differentiates these statements from being
parameters.
As init is used to initialize a variable within the for() loop iteration structure, the
scope of this variable is limited to the for() structure. What this means is that the
variable i in our previous example will not be accessible in other places within
our sketch and only be accessible within the for() structure. As a result this
variable name is usually i or n and not very descriptive. It is actually more
distracting to call a variable initialized within a for() loop anything other than i or
n (some people might also use x but this can be a bit distracting from variables
that use x to denote a position on the X axis). It is therefore advisable to not use a
variable name that is any more descriptive than a single character such as i or n.
Once we have the variable initialized we can then use it in a test, if the test
evaluates to true the code within the for structure will be run. It is important to
note that if the test evaluates to true the code within the for structure is run, and
only after this code is run is the update statement executed.

A graphical representation of how an iteration works

Iterations 161
An Introduction To Programming With Processing

The update statement in our example is an incremental statement, which adds one
to the variable from init subsequently increasing the value of the variable with
each iteration. On the tenth occasion that the loop repeats the variable is
incremented to a value of 10, so when the conditional evaluates the test (10<10)
will return false. This will break the loop and stop it from being repeated.

Using a for() loop as a counter can be a convenient method of updating values in


a sketch, but for() loops can be extended to be more than just simple counters and
can be used to iterate complex blocks of code that can contribute significantly to a
program's flow of control. For example in our mystery shape maker sketch we
have used a for() loop between beginShape() and endShape() to create multiple
vertices for the irregular shape we would like Processing to draw. The iteration
follows:

beginShape();

for(int i = 0; i < points; i++){


vertex(numx[i], numy[i]);
}

endShape();

Using this method we can let the user decide what the shape should look like. If
you recall beginShape() and endShape() require the vertex() function between
them. The difference with this sketch is that we have nested the vertex() function
inside a for() loop iteration. The program will loop through the vertex() function
as many times as the variable initialized within the for() loop called i, is less than
the points variable declared earlier in global space. What this translates to is the
the vertex() function will be run six times and on the seventh attempt to run the
for() loop the conditional of the for() loop will evaluate to false as i will be equal
to points (i == points) causing the loop to break and running the rest of the code
that follows the for() loop structure, which would be the endShape() function.
This creates a shape with six vertices (according to our example) in the positions
that the user specified by clicking in the Display Window. The coordinates of
these vertices are determined by extracting the values associated with each
element in the arrays numx[] and numy[], as the index number of each element is
referenced with the for() loop variable i. A full listing of the mystery shape
program follows:

Iterations 162
An Introduction To Programming With Processing

int points = 10;


int clicks;
int[] numx = new int[points];
int[] numy = new int[points];
color randCol = color(random(255), random(255), random(255));

void setup() {
size(300,300);
smooth();
}

void draw() {
background(100);

if (clicks<points){
numx[clicks] = mouseX;
numy[clicks] = mouseY;
}else{
fill(randCol);
beginShape();
for(int tempx = 0; tempx < points; tempx++){
vertex(numx[tempx], numy[tempx]);
}
endShape();
}
}

void mouseClicked(){
clicks++;
}

Iterations 163
An Introduction To Programming With Processing

Transforms
Processing provides a convenient method for animating and interacting with
components of a sketch that are transformed in various ways. The term transform
when used in this context generally refers to any one of, or combinations of the
following three actions:

Translation, Scaling, Rotation.

Translation is simply another way of saying moving but as the term moving can
tend to be somewhat ambiguous when you consider that rotation also involves
movement and so too does scaling (when you consider that the components
making up an object such as it's vertices move when the object is scaled), we
prefer to use the term translation as it specifically refers to positional data in terms
of X, Y and Z of an entity. The function for applying translations within a sketch
is translate() and it accepts parameters in the form of X and Y with an optional
third parameter for Z (which we will discuss later) when using a 3D renderer.

Rotation is a transform that we have not discussed in any of our previous


sketches, and as you will see can be a useful asset to creating certain types of
animation within a sketch. Amongst the functions that provide us with access to
rotation are rotate(), rotateX(), rotateY() and rotateZ() these functions accept
values in radians.

Scaling is a transform accessed with the scale() function and it accepts a single
float value or two floats that relate to X and Y or three floats that relate to X, Y
and Z for 3D sketches. Scaling creates the impression of making things appear to
be bigger or smaller within a sketch.

Let's have a look at an example of a static sketch using the translate() function.

size(400,60);
rect(0,0,50,50);
translate(width/2, 0);
fill(255,0,0);
rect(0,0,50,50);

Transforms 164
An Introduction To Programming With Processing

A static sketch using transforms

In the first line of the sketch, we simply defined the size of the window in which
the sketch is running as being very long horizontally and short, vertically. In the
following line we drew a rectangle at the origin, and because the rectMode()
function by default is set to CORNER, the rectangle sits perfectly flush with the
top left hand corner of the Display Window. We then used the translate() function
with a modification to the X parameter, and as you would expect the next time we
draw a rectangle (after changing the fill color) it's position on the X axis reflects
the translation we previously applied. However, if you have a look at the X
parameter for the rect() function you will notice that things are a bit different to
what you might expect as the X parameter reads 0 whereas the rectangle is drawn
close to the center of the Display Window and to the right of the previously drawn
rectangle.
Shouldn't the rectangle be drawn at the origin if it's X parameter is 0?
If you were thinking something along those lines then you are absolutely correct
and in fact the rectangle is being drawn at the origin, the main difference here is
that we have used the translate() function to move the origin, not of the rectangle
but of the entire coordinate system. Let's have a look at how this happens.

Transforming Coordinate Space


Although the effect of what you are seeing in the Display Window creates the
impression that Processing has moved the rectangle, the rectangle as it is
indicated by it's X parameter in both rect() function calls tells us something
different. That is, that the rectangle has in fact not moved. The reason that the
rectangle has come to be drawn in this new location is due to the effect of the
entire coordinate system moving.
If you were for a moment to reflect back on the Cartesian graph system that we
discussed earlier you might remember that everything in Processing works in a
similar fashion to that of something drawn on graph paper. Bearing this in mind,

Transforms 165
An Introduction To Programming With Processing

what we have done in the previous sketch cannot accurately be described as


moving the rectangle, but more akin to moving the graph paper.
For example if we were to draw a rectangle on a piece of graph paper, then move
the graph paper around, we would in effect be creating the impression of the
rectangle drawn on the graph paper moving around. The rectangle itself would not
be what you are moving around, in terms of the fact that the rectangle's positional
X and Y data has not changed with relation to the origin of the coordinate system
it was drawn relative to. We can therefore say that the rectangle has not moved,
however the coordinate system associated with it has.

An object drawn on graph paper does not move but the graph paper does

This is the purpose of transforms in Processing, they move the coordinate system
for us. We can still move the components of a sketch through their own positional
parameters, which we usually supply in terms of X and Y data for parameters of a
function, but bear in mind that mixing translation techniques like this will result
in the component appearing to have moved by the sum of the two data sets. To
put this in another way, the distance the entity would appear to have moved would
be the sum of the translate() function plus the X, Y and Z parameters of the
function to draw the entity.

A Convenient Animation System


So if we still have the ability to modify components of a sketch via their own X
and Y parameters what's the benefit of having transforms?
Transforms can save us a lot of unnecessary work, make our code a lot easier to
read and provide us with functionality that would not be possible without them.
Lets have a look at an example of how this works.
In order to see the benefits that transforms have on our code we'll revisit the smile
sketch from our static sketch examples at the beginning. If you recall, the purpose
of the sketch was simply to draw a smiley face to the Display Window in static
mode with some other components. We're only interested in the smiley face, so

Transforms 166
An Introduction To Programming With Processing

first we're going to adapt the sketch for active mode by including the drawing of
the face within the draw() structure:

void setup(){
size(640,480);
}

void draw(){
background(127);
//Drawing the face
fill(191,233,255);
ellipse(width/2, height/2, 100, 100);
//smile
noFill();
stroke(255,0,0);
arc(width/2, height/2 + 10, 50, 50, 0, PI);
//eyes
stroke(0,0,0);
fill(0,255,0);
ellipse(width/2-15, height/2-15, 20, 30);
ellipse(width/2+15, height/2-15, 20, 30);
}

The smile static sketch revisited and modified to fit an active mode sketch

As you can see nothing surprising about the sketch, but what if we wanted to
animate the smiley face by moving it across the Display Window, or attaching it
to the mouse?
This could become quite a cumbersome task as every component of the smiley
face that has X and Y parameters would have to be updated for every frame. To

Transforms 167
An Introduction To Programming With Processing

give you an indication of how much extra work this is here's a look at what sort of
changes in the sketch would need to be implemented if we wanted to attach the
smiley face to the mouse:
void setup(){
size(640,480);
}
void draw(){
background(127);
//Drawing the face
fill(191,233,255);
ellipse(mouseX, mouseY, 100, 100);
//smile
noFill();
stroke(255,0,0);
arc(mouseX, mouseY + 10, 50, 50, 0, PI);
//eyes
stroke(0,0,0);
fill(0,255,0);
ellipse(mouseX-15, mouseY-15, 20, 30);
ellipse(mouseX+15, mouseY-15, 20, 30);
}

As you can see almost every second line of code had to be updated within the
draw() structure. Now imagine if you had a whole character you wanted to draw
and how much additional work something like that could amount to?
With transforms making a change like this to your code is easy:

Transforms 168
An Introduction To Programming With Processing

void setup(){
size(640,480);
}
void draw(){
background(127);
translate(mouseX-width/2, mouseY-height/2); //transform
//Drawing the face
fill(191,233,255);
ellipse(width/2, height/2, 100, 100);
//smile
noFill();
stroke(255,0,0);
arc(width/2, height/2 + 10, 50, 50, 0, PI);
//eyes
stroke(0,0,0);
fill(0,255,0);
ellipse(width/2-15, height/2-15, 20, 30);
ellipse(width/2+15, height/2-15, 20, 30);
}

Notice that only one additional line of code was needed to accommodate for this
update, the rest of the code remained unchanged.
The additional statement is:

translate(mouseX-width/2, mouseY-height/2);

This statement simply uses the translate() function, with two parameters relating
to X and Y. The X parameter tells Processing to move the entire coordinate
system to the position of the mouse's X value then to subtract half the width of the
Display Window from this value. The reason we need to subtract half the width of
the Display Window from the mouseX system variable is because our entire
sketch was originally made to draw the smiley face in the center of the Display
Window.

Transforms 169
An Introduction To Programming With Processing

Offset from the origin with


mouseX

Offset from the origin with


mouseX - width/2

As the coordinate system is transformed, it's origin can exist within the boundaries of the
Display Window or outside of these boundaries.

pushMatrix() and popMatrix()


As transforms effect everything below their implementation within a sketch, due
to them transforming the entire coordinate system, there are times when you will
find that this is not the effect that you want.
The image below of a cart is made up of three separate images which are rendered
in the following order the wheel in the background, the main cart and the wheel in
the foreground. If our intention was to rotate the back wheel first, as the back
wheel would have to be rendered before any of the other images, we run the risk
of having the transforms applied to the back wheel effecting the main cart and the
wheel in the foreground as they are rendered after the back wheel, and will
therefore be effected by any scale(), translate() and/or rotate() function that is
intended for the back wheel. This would create the impression of the cart orbiting
around the back wheel, which is obviously not what we where trying to
accomplish. Two functions in Processing called pushMatrix() and popMatrix()
help us to solve this problem.

Transforms 170
An Introduction To Programming With Processing

Main Cart
Background wheel
Foreground wheel

The template rendering of the cart.pde sketch

The function pushMatrix() when called before a transform is executed will store
the current state of the coordinate system. This means that if you call a
pushMatrix() function at the start of the draw() structure it will remember the
default position of the coordinate system (pre-transform). You are then free to
apply transforms to the particular component of the sketch that you would like to
scale, rotate and/or translate. Once you are satisfied with the transforms you have
performed you can then render the component, for example by means of a call to
the image() function. Running the popMatrix() function at this point will then be
necessary to restore the coordinate system back to the state it was in when the
previous pushMatrix() was called. You can then proceed to run more
pushMatrix(), transforms, render, popMatrix() combinations on other components
of the sketch which will remain unaffected by the previous transforms. Using
pushMatrix() and popMatrix() in this way allows us to apply multiple transforms
to a component of a sketch ,and not have those transforms effect other
components.

Transforms 171
An Introduction To Programming With Processing

Lets have a look at how to use this technique to make the cart move across the
Display Window and have the wheels of the cart rotate accordingly.
We'll start as always with a template of what we want the final result should look
like:

PImage cart;
PImage wheelFd;
PImage wheelBd;
PImage grass;

void setup(){
size(800,600);
cart = loadImage("cartMain.png");
wheelFd = loadImage("wheelFd.png");
wheelBd = loadImage("wheelBd.png");
grass = loadImage("grassLessBlur.jpg");
}
void draw(){
background(grass);
imageMode(CENTER);
image(wheelBd, -75, 25);
image(cart, 0, 0);
image(wheelFd, -95, 35);
//println(mouseY);
}

Transforms 172
An Introduction To Programming With Processing

Out of interest you might be wondering how the X and Y parameters of the
image() functions which render the wheels relative to the position of the cart were
determined. If you look at the last line you'll see a println() function that has been
commented out. By replacing the image() function's X and Y parameters with
mouseX then mouseY, respectively and one at a time, you can run the sketch with
the image of the wheel attached to either the mouse's X or Y position. Place the
wheel in the position it should be in, the println() function (when uncommented)
will print out the position of your mouse, note this value and replace it with the
mouseX or mouseY system variable in the wheel's image() function's
corresponding X or Y parameter.
As the imageMode() function is set to CENTER in this example you will have to
move the main cart image to a location that is not the origin, so that the left and
top halves of the image is not obscured by the boundaries of the Display Window.
You will then need to subtract the value that you added to the X and Y parameters
of the image() function to draw the cart from the respective values printed in the
Text Area/debugging console that will be used to place the wheels in the correct
locations.
Now that we have a template from which to start let's set up a temporary system
that allows the cart to trail after the mouse with a bit of friction, we'll then modify
this code to suit the needs of our sketch. This methodological approach to
sketching by creating a rough idea then refining it will allow us to see results
much sooner in the sketching process, rather than spending a lot of time on a
sketch only to find out when it is almost done that the effect we were trying to
achieve isn't quite working out.
We'll start by adding the following global variables:

float xPos;
float difX;
int drag = 30;

If you recall from the imageScroll.pde sketch, we used the technique of creating
the impression of friction with a similar set of global variables. The only
difference is that in this sketch we are now using the same technique to create the
impression of friction along the X axis. Next we'll need to add the following
statements to the draw() structure after the imageMode() function call:

Transforms 173
An Introduction To Programming With Processing

image(wheelBd, -75, 25);


image(cart, 0, 0);
image(wheelFd, -95, 35);
difX = mouseX - (xPos + cart.width/2);
xPos += difX/drag;

Since we want the cart to move with relation to the mouse moving past the end of
the cart on the right hand side, we're going to divide the cart.width object variable
by 2 and add it to the position of the cart which is now determined by the center
of the cart object because we have set imageMode() to CENTER. If imageMode()
had been at it's default value of CORNER we would simply use cart.width to
determine the right edge of the cart image.
To temporarily link these statements to the rendering of the cart, directly after the
previous statements add the following code:

pushMatrix();
translate(xPos, 250);
image(wheelBd, -75, 25);
image(cart, 0, 0);
image(wheelFd, -95, 35);
popMatrix();

Notice that we just added three additional statements. The first new statement is
pushMatrix() this tells Processing to store the current transformational data of the
coordinate system in memory, we then use the translate() function to to modify
the coordinate system along the X axis by the value of the variable xPos and the
numerical constant of 250 for the Y parameter. The Y parameter is a numerical
constant simply because it will not change throughout the duration that the sketch
is running. Next we render the images without any changes to their parameters as
all of their positional data remains the same, the transform will create the
impression of movement for us. Then finally we use the popMatrix() function to
restore the transformational data relating to the coordinate system when
pushMatrix() was initially called.
When using pushMatrix() it must always be coupled with popMatrix() or
Processing will complain about there being too many calls to pushMatrix() and
not enough to popMatrix().

Transforms 174
An Introduction To Programming With Processing

What is the Transformation Matrix


The term matrix simply refers to a grid of numbers, which is how Processing
stores information about the coordinate system in memory. For example a matrix
can be represented as:

1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20

We would call this a 4 x 5 matrix meaning that it is made up of 4 rows and 5


columns. This is not an actual representation of a matrix that Processing uses to
calculate transforms but simply an example of what a matrix could look like, in
fact the matrices that Processing uses are simpler than the previous matrix
example.
You might hear the term transformation matrix used on occasion, this is just
simply referring to the numbers that make up the matrix that the matrix
representing the current coordinate system must be processed through in order to
produce the representation of the coordinate system in it's transformed state.
Although this might sound like a bit of a tongue twister, the concept is less
complicated when you think of it in graphical form. Following is an example of
what this might look like as a graphical representation, remember the numbers are
purely illustrative, and not intended to represent actual numerical data and
patterns that Processing calculates:

M atrix representing Transformation matrix Resulting matrix


current coordinate stores data about representing new
system translation, rotation coordinate system
and scaling

pushMatrix() = popM atrix()

Transforms 175
An Introduction To Programming With Processing

A Programmatic Solution For Rotating Wheels


Now that we have an idea of what the cart is going to look like when it's moving,
lets concentrate on getting the wheels to rotate and translate.

pushMatrix();
translate(xPos -75 , 250 +25);
rotate(xPos/wheelBd.width);
image(wheelBd, 0, 0);
popMatrix();
image(cart, 0, 0);
image(wheelFd, -95, 35);

As you can see we have removed the image() function that renders the wheelBd
object and placed it between a pushMatrix() and popMatrix() function pair.
Between pushMatrix() and popMatrix() we are free to use translate() and rotate()
to modify the coordinate system before rendering wheelBd with a call to the
image() function. When we originally rendered the three images making up the
cart, we had to offset the back wheel and front wheel so that they we in the correct
places in relation to the position of the main cart. When performing
transformations to an image it's best the have the image transform from the origin.
As a result the X and Y parameters of the image() function used to render the
image should remain at 0, and translations should be used when the image's X and
Y coordinates need to change. This is often the simplest and most logical
approach to working with transforms as it ensures that the image's relative
distance to the origin is not modified which could lead to unexpected results.

Transforms are more predictable when the image() function's parameters are set to 0, 0
for X and Y. Offsets in these parameters will often result in undesirable transformations.

Transforms 176
An Introduction To Programming With Processing

By setting the imageMode() function to CENTER and the X and Y parameters for
the image() function to 0 and 0 we can be assured that the image of the wheel is
going to be rendered with it's center at the origin. This is important because all
transformations are relative to the origin, so that when we rotate the wheel it will
appear to rotate from it's center, this is also due to setting imageMode() to
CENTER and not leaving it at it's default of CORNER which would have resulted
in the wheel appearing to rotate from it's top left hand corner. Bearing this in mind
it is also important that the images that we use for the wheels are square in shape,
in other words the image's width should match the same image's height. This
creates the impression of the wheels being flat on the ground when they start to
rotate. The following statement, is how we remove the image() functions offset
and are still able to match the position of the cart with the mouse's X value:

translate(xPos -75 , 250 +25);

The xPos variable has not changed in terms of how it is applied in this sketch, the
difference is that the X and Y parameter values that were used in the image()
function to render the wheel have now been added to the translate() function's X
and Y parameters. The rotate() function follows:

rotate(xPos/wheelBd.width);

As the xPos variable changes relative to the distance the cart has moved we can
use the changing properties of this variable to make the wheels rotate. We can
then divide this number by the width of the wheel image which is also the
diameter of the circular shape of the wheel. This expression is based on the
formula for pi which is pi = circumference/diameter, but it is worth noting that the
value returned from our modified expression is not equal to pi, as this would be a
constant value as a result xPos is substituted for the circumference of the circle as
this will yield a value that changes relative to the distance that the cart has
traveled.
We can then render the image at the origin after the coordinate system has been
transformed, so the image appears to have moved because the coordinate system
it is rendered relative to has, by then, been transformed.

image(wheelBd, 0, 0);

Transforms 177
An Introduction To Programming With Processing

Finally use popMatrix() to reset the coordinate system back to it's original
transformations.
We can then continue to render the main cart and foreground wheel using the
same techniques, and not have transformations from one rendering effect another.
In the final cart.pde example I've added a shadow, try to figure out how you
would go about creating this effect before looking at the code. Here's a hint, I've
added four additional images to the sketch.

The completed cart.pde sketch

Transforms 178
An Introduction To Programming With Processing

An Introduction to 3D in Processing
Up until now we have been using Processing to create 2D sketches, that is
sketches with 2 measurable dimensions such as width and height, however
Processing allows us easy access to another dimension that being depth. As width
is usually associated with the X axis and height is usually associated with the Y
axis, depth is commonly associated with the Z axis in Processing.

X Z

Axes indicating 3 Dimensions

In Processing we have access to two 3D renderers, P3D and OpenGL. The P3D
renderer is used mainly for 3D sketches on the web, the OpenGL renderer
requires that the machine running the sketch must have OpenGL acceleration
capabilities. Many modern 3D games (particularly those that are commonly
termed platform independent) and most 3D content creation software uses
OpenGL, as it is not specific to Processing and a set of features that abstract the
details of hardware acceleration for software developers. Using the P3D renderer
in a Processing sketch is easy, as this renderer is simply invoked by adding an
extra parameter to the size() function. For example:

size(800, 600, P3D);

This would cause Processing to use the P3D renderer. Using the OpenGL renderer
is slightly different as this requires that the OpenGL library is first imported:

An Introduction to 3D in Processing 179


An Introduction To Programming With Processing

import processing.opengl.*;

All import statements in a sketch should precede all other statements. You can
then use the OPENGL mode as a third parameter for the size() function.

size(800, 600, OPENGL);

A typical example of a sketch using OpenGL might look something like this:

import processing.opengl.*;

void setup(){
size(500,500,OPENGL);
}

void draw(){
background(127);

}

3D Primitives
In a similar way that Processing has 2D primitives such as rectangles, ellipses,
lines etc you will also find a set of 3D primitives such as a box and a sphere.
However you are free to use 2D primitives in a 3D sketch, but not 3D Primitives
in a 2D sketch. One of the fundamental differences that separates the way in
which the functions used to render 3D primitives differs from rendering 2D
primitives, is that 3D primitives do not have parameters for X, Y and Z
coordinates. For example the function to draw a box which is box() can accept
three parameters but these parameters relate to width, height and depth.

So how to we place 3D primitives in a sketch and move them around?


This is achieved with the transform functions we have been using in our 2D
sketches. The main difference is that now we have an additional axis to consider
the Z axis, as a result in a 3D sketch translate() can be used with either 2 or 3
parameters for example:

translate(X, Y);
//or
translate(X, Y ,Z);

An Introduction to 3D in Processing 180


An Introduction To Programming With Processing

Where X, Y and Z would be the numerical values relating to how the coordinate
system is translated. The rotate() function can also be used in the following
context:

rotateX(num);
//or
rotateY(num);
//or
rotateZ(num);

Where num is the numerical value in radians that the coordinate system will be
rotated around the corresponding axis.
Using the box() function and translations here's an example of how we could go
about drawing a simple robot character using OpenGL:

import processing.opengl.*;

void setup(){
size(500,500,OPENGL);
}

void draw(){
background(127);

pushMatrix();
translate(width/2, (height/2)-100);
box(40);
translate(0,80);
scale(0.8,1);
box(80);
translate(70,0);
scale(1,2);
box(30);
translate(-140,0);
box(30);
translate(50,50);
scale(1,1.5);
box(30);
translate(40,0);
box(30);
popMatrix();
}

An Introduction to 3D in Processing 181


An Introduction To Programming With Processing

A simple robot character using the OpenGL renderer

Creating 3D sketches can be fun, but can also become exceedingly difficult for
the beginner as you will often find that a firm grasp of trigonometry is necessary
and depending on what you are wanting to achieve an understanding of vector
math and matrices might also be a prerequisite. However if you are interested in
learning more about creating 3D sketches the best place to start is to work your
way up from creating 2D sketches, that make use of the transformation matrix and
basic trigonometric functions, then try adapt these ideas to include three
dimensions.

An Introduction to 3D in Processing 182


An Introduction To Programming With Processing

Guess My Number Game


Using the information you've learned, thus far you should be able to follow the
code within the guess my number game. Have some fun by modifying the code
and try to make your own!

One of the many possible implementations of The Guess My Number Game

Guess My Number Game 183


An Introduction To Programming With Processing

Object Oriented Programming


Object Oriented Programming is a modern day programming paradigm, meaning
that it is a fundamental style that suits the task of creating modern software. Most
popular modern programming languages support OOP (Object Oriented
Programming), and as a result understanding the fundamental concepts that define
it within Processing can help in implementing it, by means of adapting your
knowledge to suite any programming language that supports Object Oriented
Programming.
Earlier we discussed that OOP can be contrasted with Procedural Programming if
you consider that Procedural Programming is a style of programming where the
program is tailored to suite the data as opposed to Object Oriented Programming
which is more akin to a style of programming where the data is tailored to suite
the program. To briefly recap on these concepts, typically when creating programs
using the procedural programming paradigm we use the programming language's
built-in API features and associate the data we are representing in our program
with the features that are defined by the developers of the language. The data that
is associated with the API features is what we then use in our main program. This
is in contrast to the object oriented programming paradigm where we define new
types of data (called classes) to categorize and associate the data we are
representing in our programs with the programming languages built-in API
features. We then use instantiations of the classes called software objects in our
main program.

From this description you can see that the results of both programming paradigms
can eventually lead to the same thing, however the process of getting to that result
is what distinguishes one programming paradigm from that of another.

Object Oriented Programming 184


An Introduction To Programming With Processing

The Procedural Programming The Object Oriented


Paradigm Programming Paradigm

Data to represent Data to represent

API features API features Class organizes data

Data represented with Objects representing


API features Class

Main Program Main Program

An graphical representation of how OOP contrasts Procedural Programming

OOP as you are aware relies on classes, from which we instantiate objects. These
objects are the reason why we refer to this programming paradigm as Object
Oriented Programming, and emphasize the Object part. We have already been
using classes that are a part of Processing's API such as PImage from which we
have instantiated object variables which we have given names, and those objects
have inherited various properties and functions (called methods in OOP) from the
classes from which they where instantiated. But what exactly is a class?

The concept of a class


A class is simply a body of code that, in a similar way to a function, exists
independently of the main body of code from which it is referenced. However, a
class does not only have a singular purpose like a function that checks the
position of the mouse, or moves and image around in a specific way or has some
other purpose that can be summarized by a singularly specific directive. A class
can consist of many functions, which in the context of OOP we refer to as
methods. These methods can be used like functions of your main program but
with the inherited properties of the class from which it came. As a result you can
think of a method as being a function of a class, that when used in your main
program will, like a function, have a definition independent of the main program
and also have properties that are specific to the class it was instantiated from.

Object Oriented Programming 185


An Introduction To Programming With Processing

The benefit of this is that when multiple objects are instantiated from a single
class they all inherit the methods of that class, this allows you to use certain
methods with one object and certain other methods with another object. Thereby
creating relationships between those objects (and ultimately the data you are
representing with you main program) with other data or API features in ways that
would be very difficult or maybe not practically possible without OOP.

Branch 01

M ethod 1

Branch 02

Class Object 1 M ethod 3


Method 1
Method 2 MAIN PROGRAM
Method 3 Object 2 M ethod 2 Function Call
Function
Definition

M ethod 2

Branch 04

Branch 03
One class can result in many different branches.

The Blueprint Analogy


By creating classes we categorize the data we are representing and give these
representations a context by associating them with features in the programming
languages API. However a class is never used in the main program, it must first
be instantiated as an object and the object is what we would use in our main
program. In this sense a class is more like a blueprint, that describes the complex
relationships between the data we are representing, like the blueprint of a house
can describe how tall a wall will be or how far a window will be from the ceiling.

Object Oriented Programming 186


An Introduction To Programming With Processing

If you can imagine a class to be like a blueprint then a software object is like a
house made from that blueprint. For example, a class only describes the possible
objects that can be instantiated from it, taking the blueprint analogy further we
cannot live in a blueprint yet it has all the information we need to build a house
which would be something that we use as a functional object. In other words we
use the blueprint to build a house, this is just like instantiating an object from a
class. The class only describes the possibilities of an object that can be
instantiated from it and when we finally do instantiate an object from the class, it
is the object that we use in our main program.
Just like a blueprint describes a structure it does not say anything about how the
structure can be used for example a blueprint can be used to build somebody's
home or the same blueprint can be used to build an office. The purposes the
buildings serve are different, but the structure of the buildings remains the same.
The relationship between classes and software objects is very similar, in that one
object instantiated from class can serve a certain purpose and another object
instantiated from the same class can serve a different purpose, but because both
objects are instantiated from the same class the context in which they are used
will tend to have similarities.

A single blueprint could be used to make several derivatives

Object Oriented Programming 187


An Introduction To Programming With Processing

Why use Object Oriented Programming


One of the fundamental concepts that makes OOP so popular is known as data
encapsulation. We have already discussed how a variable can have a greater or
lesser scope depending on where it is declared, that is to say that when a variable
is not declared within the global variable scope it can only be accessed in some
parts of a program and not in others that are outside of the structure in which it
was declared. The range over which the variable is accessible refers to the
variable's scope. Data encapsulation is a similar concept, except that the concept
of hiding data is emphasized as opposed to defining a variable in the global
variable scope where the concept of exposing data is emphasized. Another
major difference between the two concepts is that with data encapsulation as
opposed to variable scope we are not referring to a single variable but can, in fact,
be referring to entire structures. These structures that we make inaccessible to the
main program are what form the body of code that defines a class. By defining a
class we use a modular approach to designing software, in the sense that the class
that we have defined is not necessarily specific to the program we initially wrote
it for, and as a result can be used in our program or removed from our program
without us having to rewrite the entire program this is an inherent design
characteristic of data encapsulation.
Amongst other applications, creating a class defines the behaviors that an object
instantiated from it will inherit. In order to interact with an object in a program,
and subsequently use that which it has inherited from a class, we interact with the
object via it's behaviors which are more commonly referred to as methods. This is
a form of data encapsulation, in that we do not have direct access to how that
object works as that is defined within the class. However we can still have the
object interact with our main program through it's methods. In this sense Object
Oriented Programming can provide a level of abstraction, when working with
objects in the main program.

Creating a Class
As previously mentioned a class typically consists of method definitions and
various fields (which we also refer to as member variables) that store information
about the current state of the object instantiated from the class. The term fields
refers to variables that are members of a particular class, and as a result are
encapsulated data that store information about the object itself and are sometimes
referred to in Processing as class data.

Object Oriented Programming 188


An Introduction To Programming With Processing

Typically in Processing creating a class is a four step process that involves,

1)Class Name creation


2)Field declarations
3)Constructor creation
4)Method definitions

The structure of a class looks similar to setup() and draw() and user defined
functions, but since a class is not a function, but may contain many functions
(called methods) it's name is not followed by parenthesis. An object variable
name which we will have a look at shortly, on the other hand is followed by
parenthesis in order to provide a means of communicating with the object's
internal structure.

void setup(){
}
void draw(){
}
class ClassName{
}

As you can see a class definition usually finds it's place at the very end of a
sketch, this is sometimes referred to as an in-line class definition. This simply
emphasizes that the class is directly related to the sketch that it is defined within.
As defining a class at the end of a sketch, after user defined functions, mouse and
keyboard functions etc can create a cluttered looking sketch Processing also
provides us with Tabs in which we can place additional code that will be compiled
with the sketch we are currently working on. You can create a new tab by clicking
the arrow pointing to the right on the far right of the PDE and a fly-off menu
relating to Tabs will appear.

The Tab fly-off menu from the PDE

Object Oriented Programming 189


An Introduction To Programming With Processing

Processing will then ask you to provide a name for the new tab.

Creating a new Tab

Once you supply a unique name and click OK Processing will create a new blank
Tab next to the original Tab. What has actually happened is that Processing has
created a new .pde file that has the name you specified for the Tab that was just
created. This new .pde file resides in the same location as the sketch you are
currently working on, as a result it can access anything in the data folder that you
can access from the code of the original Tab. Although Processing has created
another .pde file this file is only part of a sketch. In a similar way that the original
pde file can be reliant on the contents of the data folder, the new .pde file in the
same location as the original .pde file can also be reliant on the original .pde and
the contents of the data folder. As a result we refer to this collection of elements
(i.e. pde files, txt files, spreadsheets, images and anything else that is in the data
folder used in the sketch) collectively as the contents or components of a sketch.
Using additional Tabs in a sketch provides us with a convenient location for
placing classes. This is useful because it emphasizes the modular design of classes
and clears the main .pde file from becoming over-cluttered with code. Working
with additional tabs is not synonymous to working with multiple sketches.
Multiple tabs are a means of breaking up the current sketch you are working on
into smaller manageable portions of code. As a result when a sketch with multiple
Tabs is run all the code within all the Tabs of that sketch are compiled together.
This means that only one of the Tabs should have setup() and draw() structures,
the other Tabs should be used for class definitions, user defined functions or other
elements of a sketch that exist outside of setup() and draw() structures.

Object Oriented Programming 190


An Introduction To Programming With Processing

A Button Class
If we wanted to create a class for a button, that we will call Button. This class will
have
fields that will contain certain information about the object instantiated
from the class such as the color of the button, it's size and position.
The class will also have a constructor that will use the class's fields to
create an initial state for the object.
Finally the class will have two methods, one that renders (or displays) the
button and another that tests whether the user's mouse is over the button.

The completed buttonClassExample file

Class Name
In order to give the class a name and let Processing know that we are about to
create a class we must use the class keyword. The name of a class generally starts
with an upper-case character. For example. We'll start by adding a new tab and
calling it Button. In this tab add the following code:

class Button{
}

This is how we create a class and name it in Processing. As you can see the class's
name is Button which starts with an upper-case character, with regards to popular
standardized coding practices.

A Button Class 191


An Introduction To Programming With Processing

Fields
When we instantiate an object from this class there are several properties we'd
like this object to inherit from the class, which we will have access to modifying
from the main program but not be able to modify the definitions of these
properties as this will be encapsulated within the Button class. A list of the these
properties follow:

1. the color of the rectangle that will visually represent the button object,
2. the object's X coordinate
3. the object's Y coordinate
4. the object's width
5. the object's height
6. and a name for the object.

As a result we will need at least all six of these properties represented in the
class's fields as variables.
Let's add those fields to the class, inside the braces of the Button class add the
following declarations:

color cB;
float xLocB;
float yLocB;
float xSizeB;
float ySizeB;
String nameB;

As you can see each of these variables will hold the information related to the
previous list of six items.

Constructor
To give you an idea of how these fields (or variables) will be used we need to fast
forward a few steps into the future and take a quick look at what happens when
we instantiate the class. The process of creating an object is actually nothing new
to you, as you have already instantiated objects from the PImage class. One of the
main differences with our Button class is that we will be using it's constructor to
initialize objects instantiated from it, so when we get to doing this we will use an
initialization statement that will in part look like this:

A Button Class 192


An Introduction To Programming With Processing

//this is simply for illustrative purposes


Button(cB, xLocB, yLocB, xSizeB, ySizeB, nameB);

From this partially complete code fragment, Button accepts the parameters the
user has input, which will be assigned to the object's fields (which were inherited
from the class's fields). These parameters will be used to initialize the object
instantiated from the Button class. However at the moment, these variables don't
really do much, or store any information that will help in constructing the button
object. This is why we need a constructor. The constructor is like a method that is
automatically called every time a new object is instantiated from a class.
The main purpose of a constructor is to determine a default state that an object
will exist in as soon as it is instantiated. The constructor is defined below the
fields declaration of a class and our constructor will look like this:

Button(color tempcB, float tempxLocB, float tempyLocB, float


tempxSizeB, float tempySizeB,String tempNameB){
cB = tempcB;
xLocB = tempxLocB;
yLocB = tempyLocB;
xSizeB = tempxSizeB;
ySizeB = tempySizeB;
nameB = tempNameB;
}

Note that the constructor has the same name as the class, this is a requirement for
using a constructor. When we refer to Button() we are actually referring to the
constructor of the class and not the class itself, which we simply refer to as
Button.
The first line of the constructor tells Processing how the Button class will accept
parameters when a new object is instantiated from it. You might have also noticed
that we have declared six new variables that will temporarily store the values that
the user inputs as parameters when an object is instantiated. These values will
then be assigned to the original member variables which will store the values that
the user has input as parameters when instantiating the button. Using this
approach to designing a constructor ensures that multiple objects can be
instantiated using different parameters with the same constructor.
At this stage in the design of the Button class we have fields declaring the
member variables that will be used to store information about the button, and how
we would like to use those fields to construct the button, but we have not told

A Button Class 193


An Introduction To Programming With Processing

processing to actually draw the button to the Display Window so that the user can
see a visual representation of the object and interact with it. This is amongst one
of the many reasons why class's have methods.

Methods
In order to render this visual representation we're going to create a method called
disp() which will create a rectangle from the parameters the programmer inputs
into the Button() constructor when instantiating a new object. Just like user
defined functions methods must use the void keyword if they do not return a
datatype. Here's what our disp() method (short for display method) will look like:

void disp(){
fill(cB);
rect(xLocB, yLocB,xSizeB, ySizeB);
fill(0);
text(nameB, (xSizeB/2)+xLocB-((xSizeB/2)/2),
(ySizeB/2)+yLocB+((ySizeB/2)/2));
}

Creating a method follows the same routine as creating a user defined function.
Our disp() method is really quite simple all it does is accept the cB variable as a
fill() color, draw a rectangle with the positional data from xLocB and yLocB and
finish the rectangle by determining it's size from the xSizeB and ySizeB
variables. The method then goes on to set the fill() to black and render the name
of the button (nameB) in the center of the button.
A class can be as simple or a complex as you want, and since we have all the main
ingredients of our class we're going to return to our main program and have a look
at how to instantiate an object from this class.

Object Instantiation
Object instantiation is not a new concept to you as you have already instantiated
objects from the PImage class. The process of instantiating an object from our
Button class will follow a very similar pattern.
Since we want this object to be accessible from both setup(), draw() and user
defined functions we are going to declare an object variable in the global variable
scope by adding the following declaration outside of both setup() and draw():

Button myButton;

A Button Class 194


An Introduction To Programming With Processing

We now have a variable name that we can use to reference the object we just
instantiated from the Button class, this name is myButton.
Within the setup() structure we'll initialize the button, by use of it's constructor:

myButton = new Button(color(255), width/2, height/2, 100, 40,


"myButton");

myButton (the object variable) has inherited the properties of the Button class. If
you were to compare this statement with the modified example of the class's
constructor:
//this is simply for illustrative purposes
Button(cB, xLocB, yLocB, xSizeB, ySizeB, nameB);

You will notice that this button is currently being constructed, but remember that
you will not actually see the button at this stage as all we have done is told
Processing how we would like the button to be constructed we have not told
Processing to actually display the button. The use of the new keyword in the
previous listed assignment statement is followed by the class's constructor which
is why we are using Button() and not Button.
Now that we have told Processing how we would like this new button constructed
let's move onto the draw() structure and actually render the button.
Using an object's method is easy, and is very similar to a function call. The main
difference is that the name of the method is preceded by the name of the object
itself. For example:

myButton.disp();

Add this statement to the draw() structure, and you'll finally see your button.

The button instantiated and displayed by it's disp() method

A Button Class 195


An Introduction To Programming With Processing

As you can see when working with OOP the main program looks less cluttered
with code and the majority of the code exists in creating classes. This for many
people creates a more readable interface for designing software, and once you get
the hang of using OOP it can also help to localize problematic code that might be
difficult to locate without a program adopting a modular design.
The completed sketch ButonClassExample.pde also contains another method
called over() which will identify if the users mouse is over the button, if you take
some time to examine the sketch you should be able to add your own
functionality to the button.

A Button Class 196


An Introduction To Programming With Processing

Working with external data


There are many ways of getting data into a Processing sketch from importing a
simple image, 3D geometry or importing spread sheet data and the list goes on.
But amongst the simplest and most versatile methods of getting external data into
Processing is by means of a text file.

A simple text file

A text file imported into a sketch should have the file extension .txt. A word
processor document might have additional formatting and as a result might
produce unexpected results when used in a sketch. For this exercise it is
recommended that you use the file named names.txt in the data folder of the viz05
exercise directory.
Importing a text document into a sketch works in the same way that images are
imported into a sketch. Locate the file to be imported and click and drag it into the
PDE with the sketch you are working on. The PDE will report that a file has been
added successfully to the sketch and if you were to open the sketch's data folder
you will find a copy of the file in there. In order to display the contents of the
names.txt file in the Display Window we will use an array of Strings with each
element of the String array representing a line of characters in the names.txt file.
Lets have a look at how to do this.

In the global variable scope declare a new array of Strings and call it names:

String[] names;

Working with external data 197


An Introduction To Programming With Processing

Notice that declaring an array like this does not indicate how many elements will
be in the array. This is because we want Processing to tell us how many elements
are going to make up this array. In other words if we had a text document with
many lines each of which was intended to be an element in an array, instead of
counting the lines in the text document and creating the array like so:

String[] names = new String[10560];

We would use the former method were the number of elements is decided by
Processing and if we wanted to know how many elements Processing has
populated the array with, we would use the array's object variable, length to find
out. We'll have a look at how to do this a bit later.
In setup() we're going to populate the array with the loadStrings() function, which
will accept one parameter that is the name of the text file containing the data that
will be used to populate the array.

names = loadStrings("names.txt");

We now have an array of Strings that we can refer to by it's variable name called
names. This array has several elements each consisting of a String representing
each individual line of the names.txt file.
Finally to display the information contained within the elements of the names
array we will use the text() function within a for loop:

void draw() {
for(int i = 0; i < names.length; i++){
text(names[i], 20, i*20 + 20);
}
}

The array object variable's names.length data stores the amount of elements in the
names array, this information is important for creating the test of a for loop
iteration.
The text() function uses each element in the names array as a data input
parameter, subsequently rendering each line of the text file one after the other and
offset on the Y axis.

Working with external data 198


An Introduction To Programming With Processing

The loadStringsExample.pde file

Using this technique of loading external data does not have to be confined to
working with the Strings datatype. Typecasting provides a convenient approach to
converting String data into numerical data that can be calculated. Here's an
example of the loadStringsExample.pde file that does just that with a file
containing numbers. It is worth noting that although when you open the
numbers.txt (in the viz05 data directory) file it reveals a list of numbers to you,
when this information is read into our sketch Processing identifies this data as
String data. Which is why we must first typecast each element of the numbers
array with the int() function into an int datatype before we can perform addition
on the data.

String[] names;
String[] numbers;
int tCast;

void setup() {
size(300,300);
smooth();
names = loadStrings("names.txt");
numbers = loadStrings("numbers.txt");
}
void draw() {
background(100);
for(int i = 0; i < names.length; i++){
text(names[i],20,i*20 + 20);
}
for(int i = 0; i < numbers.length; i++){
tCast += int(numbers[i]); //typecasting int(numbers[i])
}
text(tCast,250,20);
}

Working with external data 199


An Introduction To Programming With Processing

Attribution

Images

Apollo Guidance Computer 10


Copyright NASA
NASA Manned Spacecraft Center 10
Copyright NASA
Japanese Rickshaws 11
Public Domain
Medical Equipment 14
Copyright the owner of the image
Gambling Machines 15
Yamaguchi /Wikipedia
Alan Turing 16
Copyright the owner of the image
LOLCAT image 17
M-J
Processing.org image 41
Copyright the owner of the image
Star Wars ARC-170 Starfighter Guess My Number Game
Cody Borst (Sqorck)
Coat of Arms Icons Social Commentary Viz
Copyright the owner/s of the images

Attribution 200

Você também pode gostar