Hello Processing - Vula
Hello Processing - Vula
Hello Processing - Vula
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
An Introduction To Programming With <strong>Processing</strong><br />
This publication is released under a Creative Commons Attribution-<br />
NonCommercial-NoDerivs 3.0 License. CC BY-NC-ND 2011<br />
You are free to share, and redistribute this publication in whole, but not in part<br />
under the following conditions.<br />
The person identified as the author in the following terms is also known as<br />
Lyndon Daniels and is the owner of the domain name<br />
http://www.lyndondaniels.com<br />
“Classified works of the author” and “a classified work of the author” will include<br />
all content and redistributions of the content, that the author has created and is<br />
licensed to the author by de facto or de jure.<br />
“This publication” refers to the document you are currently reading in it's entirety<br />
and is also a classified work of the author.<br />
1. This publication and all redistributions of this publication must remain as<br />
is, and not in any way be modified.<br />
2. All redistributions of the source code and related material, including but<br />
not limited to the images associated with this publication, that are not<br />
licensed under other terms or are not classified works of the author, also<br />
fall under the same license of this publication.<br />
3. Attribution must be given to the author for all redistributions of the<br />
classified works of the author.<br />
4. Acceptable attribution for redistributions of this publication must associate<br />
the publication/s duplicated as being a classified work of the author.<br />
5. This publication is only to be redistributed digitally and not to be<br />
redistributed in any other format including, but not limited, to print.<br />
6. No capital or commercial profit, monetary or other, is to be gained from<br />
this publication or redistributions of this publication without the author's<br />
consent. This includes, but is not limited to selling and/or trading this<br />
publication or any redistributions.<br />
7. All redistributions of this publication are to be released under the same<br />
license that this publication is released under.<br />
8. The author solely reserves the right to change this agreement at any time.<br />
For additional information regrading this license please see<br />
http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode<br />
2
An Introduction To Programming With <strong>Processing</strong><br />
Table Of Contents<br />
About This Guide 7<br />
Hardware and Software Theory 7<br />
What is Programming? 7<br />
How does Programming relate to Hardware and Software? 8<br />
Abstraction 10<br />
Speed 11<br />
Efficiency 12<br />
Disambiguation 14<br />
The Unique Qualities of a Programming Language 17<br />
Lower Level Languages and Higher Level Languages 20<br />
An Analysis of a Computer Program 22<br />
Commands 23<br />
Expressions 23<br />
A Scalable Software Development Model 25<br />
Plan 25<br />
Research 26<br />
Mockup Designs 27<br />
Data Acquisition: Sourcing The Data Needed For Your Project 28<br />
Filter 29<br />
Clustering and Data Mining 29<br />
Parsing 32<br />
Determining Flow of Control Through Stepwise Refinement 32<br />
Implement, Test and Document. Repeat 34<br />
Deliver 35<br />
Why Learn Programming using <strong>Processing</strong>? 36<br />
Code For Artists 36<br />
Java Based 36<br />
Open Source 37<br />
PDE 38<br />
Source Code Editor 40<br />
Build Automation Tools 40<br />
Compiler and/or Interpreter 41<br />
Debugger 42<br />
Active Online Community 43<br />
Table Of Contents 3
An Introduction To Programming With <strong>Processing</strong><br />
<strong>Hello</strong> <strong>Processing</strong> 44<br />
Install <strong>Processing</strong> 44<br />
Sketches 44<br />
<strong>Hello</strong> World Program 1.0 45<br />
The println() Function 47<br />
Syntax And Syntax Errors 48<br />
Logical Errors 50<br />
Display Window 50<br />
Standardized Coding Practices 52<br />
Comments 52<br />
Whitespace 53<br />
Program Notes 54<br />
Cartesian Graph and the <strong>Processing</strong> Coordinate System 54<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 56<br />
text() 56<br />
Program Notes 57<br />
Formatting Text 58<br />
Color 59<br />
Drawing 62<br />
2D Primitives 62<br />
The Origin of an Ellipse 63<br />
Aliasing 66<br />
Smile 66<br />
Angles in <strong>Processing</strong> 66<br />
Editing the Smile 69<br />
Adding Eyes 72<br />
Drawing Irregular Shapes 73<br />
Order, Order! 78<br />
Finishing the Sketch 78<br />
Programming Paradigms 80<br />
Datatyping Categories 81<br />
Primitive Data Types 81<br />
<strong>Processing</strong> API Data Types 82<br />
User Defined Complex Data Types 83<br />
PImage 83<br />
The Design and Layout Program 86<br />
Program Notes for Interface01.pde 86<br />
Table Of Contents 4
An Introduction To Programming With <strong>Processing</strong><br />
The PDE Tools Menu 86<br />
Beyond Static Sketches and on to Active Mode 90<br />
Methods, Functions and their contexts 91<br />
The setup() function 92<br />
The draw() function 94<br />
Experimentation 96<br />
Datatyping 101<br />
Variables 102<br />
Variable Scope 104<br />
Interacting with Images 106<br />
Friction Simulation 109<br />
Variable Naming Conventions 111<br />
Planning and Pre-debugging 112<br />
Implementing a Programmatic Solution 114<br />
Constraining Values 116<br />
Branching 118<br />
The if() structure 120<br />
Relational Operators 121<br />
Comparison 121<br />
Extending the if() structure with else 124<br />
Extending the if() construct with if else if else 126<br />
Logical Operators 127<br />
Interface Controls Setting up a Slider 128<br />
User Defined Functions 130<br />
Creating a User Defined Function 134<br />
Datatyping a Function 134<br />
Determining a Range 134<br />
Returning Data from a Function 138<br />
Dragging the Slider Button 140<br />
Setting up Regional Constraints 142<br />
Finishing the Slider 144<br />
Mapping Values 144<br />
The Mystery Shape Maker 148<br />
Arrays 149<br />
Program Notes 153<br />
Dynamic Assignment for Elements in and Array 155<br />
Iterations 158<br />
Table Of Contents 5
An Introduction To Programming With <strong>Processing</strong><br />
Transforms 162<br />
An Introduction to 3D in <strong>Processing</strong> 176<br />
3D Primitives 177<br />
Guess My Number Game 179<br />
Object Oriented Programming 181<br />
The Concept of a Class 182<br />
The Blueprint Analogy 183<br />
Why Use Object Oriented Programming 185<br />
Creating a Class 185<br />
A Button Class 188<br />
Object Instantiation<br />
Working with External Data 193<br />
Attribution 197<br />
Images 197<br />
Table Of Contents 6
An Introduction To Programming With <strong>Processing</strong><br />
About this Guide<br />
Introduction to Programming with <strong>Processing</strong> is a guide to creating interactive<br />
software with the programming language, <strong>Processing</strong>. The main focus of the<br />
documentation is to give the reader an understanding of the programming<br />
language, <strong>Processing</strong> and also to give the reader the knowledge to apply an<br />
understanding gained from reading this documentation to learning other similar<br />
high level programming languages.<br />
Hardware and Software Theory<br />
What is programming?<br />
A software program is a set of instructions issued to a computer via source code.<br />
Source code is data that usually resembles a text document which is typed in a<br />
specific programming language that is somewhere between a language that<br />
computers can process efficiently and humans can understand. The task of<br />
creating source code is known as programming.<br />
Human readable source code on the left and machine code on the right.<br />
Although source code does not make sense at first glance to someone new to<br />
programming, when compared to it's equivalent in machine code it definitely looks more<br />
appealing.<br />
Hardware and Software Theory 7
An Introduction To Programming With <strong>Processing</strong><br />
How does programming relate to hardware and<br />
software?<br />
Before we get into the process of creating software programs, lets first examine<br />
the relationship between a software program and a computer.<br />
One of the fundamental functions of a computer is it's ability to control electrical<br />
energy and ultimately transform that energy into another form of energy such as<br />
light, sound or motion. We use software to communicate with a computer, which<br />
will determine the various paths that the electrical energy will take, in order to<br />
achieve the goal we have stipulated through programming.<br />
Computers are designed to react to electrical energy, this energy can be of a high<br />
or low voltage and forms the basic premise of all the complex interactions that<br />
exists between humans and computers. These high and low voltages of electrical<br />
energy are relayed within the circuitry of a computer in very short intervals that<br />
allow us to distinguish one from the other and will eventually be sequenced<br />
together to form a protocol for communicating with computers.<br />
This protocol of communication we represent with two numerical digits a 1 and a<br />
0, which to a computer equates to a high and a low voltage. We refer to this form<br />
of representation as Binary Code. Of course, this representation means nothing to<br />
a computer as it is only reacting to the electrical energy that is being relayed<br />
within it's circuitry. But to us using a 1 and 0 as a form of representation creates a<br />
means for every simple to complex interaction we have with computers through<br />
software.<br />
By combining various sequences of 1's and 0's (and ultimately sequences of high<br />
and low voltages) followed by more sequences of 1's and 0's arranged in similar<br />
or different patterns the effect of a continuous flow of energy is created that<br />
results in light or sound or one of the many other capabilities of a computer. The<br />
fact that this flow of electrical energy is broken up into smaller chunks means that<br />
each chunk can be made up of a different sequence of 1's and 0's which could be<br />
used to create the impression of a change or variation which could finally be<br />
perceived as an image moving in an animation or the diaphragm of a speaker<br />
vibrating at different amplitudes which, for example, we ultimately perceive as<br />
the sound of our favorite track.<br />
Hardware and Software Theory 8
An Introduction To Programming With <strong>Processing</strong><br />
Although useful, representing data in this way can become quite cumbersome and<br />
error prone. If developing software meant having to learn endless sequences of<br />
binary code, becoming a programmer would be a very daunting task. This is,<br />
however, not the case as we can use a 1 and a 0 to represent a high and a low<br />
voltage we can use a sequence of 1's and 0's to represent more complex ideas<br />
such as a larger number like 155 which can be translated into binary as 10011011.<br />
This form of representation can furthermore be extended to include typographic<br />
characters, which in themselves can be strung together in sequences to create<br />
words, which can in themselves be strung together to issue commands to a<br />
computer through programming. We refer to this process as abstraction.<br />
Programming in it's simplest form is the process of creating and modifying a<br />
series of 1's and 0's that influences the path of the electrical current, by means of<br />
abstraction.<br />
At some point everything that a computer processes (including our own<br />
interactions with it) has to exist in binary code representations. However, it's<br />
important to remember that binary code is simply just a human representation, for<br />
determining a sequence of high and low voltages, that we use to make the<br />
complexities that occur within a computer more understandable to us.<br />
As I mentioned earlier, a computer does not really care about what form of<br />
representation we use, however this process of representing data certainly does<br />
make it a lot easier to communicate with computers.<br />
We interface with computers via software which allows us to work in an individual<br />
capacity, whenever applicable, in fields that would previously have required teams of<br />
people working together.<br />
Hardware and Software Theory 9
An Introduction To Programming With <strong>Processing</strong><br />
Abstraction<br />
Representing the abstract concept of something like data in the form of high and<br />
low voltages with a series of 1's and 0's can be quite useful, but still very difficult<br />
to read and understand. Imagine having to memorize all of those sequences in<br />
order to be an efficient programmer. It would take exorbitant amounts of time to<br />
create the simplest of software programs. Fortunately the process of representing<br />
human-relevant concepts to a computer does not stop at binary code. Since we<br />
know that a certain sequence of 1's and 0's on a certain type of machine such as<br />
the sequence “00110101” can be used to represent the number “53” why not make<br />
the sequence “01001000” and “01101001” represent the characters “h” and “i”<br />
put together to make the word “hi”. This is exactly what software developers do,<br />
the process of taking a complex set of data and representing it in a more humanreadable<br />
format is known as abstraction. As you can image this makes it a lot<br />
simpler to communicate with a computer, so instead of typing “01001000<br />
01101001” we can simply type “hi” and thanks to the process of abstraction our<br />
computer knows what to display even though it's reading a sequence of high and<br />
low voltages at the simplest level.<br />
Abstraction is great because it makes the process of communicating with<br />
computers easier, so you might be thinking to yourself why then is programming<br />
and source code so cryptic and far removed from a common natural spoken<br />
human language such as English? Surely, if we can abstract complex data why<br />
not keep on abstracting concepts to computers until it can understand a human<br />
specific language like plain and simple English?<br />
For example if we wanted to draw a circle on a computer screen why can't we just<br />
say to a computer:<br />
“Computer, could you please draw a circle that has a diameter of<br />
55 pixels and who's center is somewhere close to the top left of<br />
my screen, thanks?”<br />
Instead we communicate with our computers like this:<br />
ellipse(56, 46, 55, 55);<br />
Abstraction 10
An Introduction To Programming With <strong>Processing</strong><br />
There are three main issues to consider here speed, efficiency and disambiguation.<br />
Speed<br />
One of the main reasons we cannot continue to abstract our communications with<br />
computers to the point where everyday English is used, is due to the speed at<br />
which data can be processed.<br />
As we abstract data in order to make it more human-readable that same data<br />
becomes less machine-readable, and in order for a machine to be able to make<br />
anything useful out of that data it must first convert that data into a machinereadable<br />
format.<br />
All of this abstracting and un-abstracting requires valuable system resources and<br />
energy, system resources and energy that could be used more effectively<br />
elsewhere. Subsequently as we move further away from machine code we require<br />
faster more powerful computers to process the data we create.<br />
It's estimated that under certain circumstances a consumer grade Intel Core i7 3.3<br />
GHz processor can preform 147,600 Million instructions per second, and if<br />
you've ever used one of these processors you'll probably also note that even with<br />
all of that processing power there are certain situations where your computer can<br />
still lag!<br />
This does not necessarily have anything to do with the processor specifically but<br />
simply due to the massive amounts of data that an average modern day computer<br />
is expected to cope with. To put this into perspective consider that 40 years ago in<br />
order to send a man to the moon computers with a clock speed of 0.043MHz and<br />
64Kbyte of RAM were required to run software ranging about 6MB in size, by<br />
today's standards a single modern day home computer could be about 77 million<br />
times more powerful than the computers used to launch a space shuttle, navigate<br />
it to the moon and safely return it to earth such as the Apollo Guidance Computer.<br />
In retrospect the modern day needs we place on our computers can be somewhat<br />
demanding.<br />
Abstraction 11
An Introduction To Programming With <strong>Processing</strong><br />
The Apollo Guidance Computer used on Apollo 11 on the left and the NASA Manned<br />
Spacecraft Center on the right. Technology from the 1960's.<br />
Efficiency<br />
Like any natural language, computer languages are built around their<br />
environments. Human cultures have developed languages as a means of<br />
communicating their perceptions of internal, conceptual and external<br />
environments. However what exists in one environment might not be a part of<br />
another. Subsequently, a string of words might be used to describe something that<br />
is uncommon to one environment, whereas in another culture where that thing is<br />
common a single word might be used to describe it.<br />
For example a visitor traveling to Japan in the late 1800's might describe a<br />
specific mode of transport as:<br />
“A human-powered two wheeled cart, that seats one or two people<br />
reserved for the social elite.”<br />
However a person familiar with this mode of transport might have a specific name<br />
for it, such as:<br />
Abstraction 12
An Introduction To Programming With <strong>Processing</strong><br />
“Rickshaw”<br />
Rickshaws are not a common sight in modern times but where a regular mode of<br />
transport in Japan, in the 1800's<br />
Obviously if you are living in an environment where such things are common<br />
using a single word that can effectively describe a whole sentence can be a more<br />
efficient means of communication.<br />
Computer languages are similar in this way, each language is developed to run<br />
efficiently under certain conditions and circumstances yet the same language may<br />
perform less efficiently under a different set of circumstances.<br />
What qualifies as an optimal environment for a computer's programming<br />
language is something that the developer of that language will have to define. An<br />
environment in this sense could be an operating system, the world wide web, a<br />
network, or a combination of these environments. This could also be a large<br />
contributing factor, possibly explaining why there are so many different computer<br />
languages currently in existence each with it's efficiency optimizations for<br />
specific “environments”.<br />
Currently Wikipedia lists approximately 661 popular computer languages and this<br />
number is constantly growing compared to it's listing of 540 currently spoken<br />
languages (not including their derivatives). Of course there have been many more<br />
Abstraction 13
An Introduction To Programming With <strong>Processing</strong><br />
spoken languages throughout human history, The Cambridge Encyclopaedia of<br />
Language estimates this number to be between 3000 to 10000, but then again<br />
what actually qualifies as a language is a whole other topic for discussion in itself.<br />
Computer languages share in this ambiguity. Throughout the comparatively short<br />
history of computer languages, which can arguably be traced as far back as the<br />
first programmable computer, the Z1 invented by Germany's Konrad Zuse in<br />
1938, programmers have seen languages raise to popularity and become virtually<br />
obsolete, one such language is LISP. LISP was in many ways synonymous with<br />
Artificial Intelligence (AI) from the mid 1950's till the early 1970's but gradually<br />
gave way to a dwindling numbers of devotees, who where lured by new<br />
programming paradigms such as object oriented programming and other higher<br />
level programming language concepts, which we will explore in greater detail<br />
later. Although this language never really died, some would say it became<br />
somewhat antiquated. Nonetheless, LISP started to regain popularity in the mid<br />
1990's in a new implementation currently known as Common LISP. Determining<br />
whether a programming language closely based on a previous programming<br />
language should be considered a new language that is able to stand on it's own,<br />
can be a difficult distinction to make and can add considerably to the ambiguity<br />
around what defines and distinguishes one computer language from another.<br />
<strong>Processing</strong> too, has been subject to this topic of debate as it's roots in the<br />
programming language Java have seen it referred to as a library for Java while<br />
others identify it as stand-alone programming language.<br />
Regardless of whether a programming language derived from another can stand<br />
on it's own or not one of the key factors that determine it's popularity, and<br />
ultimately contributes to a following of devotees that develop and maintain the<br />
language, is the language's ability to achieve a balance of being fast enough for a<br />
computer to process but easy enough for a human to read. It is this balance that<br />
currently determines the efficiency of a computer's programming language.<br />
Disambiguation<br />
Computers tend to be very literal. They accept specific instructions more readily<br />
than vague descriptions of what you are hoping to achieve with their help. Such<br />
that a statement like the above mentioned, and repeated below:<br />
“... draw a circle that has a diameter of 55 pixels and who's<br />
Abstraction 14
An Introduction To Programming With <strong>Processing</strong><br />
center is somewhere close to the top left of my screen...”<br />
would not be as effective as the statement:<br />
ellipse(56, 46, 55, 55);<br />
The first statement although a perfectly acceptable command issued in English,<br />
would fail dismally when translated directly into computer-speak for several<br />
reasons relating to the ambiguity associated with it.<br />
Firstly the longer a command tends to be the more prone it is to incorporating an<br />
erroneous syntax. Computers are very specific about the type of syntax you use to<br />
communicate with them. Syntax in terms of the English definition is the particular<br />
arrangements of words making up a sentence. In computer terms, syntax has a<br />
very similar meaning but is even more relevant and specific in it's<br />
implementation. Words must follow a particular sequence within the context of a<br />
command issued to a computer determined by the language you are currently<br />
programming in, and may not be rearranged into various discourses simply<br />
because you find them to be more meaningful.<br />
Computers have truly amazing mathematical capabilities and predictably<br />
congruent mediocre social skills. Subsequently concepts such as circles and<br />
squares which are simply mathematical concepts abstracted for human<br />
convenience have little or no relevance to a computer. For example if you were to<br />
consider that a circle, as per another description, could be an ellipse with<br />
equidistant radii to each point encompassing it's edge; or technically speaking a<br />
square is actually a rectangle with it's height equal to it's width. Descriptive<br />
abstractions such as these for human convenience are in fact very inconvenient<br />
for a computer, and as a result in <strong>Processing</strong> we refer to a “circle” and an “ellipse”<br />
using <strong>Processing</strong> specific syntax that removes the ambiguity and abstraction for<br />
the convenience of a spoken language and groups them into the same context.<br />
Subsequently if we want to describe a circle we refer to it as an ellipse with equal<br />
dimensions in height and width or more specifically:<br />
ellipse(56,46,55,55);<br />
Finally I'm sure that if computers had a sense of humour, they would find our<br />
former description of the location of our circle “ somewhere close to the top<br />
Abstraction 15
An Introduction To Programming With <strong>Processing</strong><br />
left of my screen” to be somewhat uninformed and laughable, not to mention<br />
words such as “somewhere” and “my” which might condition a response<br />
equivalent to that of an existential dilemma for a computer. If you supply a<br />
computer program with specific screen positions in terms of x, y and z and<br />
dimensions in terms of width, height and depth either communicated explicitly or<br />
implicitly through an expression (which is something we will discuss in more<br />
detail later) you will find your programs to have more predictable and efficient<br />
results and would help to remove ambiguities that could lead to errors. Screen<br />
space and dimensions are concepts we will be dealing with in more detail in later<br />
chapters. Of course there are times when randomness and unpredictability are<br />
desirable qualities in a program, in which case no other resources available to<br />
man can produce a series of unpredictable results more efficiently than<br />
computers. This is a testament to why people devotedly invest in computers to<br />
provide the sequence of random digits that could potentially make casinos loose<br />
millions upon millions to gambling patrons.<br />
Computers, and subsequently software are used in various fields of medical technologies<br />
where predictability is of the utmost importance. Gambling machines also use software<br />
but in contrast to medical software predictability in the application of the software, is an<br />
undesirable effect for the machine owners.<br />
Abstraction 16
An Introduction To Programming With <strong>Processing</strong><br />
The Unique Qualities of a Programming<br />
Language<br />
At the simplest level a programming language should be Turing complete. Turing<br />
complete refers to a set of data manipulation rules that, can simulate a Turing<br />
machine. This begs the question to be asked, who is Turing and what is his<br />
machine?<br />
Alan Turing was a British mathematician that is heralded as the father of<br />
computer science. He lived from 1912 to 1954 when he died at the age of 41.<br />
Turing is responsible for creating the Turing machine which is a theoretical<br />
device that operates with a strip of tape imprinted with an infinite array of<br />
symbols, the machine is able to read a symbol and alter the symbol and the<br />
symbol in turn affects the behaviour of the machine. The tape that the symbols are<br />
printed on represent memory and it can move back and fourth so that any symbol<br />
can be read by the machine and altered by it, additionally at any given time a<br />
symbol is affecting the state of that machine.<br />
Turing referred to this machine as an "a(utomatic)-machine" and it forms the<br />
fundamental logic of all computer algorithms. This principle is still used in<br />
modern computers. A programming language that is Turing complete complies<br />
with this logic, and will subsequently be able to run on all computers based on the<br />
Turing machine. What this simply means is that programming languages will<br />
need to be able to run on a basic computer system that at the very least has a<br />
Central <strong>Processing</strong> Unit (CPU) that is based on the Turing machine, which<br />
includes all known operational computer models.<br />
Quantum computing models are commonly based on the quantum Turing<br />
machine also known as the Universal Quantum Computer, and even these models<br />
can be related back to the classical Turing machine. Quantum computing models<br />
are theoretical models of how a quantum computer could work once the<br />
technology can be implemented, in much the same way that the Turing machine<br />
was a theoretical model of today's modern computer before it's current<br />
implementation.<br />
The Unique Qualities of a Programming Language 17
An Introduction To Programming With <strong>Processing</strong><br />
Alan Turing (1912 - 1954) is heralded as the father of computer science<br />
What about speed, efficiency and dis-ambiguity, are these not also amongst the<br />
unique qualities of a programming language?<br />
Simply put, no they are merely guidelines that programmers may or may not<br />
adapt into the computer languages they develop. However, most useful<br />
programming languages will in some form or another adapt these standards into<br />
their design. There is another form of computer language development that does<br />
not comply with these standards, but the languages that develop from this field do<br />
still comply with Turing completeness, as without this design implementation it<br />
would not be possible to run the language on a computer modern or old.<br />
This field of computer science is referred to as esoteric programming languages.<br />
Esoteric programming languages usually are not designed to be useful for realworld<br />
programming situations but are usually more popular among hackers that<br />
develop these language to test the boundaries of computer programming language<br />
design.<br />
A relatively well known example of an esoteric programming language is the<br />
language known as brainfuck . Brainfuck is known as a Turing-tarpit language as<br />
it still qualifies as a Turing complete language even though the entire language<br />
consists of only 8 commands and no operands. We'll be discussing what exactly a<br />
command is shortly and what an operand is a bit later, but needless to say this is a<br />
language that is still functional with a bare minimum of interfacing protocols. An<br />
example of a “hello world program” (yet another concept we will get to a bit<br />
later), which is a program that simply prints the words “hello world” to the screen<br />
in brainfuck code follows:<br />
The Unique Qualities of a Programming Language 18
An Introduction To Programming With <strong>Processing</strong><br />
++++++++++[>+++++++>++++++++++>+++>+.<br />
LOLCODE is another example of an esoteric programing language that is based<br />
on the text within lolcats images. Lolcats are images of cats that circulate the<br />
Internet, often in cute and whimsical representations. These images are<br />
accompanied with text that is generally idiosyncratic and grammatically incorrect<br />
with the intent to contribute humour to the image.<br />
An example of a typical lolcat image<br />
An example of a <strong>Hello</strong> World program in LOLCODE follows:<br />
HAI<br />
CAN HAS STDIO?<br />
VISIBLE "HAI WORLD!"<br />
KTHXBYE<br />
As you can see the language uses what is typically termed as “lol-speak” as an<br />
integral part of it's syntax and keywording.<br />
The Unique Qualities of a Programming Language 19
An Introduction To Programming With <strong>Processing</strong><br />
Lower Level Languages and Higher Level<br />
Languages<br />
Generally speaking higher level programming languages are closer to human<br />
spoken languages and lower level programming languages are closer to machine<br />
code, or binary. However this classification might not always be so clear. C++ is<br />
one language that some might argue challenge this programming language stereo<br />
type. C++ is a programming language that has all the features that one would<br />
expect from a higher level language such as an easy to read syntax, object<br />
oriented programming and extensive collections of libraries to add to the<br />
language's capabilities but also has other features that are not commonly found in<br />
higher level languages such as memory management, user defined operator<br />
overloading, six different integer datatypes and a plethora of compilers to choose<br />
from. As a result many refer to C++ as a mid-level programming language.<br />
For <strong>Processing</strong> this distinction is currently not so difficult to make. <strong>Processing</strong> is a<br />
high level language, meaning it has an easy to read syntax, supports modern day<br />
programming concepts such as Object Oriented Programming, has it's own IDE<br />
(Integrated Development Environment something we will become more familiar<br />
with throughout this guide) and fundamentally it abstracts a lot of machine<br />
specific interactions for us making the code more readable for humans.<br />
However, it's worth considering that the terms “higher” and “lower” level<br />
programming languages are relative to the time period in which they are used. For<br />
example when the programming language C (that C++ is based on) was first<br />
introduced in the early 1970's it was considered to be a high level language as it<br />
supported such features as expression evaluation and datatyping, both of which<br />
are programming concepts common to most modern day programming languages.<br />
As technology progresses, new concepts become common place and rapidly<br />
replace older more cumbersome programming designs, till we get to the point<br />
where there are far less people that would refer to an older language such as C as<br />
being a high level language and a lot more people that would refer to it as a low<br />
level language, lacking modern abstractions and less direct hardware interactions.<br />
<strong>Processing</strong> might one day, also be subjected to such a topic of discussion.<br />
Lower Level Languages and Higher Level Languages 20
An Introduction To Programming With <strong>Processing</strong><br />
Following is the C version of a “<strong>Hello</strong> World” Program:<br />
#include <br />
int main(void)<br />
{<br />
printf("hello, world\n");<br />
return 0;<br />
}<br />
The level of abstraction that is needed in order for a language to qualify as a<br />
higher level programming language does not come without it's penalties. Lower<br />
level languages, because they are conceptually closer to machine code are<br />
considered to produce more efficient machine readable code, of course this is<br />
largely dependent on the programmer creating the code. As mentioned before the<br />
greater the level of abstraction of the code, the more stress that is placed on the<br />
machine interpreting the code, and subsequently more system resources are<br />
required. As a result of this cycle higher level programming languages generally<br />
cannot run on systems where resources are limited. Initially, this might not seem<br />
like such a big issue to you, but have you ever considered the amount of<br />
technology running on limited resources like a television, fridge, GPS, mobile<br />
phone, remote-controlled air-conditioner, electronic toys, media players and the<br />
list goes on...? In fact if you were to think about it there are not many devices like<br />
computer workstations, laptops or computer servers that are designed to have<br />
their resources, available to the software that runs on these machines, extended.<br />
Yet, even these machines have their limitations.<br />
Ultimately software, whether it is designed with a high level or low level<br />
programming language, should always take into consideration the possible<br />
limitations of available system resources.<br />
Lower Level Languages and Higher Level Languages 21
An Introduction To Programming With <strong>Processing</strong><br />
An Analysis of a Computer Program<br />
As we are already aware Binary is a conceptual model that people have invented<br />
to represent the workings of a machine. Binary resultantly forms the basis of all<br />
software because as mentioned earlier no matter what programming language you<br />
use that code must be translated into a machine readable format before it can be<br />
interpreted by a machine, the product of this translation is usually represented as<br />
binary code.<br />
Computer Software is conceptual and intangible as opposed to hardware which is<br />
tangible such as a motherboard, a CPU, an optical drive or a monitor. As a result<br />
the word software is intentionally used to contrast the term hardware.<br />
Programming is a means of creating software and a computer program is a type of<br />
software. Specifically, a program is a set of instructions issued to a computer in a<br />
programming language, such as <strong>Processing</strong>. These instructions are usually made<br />
up of one or many statements. Depending on what language you are programming<br />
in statements can consist of several different parts, such as<br />
• expressions<br />
• commands<br />
• assignments<br />
• comparisons.<br />
Statements can also be made up of many other parts not mentioned here, but for<br />
now we are most interested in two of these components making up a statement,<br />
commands and expressions, the rest we will get to later.<br />
An Analysis of a Computer Program 22
An Introduction To Programming With <strong>Processing</strong><br />
Commands<br />
If you were to compare a statement in computer programming to a sentence in a<br />
natural language, a computer programming statement could be considered to be<br />
somewhat imperative. For example the following sentence in a natural language:<br />
“Run, as fast as you can!”<br />
This would be an imperative statement in English issued to the implied subject. In<br />
extending this comparison, a verb in an imperatively spoken sentence would have<br />
the same purpose as a command in a programming language. A command in a<br />
programming language usually implies a directive issued to a computer, in other<br />
words it's a means of telling a computer to do something. In <strong>Processing</strong> we often<br />
use functions to tell a computer what to do, a function in this sense is a type of<br />
command. Functions are the building blocks of <strong>Processing</strong> programs, as you will<br />
come to see. Additionally many functions in <strong>Processing</strong> accept parameters, which<br />
modify how the function is interpreted the program.<br />
If we were to extend on our previous example and apply this programmatically,<br />
the word “Run” in the sentence would be a function and “as fast as you can!”<br />
would be representative of a parameter.<br />
Expressions<br />
Expressions in computer programming languages can consist of single or multiple<br />
different types of data such as numbers, typographic characters and many other<br />
types of data that can be interpreted in various ways according to rules established<br />
by the language you are programming in. The process of how this expressional<br />
data is interpreted is known as evaluation and is similar to the term as it is used in<br />
mathematics. For example 3 + 2 is an expression that evaluates to 5.<br />
Mathematical operators such as +, -, *, etc. work in <strong>Processing</strong>, as you would<br />
probably expect them to. As the term implies the programmatic mathematical<br />
operator is often interchangeable with the standard classical mathematical<br />
operator in <strong>Processing</strong>. For example the statement in <strong>Processing</strong>:<br />
An Analysis of a Computer Program 23
An Introduction To Programming With <strong>Processing</strong><br />
println(5+3);<br />
Consists of two parts, first the function println() which accepts a parameter. In<br />
this case the second part of the statement, the parameter, is an expression and the<br />
expression is 5+3 which evaluates to 8.<br />
One of the basic features of <strong>Processing</strong> is it's ability to act as a calculator when<br />
computing values separated by mathematical operators such as + (plus), - (minus),<br />
* (multiply), / (divide) and % (modulus). But this inherent ability of <strong>Processing</strong><br />
extends a lot further than simply evaluating numerical expressions, as expressions<br />
amongst other types of data can also consist of other typographic characters that<br />
can be evaluated. For example the statement:<br />
println(“h” + “i”);<br />
This statement evaluates to “hi”. Using a mathematical operator in this way is<br />
known as operator overloading and is an inherent quality of <strong>Processing</strong> that<br />
comes from it being a C based programming language. Operator overloading is a<br />
common feature in higher level languages and simply refers to the level of<br />
abstraction built into a higher or mid level programming language that allows us<br />
to use the same operator in more ways than one. For example the plus sign can be<br />
used to add numbers or other typographic characters, but not numbers and<br />
characters at the same time without the use of a process known as typecasting<br />
(which we will cover in more detail later).<br />
What makes operator overloading so useful is that we often don't need to be<br />
aware of it, because the way that the operator is used will be determined by the<br />
context in which the programmer has used it and this is something that the<br />
program converting our human readable code into a version that is more machine<br />
readable will handle for us.<br />
An example of operator overloading and typecasting in <strong>Processing</strong>'s PDE<br />
An Analysis of a Computer Program 24
An Introduction To Programming With <strong>Processing</strong><br />
A Scalable Software Development Model<br />
Programming is only one of the steps required in the process of developing<br />
software. Establishing a scalable model for software development will help you<br />
determine what the requirements of the project are before programming begins.<br />
As you start developing larger programs this development model can be scaled to<br />
help you allocate your time appropriately to the various needs of your project, and<br />
ultimately contribute to more realistic deliverables within a predictable timeframe.<br />
The idea behind a scalable software development model is that it can be<br />
adapted to suit any project large or small. Although certain areas might require<br />
more focus than others dependent on the project you are working on, having an<br />
established software development model can contribute to a progressive workflow<br />
that does not stagnate when difficulties within a project are encountered.<br />
1. Plan<br />
• What are the goals for the project?<br />
• How would you ideally like to implement these goals?<br />
• Have there been similar projects undertaken by yourself or others, if so is<br />
it possible to obtain those implementations?<br />
Asking yourself similar questions following this line of thought can help you<br />
visualize the steps, leading to your goals, that need to be taken well before<br />
programming begins.<br />
This process of visualization contributes to creating a conceptual sketch of the<br />
project as a whole and in it's completed form. This idea can then serve as a means<br />
of deconstructing the main concept into smaller workable objectives.<br />
Planning your project through conceptual visualization should be supplemented<br />
with a few rough ideas jotted down on a piece of paper. It's not uncommon to<br />
spend days and sometimes longer periods of time conceptualizing a project before<br />
considering trying to implement any of these ideas.<br />
Depending on the complexity of your project, you may have to further refine the<br />
process of breaking down the smaller tasks into even smaller tasks until you reach<br />
a task or set of tasks that are achievable in the short term. Often these short-term<br />
objectives will not necessarily relate directly to programming but rather to a set of<br />
A Scalable Software Development Model 25
An Introduction To Programming With <strong>Processing</strong><br />
questions that need to be answered before the implementation of the project can<br />
begin. These questions that you derive from planning your project will form the<br />
basis for the research that follows planning.<br />
Examples of an abstraction, followed by a deconstruction and finally a technical<br />
overview of a project plan.<br />
2. Research<br />
Addressing the details of how you see your project being implemented should<br />
bring certain technical questions to your attention. Questions such as,<br />
• What is the target system you would like your software to run on?<br />
• Will my software require additional resources such as plug-ins?<br />
• Can the software also be distributed for both online and offline usage?<br />
These are amongst many questions that you might not be able to answer in your<br />
own capacity. The Internet is a seemingly endless resource of information and<br />
probably your best bet when it comes to answering these and many other<br />
technical questions you can think of.<br />
Research might also reveal that the code you are interested in creating might<br />
already exist. If the code is distributed under a license that permits you to reuse it,<br />
then by all means you are encouraged to do so. It is often said that up to 80<br />
percent of a programmers time is spent maintaining already developed code.<br />
What this means is that generally developers will spend a comparatively small<br />
amount of their time developing their own code from scratch and far more time<br />
A Scalable Software Development Model 26
An Introduction To Programming With <strong>Processing</strong><br />
adapting and modifying already existing code to suit the needs of their projects.<br />
Finally researching your project can also reveal useful sources for data<br />
acquisition, which will be particularly helpful in the fourth phase of your<br />
development model.<br />
The various sites on the Internet have vast resources of reusable code<br />
3. Mockup Designs<br />
Once you have answered the questions you had about implementing your project<br />
consider returning to the notes you created during the first phase of Project<br />
Planning. With the new information you have derived through your research,<br />
refine your ideas into graphical representations of your program.<br />
By now you should have a clearer idea of what your end product should look like.<br />
Avoid prematurely designing your project only to realize your goals where not<br />
realistic given a particular time-frame or some other design flaw, following this<br />
development model in the predetermined order will help avoid such a situation.<br />
Use the mockup design phase of software development to start drawing out<br />
conceptual sketches of your program, in the form of schematic diagrams that<br />
outline the program's flow of control (which we will discuss in more detail in Step<br />
8) and map out the user experience you hope to achieve.<br />
If your software is visually oriented you may wish to create more detailed and<br />
specific designs of your application, for example by designing an interface for a<br />
data visualization program or designing a theme for an online game. Consider<br />
how your designs can contribute to making the user's experience more immersive.<br />
The design phase of software development can also help to identify and even<br />
A Scalable Software Development Model 27
An Introduction To Programming With <strong>Processing</strong><br />
solve how programmatic implementations of visualizing data might be addressed<br />
through various programming methodologies.<br />
Mockup Designs should include some rudimentary visualizations of the final project and<br />
schematic diagrams detailing the program's flow of control.<br />
4. Data Acquisition: Sourcing the data needed<br />
for your project.<br />
Obtain all the data you need to create your software, this data could include<br />
statistical information from books, tabulated data from a website, printed lists of<br />
sales from business owners or even screen-scraped data.<br />
Screen-scraping data is a technique that has been in use for many years and is<br />
used to acquire data from new and old computers alike. In modern times one of<br />
it's most common implementations involves the process of acquiring data that is<br />
in no particular standardized format and commonly sourced from from an html<br />
page of a website. The idea of screen-scraping is that data exists remotely from<br />
the program you are creating, in a format that your program cannot process. As a<br />
result you may need to write another program that serves as an in between<br />
application converting the remote data from an undesirable format to the desired<br />
format of the main software program you are developing.<br />
Screen-scraping is a technique of data acquisition that is differentiated from<br />
parsing, as the data that is being acquired is not intended for another software<br />
program but often intended to be read by a human. Parsing data is something that<br />
happens much later in the software development process and relies on proper data<br />
acquisition. Parsing data is something we will discuss in more detail during the<br />
A Scalable Software Development Model 28
An Introduction To Programming With <strong>Processing</strong><br />
seventh phase of the software development model.<br />
Acquired data might be in the form of a spreadsheet, a text document, images and many<br />
other different formats that might not, even at this stage, be digital.<br />
5. Filter<br />
Filtering data is simply the process of removing all components of your data that<br />
are not necessary for the proper functioning of the main program. If your data is<br />
in a <strong>Processing</strong> friendly format such as tabulated data, a multi-line text file, a<br />
comma separated value text file or other similar format the process of filtering<br />
data could be as simple as selecting those components (including spaces and new<br />
line characters in a text file) and deleting them. However, if your data is not in a<br />
<strong>Processing</strong> friendly format you might have to spend quite a bit of time filtering<br />
out data that is not relevant to your program.<br />
6. Clustering and Data Mining<br />
Data mining is the process of identifying patterns within the data you have<br />
acquired. The purpose of doing this is to place the relationships that exist between<br />
the various aspects of your data in a more mathematical context that can<br />
ultimately be used programmatically (in the program you are developing).<br />
Data mining can be done manually or it could be automated. When dealing with a<br />
A Scalable Software Development Model 29
An Introduction To Programming With <strong>Processing</strong><br />
small data set with a high ratio of inconsistent data types, manual data mining<br />
could be more effective and save you some time.<br />
For example, lets take a hypothetical situation where the owner of a small café<br />
has asked you to determine what items a customer is likely to purchase together.<br />
The data set you have acquired consists of all the items customers have purchased<br />
in the store over the past year. From that data you could determine that goods can<br />
be divided up into food, drinks, magazines, stationary etc, and then into even<br />
smaller groups like fruit, vegetables, soft-drinks etc. Identifying these groups<br />
would be the first step of data mining and is a process also known as clustering. If<br />
the café has a large variety of items to choose from the clusters making up the<br />
data could resultantly be numerous, yet the data set as a whole is actually quite<br />
small, only consisting of a single year of purchased items.<br />
In contrast a more established café that has been operating for several years<br />
proposes the same question to you. In the case of the smaller café groupings of<br />
purchased items would yield a lower probability of repeating in a shorter period<br />
of time. In contrast the more established café has a better chance of the same<br />
groups of items being purchased together over a longer period of time.<br />
In the former case manually mining this data set could be more effective because<br />
of the lower probability of the same items being purchased together in a relatively<br />
short space of time. In this scenario the majority of your time would be spent on<br />
clustering and populating the resultant groups after eliminating the majority of<br />
items purchased in that year because they will not fall into any cluster.<br />
However in the case of the established café although there may be just as many<br />
clusters the values that these clusters are populated with have a higher probability<br />
of being repeated, it might therefore be more efficient to have a computer<br />
program count, cluster and mine the data.<br />
Regardless of whether you choose to manually mine your data or have a software<br />
program do the work for you, you should have a set of data at the end of the<br />
process that can be manipulated programmatically.<br />
A Scalable Software Development Model 30
An Introduction To Programming With <strong>Processing</strong><br />
Raw Data<br />
Manual Clustering<br />
Digital Results<br />
The process of getting external data into a program, via clustering and data mining.<br />
A Scalable Software Development Model 31
An Introduction To Programming With <strong>Processing</strong><br />
7. Parsing<br />
The process of transferring data from one computer program to another program<br />
that requires the data in a specific format that is different to the original format, is<br />
referred to as parsing data. The program that converts the original data to an<br />
acceptable format for the main software program to process is referred to as a<br />
parser. Parsing in <strong>Processing</strong> should return a set of data that your main program<br />
can read directly in a text file, a spreadsheet or other such data format that does<br />
not require any further levels of un-abstraction.<br />
Sometimes, the decision to write a parser might not be an easy choice to make.<br />
Weigh up the amount of time you think it will take to manually convert the data<br />
(as illustrated in the above diagram) compared to the amount of time it will take<br />
you to develop a parser, along with it's overall usefulness (as a parser can<br />
sometimes end up being specific to one application) and try to make an informed<br />
decision based on these factors before jumping head first into the task at hand.<br />
8. Determining Flow of Control through<br />
Stepwise Refinement<br />
A program's flow of control refers to the order in which statements are run within<br />
in a program. The results of these statements can ultimately determine how a user<br />
interacts with the program by means of various branches of code structures within<br />
your program that the program determines whether to execute or not based on the<br />
choices the user has made through interactions with the program.<br />
Branching is an important part of a programs flow of control as it allows your<br />
program to determine, through a logical decision, what path to take within your<br />
program's code based on various circumstances you have defined for the user.<br />
Planning the program's flow of control allows us to address what we would<br />
ultimately want our users experience of the program to be, and the best place to<br />
start with this process would be to write out a list. This list should contain a set of<br />
instructions that determine how you would like the program to work and<br />
ultimately describe a user's experience of interacting with the program. Once you<br />
have this information remove unnecessary clutter from the list and identify the<br />
key points, keep it concise and short. Once you have this list keep refining it until<br />
you have something resembling a step by step process of the tasks the program<br />
will eventually perform.<br />
A Scalable Software Development Model 32
An Introduction To Programming With <strong>Processing</strong><br />
An example of such a list for a guess my number game follows:<br />
1. Start the game and generate a random number.<br />
2. Render the space scene interface including a slider,<br />
spaceship and a panel to show user's guesses which are<br />
either too high or too low.<br />
3. Click and drag the slider and a number is displayed<br />
indicating the users current guess.<br />
4. When the slider is released the user's guess is made<br />
5. If the guess is the same as the random generated number,<br />
show the “win screen”.<br />
6. If the guess is too high, tell the user the guess is too<br />
high and increment the number of user's guesses.<br />
7. If the guess is too low, tell the user the guess is too low<br />
and increment the number of user's guesses.<br />
8. If the user has not guessed the number within five tries,<br />
show the “lose screen”.<br />
Your list at this stage should start to read more like a program rather than a<br />
paragraph written in a natural language. This resemblance is no coincidence and<br />
forms the basis for the process programmers use for developing what is known as<br />
pseudo code. Pseudo Code is somewhere between a programming language and a<br />
natural language and forms the basis for stepwise refinement. During stepwise<br />
refinement rewrite your list so that it resembles something closer to the code of<br />
your program each time the pseudo code is refined.<br />
A Pseudo code example for a guess my number game might look something like<br />
this:<br />
choose a random number between 1 and 100<br />
set the number of user guesses to 1<br />
get the user's guess<br />
while the user's guess is not equal to the random number and less<br />
than 5 guesses<br />
if the guess is too high<br />
tell user “guess too high”<br />
increment user guesses<br />
else if the guess is too low<br />
tell the user “guess too low”<br />
increment user guesses<br />
if the number of guesses is 5 or greater user has lost<br />
else if the guess is equal to the random number<br />
user has won<br />
A Scalable Software Development Model 33
An Introduction To Programming With <strong>Processing</strong><br />
9. Implement, Test and Document. Repeat.<br />
Implementation is the phase of software development where the actual source<br />
code is created, by means of programming.<br />
As the code is created it should be constantly tested. This helps to identify bugs in<br />
the program during current implementation or that could occur in the future<br />
development of the software.<br />
While implementing and testing a program it is important to document the steps<br />
taken to achieve the goals of the project. This could either be done in a<br />
comprehensive form of external documentation but should always include<br />
documentation within the code itself in the form of comments and multi-line<br />
comments.<br />
This phase is repeatable and should be constantly updated by the recursive nature<br />
of it's design which should eventually lead to a erroneous free implementation of<br />
the software.<br />
Comments in <strong>Processing</strong> start with the // characters and multi-line comments in<br />
<strong>Processing</strong> start with the /* characters and end with the characters */<br />
A Scalable Software Development Model 34
An Introduction To Programming With <strong>Processing</strong><br />
10. Deliver<br />
Once the software has been thoroughly tested it should be delivered. Delivery<br />
could involve something as simple as uploading the software to a website, or as<br />
complex a task as marketing and selling the software. However you deliver your<br />
software, you should always accommodate for the delivery phase of the project<br />
uncovering unforeseen bugs and errors in the software as users test it on systems<br />
that differentiate substantially from that of the systems it was tested and<br />
developed on. As a result maintenance is a crucial part of delivery and an<br />
appropriate time-frame should always be allocated for it within software<br />
development. In some dire situations an entire redesign of the software might be<br />
deemed necessary during the delivery phase, in this case allocating a specific<br />
time-frame for software maintenance might not be adequate to accommodate the<br />
requirements of the development of the software.<br />
There are various options for publishing your software, once it is complete.<br />
A Scalable Software Development Model 35
An Introduction To Programming With <strong>Processing</strong><br />
Why Learn Programming using <strong>Processing</strong>?<br />
<strong>Processing</strong> covers a lot of ground as it is a great way to learn programming for the<br />
novice and for the experienced programmer provides a fast and efficient approach<br />
to developing advanced applications.<br />
Code for Artists<br />
<strong>Processing</strong> is built with the intent to be a tool for creating visual and interactive<br />
representations of code. This means that it is not as generic in it's application such<br />
as a programming language like C++ which can be used for engineering,<br />
mathematics, scientific applications and even games development but which also<br />
has it's limitations as it is generally not used to create online applications that<br />
might appear on a website. <strong>Processing</strong> is built for specific fields of interest and as<br />
a result less coding is needed in <strong>Processing</strong> than might be required in more<br />
generic programming languages when developing programs that are suited for the<br />
<strong>Processing</strong> environment, such as data visualization, interactive online<br />
applications, animation and many other similar fields. This is not to say that<br />
<strong>Processing</strong> is limited to one particular genre of application, but merely to say that<br />
<strong>Processing</strong> provides a set of tools that make the process of creating certain types<br />
of applications easier.<br />
<strong>Processing</strong> has developed since 2001 initially as an extension to a programming<br />
language, then to a prototyping tool and to it's current implementation of being a<br />
fully developed programming language that continues to develop in fields such as<br />
microprocessor programming and physical computing where it has gained much<br />
recognition.<br />
Java Based<br />
<strong>Processing</strong> was originally developed as an extension to the Programming<br />
language, Java and it's roots in Java are still evident today even though <strong>Processing</strong><br />
is a language on it's own. <strong>Processing</strong>'s relationship with Java has many benefits,<br />
the two languages share a similar syntax except that <strong>Processing</strong> can make visual<br />
representations of your code easier to create than Java can (which is more generic<br />
in it's scope of application). Java shares a lot of similarities with the programming<br />
Why Learn Programming using <strong>Processing</strong>? 36
An Introduction To Programming With <strong>Processing</strong><br />
language C (from which it was originally developed) and Java is also one of the<br />
most popular languages currently in use. If you are familiar with Java or C++<br />
(which is closely based on C) learning <strong>Processing</strong> should come quite naturally to<br />
you.<br />
The Java programming language is a popular language for software development<br />
and is almost entirely open source.<br />
C++ is a widely implemented language, as it is available on many popular platforms<br />
Open Source<br />
The <strong>Processing</strong> PDE (which is used to develop <strong>Processing</strong> code and is something<br />
we will discuss in more detail later) is Open Source Software and it is released<br />
under the GNU General Public License.<br />
You've probably heard the term “open source” before and are aware that it relates<br />
to something “free”, but are you aware that the term “free” as it is used in the<br />
context of open source does not necessarily have anything to do with money or<br />
the absence thereof?<br />
The term “free” within the context of open source refers more to a philosophy or<br />
methodology rather than a monetary reference and as such is akin to the term<br />
“freedom”. However as the idea of open source has expanded in modern day<br />
society it is often come to be synonymous with something that is also free of<br />
monetarily related costs. <strong>Processing</strong> is no exception to this, it does not require a<br />
costly software license such as proprietary software vendors require for the usage<br />
Why Learn Programming using <strong>Processing</strong>? 37
An Introduction To Programming With <strong>Processing</strong><br />
of their products. Anybody can use <strong>Processing</strong> and the PDE, modify it,<br />
redistribute it and the GNU General Public License ensures that the <strong>Processing</strong><br />
PDE will always remain free.<br />
So because <strong>Processing</strong> is free what about the content you create with <strong>Processing</strong><br />
does that also have to be “free” and open source?<br />
The answer to this question is and will remain to be, no. The content you create<br />
with <strong>Processing</strong> belongs to you, the creator, and you are free to do with it<br />
whatever you please. If you wish to sell the software or code that you produce<br />
with <strong>Processing</strong> it is your right to do so. If, however, you do not wish to sell your<br />
work and subsequently do not choose to copyright your work there are various<br />
options available to you to protect you and your work. Amongst these licences is<br />
the GNU General Public Licence which protects the rights of developers of<br />
computer programs that wish to ensure that the software they develop remains<br />
free, including all derivatives that are made from the original software program.<br />
Another such licence is the Creative Commons Licence, this licence allows<br />
creators of media to reserve some rights of their work (if they choose to) and still<br />
legally allows the copying, redistribution and modification of such media if the<br />
author chooses to exercise these rights. Wikipedia is an example of a large scale<br />
organization that licenses it's contents under a Creative Commons Licence and<br />
Linux is an example of popular software that is licensed under the GNU General<br />
Public Licence.<br />
The GNU GPL 3 logo as started by the Free Software Foundation on the left and a<br />
Creative Commons logo on the right both of these trademarks have become synonymous<br />
with the term “copyleft”.<br />
PDE<br />
An IDE is an acronym for Integrated Development Environment, it refers to a<br />
software application that is used to develop code for a computer programming<br />
Why Learn Programming using <strong>Processing</strong>? 38
An Introduction To Programming With <strong>Processing</strong><br />
language. <strong>Processing</strong> has it's own IDE called the PDE or <strong>Processing</strong> Development<br />
Environment.<br />
The PDE is a popular tool for developing <strong>Processing</strong> Sketches but the popular IDE<br />
Ellipse is also quite readily used too.<br />
Of course all code is simply text, so why can't we call any text editor an IDE? An<br />
IDE such as the PDE generally has several special characteristics that separate it<br />
from other software applications.<br />
1. Source Code Editor<br />
2. Build Automation Tools<br />
3. Compiler and/or Interpreter<br />
4. Debugger<br />
Why Learn Programming using <strong>Processing</strong>? 39
An Introduction To Programming With <strong>Processing</strong><br />
Source Code Editor<br />
A source code editor is a textual editor within an IDE. The Source Code editor in<br />
an IDE is designed specifically for programming purposes and not for wordprocessing,<br />
so generally text formatting capabilities such as bold, italicising<br />
characters or directly editing characters colors is not permitted within source code<br />
editors.<br />
The source code editor within the PDE allows you to type code, and access <strong>Processing</strong>'s<br />
API.<br />
Modern day source code editors use color codes to distinguish different types of<br />
data, this is referred to as syntax highlighting and it helps to make code more<br />
human-readable.<br />
Build Automation Tools<br />
Programming can involve many repetitive tasks, build automation tools help<br />
programmers perform these repetitive tasks by use of tools built into the IDE.<br />
They might include the IDE's ability to convert source code to machine readable<br />
code with the click of a single button (the button being the build automation tool)<br />
or the ability to export your source code to multiple platforms with a menu<br />
Why Learn Programming using <strong>Processing</strong>? 40
An Introduction To Programming With <strong>Processing</strong><br />
selection. In the PDE several build automation tools for creating <strong>Processing</strong><br />
applications can be found under the Tools and Sketch menus more generic build<br />
automation tools can also be found in the other menu's in the PDE.<br />
Some of <strong>Processing</strong>'s build automation tools. <strong>Processing</strong>'s build automation toolset can<br />
also be extended by downloading tools from processing.org/reference/tools/<br />
Compiler and /or Interpreter<br />
Most modern day IDE's have a compiler and/or interpreter, as this is the feature<br />
within IDE's that enable the conversion of source code to machine readable code.<br />
It is in this feature that our code is given a “meaning” for a computer to<br />
implement and for us to observe, interact with and experience in what ever it's<br />
intended form of implementation.<br />
You might be wondering at this point what exactly is the difference between a<br />
compiler and an interpreter?<br />
The truth is that there is actually not much of a difference between what a<br />
compiler does and what an interpreter does. The terms stem from a “Compiled<br />
Language” and an “Interpreted Language”. As mentioned before in order for a<br />
computer to make any sense of our code it needs to convert this code into a<br />
machine readable format, this process of conversion is referred to as compiling.<br />
The process is specific because the code must be fed into a compiler in a specific<br />
language and then be compiled into another “language” which is no longer<br />
human-readable but machine readable and specific to a particular platform. A<br />
compiler is said to perform this task on the entirety of the source code once so<br />
that when the program is compiled there is no more conversion or compilation<br />
that needs to be performed there after.<br />
An interpreter differs in the sense that the source code is not compiled into a<br />
specific machine readable format. So how does the code run on a machine? The<br />
code is passed to an interpreter (which is another software application) that runs<br />
the code. The interpreter then determines how the code should be run<br />
continuously translating the code from a higher level to a machine readable level<br />
Why Learn Programming using <strong>Processing</strong>? 41
An Introduction To Programming With <strong>Processing</strong><br />
each time the code needs to be executed.<br />
Of course at some point in order for the code to be run on a computer it has to<br />
exist in a machine readable format regardless of whether it's compiled or<br />
interpreted, so theoretically the difference between the two methods is not<br />
inherently specific to the language you are creating the code with but rather more<br />
to do with how a language is implemented. What this means is that any language<br />
could be interpreted or compiled, it's how the code that you create is implemented<br />
that determines whether that code will be compiled or interpreted.<br />
<strong>Processing</strong> compiles to Java bytecode, and can subsequently run on any Java<br />
enabled machine it is estimated that there are currently over 4.5 billion Javaenabled<br />
machines. Java is said to be an interpreted language.<br />
<strong>Processing</strong> compiles your Sketches to Java Bytecode and uses the Display Window<br />
(foreground) for testing and development.<br />
Debugger<br />
A debugger in the context of an IDE is software that examines code either as a<br />
part of the compilation process or before compilation or interpretation in order to<br />
reduce the number of bugs within a program. The term bug in relation to<br />
computer programming is used to describe an error, fault or some means of a<br />
computer program acting in an unexpected or unintended way. The process of<br />
Why Learn Programming using <strong>Processing</strong>? 42
An Introduction To Programming With <strong>Processing</strong><br />
debugging a program is intended to identify these bugs and in some cases assist<br />
the programmer in rectifying them. In the PDE the debugger console can be found<br />
below the text editor and is used generally for debugging one's own program or<br />
allowing the PDE to determine bugs within a program.<br />
The Debugger console (also known as Message and Text area) can be used to identify<br />
bugs and track program variables which can be useful in identifying logical errors.<br />
Active Online Community<br />
<strong>Processing</strong> is not a stagnant language it is very much alive and growing. The<br />
Language's development is rapid but not so rapid that it becomes difficult to keep<br />
up with. A lot of this development can be attributed to the active community that<br />
support the project.<br />
If you are in need of any help with programming in processing, want to keep up to<br />
date with it's development or just simply want to play around with programs made<br />
with <strong>Processing</strong> online then I recommend you visit http://www.processing.org<br />
The forums are really easy to use and you are encouraged to ask questions, as<br />
there seems to be many people out there that are keen on helping you develop<br />
your software.<br />
The latest version of <strong>Processing</strong> can be downloaded at http://processing.org/<br />
download<br />
The <strong>Processing</strong> logo is a trademark of processing.org<br />
Why Learn Programming using <strong>Processing</strong>? 43
An Introduction To Programming With <strong>Processing</strong><br />
<strong>Hello</strong> <strong>Processing</strong><br />
Now that we have an idea of what programming is and how we will be using the<br />
PDE to create our own code in <strong>Processing</strong> lets start coding!<br />
Install <strong>Processing</strong><br />
Once you have downloaded <strong>Processing</strong>, depending on your platform you might<br />
need to install it or just simply uncompress/unzip the package to a location on<br />
your hard disk drive and run it from there. Open the processing root folder inside<br />
which you will find an executable file called processing, double click this file to<br />
start the PDE and you are ready to start programming with <strong>Processing</strong>.<br />
If however you are unable to run the PDE check that you have permission to<br />
execute/run the processing file and that Java or more specifically the JRE (Java<br />
Runtime Environment) is properly installed.<br />
It is recommended that you use the Java version that is available from Sun<br />
Microsystems (a subsidiary of Oracle), alternative open source versions of the<br />
JRE and Java Development Kit (JDK) such as OpenJDK do exist but are currently<br />
not recommended with <strong>Processing</strong>, however this might change at some point in<br />
the future, see the <strong>Processing</strong> website for updates.<br />
You can get the latest version of Java from http://www.java.com/getjava<br />
Sketches<br />
A program created in <strong>Processing</strong> is known as a Sketch. <strong>Processing</strong> Sketches are<br />
stored in a folder called the sketchbook folder. Being able to identify the location<br />
of this folder will be useful particularly when adding external data to a sketch. To<br />
identify the location of the sketchbook folder within the PDE click:<br />
File → Preferences → “Sketchbook location”<br />
In the Preferences dialogue box the sketchbook folder can be identified under the<br />
heading “Sketchbook location” or changed by clicking the “Browse” button and<br />
navigating to and choosing a new location under the same heading.<br />
All Sketches you create should be stored within your sketchbook folder.<br />
<strong>Hello</strong> <strong>Processing</strong> 44
An Introduction To Programming With <strong>Processing</strong><br />
<strong>Hello</strong> World Program 1.0<br />
Programming can be simple or very complex depending on what you are hoping<br />
to achieve. Since this is our introduction to programming we'll be following<br />
programming tradition and starting with a simple <strong>Hello</strong> World program. A <strong>Hello</strong><br />
World program is a program that simply prints the words “hello world” to a<br />
display, that display in our case in the “<strong>Hello</strong> World 1.0” program is going to be<br />
the debugging console in the PDE. The purpose of the <strong>Hello</strong> World program is<br />
not as much to impress but rather to get a firm grasp on the key points that make a<br />
successful program and then to later expand on this understanding.<br />
If you have not already done so open the PDE and start a new sketch. You can do<br />
this by clicking<br />
File → New<br />
Save the sketch in your sketchbook folder<br />
File → Save As...<br />
Give the sketch a unique name that you will remember.<br />
In the text editor of the PDE create the <strong>Hello</strong> World 1.0 program by typing<br />
println("<strong>Hello</strong> World");<br />
Press the “Run” button in the PDE which looks like a play button, or ctrl-r on<br />
your keyboard. The PDE checks, compiles and executes your your program. If all<br />
has gone well you should get a result similar the following image.<br />
<strong>Hello</strong> World Program 1.0 45
An Introduction To Programming With <strong>Processing</strong><br />
The typical “<strong>Hello</strong> World” program is many a programmers first attempt at coding.<br />
If your console window has the phrase “<strong>Hello</strong> World” printed in it,<br />
congratulations you've successfully completed the <strong>Hello</strong> World 1.0 program!<br />
Like I said earlier, don't expect to be impressed right away, building a more useful<br />
program is going to take a little more practice. Nonetheless let's have a look at<br />
what is going on here.<br />
Firstly you'll notice that the text editor has formatted the text we input in different<br />
colors.<br />
The colors denote specific meanings in <strong>Processing</strong>, for example in our <strong>Hello</strong><br />
World 1.0 program:<br />
Orange<br />
Orange is used to identify a command.<br />
Black<br />
Black identifies syntax formatting characters such as parenthesis and a statement<br />
terminator.<br />
Blue<br />
Blue identifies a string of data.<br />
<strong>Hello</strong> World Program 1.0 46
An Introduction To Programming With <strong>Processing</strong><br />
IDE's such as the PDE that use syntax highlighting make reading code easier to<br />
decipher and once you get familiar with what the colors represent you'll find<br />
yourself separating the code you are reading into smaller manageable chunks by<br />
identifying the colors that serve specific functions.<br />
We refer to the sentence typed in the text editor as a statement. Statements are<br />
easy to identify because they always end with a semi-colon and not with a period<br />
(like in English). Our entire <strong>Hello</strong> World 1.0 program consists of only one<br />
statement which in itself consists of only one command.<br />
<strong>Processing</strong> is a case sensitive language so it is very important that when you type<br />
a command you do not mix it's casing because println() and printLn() will not<br />
yield the same results, in fact the latter will cause an error.<br />
The println() function<br />
println() is a special type of command called a function.<br />
Sometimes a function is also referred to as a subroutine so how the term is used<br />
from one language to another may vary but regardless of what you call it the<br />
purpose of a function is generally the same in any programming language, a<br />
portion of code (usually a single word followed immediately with parenthesis)<br />
that exists within a larger body of code (in our case this could be the sketch we<br />
are creating) and performs a specific task within the context of the program but is<br />
also independent of the program.<br />
As you are aware, we have not defined the function println() we are just simply<br />
using it as it has been defined by the people that developed <strong>Processing</strong>, in other<br />
words we have not told the computer what to do when it comes across println() in<br />
our <strong>Hello</strong> World 1.0 program. This means that the main body defining how<br />
println() acts in our program is not defined within our program but exists<br />
independently of our program, probably somewhere else on your hard disk drive<br />
where you installed <strong>Processing</strong>. If we were to take another look at the <strong>Hello</strong><br />
World 1.0 program, we can see the function println() is telling the machine, that<br />
the sketch is running on, to print whatever is inside the parenthesis. We call data<br />
we input to a function through parenthesis, parameters and some other higher<br />
level languages might refer to parameters as arguments. The parameters our<br />
println() function accepts in this case is the string of characters that spell out the<br />
words “<strong>Hello</strong> World”.<br />
<strong>Hello</strong> World Program 1.0 47
An Introduction To Programming With <strong>Processing</strong><br />
There are two points worth noting here, firstly we have input data into the<br />
println() function and secondly it has returned data back to us, that being what it<br />
has printed to the debugger console. When a function is used in this way we are<br />
said to be calling a function. Functions are the building blocks of <strong>Processing</strong> and<br />
we will be using them regularly and even creating our own.<br />
The process of calling a function visualized.<br />
Syntax and syntax errors<br />
The arrangement of components within a statement is exceptionally important in<br />
programming. Unlike in natural languages, where sentences can be structured in<br />
several different configurations and still have the same meaning. In programming<br />
a specific syntax exists for all languages and must be adhered to or your compiler/<br />
interpreter might throw an exception or a syntax error. Syntax errors are generally<br />
quite common when you first start programming, it is easy to forget to place a<br />
semi-colon at the end of a statement or close parenthesis that have been left<br />
hanging open. Errors like these are often easy to debug, particularly when using<br />
the PDE. For example if we were to make a mistake in our <strong>Hello</strong> World 1.0<br />
program and forget to close the open parenthesis, when trying to run the sketch<br />
we could get an error looking something like this...<br />
<strong>Hello</strong> World Program 1.0 48
An Introduction To Programming With <strong>Processing</strong><br />
Syntax errors are common when one first starts programming, but with the help of the<br />
debugging console they can be relatively easy to identify.<br />
As you can see debugging the program in this case is really quite simple, in fact<br />
the PDE tells us exactly where the error is. In larger programs however it might<br />
not be so obvious where the problem lies, although the PDE will try to help you in<br />
tracking down a bug where ever it can.<br />
Some pointers to remember when constructing statements in <strong>Processing</strong><br />
• Always end statements with a semi-colon<br />
• All parenthesis (), brackets [] and braces {} that are opened with their<br />
corresponding left characters must be closed with the right version of the<br />
same character. None of these sets are interchangeable, but some of these<br />
sets are nestable.<br />
• A String of literal characters (such as “hello world”) must exist between<br />
double quotes. Single quotes are reserved for the char data type (discussed<br />
later).<br />
• If you have any uncertainties about your program, such as how to use a<br />
function or it's syntax, look it up in the <strong>Processing</strong> reference which can be<br />
accessed online at http://processing.org/reference/ or from the PDE ,for<br />
offline viewing, click :<br />
Help → Reference<br />
Of course there are many other points worth noting on syntax and program<br />
structure but we will get to these in due time, for now there's no need to get ahead<br />
of ourselves.<br />
<strong>Hello</strong> World Program 1.0 49
An Introduction To Programming With <strong>Processing</strong><br />
Logical Errors<br />
Logical errors are errors that do not cause the program to halt, crash or throw an<br />
error but will cause the program to act in an unexpected manner or produce<br />
unintended results. Logical errors can therefore be difficult to track down and<br />
rectify because the PDE does not indicate the specific location of an error.<br />
Keeping track of your data through documentation and organizing it into small<br />
manageable chunks can be one method of avoiding logical errors. If your program<br />
seems to have a logical error you might have to use the println() function to track<br />
the values you were hoping to have your program return to you.<br />
Display Window<br />
In our <strong>Hello</strong> World 1.0 program after pressing the Run button you will notice that<br />
a new smaller window was created. This is the Display Window and because<br />
<strong>Processing</strong> is a visually oriented language it automatically creates this window<br />
which you will usually use to draw to.<br />
The default Display window has dimensions 100 pixels in width by 100 pixels in height.<br />
<strong>Hello</strong> World Program 1.0 50
An Introduction To Programming With <strong>Processing</strong><br />
Lets take a look at how we can control the Display window with the size()<br />
function.<br />
The size() function allows you to specify the dimensions of the Display window<br />
in pixels. You use the size() function by supplying two parameters to it, an x<br />
value which defines the horizontal dimension of the Display window and a y<br />
value which defines the vertical dimension of the Display window. Just like the<br />
println() function, parameters for the size() function are entered between the<br />
function's parenthesis. For example if we wanted the dimension of the Display<br />
window to be 640 pixels across by 480 pixels down we would type:<br />
size(640,480);<br />
Note that because we have just entered a statement telling <strong>Processing</strong> how big we<br />
want the Display window to be we must terminate this statement with a semicolon.<br />
You will also note that the two values 640 and 480 are separated with a comma.<br />
Do not try to separate values with a semi-colon because the statement is<br />
incomplete at that point and you are therefore attempting to terminate it<br />
prematurely. This will most commonly result in a syntax error or even worse in a<br />
logical error in some cases.<br />
Parenthesis following a function's name is usually reserved for parameters<br />
relating to the function and these parameters are most commonly separated by<br />
commas. This is pretty easy to remember because in English you generally list<br />
items by separating them with a comma in <strong>Processing</strong> and many other higher<br />
level languages you separate parameter values for a function with a comma.<br />
The two values 640 and 480 have been “listed” in this particular order because<br />
when <strong>Processing</strong> accepts parameters of dimensional type like x and y (in 2<br />
dimensions) or x, y and z (in 3 dimensions) it will generally accept values in the<br />
order x first, y second and z third. This is with the exception of a trigonometric<br />
function called atan2() in which y is read first followed by x due to the special<br />
circumstances of how this function works.<br />
Add the second statement to your <strong>Hello</strong> World 1.0 program<br />
Below the first statement type the second statement so that your code reads:<br />
println("<strong>Hello</strong> World");<br />
size(640,480);<br />
<strong>Hello</strong> World Program 1.0 51
An Introduction To Programming With <strong>Processing</strong><br />
Standardized Coding Practices<br />
Comments and white space form a part of standardized coding practices.<br />
Standardized coding practices establish a consistency between different software<br />
languages. If you do not use them your software may or may not throw an<br />
exception or an error, but you can be certain that there are many people that might<br />
read your code who will find it non-user-friendly when you do not use<br />
standardized coding practices and try to invent your own.<br />
Comments<br />
Comments are lines of information inserted between code that informs a person<br />
reading the code of it's purpose and intent. Comments are completely ignored by<br />
the software executing the code such as the PDE and they should be written in<br />
plain and simple English or, what ever your chosen language. Consider that the<br />
comments you write might not always be for your personal understanding but for<br />
another person reading your code and therefore should reflect a clear and<br />
impartial explanation of your code.<br />
Commenting your code becomes particularly useful for code that you have not<br />
revisited over a long period of time. Regardless of whether you wrote the code or<br />
not, trying to understand what revisited code is supposed to do after long periods<br />
of time becomes a cumbersome process when it is not commented properly.<br />
Comments in <strong>Processing</strong> and many other higher level languages are indicated<br />
with two forward slashes:<br />
// for a single line comment, that is a comment that is<br />
// only one line long,<br />
// but can also have one comment following another.<br />
Comments that are more than one line long are called multi-line comments in<br />
some programming languages and documentation comments in <strong>Processing</strong>. They<br />
are indicated by starting the comment with:<br />
/** typing the multi-line comment<br />
...<br />
...<br />
and ending it with */<br />
<strong>Hello</strong> World Program 1.0 52
An Introduction To Programming With <strong>Processing</strong><br />
White space<br />
White space is also sometimes referred to as negative space and is the space<br />
between the characters of text that make up the lines of your source code text file.<br />
For example a space, tab or enter/break are all referred to as white space.<br />
<strong>Processing</strong> unlike other programming languages (such as Python) completely<br />
ignores white space, just like it ignores comments. However just because<br />
<strong>Processing</strong> ignores white space doesn't mean you should. Using a consistent<br />
spacing and formatting of your code will make it easier to read. For example:<br />
println("<strong>Hello</strong> World");size(640,480);<br />
is valid code but less readable than the same program with white space:<br />
println("<strong>Hello</strong> World");<br />
size(640,480);<br />
You can probably imagine how unreadable code could quickly become when<br />
creating more complex programs with hundreds of statements.<br />
Let's revisit our <strong>Hello</strong> World 1.0 program and retype it taking standardized coding<br />
practices into consideration.<br />
/**<br />
* <strong>Hello</strong> World 1.0 Program<br />
* by Lyndon Daniels.<br />
* 11/01/2011<br />
* This example program demonstrates how to<br />
* create a <strong>Hello</strong> World Program in <strong>Processing</strong>.<br />
*/<br />
//Determine the size of the Display window<br />
size(640,480);<br />
//Print characters to the console<br />
println("<strong>Hello</strong> World");<br />
<strong>Hello</strong> World Program 1.0 53
An Introduction To Programming With <strong>Processing</strong><br />
Program Notes<br />
Firstly you'll notice that every line in the documentation comment except the first<br />
and last lines of this comment is started with an asterisk “*”. This is not necessary<br />
but, it does make the code look somewhat nicer and many programmers adopt this<br />
fashion of multi-line commenting so I've included it in this program. As<br />
mentioned earlier to <strong>Processing</strong> it makes absolutely no difference, but to us it<br />
makes the code easier to read.<br />
It is standardized coding practice to include the following information in the<br />
documentation comment.<br />
• Name of the program,<br />
• The programmers name,<br />
• The date on which the program was released,<br />
• A brief description of what the program does.<br />
Secondly you'll also note that I've changed the order in which the statements are<br />
executed (or run). Code written in this way resembles a procedural programming<br />
style meaning that the code is executed one line after the next starting at the top of<br />
the document and working down. Subsequently it makes more sense to define the<br />
size of the Display window before any other code is run. At a later stage you will<br />
see that when using the setup() function starting with the size() function, before<br />
any other functions following setup(), is mandatory.<br />
Cartesian Graph and the <strong>Processing</strong><br />
Coordinate System<br />
As mentioned earlier the Display Window's dimensions are determined within the<br />
size() function via the parameters that it accepts. Those dimensions are measured<br />
in pixels. When we start drawing to the Display Window we need to tell<br />
<strong>Processing</strong> where exactly we are attempting to draw to within the Display<br />
Window, this information we supply to <strong>Processing</strong> in the form of x and y<br />
coordinates when dealing with a 2D sketch and x, y and z coordinates when<br />
dealing with a 3D sketch. As a result you can think of the Display window as<br />
being a piece of graph paper with invisible lines.<br />
Cartesian Graph and the <strong>Processing</strong> Coordinate System 54
An Introduction To Programming With <strong>Processing</strong><br />
The Display Window can be divided up into a grid.<br />
The origin of the Display window is in the top left hand corner, being the origin<br />
it's coordinates will be (0,0) meaning 0 x and 0 y respectively. This type of layout<br />
might look familiar to you, that's because it's based on the Cartesian graph<br />
system. This is the name for the type of graph layout we use in <strong>Processing</strong> and<br />
many other programming languages that allow us to create and place components<br />
of a sketch within an area such as the Display Window. The main difference<br />
between the programmatic version of the Cartesian graph and the mathematical<br />
version of the Cartesian graph is that in the programmatic version the positive y<br />
axis runs downwards not upwards as is usually the case in the mathematical<br />
representation of this graph. This actually does not change anything about how<br />
the graph system is used, if you find this to be a bit odd you can think of it as if<br />
we were looking at a piece of graph paper rotated 180 degrees around the x axis<br />
so we're looking at the back of the graph paper and everything drawn on the paper<br />
now appears upside down. As you can imagine nothing drawn on the graph paper<br />
has changed just the way we are looking at it is different. Understanding how the<br />
Cartesian graph system is applied in programming is a lot easier when we have an<br />
example to work with, so lets add to our <strong>Hello</strong> World 1.0 program.<br />
Cartesian Graph and the <strong>Processing</strong> Coordinate System 55
An Introduction To Programming With <strong>Processing</strong><br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1<br />
In the revised version of our <strong>Hello</strong> World Program we will start using the Display<br />
Window, firstly to display the original character set “<strong>Hello</strong> World” then to display<br />
a few shapes too.<br />
text()<br />
The text() function is the first function we will use to make <strong>Processing</strong> draw<br />
something to the Display Window for us. The text() function accepts parameters<br />
in various formats of which the simplest format is:<br />
text(data, x, y);<br />
The data parameter in this case will be the string of characters that spell the<br />
phrase “<strong>Hello</strong> World” and as you've probably already guessed the x and y<br />
parameters tells <strong>Processing</strong> where in the Display Window we would like to draw<br />
the text in terms of x and y coordinates.<br />
So let's give it a try, add the following line to the bottom your <strong>Hello</strong> World 1.0<br />
sketch:<br />
text(“<strong>Hello</strong> World”, width/2, height/2);<br />
Using the Display Window gives you immediate feedback for testing your code.<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 56
An Introduction To Programming With <strong>Processing</strong><br />
Program Notes<br />
You'll notice that your sketch is now making use of the Display Window, which<br />
is the first step towards creating visual representations of your code. We used the<br />
string of text “<strong>Hello</strong> World” in the data parameter, but the x and y parameters are<br />
looking a little different particularly if you were expecting them to be numbers. In<br />
fact they are numbers, instead of inputting a specific number for the x and y<br />
parameters we used an expression and in this case the expression evaluates to a<br />
number. It is this number that <strong>Processing</strong> reads and accepts as the parameter. But<br />
what exactly do the expressions mean?<br />
Amongst the many things that <strong>Processing</strong> is, it is also a very sophisticated<br />
calculator. It has the ability to calculate very complex mathematical formulae and<br />
also is able to do very simple math too. The expression:<br />
width/2<br />
is asking <strong>Processing</strong> to get the width of the Display Window and divide (/) it by 2.<br />
The keyword width is a type of data known as a system variable. Basically the<br />
width system variable stores information set by the first parameter in the size()<br />
function, and as you are aware the first parameter in the size() function<br />
determines the width of the Display window. In our program we set the size()<br />
function to read:<br />
size(640,480);<br />
How this relates to the width system variable is that every time <strong>Processing</strong> sees<br />
the keyword width it replaces it with whatever we set the width value to be in the<br />
size() function. In this case since we set the width to 640 the text statement as<br />
<strong>Processing</strong> reads it looks something like this:<br />
text(“<strong>Hello</strong> World”, 640/2, 480/2);<br />
The height system variable has the same effect but relates to the second parameter<br />
of the size() function.<br />
So the question is why did we not just simply type the values 640 and 480 instead<br />
of using the keywords width and height respectively? Even further still why didn't<br />
we just type the values 320 for the x parameter and 240 for the y parameter of the<br />
text() function, so that it looks like this:<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 57
An Introduction To Programming With <strong>Processing</strong><br />
text(“<strong>Hello</strong> World”, 320, 240);<br />
Although this is a perfectly valid methodology, it is not very versatile. Currently<br />
there is not too much maintenance involved in updating the code if we were to<br />
decide that the Display Window needs to be smaller, however when it comes to<br />
creating the rest of the sketch which is going to involve drawing shapes to the<br />
Display Window of which each shape will need to have it's own set of<br />
coordinates, if we had typed in a specific value for each x and y position, updating<br />
the code to reflect the change of dimensions of our Display Window would mean<br />
changing each statement where we input specific x and y values. That could mean<br />
a lot of extra and unnecessary work. By using an expression with the keywords<br />
width and height we can place whatever we are drawing relative to a position<br />
determined by the size() function. So all we need to do now is update the size()<br />
function and every place that we have used the keywords (width and height)<br />
relating to the size() function updates without us having to change anything more<br />
than a single statement. This is a programming methodology that is used often<br />
and referred to as implicit programming, and although it might not seem entirely<br />
obvious to you at this point why it is a recommended methodology it should<br />
become more clear as you delve deeper into the <strong>Hello</strong> World 1.2 program.<br />
Formatting Text<br />
You might have noticed that the text is supposed to be in the center of the Display<br />
Window but looks more like it's leaning to the right hand side of the window.<br />
<strong>Processing</strong> allows us to align text relative to the coordinates we specified for the<br />
text() function's x and y parameters. The relative positions are LEFT, RIGHT or<br />
CENTER. I have typed them in upper case because that is the format that<br />
<strong>Processing</strong> accepts them as, when entered as a parameter for the textAlign()<br />
function.<br />
Lets fix the text alignment so that it is in the center of the Display Window, add<br />
the following line of code directly above the text statement:<br />
textAlign(CENTER);<br />
If you were to re-run the sketch your updated version should have the text directly<br />
in the center of the Display Window. As we are using a procedural programming<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 58
An Introduction To Programming With <strong>Processing</strong><br />
style to create this sketch, <strong>Processing</strong> needs statements input in a particular order.<br />
We'll discuss procedural programming and other programming paradigms in more<br />
detail a bit later, but for now it's very important to note the order that statements<br />
are placed in. Placing the textAlign() function before the text() function ensures<br />
that the textAlign() function is run before the text() function thereby ensuring that<br />
by the time <strong>Processing</strong> gets to drawing the text in the Display Window it already<br />
knows that the coordinates within the text() function refer to the CENTER of the<br />
text.<br />
Next we'll have a look at the size of the text. Currently the sketch looks like it's<br />
drowning the text in a sea of greyness, so lets make the text a little bigger. The<br />
textSize() function allows us to set the size of text in pixels. The size number is<br />
input as a parameter of the textSize() function. Add the following statement<br />
before the text statement:<br />
textSize(24);<br />
Now we're starting to get somewhere, although white text on a grey background<br />
does not exactly jump out at you. So in keeping with the old <strong>Processing</strong>.org color<br />
scheme we're going to use a black background with light blue text.<br />
Color<br />
Color in <strong>Processing</strong> can be input in several different formats such as RGB (Red,<br />
Green, Blue), HSB (Hue, Saturation, Brightness) or Hexadecimal code. RGB is<br />
the default color mode but this can be changed with the colorMode() function.<br />
Lets have a look at how to change the background color. Add the following<br />
statement to your sketch directly after the size() function:<br />
background(0,0,0);<br />
The background() function accepts up to three parameters, in our case the first<br />
parameter is the Red value followed by the Green value and finally by the Blue<br />
value. As we want a black background all of these values are set to 0 the<br />
minimum value for the current color mode of RGB, the maximum value for these<br />
parameters is 255, this gives you a total of 256 different color values for each<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 59
An Introduction To Programming With <strong>Processing</strong><br />
color (remember 0 is also a value). If we wanted a white background we would<br />
have to enter 255 for each of the three parameters of the background() function.<br />
Back to the color of the text. The textAlign() and textSize() functions set<br />
parameters not just for the text currently displayed but for all text that is created<br />
thereafter. Until these functions are used again to change these parameters they<br />
will remain in <strong>Processing</strong>'s memory and effect all text that is drawn to the Display<br />
Window following their execution.<br />
The fill() function acts in a similar fashion, it accepts color values and will effect<br />
everything that is drawn to the Display window that has a fill after the function is<br />
evoked. We will have a look at how to modify this behaviour a bit later, for now<br />
lets focus on getting the text to display in a light blue.<br />
In the PDE click:<br />
Tools → Color Selector<br />
The Color Selector is a build automation tool accessible within the PDE<br />
The Color Selector dialogue box is useful for finding the specific HSB, RGB or<br />
Hexidecimal color values of a color. In our case the RGB values for the light blue<br />
I'm looking for are R 191, G 233 and B 255. I can now use these values in my<br />
sketch.<br />
Before the text() function type the following statement:<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 60
An Introduction To Programming With <strong>Processing</strong><br />
fill(191, 233, 255);<br />
This statement sets the color of the text to light blue color.<br />
Before we continue drawing shapes, lets make a few adjustments to the horizontal<br />
position of the text so that we can have some space to draw a smiley face in the<br />
center of the Display Window. Once again we're not going to input a specific<br />
number into the y parameter of the text() function, we're instead going to use an<br />
expression so that we can have <strong>Processing</strong> do the work for us just in case we feel<br />
like changing the dimensions of the sketch once it's complete.<br />
Basically we want to keep the text as is but just place it closer towards the bottom<br />
of the sketch about three quarters of the way down. Since we know that the height<br />
system variable contains the y dimension of our sketch and that dividing it by 2<br />
will return a value that is half the size of the y dimension of our sketch. Dividing<br />
the height value by 4 will give us a value that is a quarter of the height of our<br />
sketch. If we then multiply this value by 3 we will have a value that is three<br />
quarters the length of the y dimension of our sketch. So our expression would<br />
look like this:<br />
(height/4)*3<br />
What this reads as is “height divided by four then multiplied by three”. Just like in<br />
mathematics anything within parenthesis is evaluated before that which is outside<br />
of parenthesis. So the expression height/4 is first evaluated, the answer of this<br />
expression is then multiplied by 3.<br />
Modify your text statement to look like this:<br />
text("<strong>Hello</strong> World", width/2, (height/4)*3);<br />
Now we can ensure that whatever the y dimension of our Sketch may be,<br />
<strong>Processing</strong> will always place our text three quarters of the length down the y axis<br />
of the Display Window.<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 61
An Introduction To Programming With <strong>Processing</strong><br />
Drawing<br />
The new <strong>Hello</strong> World Program in <strong>Processing</strong>.<br />
<strong>Processing</strong> is a language that was made to create visual representations of your<br />
code really easily, and as a result the developers of <strong>Processing</strong> have provided us<br />
with pre-configured functions for drawing primitive shapes much like you would<br />
expect in a drawing program. Shapes such as rectangles, ellipses and triangles<br />
amongst others are known as 2D primitives and can easily be drawn to the<br />
Display Window with a simple keyword. We'll start by drawing an ellipse.<br />
2D Primitives<br />
Drawing an ellipse in <strong>Processing</strong> is easy you just use the ellipse() function that<br />
accepts parameters in the following order:<br />
ellipse(x, y, width, height);<br />
As you might have already guessed the x and y parameters indicate where the<br />
ellipse is to be drawn on the coordinate system, and the width and height<br />
parameters indicate the width and height of the ellipse. Please note that the terms<br />
width and height in this context have nothing to do with the system variables<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 62
An Introduction To Programming With <strong>Processing</strong><br />
width and height which store the information relating to the x and y dimensions of<br />
the Display Window. To draw an ellipse in the Display Window add the<br />
following statement to the end of your program:<br />
ellipse(width/2, height/2, 100, 100);<br />
Once again to find the center of the Display Window I have used the expressions<br />
width/2 and height/2 this gives me the x and y coordinates respectively that will<br />
be the center of the ellipse. Technically a circle is an ellipse with an equal width<br />
and height, which is why I have input 100 for both the width and height<br />
parameters of the ellipse() function. I've also chosen to enter explicit values for<br />
the ellipse's width and height parameters, as I don't want the dimensions of the<br />
ellipse to change even if I do decide to change the dimensions of the Sketch itself.<br />
Using this hybrid style of mixing implicit programming and explicit programming<br />
can sometimes lead to logical errors, so you should always be certain of what you<br />
are doing when using this approach to programming.<br />
The Origin of an ellipse<br />
<strong>Processing</strong> provides several different ways to draw an ellipse which modify what<br />
the x and y parameters of the ellipse() function refer to. These parameters of<br />
ellipse() define what is known as the origin of the ellipse, the function<br />
ellipseMode() is used to change where the origin of the ellipse is with regards to<br />
the x and y parameters of the ellipse() function. This relationship will determine<br />
where the ellipse is drawn within the Sketch.<br />
We use the function ellipseMode() which accepts the parameters CENTER,<br />
RADIUS, CORNER, or CORNERS to determine how the circle is to be created.<br />
Using the CENTER parameter tells <strong>Processing</strong> to use the x and y parameters of<br />
the ellipse() function to determine the center of the ellipse as it's origin. The<br />
CENTER parameter for ellipseMode() is the default mode, and is subsequently<br />
why we did not add the statement to our sketch. If you did want to use the<br />
CENTER creation mode for drawing ellipses after having overridden this setting<br />
with one of the other modes, to reactivate the CENTER mode parameter you<br />
would add the following statement to your sketch before using the ellipse()<br />
function:<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 63
An Introduction To Programming With <strong>Processing</strong><br />
ellipseMode(CENTER);<br />
Remember <strong>Processing</strong> is case sensitive so don't forget to type this parameter in<br />
upper-case.<br />
Drawing an ellipse with the CENTER parameter of ellipseMode()<br />
The CORNER parameter for ellipseMode() function allows you to create an<br />
ellipse by specifying the x and y coordinates as the corner of an imaginary<br />
bounding box that surrounds the ellipse. The x and y parameters are used to<br />
determine the top left-hand corner of the bounding box from where the width and<br />
height parameters are used to extend to the maximum width and height values of<br />
the ellipse.<br />
Drawing and ellipse with the CORNER parameter of ellipseMode()<br />
To use this creation method for ellipses type the following code:<br />
ellipseMode(CORNER);<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 64
An Introduction To Programming With <strong>Processing</strong><br />
It's time to save your sketch if you haven't already done so. In the PDE click<br />
File → Save As...<br />
Change the name of your sketch and save it. <strong>Processing</strong> will create a new folder<br />
in your sketchbook folder with the new name of your sketch, it's also worth<br />
noting that if you have added any additional files to your sketch such as images or<br />
other files processing will also copy the data folder that it created automatically<br />
when you added external content to a sketch to the new sketch location. This is<br />
something to be aware of as you can inadvertently duplicate the amount of data<br />
on your hard disk drive if you are unaware of this feature in <strong>Processing</strong>. Adding<br />
external content to a sketch is something we will get into a bit later when we start<br />
adding images to our sketch.<br />
Your sketch should read something like this:<br />
/**<br />
*<strong>Hello</strong> World 1.2 Program<br />
*by Lyndon Daniels.<br />
*<br />
*This example program demonstrates how to<br />
*create a <strong>Hello</strong> World Program in <strong>Processing</strong>.<br />
*/<br />
//Determine the size of the display window<br />
size(640,480);<br />
background(0,0,0);<br />
//Print characters to the console<br />
println("<strong>Hello</strong> World");<br />
//Render and format text<br />
textAlign(CENTER);<br />
textSize(24);<br />
fill(191,233,255);<br />
text("<strong>Hello</strong> World", width/2, (height/4)*3);<br />
//Drawing the face<br />
ellipse(width/2, height/2, 100, 100);<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 65
An Introduction To Programming With <strong>Processing</strong><br />
Aliasing<br />
You might have noticed that the ellipse is looking a bit pixelated and not very<br />
smooth this effect is known as aliasing and is often counteracted with the effect<br />
of anti-aliasing which creates the impression of the data (such as an ellipse)<br />
drawn to the display of a computer screen as appearing to look smoother.<br />
Fortunately in <strong>Processing</strong> we have a function that is made exactly for the purpose<br />
of making the contents of a sketch look smoother. Add the following statement to<br />
the first part of the sketch just after the size() function:<br />
smooth();<br />
The smooth() function does not accept any parameters but still requires<br />
parenthesis, it's also worth noting that although using the smooth() function will<br />
make your geometry appear smoother it might come at the expense of slowing<br />
down the rate at which your sketch runs. By default a <strong>Processing</strong> sketch will try to<br />
update itself 60 times in one second (if a program loop such as draw() is used),<br />
this allows for smooth looking motion in a <strong>Processing</strong> sketch and almost<br />
instantaneous interactivity. We are creating what is known as a static sketch<br />
which does not involve any interactivity or animation, so using the smooth()<br />
function in this situation should not greatly influence the sketches performance.<br />
Smile<br />
The ellipse needs a smile in order to make it into a smiley face. We will use an arc<br />
to draw the smile, the main reason we are using an arc is firstly to introduce the<br />
arc() function but more importantly it's an opportunity to explore working with<br />
angles in <strong>Processing</strong>.<br />
Angles in <strong>Processing</strong><br />
In mathematics angles are usually measured in either degrees or radians,<br />
<strong>Processing</strong> and many other programming languages generally accept and/or prefer<br />
the latter. One of the main reasons most programming languages accept a unit of<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 66
An Introduction To Programming With <strong>Processing</strong><br />
measuring angles in radians is because it allows us to work with the value known<br />
as PI (pronounced py rhymes with “try”) and represented mathematically as π. PI<br />
is a number that has the approximate value 3.1415927 (calculated to seven<br />
decimal places). The actual number that PI represents, in programming, is not<br />
quite as important as it's mathematical equivalent subsequently we will generally<br />
never need to remember what this number is in programming but rather what the<br />
language we are choosing to use it in, represents it as. In <strong>Processing</strong> the value of π<br />
is represented by the mathematical constant PI. To <strong>Processing</strong> and many other<br />
programming languages a constant is a value that does not change, as a result it<br />
makes sense for the <strong>Processing</strong> representation of pi to be a constant. Pi has always<br />
been the same value long before Archimedes approximated it's value in the 200's<br />
BC as it's implication in the construction of many architectural wonders of human<br />
ingenuity from as far back as the Egyptian pyramids and even further back in<br />
human history suggests, and it's highly unlikely that pi could be used to represent<br />
any other value. So what does it mean?<br />
Pi is the ratio of the circumference of a circle to it's diameter, and pi radians is<br />
also equal to approximately 180 degrees. Pi can be expressed mathematically as:<br />
π = C/d<br />
Where C is the circumference of a circle and d is the diameter of a circle.<br />
So how do we use this information about pi to work with radians and degrees?<br />
Well we already know that pi radians is equal to 180 degrees so that means twice<br />
pi radians (or you might be more familiar with the mathematical notation 2πr) is<br />
equal to a full revolution or 360 degrees, or as the value is referred to in<br />
<strong>Processing</strong> TWO_PI. <strong>Processing</strong> also has other mathematical constants to<br />
represent pi in other useful quantities such as HALF_PI which is the<br />
approximately equivalent to 90 degrees and finally QUARTER_PI. But what<br />
about all the other infinite angles how do we reference these values in <strong>Processing</strong>?<br />
You could either type them out explicitly as radians or if you know their<br />
approximate equivalent in degrees you can use a formula to convert the value<br />
from degrees to radians:<br />
radians = (π/180)*angle in degrees<br />
For example if we had the angle 270 degrees and we needed this in radians so that<br />
we could use it in our <strong>Processing</strong> sketch we could either use the mathematical<br />
constants <strong>Processing</strong> provides us with and type the following expression:<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 67
An Introduction To Programming With <strong>Processing</strong><br />
PI + HALF_PI<br />
This expression would return the equivalent of 270 degrees in radians. Or we<br />
could use the above mentioned formula and type the following expression in<br />
<strong>Processing</strong>, which would also return the equivalent of 270 degrees in radians:<br />
(PI/180)270<br />
Remember that because there is no mathematical operator between 270 and<br />
parenthesis the value of what is in parenthesis must be multiplied by 270, this will<br />
return the equivalent of 270 degrees in radians.<br />
One of the simplest methods of converting degrees to radians in <strong>Processing</strong> is to<br />
use the radians() function. If you know the value of the angle in degrees you can<br />
simply use the value in degrees as a parameter of the radians() functions. For<br />
example:<br />
radians(270);<br />
This will convert 270 degrees to it's equivalent in radians. It is important that<br />
angles in <strong>Processing</strong> are converted to radians because all trigonometric functions<br />
that require angles accept this value in radians.<br />
Getting the hang of working with radians at first might be a little tricky if you are used to<br />
degrees, but if you think of them in terms of pi they can be a lot easier to work with.<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 68
An Introduction To Programming With <strong>Processing</strong><br />
The arc() function in processing accepts six parameters in the format x, y, width,<br />
height, start, stop. You are already familiar with the first four parameters x and y<br />
determine the point of origin of the arc and this can be further controlled with the<br />
ellipseMode() function. width and height represent the dimensions of the arc in<br />
much the same way that these parameters, determine the dimensions of an ellipse.<br />
The last two parameters you might not be familiar with start and stop determine<br />
the starting and ending values of the angle of the arc, so for example we are going<br />
to draw a half circle which you know has an angular value of 180 degrees,<br />
secondly because we want our smile to be straight we will start it at 0 and end it at<br />
PI (which is approximately 180 degrees). Add the following statement to your<br />
sketch following the ellipse statement:<br />
arc(width/2, height/2, 50, 50, 0, PI);<br />
A Smile on the “<strong>Hello</strong> World” Program.<br />
Editing the smile<br />
Our smile drawn with the arc() function looks fine but needs a bit of work. Firstly<br />
although you cannot see it the arc actually has a fill. In order to see the fill we will<br />
first have to remove or hide the ellipse, but we're happy with the way the ellipse<br />
looks so instead of deleting the statement or cutting it to the clipboard we'll<br />
comment it out. Commenting out a statement or a group of statements is the<br />
process of adding comment tokens to the statements that cause the statements to<br />
be ignored by the compiler. Comment tokens in <strong>Processing</strong> are two forward<br />
slashes “//” as mentioned previously. The easiest way to comment out the ellipse<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 69
An Introduction To Programming With <strong>Processing</strong><br />
statement is simply to place the comment tokens at the start of the statement so it<br />
looks like this:<br />
//ellipse(width/2, height/2, 100, 100);<br />
you will notice that when you comment out a statement, syntax highlighting<br />
causes the statement to turn grey. This means we can now run the program and<br />
<strong>Processing</strong> will no longer draw our ellipse, until we uncomment the statement by<br />
deleting the comment tokens. Another way of commenting out a whole block of<br />
code is to select the lines of code you wish to comment out in the PDE click:<br />
Edit → Comment/Uncomment<br />
This will toggle your selection between a commented state and a standard block<br />
of non-commented code. Commenting and uncommenting is just simply a<br />
convenient and easy way of testing a program by including and excluding<br />
statements easily without having to retype out a statement that has been deleted or<br />
using our operating system's clipboard.<br />
Commenting out the ellipse statement reveals that the arc is drawn with a fill.<br />
To remove the fill we will use the noFill() function. So between the ellipse<br />
commented statement and before the arc statement add the following code:<br />
noFill();<br />
The order in which commands are issued to <strong>Processing</strong> is very important.<br />
Functions such as rectMode() and noFill() not only effect the command that<br />
directly follows them (such as the arc statement being effected by the noFill()<br />
function) but they also effect all statements that follow there after that rely on<br />
these special functions. So what that means is that if we were to place the noFill()<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 70
An Introduction To Programming With <strong>Processing</strong><br />
function before an uncommented ellipse statement followed by the arc statement<br />
both the ellipse and the arc would have no fill. This is obviously not what we<br />
want, we only want the arc to be without a fill and subsequently run the ellipse()<br />
function before noFill().<br />
If you were to run the sketch at this point it might look as though the noFill()<br />
command has removed the arc completely from the Display Window, but this is<br />
not the case. In <strong>Processing</strong> 2D primitives such as triangles, arcs, quads, ellipses<br />
and rectangles are actually made up of both a fill and a stroke. We've already seen<br />
that the fill can be controlled with the noFill() function, the fill() function and that<br />
the default in <strong>Processing</strong> is that all 2D primitives have a fill.<br />
The stroke is the outline that surrounds all 2D primitives and looks like a line.<br />
The stroke can also be turned off by a function similar to the noFill() function, as<br />
you might have guessed it's noStroke().<br />
To turn the stroke or fill back on or to simply edit an existing stroke or fill we use<br />
the stroke() or fill() functions. Both of these functions accept parameters in the<br />
form of a grayscale color, an RGB value or a RGBA value by default. You can<br />
also control how <strong>Processing</strong> accepts parameters for these two functions with the<br />
colorMode() function. We'll be changing our black stroke (which is why it seems<br />
to have disappeared, because it's camouflaged into the black background) to a red<br />
smile. Add the following statement after the noFill statement:<br />
stroke(255,0,0);<br />
The stroke() function can be used in a similar way fill() is used but for editing the color<br />
of lines.<br />
Now we have a smile floating above our text, so we're going to uncomment the<br />
ellipse statement and when we run the sketch our smile is restored to it's elliptical<br />
face.<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 71
An Introduction To Programming With <strong>Processing</strong><br />
The smile is looking a little too high up on the face so we're going to move it<br />
down, this is easy enough as we already have the style of the smile we are looking<br />
for we just need to offset it's y position. To do this we are going to edit the arc()<br />
function once more to the following state:<br />
arc(width/2, height/2 + 10, 50, 50, 0, PI);<br />
Notice that because we are using an inverted Cartesian graph adding 10 to the<br />
arc's current y value actually moves the arc down, inversely if we subtracted 10<br />
we would move the smile up. At first getting used to this system might be a little<br />
tricky.<br />
Adding Eyes<br />
What's a smiley face without eyes. Add the following code to your sketch after<br />
the previous arc statement:<br />
stroke(0,0,0);<br />
fill(0,255,0);<br />
ellipse(width/2-15, height/2-15, 20, 30);<br />
ellipse(width/2+15, height/2-15, 20, 30);<br />
As we changed the stroke to red in our previous statement to draw the smile, we<br />
need to change it back to black so we add the second stroke statement to our<br />
program to change the stroke color back to black. Having also turned the fill off<br />
for the arc statement we need to turn it back on and set it to green, we can<br />
conveniently achieve both of these tasks with one function in the form of our fill<br />
statement. The x and y parameters of the ellipse functions that actually draw the<br />
eyes have had their expressions added to. For the eye on the left's x parameter I've<br />
subtracted 15 and for the eye on the right' x parameter I've added 15. When<br />
working with expressions like this it's important to remember that certain<br />
mathematical operators have precedence over others. For example * and / have<br />
precedence over + and -, this means that the expression width/2-15 is actually<br />
being evaluated like so (width/2)-15. This effect is known as operator<br />
precedence. Finally I offset the y position of the ellipses by subtracting 15 and<br />
drew them as more oval shaped by making their height's greater than their widths.<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 72
An Introduction To Programming With <strong>Processing</strong><br />
Drawing Irregular Shapes<br />
Fortunately we are not limited to drawing only 2D primitives in <strong>Processing</strong>, but<br />
we can in fact draw any shape that we can imagine. We use two main functions in<br />
conjunction with several calls to another function in order to achieve this, and the<br />
main functions are beginShape() and endShape() issued in that particular order.<br />
We're going to start off by experimenting with this feature by drawing a speech<br />
bubble surrounding the “<strong>Hello</strong> World” text in our sketch.<br />
The beginShape() function tells <strong>Processing</strong> to start recording the following set of<br />
points that are given to it and the endShape() function tells <strong>Processing</strong> to stop<br />
recording, between these two functions we are going to supply <strong>Processing</strong> with a<br />
set of special coordinates in the form of the vertex() function. Since we are using<br />
the vertex() function to determine where the points of our irregularly shaped<br />
object will be drawn we cannot use any other function other than vertex() between<br />
beginShape() and endShape(). The vertex() function accepts parameters in the<br />
form of x and y, which determine where in terms of x and y the point (or vertex)<br />
is in the Display window. By adding the following statements in this particular<br />
order we will be able to draw our speech bubble:<br />
beginShape();<br />
//Start the shape in the middle of<br />
//the Display Window's x axis<br />
vertex(width/2, (height/4)*3-35);<br />
vertex(width/2-70, (height/4)*3-35);<br />
vertex(width/2-80, (height/4)*3-25);<br />
vertex(width/2-80, (height/4)*3+5);<br />
vertex(width/2-70, (height/4)*3+15);<br />
//The following statement marks the point<br />
//where the shape starts to mirror itself<br />
vertex(width/2, (height/4)*3+15);<br />
//The Previous statement marks the point<br />
//where the shape starts to mirror itself<br />
vertex(width/2+70, (height/4)*3+15);<br />
vertex(width/2+80, (height/4)*3+5);<br />
vertex(width/2+80, (height/4)*3-25);<br />
vertex(width/2+70, (height/4)*3-35);<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 73
An Introduction To Programming With <strong>Processing</strong><br />
//this is the arrowhead that points out of the<br />
//speech bubble towards the smiley face<br />
vertex(width/2 + 50, (height/4)*3-35);<br />
vertex(width/2 + 40, (height/4)*3-55);<br />
vertex(width/2 + 30, (height/4)*3-35);<br />
//the end of the shape is the same as<br />
//the beginning<br />
vertex(width/2,<br />
(height/4)*3-35);<br />
endShape();<br />
Although at first this might appear to be a lot of typing, upon further inspection<br />
you will notice that it is in fact very repetitious and more of copy, pasted and<br />
modified code. So lets have a look at what's going on here.<br />
Each vertex position can be mapped to a vertex() in the code.<br />
In the above illustration we can see that beginShape() has started recording the<br />
various points that make up the irregular shape of the speech bubble, which we<br />
subsequently define for the beginShape() and endShape() functions one vertex at<br />
a time. The first vertex is located along the center of the Display Window's x axis<br />
followed by the y parameter for this vertex which is 35 pixels above the center of<br />
the text that says “<strong>Hello</strong> World”. Of course we could just have easily typed in the<br />
values explicitly such as:<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 74
An Introduction To Programming With <strong>Processing</strong><br />
vertex(320, 325);<br />
But using this method of explicit programming does not leave much room for<br />
changes and could subsequently lead to the extremely time consuming task of<br />
changing each explicitly determined point in your program manually, if it is<br />
deemed that such a change is necessary at a later stage.<br />
From the next vertex on we can use the Display Windows width and height<br />
system variables and the text's x and y position as a starting point from which we<br />
can place every vertex that follows relative to the position of the previous one and<br />
in relation to the other elements making up our program.<br />
Using this method of implicit programming also makes it easier for us to “mirror”<br />
the coordinates of the irregularly shaped speech bubble across the center of it's<br />
own Y axis. As you will notice once we get to the vertex marked as “the point<br />
where the shape starts to mirror itself” it's just a simple question of copying and<br />
pasting the previous code excluding the first vertex statement, changing the<br />
negative values associated with the vertices' x parameters to positive values, and<br />
reversing the order of the statements in a mirrored fashion.<br />
Using an implicit style of programming can also make patterns in your code easier to<br />
identify.<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 75
An Introduction To Programming With <strong>Processing</strong><br />
This can save us quite a bit of work as we don't have to work out the specific<br />
coordinate of each vertex individually all we need to work out is half of the<br />
coordinates that make up the shape and since we are mirroring the shape on the x<br />
axis we simply change the negative values associated with x to positive. Once we<br />
have all the vertices mirrored on the right hand side (excluding the last vertex) we<br />
can then start to plot the points of the arrow head of the speech bubble that points<br />
to the smiley face implying that it's saying “<strong>Hello</strong> World”.<br />
This part of the shape is pretty straight forward because we already know that we<br />
will need three points to make the triangular shape of the arrowhead and two of<br />
these points we already know the y positions of because they will be at the same<br />
height of the first and last vertices. So it's just a case of simple trail and error to<br />
determine what looks best in adding the remaining parameters to the next three<br />
vertex() functions. Once that's complete we can close the shape by placing the last<br />
vertex at the same location of the first vertex.<br />
Finally to end the shape you must use the endShape() function.<br />
You might have noticed that the image of my sketch has a speech bubble with a<br />
thick blue outline around it. This is the strokeWeight() function, and it controls<br />
how thick or thin the stroke is rendered and accepts a number as a parameter, I<br />
don't recommend setting this number too high as you might find it causing<br />
undesirable effects on your sketch. The higher the number input the thicker the<br />
line. Add the following statement before the statements that draw the speech<br />
bubble:<br />
strokeWeight(8);<br />
You might remember that in order to have a black outline around the face's eyes<br />
we set the stroke to an RGB value of 0,0,0 (or black), so although the<br />
strokeWeight() function has done it's job the effects of it might not be so obvious.<br />
Changing the stroke and fill colors are functions that you might need to run<br />
several times within a single sketch to achieve the desired result. Add the<br />
following statement before the previous statement:<br />
stroke(50,127,255);<br />
This changes the stroke color for the speech bubble to a little bit of red, about 50<br />
percent green and full blue. The fill color of my speech bubble is white and if you<br />
want to change the fill color of your speech bubble you must add the fill()<br />
function before the drawing of the speech bubble. Your statement would look<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 76
An Introduction To Programming With <strong>Processing</strong><br />
something like this:<br />
fill(255,255,255);<br />
or<br />
fill(255);<br />
Either option is perfectly acceptable, the latter is used for determining a gray scale<br />
value from 0 which is black to 255 which is white.<br />
The Stroke Caps are over lapping on the first and last vertex of the speech bubble in the<br />
current version of the Sketch.<br />
The section of the speech bubble where the first and last points of the shape<br />
overlap has an unsightly blemish caused by stroke caps. Stroke Caps determine<br />
how the end of a stroke is drawn and fortunately we have a function in <strong>Processing</strong><br />
for controlling this feature, as you might have guessed the function is called<br />
strokeCaps() and it accepts the parameters ROUND, SQUARE or PROJECT.<br />
Different types of stroke caps in <strong>Processing</strong>, which are very similar in effect to that of a<br />
vector illustration package.<br />
Remember that <strong>Processing</strong> is case sensitive so you must type the parameters name<br />
with the correct casing. ROUND is the default parameter that causes strokes in<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 77
An Introduction To Programming With <strong>Processing</strong><br />
<strong>Processing</strong> to have a beveled end, SQUARE will end the stroke with a flat end<br />
and PROJECT will tend to render the end of the stroke slightly past it's destined<br />
coordinates. We are going to use SQUARE to fix the speech bubble blemish. Add<br />
the following statement after the strokeWeight() function call:<br />
strokeCap(SQUARE);<br />
Order, order!<br />
That's great we now have a speech bubble, but where's our text gone to? If you<br />
added the statement to draw the irregular shape to the end of your sketch,<br />
<strong>Processing</strong> would have drawn the speech bubble over your text. Your text is still<br />
there just underneath the speech bubble, obviously this is not the desired effect.<br />
So we are going to reorder things in our sketch, with some simple cut and paste<br />
commands. Cut the three statements that relate to rendering text to the Display<br />
window textAlign(), textSize() and text() to the end of the sketch so that they are<br />
run after the speech bubble is drawn. If you were to run the sketch now your text<br />
will still appear to be missing, but in fact is still there it's just that because it's<br />
been drawn after the speech bubble it's also been effected by the fill() function<br />
issued to change the speech bubble's fill to white. White text on a white<br />
background isn't very legible so we'll change the text to another color, I'm going<br />
to make my text the same color as the speech bubble outline by adding the<br />
following statement before the text is drawn to the display and after the speech<br />
bubble is rendered:<br />
fill(50,127,255);<br />
Finishing the sketch<br />
To add the final touches to the <strong>Hello</strong> World 1.2 Program we're going to get<br />
<strong>Processing</strong> to display an image for the sketches background instead of the black<br />
background. This exercise will also be our first introduction to the programming<br />
paradigm Object Oriented Programming and the concept of data typing.<br />
The first thing we need to do is set our sketch up to accept external data in the<br />
form of an image. With the PDE open, open a file browser via your operating<br />
system and locate the file named “smileBkg.png”. From your file browser click<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 78
An Introduction To Programming With <strong>Processing</strong><br />
and drag the file into the sketch you would like to use the image in.<br />
Adding an Image to a Sketch in <strong>Processing</strong> is easy, you just click and drag it into the<br />
PDE.<br />
When you have dropped the file to the sketch <strong>Processing</strong>, will confirm this in the<br />
debugging area by printing the phrase “One file added to the sketch”. If you get<br />
this message you are ready to start using the image in your sketch. In order for<br />
you to use external data such as an image in your <strong>Processing</strong> sketch the data has<br />
to exist in a folder called “data”, which must be a subdirectory of the location<br />
where your sketch is saved. For example, we set up <strong>Processing</strong> at the start to store<br />
all sketches in a single folder which I've called “Sketchbook”, within this folder<br />
will be located the sketches we create with the PDE. I've called my <strong>Hello</strong> World<br />
1.2 Program “smile” so within the Sketchbook folder is another folder called<br />
“smile” and within the smile folder is the file smile.pde (which is my <strong>Hello</strong> World<br />
sketch) and another folder called “data”. When we dropped the image into the<br />
PDE <strong>Processing</strong> automatically created the data folder, and placed a copy of the<br />
smileBkg.png file in it. If you would like to view the contents of this folder you<br />
can access it quite easily from the PDE by clicking<br />
Sketch → Show Sketch Folder<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 79
An Introduction To Programming With <strong>Processing</strong><br />
When transporting your <strong>Processing</strong> sketches from one computer to another you<br />
must always retain this directory structure of having your data folder as a<br />
subdirectory of the location where you saved your processing sketch which<br />
should always have the extension .pde.<br />
Programming Paradigms<br />
A programming paradigm is a fundamental style of programming, the term is<br />
often confused with programming methodology which is a style of addressing a<br />
problem within a program. But perhaps a better way to understand what a<br />
programming paradigm is would be to look at some examples of it.<br />
Many modern day software languages offer at least two fundamental<br />
programming paradigms, most commonly amongst these two choices are the<br />
Objected Oriented Programming Model and Procedural Programming Model.<br />
Procedural programming is also sometimes referred to as imperative<br />
programming. Like the name implies imperative programming is a programing<br />
paradigm that is used to determine a set of commands and/or steps a computer<br />
program must take in order to reach a desired state. It's worth knowing that the<br />
Object oriented programming model is often contrasted to the procedural<br />
programming model because of the fundamental differences that separate these<br />
programming paradigms.<br />
Procedural Programming can be summarized as a style of programming where the<br />
program is tailored to suite the data as opposed to Object oriented programming<br />
which is more akin to a style of programming where the data is tailored to suite<br />
the program.<br />
So what exactly does that mean?<br />
As mentioned earlier, programs are made up of statements and one of the things<br />
statements are made up of is commands. As you might recall a command in<br />
programming, much like in a natural language, is used to communicate a<br />
directive. In this way procedural programming is a list of statements telling a<br />
computer what to do. At this point you could be thinking “Isn't that the purpose of<br />
all programming i.e. telling a computer what to do, so how then does procedural<br />
programming differ from any other programming paradigm?”<br />
In one way or another we use programming to represent data, whatever that data<br />
may be for example the amount of tea compared to the amount of coffee<br />
consumed over the past ten years world wide, or it could be determining the<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 80
An Introduction To Programming With <strong>Processing</strong><br />
choices a character has in a game then choosing to act on those choices or it could<br />
even be something as simple as representing a set of alpha numeric characters on<br />
the screen that spell your name. Whatever way you look at it creating a program<br />
requires data. In procedural programming we use the tools provided to us by the<br />
language we are programming in to break down that data into smaller data types<br />
that the language predetermines for us and then use those representations to create<br />
a program that ultimately represents the larger original data set programmatically.<br />
This can be contrasted to object oriented programming where we use the tools<br />
provided to us by the language we are programming in to create our own data<br />
types for which we determine their meanings and use these new data types to<br />
create a program that ultimately represents our original data set.<br />
Datatyping Categories<br />
Organizing the data that we represent in a program can be a difficult task unless<br />
you have some sort of system that can be applied at a higher level to abstract the<br />
complex interactions that a machine must facilitate in order to make the data we<br />
interact with more accessible to us. Datatypes make the process of organizing the<br />
various forms of data that exist in our programs more accessible and categorically<br />
meaningful to us. What qualifies as a data type varies from one programming<br />
language to another and also forms the basis of what differentiates the two main<br />
programming paradigms we are dealing with Procedural Programming and Object<br />
Oriented Programming.<br />
In <strong>Processing</strong> there are three main categories of data types that we will be dealing<br />
with Primitive data types, <strong>Processing</strong>'s API data types and User Defined Complex<br />
data types.<br />
Primitive Data Types<br />
Primitive Data Types form the building blocks of all the other mentioned forms of<br />
data types, and as a result are immutable, meaning that what defines them cannot<br />
be modified by use of <strong>Processing</strong>.<br />
Numbers can be represented as Primitive data types and most commonly fall into<br />
the primitive data type definition of int or float. An int data type is an<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 81
An Introduction To Programming With <strong>Processing</strong><br />
abbreviation of the word integer and is used to create categories of numbers<br />
within a program that represent whole values such as 0, 1, -58, 6000000 and so<br />
on. In <strong>Processing</strong> these values can range anywhere between 2,147,483,647 to<br />
-2,147,483,648. A float (or floating point number) is a data type used to<br />
categorize numbers that have a decimal point. Numbers such as 1.5, 3.0, -56.91<br />
and even numbers such as 3.40282347E+38 in SI (the International System of<br />
Units) notation qualify to be a float primitive data type. Typographic characters<br />
such as 'A', 'b', '5', '@' etc can also be stored as primitive data types by use of the<br />
char data type which is an abbreviation for the term character. However, storing a<br />
sequence of typographic characters as a single unit requires a different data type<br />
that is more complex than a primitive.<br />
<strong>Processing</strong>'s API Data Types<br />
In order to make languages fit more specifically to an environment certain<br />
repetitive tasks are often automated by the developers of the language's API. The<br />
acronym API stands for Application Programming Interface and it refers to the<br />
means by which you communicate with a program. Although you are creating<br />
programs (known as sketches) with <strong>Processing</strong>, <strong>Processing</strong> in itself is also a<br />
software program. We have been communicating with <strong>Processing</strong> through the<br />
PDE, and within the PDE we have been typing statements instructing <strong>Processing</strong><br />
what we would like it to do with the data we have supplied it with. Those<br />
instructions such as functions, tokens, arithmetic operators etc that we are using to<br />
communicate with <strong>Processing</strong> are all defined within <strong>Processing</strong>'s API.<br />
<strong>Processing</strong>'s API Data Types are special data types defined within the <strong>Processing</strong><br />
API that may or may not be found in other languages, but will make fulfilling the<br />
requirements of creating sketches (including data visualizations, end-user<br />
interactions and many other features commonly found in sketches) easier and less<br />
repetitive for the programmer by abstracting base-level computational<br />
interactions. The PImage data type is an example of a <strong>Processing</strong> specific API<br />
Data Type that makes the task of dealing with images much simpler for the<br />
programmer. The String data type is a <strong>Processing</strong> non-specific API Data Type,<br />
meaning that although this data type is common to many different programming<br />
languages it is not a primitive data type as it uses characteristics of both int and<br />
char primitive data types in it's implementation. <strong>Processing</strong>'s API Data Types are<br />
usually quite easy to identify as the keyword used to invoke them usually starts<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 82
An Introduction To Programming With <strong>Processing</strong><br />
with an upper-case character, this is a common standardized programming<br />
practice that is used to identify Classes which are the fundamental building blocks<br />
of Object Oriented Programming and are an inherent quality of <strong>Processing</strong>'s API<br />
Data Types.<br />
User Defined Complex Data Types<br />
In procedural based programming languages the programmer is supplied with a<br />
predetermined set of keywords that can be issued during the course of the<br />
program to communicate with the languages API, as a result no matter what the<br />
data that you are representing with your program is, that data must be tailored to<br />
fit those keywords. This means that your data will need to be fragmented,<br />
categorized and associated with the predetermined data types of the procedurally<br />
based language. This differs substantially from an object oriented approach to<br />
programming, in that you tailor the program you are creating to suit the data you<br />
are representing. In Object Oriented Programming you define your own data<br />
types by combining various Primitive data types and predetermined complex data<br />
types of the programming language's API into your own User Defined Complex<br />
Data Types that are referred to as Classes. These data types can then be<br />
instantiated throughout your program as often as necessary and used in a manner<br />
that is akin to how any other data type is used. The invocation or instantiation of a<br />
Class data type is known as a Software Object, and this is how the Object<br />
Oriented Programming (or OOP for short) paradigm evolved. Objects that are<br />
instantiated from the classes that make up an OOP program fall into the category<br />
of being user defined complex data types.<br />
PImage<br />
We are going to create a new software object from the PImage class, and we will<br />
give this new object a name. It is important that the name that we assign to the<br />
new object is unique so that when ever we want to use that object we can refer to<br />
it by it's name and <strong>Processing</strong> will know exactly which object we are referring to.<br />
The PImage Class contains useful information about the image we are loading<br />
into our sketch and allows us access to this information without having to<br />
understand how it has extracted this information from the image, such as it's<br />
width, height or how many pixels make up the image and what color each pixel is.<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 83
An Introduction To Programming With <strong>Processing</strong><br />
This is one of the benefits of object oriented programming, being able to abstract<br />
complex code by referencing it with a single keyword, the name of the object.<br />
Amongst the prerequisites of using an image file as a background in <strong>Processing</strong> is<br />
that the image must be in either gif, jpg, png or tga format and must have the<br />
same dimensions as the sketch in which it will be displayed. If you have had a<br />
look at the smileBkg.png file you might have noticed that the dimensions do not<br />
match that of our current sketch. However, we are in luck because we have been<br />
using an implicit style of programming to specify the x and y parameters within<br />
our sketch so changing the dimensions of our sketch at this late point in the<br />
programming process is actually not going to cause a problem. If on the other<br />
hand we had used an explicit style of programming we would have a problem as<br />
all of our had work to keep the graphical components of our sketch in the center<br />
of the display window would now be lost and fixing it would mean having to go<br />
through every statement where x and y coordinates where used and changing<br />
them to accommodate for the new sketch size.<br />
Since we are loading our image as a background we are going to add the<br />
following statements before the background statement near the top of the sketch.<br />
To create a new object from the PImage class add the following statement before<br />
the background statement:<br />
PImage img;<br />
This statement tells <strong>Processing</strong> that we want to create a new software object<br />
which has all the properties of the PImage data type and we would like to call this<br />
new object “img”. Our new software object has inherited the properties of the<br />
PImage data type which allow us to access information about the image we would<br />
like to store within the object without us having to know how exactly it goes<br />
about accessing this information. However, what our new object does not know<br />
yet is what image exactly we would like to use in our sketch and refer to as img.<br />
Add the following statement after the previous PImage statement:<br />
img = loadImage("smileBkg.png");<br />
This statement tells <strong>Processing</strong> the name and location of the image file we would<br />
like to use and refer to as img throughout the rest of our sketch. Because the<br />
image file has already been dropped into our sketch <strong>Processing</strong> has already placed<br />
a copy of the file in our data folder. <strong>Processing</strong> will expect to find whatever image<br />
files we are using in our sketch in this folder. The loadImage() function can also<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 84
An Introduction To Programming With <strong>Processing</strong><br />
accept a URL as a parameter if you wanted to load an image that is not located<br />
locally on the same station that your sketch is running from.<br />
So now that we have the image loaded into our sketch we need to tell <strong>Processing</strong><br />
what we would like to do with and, where we want to place it and finally to draw<br />
the image to the Display Window.<br />
To display the image in our sketch we're going to modify the background<br />
statement and <strong>Processing</strong> will now draw the image to the Display Window when<br />
we run the sketch. Modify the background statement to read:<br />
background(img);<br />
This statement simply tells <strong>Processing</strong> that we would like to use the object which<br />
has the properties of an image, which we have called img, as a background. Later<br />
we will have a look at compositing images on top of each other in addition to<br />
using them as backgrounds.<br />
To briefly recap on the steps we took to load an image into our sketch<br />
1. Drop the image into the PDE<br />
2. Create a new software object from the PImage Class<br />
3. Load the image file into the new software object<br />
4. Instruct <strong>Processing</strong> to display the image through it's identifier<br />
The completed “<strong>Hello</strong> World 1.2” Program<br />
<strong>Hello</strong> Display Window: <strong>Hello</strong> World 1.1 85
An Introduction To Programming With <strong>Processing</strong><br />
The Design and Layout Program<br />
Using what we've learned thus far from this guide, I've constructed a program that<br />
“sketches” a prototype for an interface to an online portfolio.<br />
The Completed Design and Layout Program<br />
Program Notes for Interface01.pde<br />
The PDE Tools menu<br />
Under the Tools menu in the PDE are additional build automation tools that<br />
members of the community have contributed to <strong>Processing</strong>. More tools can be<br />
downloaded to add to the functionality of <strong>Processing</strong> by downloading and<br />
installing the necessary files from http://www.processing.org/reference/tools/<br />
A useful tool that comes with the PDE is the Create Font tool. This tool allows<br />
you to package any font you'd like to use in your sketch so that users accessing<br />
your sketch do not have to have that font installed on their computers in order for<br />
the sketch to display properly. To use the Create Font tool in the PDE click:<br />
Tools → Create Font..<br />
The Design and Layout Program 86
An Introduction To Programming With <strong>Processing</strong><br />
The Create Font build automation tool can be used to ensure that users do not have to<br />
have the fonts you have installed on your computer in order for your sketch to display<br />
properly on their computers.<br />
The Create font dialogue box appears in which you can scroll down to and select<br />
the font you would like to package with your sketch, choose a size you would like<br />
to have the font displayed at by specifying a value in the size field (values are in<br />
pixels). The size value determines size of the characters of the font that will be<br />
exported as bitmaps, and although you can change what size you would like to<br />
display a font as in your sketch even after it's been exported it is recommended<br />
that you use the font in your sketch at the same size that you exported it as for<br />
best results. Up-scaling a font is definitely not recommended and as a result if you<br />
do plan on using the font in different sizes it is best to use the Create Font tool to<br />
export the font at the largest size and use <strong>Processing</strong> font() function to down-scale<br />
the font only.<br />
When you are happy with your selection click “ok” and <strong>Processing</strong> will create a<br />
file with the extension .vlw in your sketch's data folder, it is important that you<br />
know the exact name of this font as you will need to load it just like you loaded<br />
an image into <strong>Processing</strong>.<br />
To use the font in your sketch, you will need to follow a procedure very similar to<br />
The Design and Layout Program 87
An Introduction To Programming With <strong>Processing</strong><br />
that of loading and displaying images. Start by creating a new object that will<br />
serve as the container for your font, by adding the following statement:<br />
PFont myFont;<br />
PFont is a special data type in <strong>Processing</strong> used for storing fonts, in a similar way<br />
that PImage works with images. myfont is the name we have chosen to create an<br />
object that inherits the unique qualities of PFont. Next you will need to load the<br />
font into your sketch, to do so add the following statement:<br />
myFont = loadFont("FancyFont-Bold-42.vlw");<br />
The loadFont() function accepts one parameter that is the name of the font,<br />
including it's extension, enclosed within double quotes. We will then need to<br />
specify what font we would like to use to display text in our sketch, because you<br />
are permitted to use more than one type of font in a sketch the next statement tells<br />
<strong>Processing</strong> which font it is you would like to render the text that follows with:<br />
textFont(myFont,42);<br />
The textFont() function accepts two parameters, the name of the PFont object you<br />
have created (which is myFont in this case) and the size at which you would like<br />
the text that follows to be rendered at. All the calls to the text() function that<br />
follow this statement will use the parameters set in textFont() until textFont() is<br />
called again with a different set of parameters. Finally you can draw the text to<br />
the Display Window with the text() function:<br />
text("Welcome to my\n<strong>Processing</strong> Portfolio", width/2, height/2);<br />
You might notice something strange about the literal string parameter for the<br />
text() function. Between the characters “my” and “<strong>Processing</strong>” are the characters \<br />
n. This is known as an escape character and is not rendered with the literal string.<br />
Escape characters are used to format text before they are drawn to the screen. In<br />
my Interface01 sketch there is a break between “Welcome to my” and<br />
“<strong>Processing</strong> Portfolio”, this is because the \n is known as a new line escape<br />
character and has the function of inserting a break between characters. This saves<br />
me having to use the text() function twice, first to render the text “Welcome to<br />
The Design and Layout Program 88
An Introduction To Programming With <strong>Processing</strong><br />
my” and adjust the y parameter in the next call to text() to render the rest of the<br />
sentence. Using a short-cut like this can save your program some overhead, but<br />
also comes with the expense of making your code look a little less readable,<br />
particularly if you have never seen an escape character before.<br />
Another place where I've used a short-cut in my Interface01 Program is in the<br />
statement where I create the objects for storing the images that I will use in the<br />
rest of the sketch. The following statement demonstrates this:<br />
PImage mGoat, banner, bkg, button;<br />
The long version of this code would look like this:<br />
PImage mGoat;<br />
PImage banner;<br />
PImage bkg;<br />
PImage button;<br />
As you can see using a shortcut in this way can save you quite a bit of typing and<br />
can actually make your code even easier to read.<br />
The Design and Layout Program 89
An Introduction To Programming With <strong>Processing</strong><br />
Beyond Static Sketches and on to Active<br />
mode<br />
Static sketches are mainly used for testing basic programs that do not incorporate<br />
interactivity or are used to output and image file such as a .png or .pdf. The<br />
majority of programs produced with <strong>Processing</strong> are made using active mode.<br />
Active mode requires two fundamental additions to a sketch, the setup() and<br />
draw() functions.<br />
setup() and draw() provide a new structure to sketches and allow for the<br />
initialization of a code block within setup() and the repetition of the code block<br />
within the draw() structure. Code blocks within the setup() and draw() functions<br />
are always cradled between braces, so they are easy to identify. The structure of<br />
an active mode sketch generally follows the pattern identified in the example<br />
below:<br />
void setup(){<br />
code...// This code block will run only once,<br />
… // at the start of the sketch.<br />
...<br />
}<br />
void draw(){<br />
code..// This code block with run repeatedly,<br />
… // throughout the duration of the sketch.<br />
…<br />
}<br />
A typical active mode sketch structure with the setup() and draw() code blocks<br />
highlighted<br />
90
An Introduction To Programming With <strong>Processing</strong><br />
Up until now our sketches have not been interactive or included any animation.<br />
The use of the active mode structure, including the addition of the setup() and<br />
draw() functions, allows us to truly access the powerful features that<br />
programming offers to developers and extend our sketches with interactivity,<br />
animation, logic and a host of other features that we shall explore.<br />
We'll start by having a look at how setup() and draw() change our sketches and<br />
make them more dynamic.<br />
Methods, functions and their contexts<br />
The setup() and draw functions() are also sometimes, less accurately, referred to<br />
as methods. A method is simply another way of saying function, but more<br />
specifically it refers to the function of a class. As you might remember, classes<br />
form the building blocks of object oriented programming and can be packaged<br />
into groups consisting of many classes which we refer to as Libraries. From<br />
Libraries we can access classes, from which we can instantiate objects that we use<br />
in our programs. But before using a particular library we would first need to tell<br />
<strong>Processing</strong> to import that library for usage within our sketch, by using the import<br />
keyword. This differs from using a class built into <strong>Processing</strong>'s API where we do<br />
not need to use the import keyword, for example we could instantiate an object<br />
from the PImage class and call it img like in our <strong>Hello</strong> World program, without<br />
using the import keyword within the PDE, like in the following code fragment:<br />
PImage img;<br />
One of the methods (that works, in a sense, just like a typical function would of<br />
our main program) of img could be to resize the width and height of the image<br />
that we have associated with it for example:<br />
img.resize(50,100);<br />
This statement would resize the width and height of the image associated with the<br />
img object to 50 and 100 respectively. In this sense the resize() keyword used in<br />
relation to the img object would be a method of the img object. Just like a<br />
function, a method's definition can also exist independently of the main program.<br />
91
An Introduction To Programming With <strong>Processing</strong><br />
So as you can see the term method is very similar to that of function in terms of<br />
the purpose they both serve. However, it is important that the terms are not used<br />
interchangeably as they can lead to ambiguity and confusion.<br />
As I have mentioned before <strong>Processing</strong> is a language on it's own and not just a<br />
library consisting of classes for Java. If it was, referring to setup() and draw() as<br />
methods would be perfectly acceptable because they would be methods of a class<br />
defined within the <strong>Processing</strong> library for Java. Although <strong>Processing</strong> can be used<br />
in this context we are not using <strong>Processing</strong> as a library for Java we are using<br />
<strong>Processing</strong> as a language that is independent of Java until implementation, this is<br />
relevant because although <strong>Processing</strong> relies on Java currently for it's<br />
implementation theoretically there is nothing stopping <strong>Processing</strong> from being<br />
implemented within other environments. Within this context <strong>Processing</strong> is a<br />
language and not exclusively a library for Java. What that means is that, setup()<br />
and draw() within this definition should not be recognized as methods of a class<br />
that has been instantiated but rather as functions of a programing language. This<br />
concept can be extended even further because setup() and draw() are such<br />
fundamentally important functions within <strong>Processing</strong>, that they could be placed in<br />
a category of their own and described as structural defining functions, because<br />
they alter the structure of a program so dramatically.<br />
The setup() function<br />
Let's have a look at how the setup() function works and how it alters the structure<br />
of a program. Code that is cradled between the braces{} of the setup() function<br />
forms the code block of the setup() function and determines it's structure. This<br />
code will run only once, throughout the duration of the sketches life-cycle.<br />
Meaning that from the time the sketch is started to the point when you close the<br />
Display Window, exit the web page the sketch was running on, close the<br />
application the sketch was running through or do whatever is needed to end the<br />
sketch, the code block within the setup() function is never repeated until that<br />
sketch is run again. So how does that make the sketch more dynamic? Well in<br />
fact, when compared to the draw() function the setup() function does not<br />
contribute to significantly making the sketch more dynamic, but it does contribute<br />
to allowing the sketch to become dynamic.<br />
In programming the term dynamic is often used to describe the changing effects<br />
of a program. If we where to contrast this definition with our previous example of<br />
The setup() function 92
An Introduction To Programming With <strong>Processing</strong><br />
the interface01 program, we would see that this program is not dynamic as from<br />
the time that the sketch starts to the point when the sketch is terminated, the<br />
program does not change. However if we where to add animation to the images,<br />
or make the “buttons” of the interface clickable, then the program would be<br />
dynamic.<br />
So how does the setup() function contribute to this?<br />
One of setup()'s main forms of contribution to active mode sketches is in<br />
something we call assignment. Assignment is actually not a new concept to us as<br />
we have already used it several times in our previous sketches and is often<br />
invoked in most programming languages with an equals sign “=” which, in<br />
programming, is called an assignment operator. For example we have previously<br />
used assignment in the following context, when loading an image into a sketch in<br />
preparation for it to be rendered:<br />
img = loadImage(“myBitmap.png”);<br />
The purpose of assignment is to make whatever the value on the left side of the<br />
operator, equal the value that is on the right side of the assignment operator. In<br />
this way assignment can be a relatively straight forward or complex procedure.<br />
For example if we have a simple value such as a number or typographic character<br />
on the right of the assignment operator, the assignment of that value to whatever<br />
exists on the left is relatively straightforward because we're just simply telling<br />
<strong>Processing</strong> to make whatever is on the left of the assignment operator be the same<br />
as that which is on the right and then store those values in the computer's<br />
memory. However if we have an expression, a command or both on the right of<br />
the assignment operator the task of assignment can become more complex not<br />
only for <strong>Processing</strong> but also for us to keep track of.<br />
In the previous example we are assigning the value of the bitmap image that<br />
exists in our data folder called myBitmap.png to img, by using the loadImage()<br />
function.<br />
But, what exactly is going on in this assignment statement, as the computer that is<br />
running the sketch sees it?<br />
Firstly the computer running the sketch must process the call to the function<br />
loadImage() this requires processing power, and secondly the computer having<br />
realized what the loadImage() function requires after processing it now accepts<br />
the parameter “myBitmap.png”.<br />
The setup() function 93
An Introduction To Programming With <strong>Processing</strong><br />
In order for it to accept this parameter it has to allocate a certain amount of it's<br />
memory to load the image. Computers have a limited amount of memory and the<br />
larger the bitmap image's size (in terms of kilobytes, megabytes, etc.) the more<br />
memory they require to be loaded into a sketch. As a result the computer must try<br />
to allocate memory that has not already been assigned to another value and does<br />
not request more memory than is necessary. All of this work performed by the<br />
computer is performed without us having to know anything about the steps it must<br />
take to display the image in our sketch.<br />
As you can see, although this assignment statement was relatively easy for us to<br />
create, the steps that our computers must take in order to make what we are<br />
requesting possible is actually not so straightforward.<br />
The setup() function can be very useful in a situation such as this, because the<br />
previous statement is so resource insensitive it is not the kind of statement we<br />
would like to have repeated throughout the duration of our running program.<br />
Doing this will simply cause a bottleneck effect on the resources of the computer<br />
running the sketch and ultimately cause the sketch's performance to drop, as the<br />
computer struggles to keep up with our requests.<br />
The setup() function as a result will run only once throughout the duration of a<br />
program, and is designed to keep system performance at optimal speeds so that<br />
our sketches can run more efficiently with the code that does need to be repeated<br />
such as that of the draw() function.<br />
The draw() function<br />
The draw() function differs substantially from the setup() function in that it is<br />
designed to repeat the code block associated with it and cradled between it's<br />
braces. The ability to repeat code and have it update itself in the process is a key<br />
feature in creating dynamic content. For example when creating interactive<br />
programs it is quite useful to know the position of the users mouse, so that you<br />
can use this information to determine whether the user is hovering over a button, a<br />
scroll bar, an image or other interactive interface feature. As the user is likely to<br />
move the mouse around several times while the program is running, the mouse's<br />
position will change regularly. Knowing the mouses current x and y position and<br />
being able to compare it with a previous x and y position can tell us something<br />
like which direction the user is moving their mouse in, this information can be<br />
used to enhance the interactive quality of the application.<br />
The draw() function 94
An Introduction To Programming With <strong>Processing</strong><br />
Using the setup() and draw() functions in <strong>Processing</strong> is actually quite easy, and in<br />
the following example we'll use them for the purpose of getting the user's mouse<br />
position in terms of x and y coordinates and then use the println() function to print<br />
these values to the debugging console.<br />
Enter the following code and run it. Don't be alarmed when <strong>Processing</strong> starts to<br />
print line after line of information to the console, this is actually the desired<br />
effect. Move your mouse around in the Display Window to see the values update<br />
in the console view then close the Display Window when you are done:<br />
void setup(){<br />
size(510,300);<br />
}<br />
void draw(){<br />
println("The Mouse's X position is " + mouseX +<br />
" The Mouse's Y position is " + mouseY );<br />
}<br />
The Mouse's X and Y position is updated every 60th of a second and printed to the<br />
console<br />
95
An Introduction To Programming With <strong>Processing</strong><br />
Experimentation<br />
The setup() function must always precede the draw() function, and is used to<br />
define the initial properties of the sketch such as the size of the sketch. The size()<br />
function when used within an active mode sketch must always follow the setup()<br />
function before any other statements. If we had images to display in our sketch<br />
assigning them to variables would generally be done within the setup() structure,<br />
we'll have a look at this technique a little later.<br />
The draw() function repeats once every 60 th of a second by default, but this<br />
behaviour can be changed with the frameRate() function which would be called<br />
within the setup() structure too.<br />
Within the println() function you might have noticed something a little different,<br />
two new commands, mouseX and mouseY are system variables in <strong>Processing</strong> that<br />
store the X and Y position of the mouse when it is over the window the sketch is<br />
running in. When used within a sketch they simply return a number that is either<br />
the respective X or Y coordinate of the user's mouse. It is also worth noting that it<br />
is necessary for the println() function to be repeated within the draw() structure<br />
because whenever the user moves the mouse within the Display Window a new<br />
value for the mouse's x and y position replaces the old value for the previous<br />
position of the user's mouse. If this command was within the setup() function<br />
<strong>Processing</strong> would only print the mouse's x and y values once and not again.<br />
Although this is perfectly valid code it, is not very useful to us because if the user<br />
has moved the mouse since the start of the program (when setup() ran for the first<br />
and only time) the current position of the user's mouse would not have been<br />
updated thereafter. The statement to update the mouse's x and y position would<br />
not have been repeated so according to <strong>Processing</strong> the x and y position of the<br />
mouse would be the same as when the program first started, this is obviously not<br />
the case if the user has moved the mouse.<br />
The repetitious nature of an active mode sketch<br />
Experimentation 96
An Introduction To Programming With <strong>Processing</strong><br />
The mouseX and mouseY system variables are important keywords in<br />
determining the interactive nature of many sketches so lets attempt to use them in<br />
another way that is more directly related to the visualization of sketches.<br />
Add the following statement before the println() statement:<br />
line(0,0, mouseX, mouseY);<br />
The mouseX and mouseY system variables can be used to add interactivity to a sketch<br />
After running the sketch you should be able to recreate an image within the<br />
Display Window like the preceding image. The line() function is used to draw a<br />
straight line in <strong>Processing</strong> and accepts four parameters in the form of the starting<br />
point of the line's x and y coordinates and the end point of the line in terms of x<br />
and y coordinates. In our sketch we made the starting point of the line the origin<br />
of the sketch, that is (0, 0) or zero x and zero y and we made the end point of our<br />
line equal whatever the mouse's current x and y values are. There are infinite<br />
ways of using the mouseX and mouseY system variables to create interesting and<br />
interactive qualities within a sketch, and they don't always have to relate to<br />
positional data as in our previous statement. For example, if we wanted to use the<br />
mouse's x value to determine the greyness of the line we could add the following<br />
statement to effect the strokes color, which we will add before the line()<br />
statement:<br />
Experimentation 97
An Introduction To Programming With <strong>Processing</strong><br />
stroke(mouseX/2);<br />
Remember that the stroke() function used in this way with only one parameter<br />
accepts values between 0 to 255 which relates to the greyness of the following<br />
strokes that are drawn? So because the size of our sketch is 510 pixels across our<br />
mouse's x position will, in the context of this sketch, return a value between 0<br />
and 510 for the mouseX system variable, as any value greater than this would<br />
mean that the mouse is no longer positioned over the sketch. Bearing this<br />
information in mind we can use what we know about the width of the sketch and<br />
divide this value by 2 so that we never receive a value greater than 510/2 or 255<br />
which is white, when input as a parameter of the stroke() function. This is a very<br />
simple example of mapping one value to another but <strong>Processing</strong> conveniently<br />
provides us with a more sophisticated method of mapping values by use of the<br />
map() function which we will look at in more detail later.<br />
By linking one value to another we can start to create some interesting effects, within our<br />
sketch<br />
Try experimenting with the mouseX and mouseY system variables until you are<br />
comfortable with them as we will be using them quite regularly in our following<br />
sketches. For example try combining the previous sketch with an ellipse that<br />
attaches itself to your mouse and has an interactive transparency feature.<br />
Experimentation 98
An Introduction To Programming With <strong>Processing</strong><br />
Here's a hint:<br />
More interactivity can be added to this sketch example quite easily<br />
fill(50, 60, 127, ??/2);<br />
ellipse(??, ??, 50,50);<br />
As you might remember, the order in which commands are issued in many<br />
programming languages is really quite important. So when <strong>Processing</strong> reads your<br />
code it is important that commands are issued to <strong>Processing</strong> in the correct order,<br />
for example we would not want to have a command that updates the color of an<br />
ellipse's fill after the ellipse has been drawn to the Display Window. We are<br />
already aware of this from our static mode sketches, however in active mode even<br />
if you do have a fill() command after an ellipse() command to update that ellipse's<br />
fill your results sometimes might be more forgiving.<br />
As active mode requires that the code within the draw() structure is repeated there<br />
remains a history from one execution of this code to the next. What that means is,<br />
even though the fill() command is issued after the ellipse() command when the<br />
program repeats the next time around <strong>Processing</strong> will remember what the value of<br />
the fill was set to in the previous execution and update your ellipse in the current<br />
cycle to match that command of the previous execution. Currently this might not<br />
seem like a big issue to you because you are ultimately getting the results that you<br />
want, but this is at the expense of creating ambiguity within your program. This<br />
could also lead to possible errors later in the programs development cycle, and is<br />
therefore not a recommended methodology for several reasons.<br />
Firstly, it is not clear within the order of such a program why the fill() command<br />
is being called. Whereas if the fill() is issued before ellipse() it is clear that it is<br />
meant to effect the color of the fill of the next ellipse that is drawn to the Display<br />
Experimentation 99
An Introduction To Programming With <strong>Processing</strong><br />
Window. Secondly, if there are other values depending on your ellipse's fill being<br />
a particular color at that point in time, and these values precede the fill()<br />
command these values will always be calculating their results based on the color<br />
of the ellipse's previous fill color and not the current color for that particular<br />
cycle. This color only becomes evident the next time the program repeats, and by<br />
then the visual representation of the fill will no longer match the values that are<br />
used in calculations preceding it. This could lead to inaccurate calculations such<br />
as division by zero which could cause your program to halt or even worse to<br />
crash. Needles to say that although you can get the results you are hoping to<br />
achieve by structuring your program in a manner that contradicts appropriate<br />
ordering, you might in effect be causing yourself more problems in the long run<br />
than necessary. Always consider how the ordering of your commands and<br />
structure of your program can be improved.<br />
Ordering statements appropriately can contribute significantly to the readability of your<br />
code.<br />
Experimentation 100
An Introduction To Programming With <strong>Processing</strong><br />
Datatyping<br />
You might have noticed something else that's new about the active mode structure<br />
of a sketch, that being the usage of the void keyword preceding both the setup()<br />
and draw() functions. The keyword void is used for defining functions that do not<br />
return a value, all other user defined functions must return a value of a certain<br />
type of data. The setup() and draw() functions differ significantly from their roots<br />
in the C/C++ main() function in that they are not intended to return a value of any<br />
type of data to the main program, the mandatory usage of the void keyword<br />
ensures this. We'll have a look at user defined functions in more detail later.<br />
The process of assigning a type to data is known as datatyping. There are many<br />
different types of data within <strong>Processing</strong> we have already had a look at some of<br />
the categories that the different types of data within <strong>Processing</strong> can be broken<br />
down into, but what exactly are these different types of data and how do they<br />
assist us in programming?<br />
One of the datatypes we're already familiar with is the PImage datatype. We know<br />
that if we want to use a bitmap image in our sketch we must first assign it to the<br />
object we created from PImage. That new object that we have then created has<br />
inherited all of the properties of the PImage data type amongst which is the ability<br />
to resize the image, get information about the pixels that make up the image and<br />
what the alpha and color values of each pixel making up the image is. We did not<br />
have to tell <strong>Processing</strong> what a pixel is or how we would like to use it, these<br />
definitions exist already predetermined within the PImage class, which will be a<br />
body of code that exists somewhere on your computer (probably in the location<br />
you installed the PDE). Now that we have a new object instantiated from the<br />
PImage class it has inherited all of the properties that define that particular type of<br />
data, in other words the new object we have created has been datatyped as<br />
PImage.<br />
But in order to understand what is really going on here we need to look a little<br />
deeper...<br />
Datatyping 101
An Introduction To Programming With <strong>Processing</strong><br />
Variables<br />
Variables are common to most programming languages as they provide us with a<br />
means of storing data within the memory of a computer without having to know<br />
the process the computer has taken to store that data and where exactly within the<br />
computers memory that data has been stored. This provides us with a convenient<br />
method for accessing data, without having to understand the complexities of<br />
manual memory management as might be the case in lower level languages. Lets<br />
have a look at how variables play a part in helping us store data.<br />
Using variables is pretty straight forward and can be thought of as a two step<br />
process, 1.) Declaration and 2.) Assignment.<br />
The second step we are already familiar with, which could imply that you might<br />
have already used variables in your previous sketches, and this is in fact correct.<br />
You have used both steps of variable creation in your previous programs as<br />
variable assignment relies on declaration.<br />
Declaration is the process of giving the data you are representing in your program<br />
a name, and is a process that involves datatyping (preformed by the programmer)<br />
and memory allocation (performed automatically in <strong>Processing</strong>). So lets have a<br />
look at a declaration in the following statement:<br />
PImage img;<br />
This is known as a form of variable declaration, you might at this point be<br />
thinking “I thought this is supposed to be object instantiation (as it has previously<br />
been referred to)?” You'd be right on both counts in this particular case because<br />
there are in fact two different things going on here. Firstly the PImage class<br />
defines all objects that are instantiated from it by whatever code that makes up it's<br />
class body, and because PImage is specific to <strong>Processing</strong>'s API and not something<br />
that exists readily within other programming languages referring to the preceding<br />
statement as object instantiation reveals the underlying structure of what is going<br />
on in <strong>Processing</strong> when compared with other programing languages. However,<br />
since PImage is a class defined within <strong>Processing</strong>'s API and can be used for<br />
datatyping the preceding statement can also be viewed as declarative, as such img<br />
can be referred to as an object variable. In contrast lets have a look at a simpler<br />
declaration that does not involve a <strong>Processing</strong> specific datatype, which can make<br />
the process of defining variables easier to grasp:<br />
Datatyping 102
An Introduction To Programming With <strong>Processing</strong><br />
int myVar;<br />
The keyword int in this statement is used to datatype a variable with the<br />
properties of type integer.<br />
Integers are primitive datatypes that must be whole numbers, such as 0, 5, -1,<br />
2430 and so on. They cannot have a decimal value. All we are doing at this stage<br />
is giving the variable a name, that being myVar, we have not given the variable a<br />
value yet the value would effectively be an integer, and associating the variable<br />
with a value is specifically what assignment is for.<br />
In the above statement we have declared a variable called myVar and datatyped it<br />
as an int. So when we want to use the variable and the data associated with it in<br />
our program we can simply refer to it by it's name for example:<br />
println(myVar);<br />
However this is getting ahead of ourselves a little, as you might remember one of<br />
the main reasons we use variables is so that we can associate data with them<br />
through the process of assignment. In the previous example we have declared a<br />
variable but not given it a value, so lets restructure the example to be more<br />
meaningful:<br />
int myVar; //Declaration<br />
myVar = 5; //Assignment<br />
println(myVar); //Prints 5<br />
In the second line we have used assignment to associate the numerical integer<br />
value of 5 with our variable, and in the third line we have put the variable to work<br />
by getting println() to read it's value back to us. You might also notice that<br />
variables are never placed between double quotes, like the literal strings we have<br />
been using with the println() function up till now.<br />
What makes variables so special is that we can get them to store any value that is<br />
valid to it's datatype, change this value then re-use it in another statement with the<br />
new value, without the help of variables a task like this would be very<br />
impractical. This is particularly useful as we never have to know what address the<br />
variable we are using has in memory, our computers take care of that for us.<br />
Here's an example of the changing (or variable) nature of a variable:<br />
Datatyping 103
An Introduction To Programming With <strong>Processing</strong><br />
int x;<br />
//declaration<br />
x = 5; //assignment x is now 5<br />
x = x + x; //assignment expression x is now 10<br />
println(x); //Prints 10<br />
The value you assign to a variable can be changed when ever you instruct your<br />
program to do so, usually through use of the assignment operator. As a result in<br />
the previous example although we started off with the variable we called x having<br />
a value of 5 assigned to it in the second statement, in the next line we added it's<br />
current value of 5 to itself then reassigned that new value of 5 + 5 (on the right of<br />
the assignment operator) back to itself (on the left of the assignment operator),<br />
making x = 10. Using this simple method we have represented two different<br />
values of 5 and 10 with only one variable, x. That does not mean that x could be<br />
either 5 or 10 it simply means that at the start of the program x was 5 and by the<br />
end of the program x ended up being 10. By having one variable that can be used<br />
to represent many different values we can save on memory as at any given time<br />
that variable can only have one value associated with it, meaning that if a new<br />
value is assigned to it like in our previous example that new value will replace the<br />
old one and so on. Not only does this make our program run more efficiently but<br />
it also makes keeping track of the representations of the different data in your<br />
program more manageable.<br />
Variable Scope<br />
An important aspect of working with variables is that they can be accessed at<br />
various places in your program so that the values associated with them can be<br />
referenced (in their original form) or changed and then referenced. For example<br />
you can reference a variable in one statement, run a couple of other statements<br />
then choose to reference the original variable again even with all the code<br />
separating the the first reference from the second, <strong>Processing</strong> will still remember<br />
what the variable you are referring to is.<br />
But not every variable is accessible from every place within a program. Variable<br />
scope refers to the enclosing range within a program that a variable can be<br />
accessed. For example variables defined within the setup() function are not<br />
accessible to the rest of the program, which is why setup() is best suited for<br />
assignment in terms of dynamic programming. As such there is a scope in which<br />
variables can be defined such that they are accessible from every place within a<br />
sketch, we call this the global variable scope.<br />
Datatyping 104
An Introduction To Programming With <strong>Processing</strong><br />
Erroneous code is produced from a lack of considering variable scope<br />
As you can see in the previous image x cannot be accessed from within draw()<br />
because it has been initialized within the setup() function. Initialization is the<br />
process of combining variable declaration and assignment into one statement. For<br />
example the following declaration and assignment statements can be written as<br />
such:<br />
int x;<br />
x = 20;<br />
//declaration<br />
//assignment<br />
or the statements could be combined in one statement and written as such:<br />
int x = 20; //initialization is both declaration and assignment<br />
Although the latter statement might save you some time in terms of typing, it is<br />
something you should be careful of doing when taking variable scope into<br />
consideration, as when this method of initialization is used within setup() it is<br />
going to create variables that are not accessible (and therefore cannot be<br />
referenced) from outside of the setup() structure.<br />
The proper way to address this issue would be to declare the variable outside of<br />
both draw() and setup(). Generally it is not a good idea to declare a variable more<br />
than once because this could cause unnecessary overhead on your program, as<br />
such, declaring variables within the draw() structure is best avoided when ever<br />
possible. Nonetheless, declaring variables within the draw() structure sometimes<br />
cannot be avoided and as a result is considered to be valid code.<br />
Each time you use a datatyping keyword for variable declaration <strong>Processing</strong><br />
thinks you are trying to create a new variable, and does not perceive the statement<br />
as updating the already existing variable with the same name.<br />
Programming like this tends to look ambiguous and difficult to read. However, as<br />
already mentioned, there are times when declaring a variable within draw() is<br />
unavoidable, or in some cases can even contribute to the readability of your code.<br />
Datatyping 105
An Introduction To Programming With <strong>Processing</strong><br />
Basically, what this boils down to is that where you choose to declare your<br />
variables is your choice, but there are also certain rules in place that if you are<br />
aware of, can make this decision somewhat easier for you.<br />
Lets restructure the previous example using a more readable format that takes<br />
variable scope into consideration:<br />
int x;<br />
//declare variable only once in global<br />
//variable scope<br />
void setup(){<br />
//assign a starting value to the<br />
x = 20;<br />
//variable. Note: accessible within<br />
} //setup()structure<br />
void draw(){<br />
//access the variable from elsewhere in<br />
println(x);<br />
//the program. Note: also accessible<br />
} //within draw() structure<br />
By declaring a variable outside of the setup() and draw() functions we have<br />
created a global variable. A global variable can be accessed from both the setup()<br />
and draw() structures, it is said to have a greater scope than a variable that is<br />
defined within the setup() or draw() structures. Within setup() the variable has<br />
been given a starting value, remember that the variable already exists before the<br />
program reaches setup(), so setup() is not being used to create or declare the<br />
variable only for assignment. By the time the program gets to draw the new value<br />
associated with the variable is the value that the println() function reads each<br />
time it repeats. It's also worth noting again that only the code block within the<br />
draw() function is repeated.<br />
Interacting with images<br />
We're going to use what we've learned to have an image in a sketch react to our<br />
mouse's Y position, making the image move up and down accordingly. You might<br />
have seen this effect when viewing so called “high resolution” images that are<br />
larger than the window they are begin displayed in, in an online gallery.<br />
Locate the image named doorsClosed.png and drag it into your sketch. We can<br />
then start by rendering the image at the origin with the following code:<br />
//declare global variables<br />
Interacting with images 106
An Introduction To Programming With <strong>Processing</strong><br />
PImage doors;<br />
void setup(){<br />
//size() always first in setup<br />
size(800,600);<br />
//use setup() for assignment where ever possible<br />
doors = loadImage("doorsClosed.png");<br />
}<br />
void draw(){<br />
//draw the image<br />
image(doors,0, 0);<br />
}<br />
When loading images into an active mode sketch, it's important that you declare<br />
the images object variable name outside of both setup() and draw(). This makes<br />
the object accessible as a global variable so that it is now within the scope of both<br />
setup() and draw(), this is important because we will need to access the new<br />
object variable from within both structures. It is advisable to use assignment in<br />
the setup() structure so that the image is loaded into the new object variable only<br />
once, placing the loadImage() function, within an assignment statement, for the<br />
new object inside the setup() structure, ensures this.<br />
Finally once we have set the image up for rendering we can use the image()<br />
function, as usual, to display the image in the sketch. It's worth noting that<br />
because the image is static, it is not possible to see that the image is in fact being<br />
redrawn to the Display Window approximately 60 times per second, when the<br />
sketch is run and although this might sound like a lot of excessive usage of system<br />
resources, most modern day computers should be able to handle this framerate for<br />
one image with relative ease. However, we will take a look at how to reduce the<br />
amount of times <strong>Processing</strong> cycles through the draw() structure in second, when<br />
we use start using the frameRate() function, a little later.<br />
Making the image follow the mouse's Y position is actually quite easy, modify the<br />
image statement to read:<br />
image(doors, 0, mouseY);<br />
Now when you run the sketch your image will start to move up and down in the<br />
Interacting with images 107
An Introduction To Programming With <strong>Processing</strong><br />
Display Window because the value that the image() function is reading for it's Y<br />
parameter is the system variable mouseY. As you might recall mouseY stores the<br />
mouse's current Y position. If your mouse has moved the new position of your<br />
mouse's coordinate will replace the previous value that was stored in the mouseY<br />
system variable of the previous run-cycle, and as a result the image will be drawn<br />
in a new position.<br />
But why does the image appear to be streaking across the Display Window?<br />
Streaking<br />
The streaking effect<br />
We have told <strong>Processing</strong> to repeatedly draw the image by placing the image()<br />
function within the draw() structure, as a result the streaking effect is actually<br />
caused by the “ghosting” of the previous image having been drawn to the Display<br />
Window and not being erased before the image is redrawn in a new position for<br />
the current frame. To fix this effect we need to tell <strong>Processing</strong> to first clear the<br />
Display Window before drawing the image again in the current position. We can<br />
do this quite easily by adding the background() function before the image<br />
statement, thereby clearing the Display of the the image's previous rendering. Add<br />
the following statement before the image() statement in the draw() structure:<br />
background(0);<br />
Now when you run the sketch it should act in a more predictable fashion. I've<br />
chosen black as a background color but you can choose any color. There are<br />
however several areas that can be improved on,<br />
• firstly the way in which the image moves in relation to the mouse is not<br />
Interacting with images 108
An Introduction To Programming With <strong>Processing</strong><br />
very interesting to interact with. It would seem that the image appears to<br />
be stuck to the mouse.<br />
In order to fix this we will make the image lag slightly behind the mouse<br />
and then slowly catch up to the position of the mouse by creating a new<br />
variable that we can use to control the speed at which the image moves.<br />
This will create the impression of the image's movement being affected by<br />
friction.<br />
• Secondly because the image's origin is it's top left hand corner, when we<br />
move the mouse down we tend to expose the background above the image,<br />
so we'll also make the image react to the mouse's y position in relation to<br />
the center of the image and not it's top left hand corner. This reduces the<br />
possibility of exposing the background and makes the image more of a<br />
focal point.<br />
• Finally we will constrain how far the image can move along the Y axis so<br />
as to completely eliminate the possibility of exposing the background.<br />
Friction simulation<br />
Friction is the force that resists the relative motion of something else (like an<br />
object, a gas, a liquid, etc), and is the effect that we will be attempting to simulate<br />
(in a simplified form) in this sketch. By moving the mouse up and down within<br />
the Display Window the image should try to follow the mouse and slow down as<br />
it approaches the mouse, this will create the impression of friction.<br />
We'll start by creating three new variables. Add the following statements at the<br />
top of the sketch, below the PImage statement:<br />
float yPos;<br />
float difY;<br />
int frict = 30;<br />
//declaration related to image Y position<br />
//declaration related to difference between<br />
//mouse and image's Y position<br />
//initialization, friction. high values make<br />
//image move slower<br />
float is a keyword for declaring floating point variables. Floating point values are<br />
numbers that have a fractional part, that is to say they are numbers with a decimal<br />
value such as 1.0, -2.9865, 10000.423, 0.0000001 and so on. Floating point<br />
numbers will tend to require more memory for storage so if you can get away<br />
Interacting with images 109
An Introduction To Programming With <strong>Processing</strong><br />
with representing the number data as type int and not compromising the integrity<br />
of your program you should consider doing so.<br />
We are using the float datatype in this program because we will be using division<br />
in one of our expressions. This is important because true division will always<br />
return a number with a decimal value, if you were to use an int instead of a float<br />
or double depending on the programming language you are using, you risk having<br />
datatype conversion errors or truncated integers returned. As a result when you<br />
use division in your expressions always consider whether representing that data<br />
with an int is a good idea or not.<br />
The three variables yPos, difY and frict are going to be used to represent three<br />
different values of which only one will remain constant throughout the duration<br />
that the program is running. The only variable that will remain constant is the frict<br />
variable. As a result the frict variable has been initialized through a declaration<br />
and assignment statement outside of both setup() and draw() structures. This<br />
value will control how fast or slow we would like the image to move towards the<br />
mouse.<br />
Creating a variable such as this within the global variable scope, will give us<br />
access to the variable within both setup() and draw() thereby allowing us to tweak<br />
the value associated with the variable and have it update throughout the program.<br />
This will save us some unnecessary work in the long run. When the sketch is<br />
complete setting the frict value high will cause the image to appear to have more<br />
resistance when moving towards the position of the mouse ultimately making the<br />
image move slower, and setting this value low (but not to zero, because division<br />
by zero is not permitted in mathematics, as is the case in programming) will cause<br />
the image to appear to have no resistance and move almost immediately to the Y<br />
position of the mouse.<br />
The variable yPos will be used to store the Y position of the image and also<br />
update the Y position of the image, and the variable difY will be used to store the<br />
difference between the mouse's Y position and the center of the image's Y<br />
position. Both of these variables will need to be updated regularly for each of the<br />
cycles of the draw() function, this is because each time the user moves the mouse<br />
the position of the image must change as a result of difY now being less or more<br />
depending on whether the mouse is closer or further from the images center.<br />
Interacting with images 110
An Introduction To Programming With <strong>Processing</strong><br />
Variable naming conventions<br />
Before proceeding, it's worth noting the convention I've used for naming these<br />
variables. There are several rules (depending on what language you are<br />
programming in) that determine what a valid variable name is generally you'll<br />
find that many popular higher level languages share these similarities regarding<br />
valid variable declaration,<br />
1. Variable names can only contain alphanumeric characters and underscores<br />
(that is “_”, “a” to “z”, “A” to “Z” and/or “0” to “9”). Spaces cannot be<br />
used in variable names.<br />
2. Variable names cannot start with numbers.<br />
3. Variable names should be descriptive but not verbose, for example “yPos”<br />
as opposed to “Y_Position_Of_The_Image”.<br />
4. Use consistent casing. Variable names generally do not start with an<br />
upper-case character. This convention is reserved for Classes. In the<br />
previous example I've used a mixture of both upper-case and lower-case<br />
characters to name my variables such as yPos which is intended to be an<br />
abbreviation for “y Position” or difY which is an abbreviation for “the<br />
difference in Y positions”.<br />
Some programmers might use different conventions including underscores<br />
because to them this might look more readable y_pos or dif_y. Either of<br />
these conventions is perfectly valid. But you should determine which<br />
convention you are using, and stick with it throughout your program.<br />
Changing from one naming convention to another can often make a<br />
program confusing and less readable.<br />
5. Your variable names should be self documenting, that is to say they<br />
should be descriptive about their purpose without having to include<br />
additional comments explaining their purpose. This point is with the<br />
exception of intentionally, explicitly documented code, which is generally<br />
a convention used for teaching programming.<br />
6. Variables that are typed in all upper-case characters are often referred to<br />
as constants. Their value is not supposed to change. This is simply a<br />
naming convention and there is nothing stopping you from changing the<br />
value of a constant in many higher level languages, although this is not<br />
recommended. So beware when using this naming convention as it could<br />
lead to confusion if not used properly.<br />
Interacting with images 111
An Introduction To Programming With <strong>Processing</strong><br />
Planning and Pre-Debugging<br />
We'll start by making an assignment within the setup() structure that sets the yPos<br />
value to the center of the Display Window. This has not effected the position of<br />
the image yet, because we have not linked the yPos variable to the image yet. Add<br />
the following statement at the end of the setup() structure, before it's closed<br />
braces:<br />
yPos = height/2;<br />
If we wanted to make sure that yPos is returning the value we are expecting it to<br />
return then we could add a println() statement within the draw() structure to test it.<br />
The statement would look like this:<br />
println(yPos);<br />
If the program was run at this stage it should print a value that is representative of<br />
the center of the Display Window's height. Using this method of tracking<br />
variables is a common technique for debugging a program and provides an easy<br />
and convenient method of understanding how the program is changing and<br />
updating values internally. When you are happy that the program is returning the<br />
results you were expecting you can simply comment out the println() statement<br />
and resist deleting the statement until the program is fully completed, tested,<br />
documented and functional.<br />
In order to render the image at the correct position we need to:<br />
Determine what the Y position of the users mouse is (mouseY) and from this<br />
value subtract the sum of the Y position of the image (yPos) and half of it's height<br />
(doors.height/2). The latter value (yPos + doors.height/2) describes the position of<br />
the image with relation to it's center.<br />
Interacting with images 112
An Introduction To Programming With <strong>Processing</strong><br />
The image's movement will react to the mouse's relative position to the images center.<br />
Once we have the mouseY – (yPos + doors.height/2) value we will assign it to<br />
difY, then in the following statement we'll divide difY by the frict variable. This<br />
is important because we're then going to take that value (that is the answer of difY<br />
divided by frict) and add it to the yPos variable, meaning that if the value of difY<br />
was initially returned as 90 dividing it by frict would return a value of 3 (because<br />
90/30 = 3) which is subsequently the value that we add to the images current Y<br />
position to cause it to move down by a value of 3 (plus moves down the Y axis<br />
minus is moves up the Y axis). On the other hand if difY returned a value of -90,<br />
this would mean that the users mouse is above the center of the image and the<br />
value of -3 would be added to the images Y position causing the image to move<br />
up by 3.<br />
Interacting with images 113
An Introduction To Programming With <strong>Processing</strong><br />
As the mouse's Y position is less than the center of the image, the image is forced to<br />
move up.<br />
Then we're going to assign the sum of those values (yPos + difY/drag) back to the<br />
yPos variable.<br />
Finally we will use this value to determine the position that the image is currently<br />
rendered at.<br />
The results of this method is that the image will start moving fast towards the<br />
mouse then get slower as it approaches the mouse.<br />
Implementing a Programmatic Solution<br />
To summarize we are dividing the difference between the mouse's Y position and<br />
the center of the image with the frict value, then adding this value to the images<br />
current position. We can express this programmatically with the following two<br />
statements, which you can add to your sketch before the image statement:<br />
difY = mouseY - (yPos + doors.height/2);<br />
yPos += difY/drag;<br />
In the second statement we use a technique known as Augmented assignment<br />
Interacting with images 114
An Introduction To Programming With <strong>Processing</strong><br />
which is the process of condensing a statement that uses the common technique of<br />
using a variable in an expression, then assigning the value of the expression back<br />
to the same variable. For example the statement:<br />
x = x + 5;<br />
Can be expressed in augmented assignment form as:<br />
x+=5;<br />
Both statements evaluate to the same answer, the latter is a more commonly used<br />
method for this type of statement, as this kind of statement is so commonly<br />
implemented in programming. Some other examples of augmented assignment<br />
follow:<br />
x = x -5;<br />
//Can be expressed in augmented assignment form as:<br />
x-=5;<br />
x = x * 7;<br />
//Can be expressed in augmented assignment form as:<br />
x*=7;<br />
/= and %= can also be used in augmented assignment. As you can see the<br />
following statement used in our sketch is an example of augmented assignment:<br />
yPos += difY/drag;<br />
//Can also be expressed as:<br />
yPos = yPos + difY/drag;<br />
At this point if you were to run the sketch, your image still would not move in<br />
relation to the two statements you just added to your sketch. However if you were<br />
to add a println() statement for the yPos variable you would see the numbers<br />
indicating that the code is working. It's always a good idea to test an<br />
implementation before fully integrating it into your program when ever possible,<br />
with the println() function.<br />
In order to create a link between these two statements and the y position of the<br />
image we would need to place the variable yPos into the Y parameter field of the<br />
the image() function. However, if we where to do this our image would continue<br />
Interacting with images 115
An Introduction To Programming With <strong>Processing</strong><br />
to move beyond it's boundaries and display the sketches background. Fortunately<br />
we have a function in <strong>Processing</strong> that allows us to stop values from getting too<br />
high or too low.<br />
Constraining Values<br />
The constrain() function works by clamping a value between a range that you<br />
specify. It accepts three parameters, the first parameter is the value that you want<br />
to constrain and in our case this would be the variable yPos. The next parameter is<br />
the minimum value of the range you would like the value constrained between<br />
and the final parameter is the maximum value for the range that the value yPos<br />
will be constrained between.<br />
Modify the image() statement to match the following code fragment, and<br />
complete your sketch:<br />
image(doors,0, constrain(yPos, height- doors.height, 0));<br />
At first this statement could look a little intimidating, but in fact you already<br />
know what's going on in most of the statement and it's only the Y parameter of the<br />
image() function that is somewhat different.<br />
As you are aware the image() function accepts three parameters, firstly the object<br />
variable containing the image (doors), secondly the value of the X position you<br />
would like the image rendered at and finally the images Y position.<br />
This statement is in the draw() structure and as a result will be repeated<br />
throughout the program's run-cycle, this means that every time the user moves the<br />
mouse the difY variable will change and as a result so too will the yPos variable.<br />
It is therefore necessary for this statement to be within the draw() structure, or<br />
these changes will never be seen. The Y parameter of the image() function<br />
accepts an expression in this example, the expression consisting of the constrain()<br />
function:<br />
constrain(yPos, height - doors.height, 0)<br />
This expression when evaluated, returns the value of the image() function's Y<br />
parameter. The constrain() function clamps the yPos value so that the image is<br />
never raised above the value returned from height – doors.height and never<br />
Interacting with images 116
An Introduction To Programming With <strong>Processing</strong><br />
lowered below 0, this will be the point where the image's origin matches the<br />
Display Window's origin.<br />
The area which the image's motion is constrained to, exists above and outside of what is<br />
visible within the Display Window.<br />
Of course if you think this example could be easier to read, you're probably right.<br />
For example you could declare a global variable to which you assign the previous<br />
expression to within the draw() structure. The additional overhead that such an<br />
action would create in this example is minimal, for example:<br />
...<br />
float imageY;<br />
void setup(){<br />
...<br />
doors = loadImage("doorsClosed.png");<br />
...<br />
}<br />
void draw(){<br />
…<br />
imageY = constrain(yPos, height- doors.height, 0);<br />
image(doors,0, imageY);<br />
}<br />
However in order to demonstrate how expressions can be used as parameters in<br />
code, this example uses the former method which does not accommodate for the<br />
imageY variable. Nonetheless if you would like to see how this example can be<br />
implemented you can examine the comments in the imageScroll.pde file.<br />
Interacting with images 117
An Introduction To Programming With <strong>Processing</strong><br />
Branching<br />
When we write a program we generally don't want the script to do the same thing<br />
every time we use it. Often, what we want is a script that is versatile in it's<br />
application. Excluding this versatility would make the interactive software<br />
predictable and boring. We therefore use certain built-in structures that help us<br />
control the way in which our programs run, allowing us to skip blocks of code<br />
and execute other blocks of code before others in a non-linear way. This can be<br />
done in a dynamic and changing sequence based on the users input, the logic of<br />
the program, the time of day or whatever other characteristic we choose to model<br />
into a program. The process of creating this dynamic ordering that determines the<br />
programs flow of control is what is referred to as branching.<br />
Branching is also referred to as conditional programing and is the process of<br />
creating code that has the ability to choose a certain path based on a set of<br />
conditions stipulated in the program but which can also be influenced by<br />
conditions outside of the program, such as a user interaction. The conditional<br />
statement is syntactically a single statement made up of multiple branching<br />
statements. What determines the course of action that the program follows is a<br />
boolean value of true or false returned from a comparison within the structure of a<br />
conditional statement.<br />
The if() structure<br />
The if() structure can also be referred to as an if statement because although, the<br />
statement is in practice made up of multiple statements the structure of the if<br />
statement is treated like a single statement during compilation and/or<br />
interpretation.<br />
if statements must always have a conditional to qualify as an if statement. An<br />
example of the structure of an if statement follows:<br />
conditional<br />
if(expression1){<br />
… do statements<br />
}<br />
keyword<br />
if() statement<br />
structure<br />
Branching 118
An Introduction To Programming With <strong>Processing</strong><br />
Multiple if statements can be used within the same program and even within the<br />
same draw() structure. They are identified by the if keyword followed by<br />
parenthesis containing a conditional. The conditional for an if() statement will<br />
always return a value that is true or false through the process of evaluation which<br />
can be based on a comparison expression. We'll have a look at the process of<br />
comparison a bit later, for now we'll focus on the boolean datatype.<br />
Data that can either be true or false is a primitive datatype known as a boolean.<br />
Just like all primitive data types booleans can be declared with a keyword<br />
followed by a variable name.<br />
The expression within the conditional of an if() statement must, through the<br />
process of evaluation, return a boolean value of either true or false in <strong>Processing</strong>,<br />
in order for the program to continue. In other programming languages the<br />
conditional can also evaluate to a 1 or a 0, with 1 being representative of true and<br />
0 being representative of false. The language's compiler/interpreter will then<br />
convert the 0 or 1 to a boolean equivalent value through a process known as type<br />
casting., <strong>Processing</strong>, however, requires that the conditional evaluate to a boolean<br />
value of true or false, so that automatic type casting can be avoided. As you are<br />
aware 1 and 0 are of type int in <strong>Processing</strong> and the <strong>Processing</strong> does not<br />
automatically convert them to boolean values. In the event of your conditional<br />
evaluating to an int or datatype other than a boolean you will receive a “cannot<br />
convert” datatype error. Later we will have a look at how to use <strong>Processing</strong>'s inbuilt<br />
ability to prevent automatic type casting to our advantage. Although<br />
automatic type casting is favored in some programming languages it is usually an<br />
inherent legacy feature of a lower level language that a current higher level<br />
language is based on. In <strong>Processing</strong> type casting must be done explicitly with a<br />
type casting function.<br />
Type casting errors<br />
Branching 119
An Introduction To Programming With <strong>Processing</strong><br />
If we were to declare a boolean variable and use it in an if statement, it might look<br />
something like this:<br />
boolean myValue = true;<br />
//initialization<br />
if(myValue){<br />
//if conditional returns true<br />
… run these statements //statements within if() structure<br />
} //are run<br />
...then run these statements<br />
//if conditional is false entire if<br />
//structure is skipped<br />
In the previous example we have used initialization to declare a variable of type<br />
boolean and assign the value of true to it. We then used the new variable in an if()<br />
statement conditional (the part between parenthesis following the if keyword).<br />
The way that an if statement works is the program will evaluate the expression<br />
within the conditional, if the conditional evaluates to true the code delimited<br />
within the if() statements braces will be run. However if the conditional evaluates<br />
and a value of false is returned, it will skip the code within the if() statement's<br />
braces and proceed to the statements that follows, for example:<br />
boolean myValue = false;<br />
if(myValue){<br />
… don't run these statements<br />
}<br />
...run these statements<br />
//variable initialized to<br />
//false<br />
//conditional evaluates to<br />
//false<br />
//entire if() structure is<br />
//skipped<br />
Using this method of programming we have allowed our program to make a<br />
decision based on certain conditions, in a real world situation the conditions the<br />
program would evaluate would usually be dynamic for example a user interaction<br />
or some other dynamic feature.<br />
Branching 120
An Introduction To Programming With <strong>Processing</strong><br />
Relational Operators<br />
Writing if() statements becomes really interesting when more than one expression<br />
is used in the conditional. Up until now we have only used a single expression as<br />
a condition.<br />
Using a single expression within a conditional<br />
In the previous image the highlighted area indicates a single expression for the<br />
conditional in the form of a variable called myBooleanVar which has been<br />
datatyped as a boolean, in this case the variable has been assigned the value of<br />
true, therefore the conditional evaluates to true. This simplistic approach to using<br />
if statements can be useful in some situations but, the ability to use comparison<br />
within a conditional statement extends it's usefulness much further.<br />
Comparison<br />
A comparison requires at least two entities (which are most commonly numerical<br />
values and/or expressions in <strong>Processing</strong>, but can extend into strings in some other<br />
programming languages) and a relational operator (also known as a comparison<br />
operator in other programming languages). Comparisons included within a<br />
conditional, just like the previous expressions we've been working with, must also<br />
evaluate to a value of either true or false. Comparisons simply instruct the<br />
program to evaluate the two expressions on either side of the relational operator<br />
and compare the results of the two expressions with each other and from this<br />
comparison return a boolean of either true or false. Relational operators include:<br />
Branching 121
An Introduction To Programming With <strong>Processing</strong><br />
< less than<br />
> greater than<br />
== equality<br />
= is greater than or equal to<br />
!= inequality<br />
Let's have a look at how we can use the a relational operator to compare two<br />
values.<br />
(5>1)<br />
This is a conditional extracted from an if() statement, it consists of a single<br />
comparison. The comparison returns a value of true and would be read as “ five<br />
is greater than one”. The next example demonstrates a comparison that returns a<br />
value of false:<br />
(5
An Introduction To Programming With <strong>Processing</strong><br />
void setup() {<br />
size(300,300);<br />
}<br />
void draw() {<br />
if( mouseY >= height/2){<br />
println("Mouse is in the bottom half of the sketch");<br />
println(mouseY);<br />
}<br />
println("Mouse could be in either half");<br />
}<br />
The program starts, as always, by running the code within the setup() structure<br />
then moves onto draw(). Within draw() it runs the if() statement which instructs<br />
the program to check whether the mouse's Y position is greater than or equal to<br />
the height of the Display Window divided by 2. For example in our sketch the Y<br />
parameter of the size function within setup() is 300 so if the user has placed the<br />
mouse at a Y position that is anywhere between 150 and 300 then the conditional<br />
will return a value of true as these values are all greater than or equal to 150 (i.e.<br />
height/2). It's also worth noting that the relational operator that has been used in<br />
this comparison is the >= (greater than or equal to) operator, which means that the<br />
value that is returned on the right side of the operator is included within the range<br />
of values (as the minimum value in this range) that will cause the conditional to<br />
evaluate to true. What this means is that if you want a value of false returned the<br />
mouse must be within the range of 0 to 149.<br />
If the conditional returns a value of true meaning that the mouseY system variable<br />
has a current value of 150 or anything between 150 to 300, the program then runs<br />
the code delimited within the if() structure, which in this case tells <strong>Processing</strong> to<br />
print "Mouse is in the bottom half of the sketch" and then print the value of the<br />
mouseY system variable. The program then moves on to the rest of the code<br />
within the draw() structure. This tells the program to print "Mouse could be in<br />
either half", as this statement exists outside of the if() structure, it will be<br />
evaluated regardless of whether the if()'s conditional is returned as true or false.<br />
The program then loops back to the beginning of the draw() function and goes<br />
through the code within the draw() structure again as it has reached the end of the<br />
draw() structure at this point. If the users mouse is not within the bottom half of<br />
the Display Window this time the comparison conditional will return a value of<br />
false, the program will then skip the code delimited within the if() structure that<br />
tells it to print "Mouse is in the bottom half of the sketch" and move onto the rest<br />
Branching 123
An Introduction To Programming With <strong>Processing</strong><br />
of the code within the draw() structure that once again tells it to print "Mouse<br />
could be in either half".<br />
if() structures can increase the amount of options that can be programmed into a sketch.<br />
As you can see branching provides us with a very easy way of changing the<br />
behaviour of our program by including variables within a comparison that in<br />
themselves are dynamic.<br />
Extending the if() structure with else<br />
In our previous example, we where able to run statements based on whether the<br />
mouse was in the bottom half of the Display Window, if we change the<br />
conditional to read:<br />
(mouseY
An Introduction To Programming With <strong>Processing</strong><br />
of the Display Window and a different set of statements when the mouse is in the<br />
other half of the Display Window?<br />
Using an if statement to do this by itself would not be possible, but fortunately we<br />
can extend the if() structure with the else keyword.<br />
Use of the else keyword within an if() structure ensures that even if the<br />
conditional returns a value of false that the code that follows else (which is still<br />
within the if() structure) will be run, before the program exits the if() structure and<br />
moves on to the rest of the statements making up the program. This can<br />
effectively provide us with a fail safe method of ensuring that code is run within<br />
an if() structure before the program exits the structure. For example if we wanted<br />
to get our sketch to tell us whether the mouse is specifically in the upper or lower<br />
half of the Display Window we would modify the previous sketch to look like<br />
this:<br />
void setup() {<br />
size(300,300);<br />
}<br />
void draw() {<br />
if( mouseY >= height/2){<br />
println("Mouse is in the bottom half of the sketch");<br />
println(mouseY);<br />
}else{<br />
println("Mouse is in the upper half of the sketch");<br />
println(mouseY);<br />
}<br />
println("Mouse could be in either half");<br />
}<br />
Notice that as soon as you start the sketch and if your mouse is not hovering over<br />
the Display Window, <strong>Processing</strong> will read the mouseX and mouseY system<br />
variables as being 0 and 0. As a result the first branch of the if() structure is<br />
skipped because the conditional evaluates to false (0 is less than 150) and the<br />
second branch is immediately run, that being the else code block. Once you start<br />
moving your mouse around in the Display Window you will see the println()<br />
statements execute depending on which half of the Display Window the mouse is<br />
in.<br />
Branching 125
An Introduction To Programming With <strong>Processing</strong><br />
Extending the if() construct with if else if else<br />
There are many times when you will require more than the two branches that an if<br />
else construct will permit, and in that case you can use the process of nesting<br />
multiple if else structures within others. For example, in our previous sketch when<br />
our program started and our mouse was not hovering over the Display Window,<br />
<strong>Processing</strong> rightfully skipped the first if() control structure and went to the else<br />
structure. However we could capture this possibility in a condition and associate it<br />
with it's own code block. An if else if else construct generally follows this pattern:<br />
if(condition){<br />
...statements<br />
}else<br />
if(condition){<br />
..statements<br />
}else{<br />
...statements<br />
}<br />
As you can see nesting if else constructs within each other is pretty easy, but<br />
when typed in the previous format they can be a bit difficult to read. As a result<br />
they are generally written in the following format, remember that because<br />
<strong>Processing</strong> is a free form programming language you are free to format the<br />
statements as you wish, however certain formats might be easier to read than<br />
others, for example the traditional format for an if else if else construct follows:<br />
if (condition){<br />
...statements<br />
}else if(condition){<br />
...statements<br />
}else{<br />
...statements<br />
}<br />
There are no limits to how many if else structures you can nest within an if else<br />
construct, but bear in mind that nesting too many if else structures within others<br />
can make it difficult to follow and keep track of what is going on in your code.<br />
<strong>Processing</strong> and many other higher level languages have structures such as<br />
switch() that might serve your purposes better, if you want your program to be<br />
able to branch between a possibility of three or more control structures.<br />
Branching 126
An Introduction To Programming With <strong>Processing</strong><br />
Logical Operators<br />
Logical operators allow us to to extend our conditionals by creating a means of<br />
comparing one relational expression with another. They come in the format of:<br />
&& logical AND<br />
|| logical OR<br />
! logical NOT<br />
These operators can be used within a conditional to return a value of true or false<br />
based on the context in which they are used, for example logical AND will return<br />
a value of true only when both expressions on either side of it evaluates to true<br />
and can be used as in the following examples:<br />
(5>3 && 3>1) //Returned as True, because both<br />
//expressions are true<br />
(5>3 && 33 || 3>1) //Returned as True, because both<br />
//expressions are true<br />
(5>3 || 3
An Introduction To Programming With <strong>Processing</strong><br />
if (!(x>1))<br />
...<br />
//can also be expressed as,<br />
if (x
An Introduction To Programming With <strong>Processing</strong><br />
PImage img;<br />
PImage sliderBk;<br />
PImage sliderFd;<br />
int margin = 50;<br />
void setup(){<br />
size(800,600);<br />
img = loadImage("tunnel.png");<br />
sliderBk = loadImage("sliderBk.png");<br />
sliderFd = loadImage("sliderFd.png");<br />
}<br />
void draw(){<br />
background(0);<br />
image(img,0,0);<br />
image(sliderBk, width/2 – sliderBk.width/2, margin);<br />
image(sliderFd, width/2 – sliderBk.width/2, margin);<br />
}<br />
Starting a sketch in this way is enables us to see a template of the sketch, and<br />
provides us with foundation on which to build. After adding the previous code<br />
you should have a sketch that looks something like the following image.<br />
The template from which the sketch will evolve.<br />
Interface Controls: Setting up a Slider 129
An Introduction To Programming With <strong>Processing</strong><br />
User Defined Functions<br />
Now that we have a template we can start modifying it, to include some<br />
interactivity. One of the fundamental components of this sketch is the slider, as<br />
the whole idea of changing the color of an image is going to be based on the<br />
user's interaction with the slider. As a result we're going to start by setting up the<br />
button of the slider first. The kind of button we will be setting up in <strong>Processing</strong> is<br />
going to be determined by a range. This range will encompass the clickable area<br />
of the button, and because our button is part of a slider the range should<br />
automatically be able to adjust itself to accommodate for the button moving<br />
around the area that it can be dragged within by the user.<br />
Slider Button<br />
Area in which button can be dragged<br />
As detecting the location of the button is a fundamental requirement for this<br />
sketch and is something that needs to work throughout the duration that the sketch<br />
is running, we are going to create a user defined function that will take care of this<br />
requirement for us.<br />
Up until now we have been using <strong>Processing</strong>'s built-in functions, which can<br />
suffice for many different situations but you will occasionally come across a<br />
situation in programming when the language you are coding in does not provide<br />
the functionality you need built directly into it's API. This is not a reflection on<br />
the language's inability to perform in a certain situation, but rather an intentional<br />
quality built into a programming language's design where paradoxically it's<br />
limitations, in terms of built-in functionality, can actually extend the languages<br />
capabilities. What this means in terms of <strong>Processing</strong> is we have a set of functions<br />
already provided for us, these functions already have definitions associated with<br />
them, by creating user defined functions we take these predetermined functions<br />
and combine them into new forms of useful, reusable and compact code. This not<br />
only allows us to extend the languages capabilities into fields that perhaps even<br />
the developers of the language never imagined but also to create our own<br />
definitions which suite the specific needs of our own applications in a more<br />
practical sense.<br />
Perhaps at this point you are wondering why all programming languages do not<br />
User Defined Functions 130
An Introduction To Programming With <strong>Processing</strong><br />
share the same set of functions? Many useful, popular programming languages do<br />
in fact share many of the same functions we find in <strong>Processing</strong>, but might be<br />
referred to as directives, commands or subroutines amongst other terms<br />
depending on which language you are programming in. Besides the functions that<br />
are common amongst many different programming languages each programming<br />
language will have certain features (perhaps in the form of functions or some<br />
other built in feature) that will tailor that language to the environment it is best<br />
suited, as defined by it's developers and possibly extended in definition by a<br />
community, as is the case with <strong>Processing</strong>. This feature set that contributes<br />
significantly to defining the language's functionality, is intentionally maintained<br />
within the languages definition or philosophy as this makes the feature set easier<br />
to contextualize and thereby easier to learn for the programmer using the<br />
language, creates an abstraction of commonly used resources within an<br />
environment and can significantly improve the performance when a user's<br />
program is implemented. For example, if you wanted to write your own class for<br />
loading and displaying images within a <strong>Processing</strong> sketch, there is nothing<br />
stopping you from doing that, however the PImage class is maintained as a part of<br />
<strong>Processing</strong>'s feature set specifically for those reasons and as a result is optimized<br />
to run as efficiently as possible for the loading and displaying of images.<br />
Subsequently the possibility of you gaining any form of performance increase<br />
from creating your own class using <strong>Processing</strong>'s built-in functions to serve the<br />
same purpose as the PImage class is, unlikely. As a result it's worth considering<br />
whether writing your own class or user defined function is applicable or not<br />
before setting out to do so.<br />
In our case we are creating a user defined function because it will make our code<br />
easier to read and not reduce the performance of the application, as our function<br />
will contribute to making our program running more efficiently than having the<br />
function definition within the draw() structure causing the computer running the<br />
sketch to process the function definition line by line every time the draw()<br />
structure repeats. With a user defined function we can avoid this by loading the<br />
function's definition into memory and calling the definition with a simple function<br />
call, as we have been doing with built-in functions.<br />
As we are using <strong>Processing</strong>'s built-in functions, within the environment that they<br />
are intended for and best suited to, we will be enhancing the quality of our sketch<br />
with our user defined function rather than trying to work against the context that<br />
<strong>Processing</strong> is best suited.<br />
However, this is not to say that it is not possible to extend a programming<br />
User Defined Functions 131
An Introduction To Programming With <strong>Processing</strong><br />
language beyond the definition or philosophy of it's environment, but if that is<br />
your intention then you would more than likely consider abstracting a far greater<br />
degree of the languages built-in features within a library consisting of multiple<br />
classes.<br />
The definitions for user defined functions must exist outside of both setup() and<br />
draw() structures if they are to have a greater scope. Our function definition will<br />
reside at the bottom of the sketch and contain three main characteristics.<br />
1. Our function should always know whether the user's mouse is over the<br />
slider button or not.<br />
2. If the user's mouse is over the slider change the cursor to a hand icon<br />
indicating that the button is clickable to the user.<br />
3. Return a value of true or false to the main program, depending on whether<br />
the mouse is over the slider button or not.<br />
Although the process of creating a user defined function might seem new to you,<br />
it is in fact not really all that different to how we have been using the setup() and<br />
draw() function's structures. Bearing this in mind, our user defined functions are<br />
going to follow a very similar structure to that of setup() and draw(), for example<br />
expressed generically:<br />
datatype functionName(){<br />
...function definition<br />
}<br />
Then within the context of draw():<br />
void draw(){<br />
..statements defining draw() structure<br />
}<br />
Now as a user defined function, applicable to our sketch:<br />
boolean myFunction(){<br />
...statements defining myFunction<br />
}<br />
As you can see, not a lot has changed in terms of how a user defined function is<br />
structured in comparison to the previous example using draw(). The fundamental<br />
User Defined Functions 132
An Introduction To Programming With <strong>Processing</strong><br />
difference is that statements delimited within the braces associated with draw()<br />
define it's structure and not the function, as the definition of the draw() function<br />
exists outside of the sketch we are creating and is something that the developers<br />
of <strong>Processing</strong> have determined. In contrast statements delimited within a user<br />
defined function form a function definition, within it's braces.<br />
In order to use the function we will then need to include a call to the function<br />
from within our main program. This is very similar to the method used to call<br />
built-in functions such as rect(), ellipse(), println() and many other functions we<br />
have already used.<br />
Let's revise our previous example to demonstrate the process of defining a<br />
function then calling it from within the draw() structure:<br />
void setup(){<br />
...statements<br />
}<br />
void draw(){<br />
...statements<br />
myFunction();<br />
}<br />
boolean myFunction(){<br />
...statements defining myFunction<br />
}<br />
From this example you can see that a call to a user defined function is as simple<br />
as a call to a built-in function. This has the added benefits of making the code<br />
easier to read and removes the function definition from the body of the draw()<br />
structure. Now we can reuse the function as many times as we would like within<br />
our main program by simply evoking it via it's name, compare this to typing out<br />
every statement within it's definition in the main program every time we wanted<br />
to instruct the program to do what the user defined function does.<br />
Now that we have an understanding of how the function will fit into the program,<br />
lets have a look at creating it's definition.<br />
User Defined Functions 133
An Introduction To Programming With <strong>Processing</strong><br />
Creating a user defined function<br />
Datatyping a function<br />
The first line of a function definition must be used to declare the function, and as<br />
you are aware declaration in <strong>Processing</strong> means giving the function (variable or<br />
other entity) a name and datatyping it. Naming a function is a very similar process<br />
to that of naming a variable as you will see in the following code fragment<br />
forming the first line of our user defined function:<br />
boolean overButton()<br />
The parenthesis following the function name are used to contain declarative<br />
parameters. These parameters will be defined within the function body, in our<br />
case this function does not accept any parameters so we leave the parenthesis<br />
empty. As you have been using functions that accept parameters user defined<br />
function can also be created to accept parameters that you define.<br />
In comparison to setup() or draw() our function is being datatyped as a boolean,<br />
all functions must return a datatype or use the void keyword like setup() and<br />
draw(). As void does not return any data it is subsequently not classed as a<br />
datatype within <strong>Processing</strong> (and traditionally in C/C++) but as a structural<br />
element, this differs to other higher level languages (some of which are closely<br />
tied to <strong>Processing</strong>) that do consider void as a datatype. Nonetheless our function<br />
is going to return data of type boolean, which will be used to determine whether<br />
the user's mouse is over the slider button or not.<br />
Determining a range<br />
In order to calculate whether the mouse is over the slider button or not we will<br />
have to determine the range in which the slider button is located. We already<br />
know where the slider button is in terms of x and y because these are values<br />
determined by parameters if the image() function used to draw the image. We can<br />
use this information, along with the width and height object variables to work out<br />
the slider button's range.<br />
User Defined Functions 134
An Introduction To Programming With <strong>Processing</strong><br />
Determining the range of the button as the area covered in diagonal stripes.<br />
In the previous image if A and B where variables the image() function to render<br />
the slider button could be rewritten as:<br />
image(sliderFd, A, B);<br />
This method of expressing the X and Y parameters as variables is particularly<br />
useful to us because, we would like the slider button to be able to “slide” along<br />
the x axis, this means the value of A would need to be dynamic.<br />
As the slider button only moves along the x axis the variable B will not change,<br />
however this value is used in more than one situation, firstly to determine the Y<br />
position of the image that will form the area along which the slider button can be<br />
dragged referred to as sliderBk (short for slider background), secondly to<br />
determine the Y position of the slider button referred to as sliderFd (short for<br />
slider foreground) and thirdly referenced within the range we will set up shortly to<br />
determine the clickable area of the button. As a result this value has been declared<br />
as a variable of type int and named margin. This way if at a later stage we decide<br />
to move the entire slider down in order to make room for other graphical elements<br />
above it then all I have to do is update the value associated with margin, instead<br />
of having to find and change an explicit value scattered throughout the source<br />
code.<br />
The value described as A in the previous image requires a more meaningful name,<br />
something that is self documenting. As a result I have created the variable<br />
buttonXPos in the global region and datatyped it as an int:<br />
int buttonXPos;<br />
Eventually I'd like to replace the X parameter for the image() function rendering<br />
sliderFd in the X position determined by buttonXPos. As we are aware what the<br />
variable buttonXPos is going to represent we're going to set it up with a<br />
User Defined Functions 135
An Introduction To Programming With <strong>Processing</strong><br />
temporary value within our sketch to test our user defined function. So we're<br />
going to add a temporary statement for testing and debugging purposes to the<br />
draw() function which assigns a value to buttonXPos and then changes the<br />
image() function of which sliderFd is associated with to reflect this assignment<br />
statement. Once the buttonXPos variable is declared in global space, you can edit<br />
the draw() structure to include the first command and update the appropriate<br />
image command:<br />
...<br />
//temp for debugging<br />
buttonXPos = width/2 - sliderBk.width/2;<br />
...<br />
image(sliderFd,buttonXPos ,margin);<br />
Once we are sure that our function is working we will return to the temporary<br />
statement that we adding for debugging and testing purposes and include the<br />
buttonXPos variable assignment statement within an if() structure.<br />
We are now ready to proceed with setting up our function. To briefly recap our<br />
function has been declared as type boolean and given the name overButton(),<br />
setting up the range will occur within a conditional consisting of multiple<br />
comparisons and will look like this:<br />
boolean overButton(){<br />
if (mouseX >= buttonXPos && mouseX = margin && mouseY
An Introduction To Programming With <strong>Processing</strong><br />
1. mouseX >= buttonXPos, this checks if the mouse is anywhere in the<br />
highlighted area. If the mouse is then a value of true is returned and<br />
<strong>Processing</strong> will continue to evaluate the rest of the conditional.<br />
2. mouseX
An Introduction To Programming With <strong>Processing</strong><br />
3. mouseY >= margin, once again this comparison is only evaluated if the<br />
previous comparison was true because both comparisons are separated<br />
with &&. This comparison returns a value of true only if the mouse is<br />
below the top of the slider button.<br />
4. mouseY
An Introduction To Programming With <strong>Processing</strong><br />
let us know that when the value returned from the function is true that the mouse<br />
is over the button and when the value is returned as false we can safely conclude<br />
from this information that the mouse is not hovering over the button.<br />
First we are going to declare another variable in the global scope and datatype it<br />
as a boolean, add the following variable to the global space of your sketch:<br />
boolean mouseOverButton;<br />
Now we'll use this variable in our user defined function to return a boolean back<br />
to the main program.<br />
boolean overButton(){<br />
if (mouseX >= buttonXPos && mouseX = margin && mouseY
An Introduction To Programming With <strong>Processing</strong><br />
datatype if it is datatyped, meaning that in our case when the mouse is not over<br />
the slider button and we did not have an else structure capturing this possibility at<br />
that point our function would not be returning any data back to the main program.<br />
This is why it is important that we add an else structure to this if() construct, so<br />
that we can set the mouseOverButton variable to false, and subsequently return he<br />
correct data back to the main program. This also gives us an opportunity to<br />
change the cursor back to an arrow, indicating to the user that their mouse is no<br />
longer over a clickable element.<br />
Our function declaration and definition is now complete and we can use it in our<br />
main program. Calls to user defined functions are as easy as calls to <strong>Processing</strong>'s<br />
API functions. Add the following statement to the draw() structure.<br />
overButton();<br />
Now <strong>Processing</strong> will run the function at every frame and set the<br />
mouseOverButton variable within the overButton() function to true or false<br />
appropriately, update the cursor and return the correct value datatyped back to our<br />
main program, which we will soon put to use.<br />
Dragging the slider button<br />
mouseDragged() is a function that provides a structure to which we can add<br />
statements each time the mouse is dragged. A dragging operation qualifies as a<br />
user clicking and dragging a mouse button anywhere in the Display Window,<br />
when this happens the mouseDragged() function will be called once, and it's<br />
structure will be executed. As a result because the mouseDragged() function is not<br />
called repeatedly for each frame that the mouse is begin dragged, we will use the<br />
function to set a variable called buttonDrag to true indicating that the mouse is<br />
currently being dragged, this variable will then be used in the draw() structure,<br />
within an if() statement which causes the slider button to follow the mouse when<br />
the variable is true and remain stationary when it is false. When the user then<br />
releases the mouse we will use a call to the mouseReleased() function (which<br />
structurally works in a similar way to the mouseDragged() function) to set the<br />
variable, buttonDrag to false within the mouseReleased() structure. What this<br />
means is that when the if() statement in draw() checks the status of this variable it<br />
User Defined Functions 140
An Introduction To Programming With <strong>Processing</strong><br />
will now be returned as false causing the slider button to remain stationary. In<br />
other words, we already have a function that tells us if the mouse is over the<br />
button or not, we will now add two more functions that will tell us whether the<br />
user's mouse is attempting to drag the button and whether it has been released.<br />
Mouse related functions usually follow the end of the draw() structure and should<br />
not be mixed amongst user defined functions.<br />
We'll start by declaring the buttonDrag boolean in global space:<br />
boolean buttonDrag;<br />
Then using it within a mouseDragged() function, remember to place all mouse<br />
related functions together and not between user defined functions:<br />
void mouseDragged(){<br />
if (mouseOverButton){<br />
buttonDrag = true;<br />
}<br />
}<br />
This simple function is run once the user clicks a mouse button and starts to drag,<br />
then the function will check if the mouse is over the slider button as<br />
mouseOverButton is returned to our main program via our overButton() user<br />
defined function. If the mouse is over the slider button and the user has clicked<br />
and dragged in the Display Window, then we can safely conclude that the user is<br />
trying to click and drag the slider button. As a result we set the buttonDrag<br />
variable to true. Now we can use this variable in our main program to update the<br />
position of the button slider in the draw() structure.<br />
Firstly we will start by commenting out the following statement as it is no longer<br />
needed for testing, as we are ready to implement the actual code:<br />
//temp<br />
//buttonXPos = width/2 – sliderBk.width/2;<br />
The following statement will replace it:<br />
if(buttonDrag){<br />
buttonXPos = mouseX - sliderFd.width/2;<br />
}<br />
User Defined Functions 141
An Introduction To Programming With <strong>Processing</strong><br />
This if() statement will form the basis of the construct used to control the<br />
movement of the slider button. If you were to run the script at this stage you 'd<br />
notice that although you can now click and drag the button, there are a few new<br />
issues that need tending to:<br />
1. The slider button now starts at the 0 x position, and subsequently needs to<br />
be constrained to the region that the sliderBd object covers.<br />
2. When the button is dragged it can be dragged well beyond the sliderBd<br />
region, so this operation also requires constraints.<br />
3. Once the button is released it continues to follow the mouse.<br />
Setting up regional constraints<br />
As we have seen from previous examples the constrain() function can be used to<br />
setup a maximum and minimum value that can be used to determine the limits of<br />
another value. This provides a convenient solution for working with the<br />
buttonXPos value of which we'd like it's minimum value mapped to the left edge<br />
of the sliderBd object and it's maximum value mapped to the right edge of the<br />
sliderBd object minus the width of the slider button (sliderFd). We need to minus<br />
the width of the slider button (sliderFd) because the top left hand corner of the<br />
slider button image is the point that will be able to move the the maximum value<br />
specified in the constrain() function, as a result of using the default setting for<br />
imageMode() which is CORNER. If this point was matched to the right edge of<br />
sliderBd the results would look like the following image:<br />
sliderBd.width<br />
SliderFd CORNER<br />
The slider button is dragged too far right<br />
As you can see the slider button has gone too far past the right edge of the<br />
sliderBd image, subtracting the sliderFd's width from the right edge of sliderBd<br />
will solve this.<br />
User Defined Functions 142
An Introduction To Programming With <strong>Processing</strong><br />
Modify the if() statement to include the following if else clause:<br />
else{<br />
buttonXPos = constrain(buttonXPos, width/2 -<br />
sliderBk.width/2, width/2 + sliderBk.width/2 -<br />
sliderFd.width);<br />
}<br />
The minimum value for the constrain() function is the center of the Display<br />
Window minus half of the width of the slider background image (sliderBd).<br />
The maximum value for the constrain function is the center of the Display<br />
Window plus half of the width of the slider background image (sliderBd) minus<br />
sliderFd's width.<br />
The values that will be used in the constrain() function to determine the slider button's<br />
draggable area<br />
With this information in mind finishing the if() construct is just a matter of copy<br />
and paste with one minor modification. Although the modification is minor it's<br />
addition to the sketch will be what finally gives the user the results they were<br />
looking for. The value we are constraining in this case is going to be mouseX.<br />
The following if construct demonstrates this:<br />
User Defined Functions 143
An Introduction To Programming With <strong>Processing</strong><br />
if(buttonDrag){<br />
buttonXPos = constrain(mouseX - sliderFd.width/2, width/2 -<br />
sliderBk.width/2, width/2 + sliderBk.width/2 -<br />
sliderFd.width);<br />
}else{<br />
buttonXPos = constrain(buttonXPos, width/2 -<br />
sliderBk.width/2, width/2 + sliderBk.width/2 -<br />
sliderFd.width);<br />
}<br />
Finishing the slider<br />
The Third issue with the slider is to get it to stop dragging once the mouse has<br />
been released. For this we're going to use the mouseReleased() function. The<br />
mouseReleased() function should be placed directly below the mouseDragged()<br />
function for the purpose of readability. However to <strong>Processing</strong> it does not make a<br />
difference if the function is before or after mouseDragged(). The<br />
mouseReleased() function is pretty simple, all it does is run the function once<br />
every time the mouse button is released in the Display Window. In our case the<br />
function will check if buttonDrag is set to true, if it is then we can be sure that the<br />
slider button is being dragged. As the function is run when the mouse has been<br />
released, we can be certain that the user no longer wants to drag the button, as a<br />
result the function then sets the buttonDrag variable back to false. This means that<br />
the conditional using this variable in the draw() structure will evaluate to false, so<br />
that mouseX will no longer be used to determine the value of buttonXPos. The<br />
mouseReleased() function should look like the following code listing:<br />
void mouseReleased(){<br />
if(buttonDrag){<br />
buttonDrag = false;<br />
}<br />
}<br />
Mapping Values<br />
Now that we have the slider moving correctly we can use the values of<br />
buttonXPos and map them to any values that we choose, for example we cold<br />
User Defined Functions 144
An Introduction To Programming With <strong>Processing</strong><br />
map the range of values that buttonXPos returns to the amount we would like an<br />
image to scale on it's x axis, how far or fast an image moves across the screen, or<br />
just about anything that can accept a range of values as an input. We're going to<br />
map the buttonXPos range to the tint of an image, making the image appear to<br />
fade in from black. Mapping one range of values to another is done with the<br />
map() function. The map() function accepts parameters in the following format:<br />
map(mValue, oldLow, oldHigh, newLow, newHigh);<br />
The parameter mValue is the value that you will be mapping to the new range, in<br />
our case this is buttonXPos. The parameters oldLow and oldHigh are the<br />
minimum and maximum values of the range you would like to map to the new<br />
range, in other words these values are the furtherest left we can drag the slider<br />
button (oldLow) or expressed within the context of our program:<br />
width/2 - sliderBk.width/2<br />
The oldHigh value is the maximum value of the original range, and in the context<br />
of our program:<br />
width/2 + sliderBk.width/2 – sliderFd.width<br />
You might have noticed, by now that these two values are the exact expressions<br />
we used to determine the minimum and maximum values for the constrain()<br />
function assigned to buttonXPos, this is no coincidence. These two values<br />
determined the maximum range of the sliders movement and this is the exact<br />
range we are mapping to a new range. The new range will be represented by the<br />
two parameters newLow and newHigh and in our case these are two simple<br />
numbers 0 and 255 respectively. As we are mapping the slider button's movement<br />
to the tinting of an image via the tint() function we will be using the single value<br />
that is returned from the map() function which will be between the newLow and<br />
newHigh parameters in order to create the impression of the image fading in. In<br />
the context of the actual values, 0 to 255 represent the range of values that the<br />
tint() function uses to tint the image with various levels of gray. For example the<br />
value 0 has the effect of making an image appear as fully gray (or black) and 255<br />
has the effect of making an image appear with no gray and no black tint.<br />
With the slider button's values converted to the correct range of values, all that is<br />
left to do is link the new values to the image. In order to do this we will start by<br />
User Defined Functions 145
An Introduction To Programming With <strong>Processing</strong><br />
declaring a new variable in the global scope. Add the following variable to your<br />
sketch:<br />
float imgTint;<br />
As you can see this variable is datatyped as float, this is because the map()<br />
function returns floats. Remember that this does not mean that the parameters<br />
themselves have to be floats, nonetheless it is worth noting that in order to<br />
perform true division if the parameters you supply <strong>Processing</strong> with for the map()<br />
function are of type int <strong>Processing</strong> will typecast them to floats for the purpose of<br />
the map() function. What this means is that once those values have been evaluated<br />
by the map() function, the answer will be returned as a float. Since this is the<br />
variable that we will assign the return value of the map() function to, and as just<br />
stated this value will be a float it makes sense to datatype this variable as a float.<br />
If we try to use another datatype, such as an int, we will get a “type miss-match”<br />
error.<br />
With our new variable, imgTint, we will use assignment in the if() construct we<br />
created earlier within the draw() function, to determine it's value as the slider is<br />
dragged. Add the following statement to the if() construct, directly under the<br />
assignment statement for buttonXPos:<br />
imgTint = map(buttonXPos, width/2 - sliderBk.width/2, width/2 +<br />
sliderBk.width/2 - sliderFd.width, 0, 255);<br />
In the previous statement we use the map() function to determine the value of the<br />
imgTint variable. Now that we have a place to store this value we can associate it<br />
with the tint() function. Which we will do before the image() function to render<br />
img. We do this by adding the following statement:<br />
tint(imgTint);<br />
This statement must precede the statement telling <strong>Processing</strong> to render the img<br />
object. If you were to run the sketch at this point you might notice that everything<br />
is working, but not quite as expected. The answer to this problem is order. If you<br />
look at the current sketch it runs like so.<br />
User Defined Functions 146
An Introduction To Programming With <strong>Processing</strong><br />
draw()<br />
If the slider button is being dragged<br />
Update variables<br />
Else leave everything as it is<br />
render the images<br />
end draw()<br />
Although this method might be somewhat functional, it's not very intuitive. What<br />
this means is that when the user drags the slider the user should be able to see the<br />
results of their actions in realtime (another way of saying immediately or<br />
something very close to that) and when the user releases the mouse button, the<br />
values should stay as the user set them and not jump around to seemingly<br />
incorrect values. As a result we need to make sure that the images are being<br />
rendered for all possible situations using the correct values, which in our case is<br />
only two different branches. So we are going to restructure our code to<br />
accommodate for a more intuitively designed interface.<br />
draw()<br />
end draw()<br />
If the slider button is being dragged<br />
Update variables<br />
render the images<br />
Else leave everything as it is<br />
render the images<br />
How this new structure is implemented in our program will follow this pattern:<br />
buttonXPos<br />
imgTint<br />
tint()<br />
img<br />
noTint()<br />
//update variable<br />
//update variable<br />
//set the tint value<br />
//render main image now effected by tint<br />
//Turn tint off so slider images are not<br />
User Defined Functions 147
An Introduction To Programming With <strong>Processing</strong><br />
sliderBk<br />
sliderFd<br />
//effected by it<br />
//render slider background image<br />
//render slider button image<br />
This is the order within the first code block of the if else construct the second<br />
code block will follow the same order. For a full listing of the code it's best to<br />
look at the sketch itself which is<br />
named slider.pde. Finally to end off the example I've added another image to the<br />
sketch which I've associated with the object I've called star and mapped it's Y<br />
movement to the slider. Like I said the mapping of one value with a range to<br />
another range can lead to in infinite array of possibilities, and is largely the<br />
premise on which more complex applications are built upon. Why not try your<br />
own custom mappings you'll soon come to realize that with this simple function,<br />
the sky is definitely not the limit.<br />
The final slider.pde sketch<br />
The mystery shape maker<br />
In this next sketch we will discover two new fundamental programming concepts<br />
arrays and iterations, learn how to work with random numbers and try out a new<br />
datatype called color. The mystery shape maker is a sketch that allows the user to<br />
make several clicks in the Display Window, and by capturing and storing the<br />
The mystery shape maker 148
An Introduction To Programming With <strong>Processing</strong><br />
coordinates of each click constructs a new shape for the user in a randomly<br />
generated color. The shapes can be as simple or complex as you want, as you<br />
determine how many times the user gets to click in the Display Window before<br />
the mystery shape is drawn.<br />
Arrays<br />
Some of the shapes that can be created with the mystery shape maker<br />
Arrays are used to store data, but unlike the other data storage types we have been<br />
using (such as variables) arrays have the ability to store more than just a single<br />
value. Arrays can store multiple values of the same datatype in much the same<br />
way that an ordinary list (such as a grocery list) consists of multiple elements<br />
related to the topic of the list. In fact, this analogy is so true to the nature of arrays<br />
that every component making up an array is referred to as an element. This<br />
analogy can be extended ever further, as with a list each element in that list can<br />
have a number associated with it, in an array each element has a number<br />
associated with it too. We refer to these numbers as indices (in plural) or simply<br />
an index number in singular form.<br />
An everyday list:<br />
My Shopping List //name of the list<br />
1. Tea //element1<br />
2. Soy Milk //element2<br />
3. Vegan Cookie //element3<br />
Arrays 149
An Introduction To Programming With <strong>Processing</strong><br />
An Array<br />
int[] myArray = {20, 30, 40};<br />
//name of array is myArray[] and it is datatyped as an int, so it<br />
//can store integer values<br />
//element 1 is 20, and has an index value of 0<br />
//element 2 is 30, and has an index value of 1<br />
//element 3 is 40, and has an index value of 2<br />
Index values for arrays start at 0 and can go as high as the number of elements in<br />
an array minus 1, for example if an array has 15 elements, the index value of the<br />
last element in the array is 14.<br />
Element No. 1<br />
has an index<br />
value of 0<br />
Element No.3<br />
has an index<br />
value of 2<br />
int[] myArray = {20, 30, 40};<br />
Element No.2<br />
has an index<br />
value of 1<br />
Understandably at first this system of numbering might seem a bit strange, so in<br />
order to simplify things you can think of an index number as a means of referring<br />
to an element within an array without having to know what it's value is. This<br />
concept should not be new to you as it does not differentiate very much from that<br />
which defines a variable, the main difference being that instead of using a<br />
variable name we are now using an index number within an array to reference that<br />
specific value. The syntax for referencing an element within an array follows:<br />
int[] myArray = {20, 30, 40}; //initialize array<br />
myArray[0];<br />
//reference array element with<br />
//index number 0, which has a value<br />
//of 20.<br />
We can also use an array in a program in a similar way that we would use a<br />
variable, for example:<br />
Arrays 150
An Introduction To Programming With <strong>Processing</strong><br />
Index Number 0 1 2<br />
int[] myArray = {20, 30, 40}; //initialize array<br />
int x = myArray[0] + myArray[2]; //sets x to 20 + 40 i.e. 60<br />
Using an array in this format can be very similar to the way in which variables are<br />
used, and the comparison can extend further than the previous expressional<br />
example into initialization and assignment. As you can see in the previous<br />
example the array was initialized through both declaration and assignment in one<br />
statement in a similar way that variables use initialization.<br />
As arrays have multiple elements assigning values to the elements of an array<br />
cannot be through a simple reference to the arrays name, as <strong>Processing</strong> would not<br />
know which element is to inherit the value on the right of the assignment<br />
operator. As a result the process of assigning values to elements of an array after<br />
declaration or initialization must also include the index number of the element<br />
you wish to assign a value to, on the left hand side of the assignment operator. For<br />
example:<br />
int[] myArray = {20, 30, 40}; //initialize array<br />
myArray[2] = 10;<br />
//element 3 was 40 now has a value<br />
//of 10<br />
With all the similarities between variables and array elements you might be<br />
wondering what the purpose of an array is? Unlike variables storing one value<br />
followed by another value of the same type within the same variable, the array<br />
does not have to replace the previous value in order to store a new value. For<br />
example, what if I wanted to store the x position of the mouse when the user<br />
clicks in the Display Window. This would be easy enough, I'd just create a<br />
variable and assign it the value of the mouseX system variable. This is fine if all I<br />
need to know is the current x position of the mouse when the user clicks.<br />
However, what if I need to know the previous x coordinate of the mouse, or the<br />
one before that and so on. Retrieving this information with a simple variable<br />
would not be possible because each time the user clicks the mouse the current<br />
value of mouseX replaces the previous value.<br />
Arrays 151
An Introduction To Programming With <strong>Processing</strong><br />
int mXPos;<br />
if(userClicked){<br />
mXPos = mouseX;<br />
}<br />
//declare variable to store mouse x<br />
//position<br />
//hypothetical conditional to test if<br />
//user has clicked<br />
//sets variable to current X position of<br />
//mouse<br />
//user moves the mouse around and clicks again<br />
if(userClicked){<br />
mXPos = mouseX;<br />
}<br />
//hypothetical conditional repeats to<br />
//test if user has clicked<br />
//replaces the previous value for mXPos<br />
//with the new X position of the mouse,<br />
//and the previous value of mXPos can no<br />
//longer be retrieved.<br />
With arrays this information becomes accessible to us. By using the elements of<br />
an array we can store the first x coordinate of the mouse at index 0, the second<br />
coordinate at index 1 and so on. Lets have a look at an example of this in a sketch.<br />
int[] myArray = new int[4];<br />
int clicks;<br />
void draw() {<br />
}<br />
void mouseClicked(){<br />
if(clicks
An Introduction To Programming With <strong>Processing</strong><br />
}<br />
println(myArray[2]);<br />
println(myArray[3]);<br />
clicks++;<br />
}<br />
//print the value of the<br />
//third x coordinate<br />
//print the value of the last<br />
//x coordinate<br />
//increment the click value<br />
//by 1<br />
Program Notes<br />
In the first line of the sketch we declare an array with four elements. When using<br />
this technique to create a new array we must indicate the datatype of the array and<br />
use brackets[] to tell <strong>Processing</strong> that we are about to create an array (and not just<br />
simply declare a variable). We must then name the array and use the assignment<br />
operator to populate the array with the new elements (which do not have values<br />
assigned to them as of yet). We do this by use of the new keyword, followed by<br />
the datatype of the new elements which must match the array's datatype and<br />
finally, brackets indicating how many of these new elements will populate the<br />
array.<br />
int[] myArray = new int[4];<br />
Next the variable clicks is declared, this variable will be used to count how many<br />
times the user has clicked in the Display Window. The draw() function is then<br />
initiated in order to keep the program running, and prevent the sketch from<br />
turning to static mode.<br />
The mouseClicked() function consists of a simple if() statement. The conditional<br />
of the if() statement is executed when the user clicks a mouse button within the<br />
Display Window. The conditional checks if the clicks variable is less than four,<br />
which is the amount of elements in the array. If this is the first time the mouse has<br />
been clicked, clicks will equal a value of 0 as it has not been assigned a value<br />
through initialization, it has only been declared. As a result the following<br />
statement is run:<br />
myArray[clicks] = mouseX;<br />
Arrays 153
An Introduction To Programming With <strong>Processing</strong><br />
This is the statement that assigns a value to each element in the array. If this is the<br />
first time clicks has been used in the comparison it will also be the first time the<br />
user has clicked in the Display Window and therefore clicks will have a value of<br />
0, as a result the preceding statement can be translated and explicitly expressed<br />
as:<br />
myArray[0] = mouseX;<br />
This means the element with the index number 0 is assigned the value of<br />
whatever the mouse's x coordinate was at the time the user clicked a mouse<br />
button. The next four println() statements print the value of each of the four<br />
elements in the array. As only the first element has a value at this point in time, it<br />
will be the only element that is non-zero until the user clicks again (up to three<br />
more times).<br />
clicks++;<br />
In a similar way that we used augmented assignment to shorten an expression that<br />
is commonly used in programming, we have used an increment operator in the<br />
previous example to shorten this statement. The increment operator works by<br />
adding 1 to the current value of the particular variable it is used with, then<br />
assigning this new value back to the original variable. This is a common method<br />
of getting a program to count for you as each time the variable is used with the<br />
increment operator it will return a value that is one more than it's previous value.<br />
Writing this statement without the increment operator would look like this:<br />
clicks = clicks + 1;<br />
As you can see using an increment operator can make your code easier to read<br />
and save you some keystrokes.<br />
The decrement operator (which is two minus signs --) works in a similar way to<br />
the increment operator except that it subtracts 1 from the variable's current value<br />
before reassigning the new value back to the original variable.<br />
The result of this statement is that the clicks variable will now be one more than<br />
it's previous value by the time the program repeats. For example the clicks<br />
variable was initially 0, but at the end of the if() statement the clicks variable will<br />
have a value of 1. This is important because the next time the user clicks a mouse<br />
Arrays 154
An Introduction To Programming With <strong>Processing</strong><br />
button the comparison will be working with different values. For example on the<br />
first click the comparison can be expressed as (0
An Introduction To Programming With <strong>Processing</strong><br />
evaluating to true and subsequently assigning positional data to the elements in<br />
the array, will now evaluate to false as the number of clicks increases in value.<br />
We will then use the beginShape() and endShape() functions and combine each<br />
one of the two arrays' corresponding elements into a coordinate for the vertex()<br />
function, which will be embedded within a loop that cycles through the two arrays<br />
extracting the information from them and subsequently drawing the mystery<br />
shape.<br />
Although this might sound like a handful, you already know how to create two<br />
thirds of this program. Nonetheless, lets recap on these fundamental programming<br />
topics as they will more than likely prove to be a useful asset in many a sketch.<br />
First we are going to start by declaring and/or initializing the following global<br />
variables:<br />
int points = 6;<br />
int clicks;<br />
int[] numx = new int[points];<br />
int[] numy = new int[points];<br />
//number of points<br />
//click counter<br />
//array for mouse x<br />
//coordinates<br />
//array for mouse y<br />
//coordinates<br />
//generate a random color for the shape's fill<br />
color randCol = color(random(256), random(256), random(256));<br />
The points variable will be a number that we can change before running the<br />
sketch so that we can make our shape consist of as many or few points as we like,<br />
this number should not be negative.<br />
The clicks variable will be used to store the amount of times the user has clicked<br />
in the Display Window, it will also be an operand within the conditional that<br />
populates the array.<br />
Then we move onto declaring the arrays that will store the x and y coordinates of<br />
the user's clicks. Notice how the number of elements in this array has been<br />
defined as the variable points. As points is of type int it can be placed within the<br />
array's declaration brackets. The preceding statement relating to the declaration of<br />
the numx array can be translated and explicitly expressed as:<br />
int[] numx = new int[6];<br />
It is worth noting that in the actual sketch we have not used a numerical constant<br />
Arrays 156
An Introduction To Programming With <strong>Processing</strong><br />
but rather a variable to determine how many elements will populate the array, this<br />
is because if we decided we want to use more or less points making up the<br />
mystery shape, it would be easier to implement this change by means of<br />
modifying the initialization statement for the points variable rather than having to<br />
change numerical values scattered throughout the sketch.<br />
The final variable we have created within the global space is called randCol and<br />
has been datatyped as color. The color datatype is used to store color values, in<br />
our case we are using the format of:<br />
color varName = color(R, G, B);<br />
Where color is the keyword used to declare variables of type color, varName is<br />
the name of the variable, and the assignment operator is used to assign a color<br />
value in R (red), G (green) and B (blue) values. RGB values range from 0 to 255<br />
each. Note the expression used for each of the R, G and B values:<br />
random(256)<br />
random() is a function that is used to return a random number, that is between 0<br />
and the number specified, but not including the specified number. As a result the<br />
parameter 256 is used so that <strong>Processing</strong> will include values between 0 up to and<br />
including 255. random() also accepts parameters in the form of:<br />
random(Low, High);<br />
Where Low is the minimum number in the possible range of random numbers and<br />
High is one more than the maximum number in the range. If you assign the<br />
random() function to a float <strong>Processing</strong> will return random floats.<br />
The next step is to setup the setup() and draw() functions as per usual, then add<br />
the following if() statement to the draw() function:<br />
if (clicks
An Introduction To Programming With <strong>Processing</strong><br />
There's not really anything new about this if() statement, so we'll just run through<br />
it really briefly. First the conditional checks if the amount of times the user has<br />
clicked is less than the amount of elements in the arrays. Using this method<br />
creates an error catching scenario, as opposed to if the user was allowed to click<br />
repeatedly beyond the number of elements in the arrays which would result in the<br />
amount of elements that the program would attempt to store in the arrays<br />
exceeding the amount of elements that can be stored in the arrays. This would<br />
cause an “Array Index Out of Bounds” exception.<br />
We can then use the clicks variable in the if() structure to determine which<br />
element in the array is assigned the corresponding mouse X or mouse Y value.<br />
void mouseClicked(){<br />
clicks++;<br />
}<br />
Outside of the draw() function we setup a simple mouseClicked() function, which<br />
works in a very similar way to the mouseReleased() function. The difference<br />
being that the mouseClicked() function does not wait for the mouse to be released<br />
before running the code that makes up it's structure, it executes the code within<br />
it's associated braces as soon as the mouse is clicked within the Display Window.<br />
The purpose of the mouseClicked() function is simply to increment the clicks<br />
variable, which it does so within the function's only code block.<br />
Iterations<br />
<strong>Processing</strong> has two main types of iterations the for() structure and the while()<br />
structure. The while() structure can be thought of as a simplified version of the<br />
for() structure. We will be focusing on the for structure.<br />
The for() structure is used to iterate a value, that is to change a value by means of<br />
a recurring pattern. for() structures are also referred to as for() loops in some<br />
programming languages, whatever you call them they usually will be structured<br />
according to the following protocol.<br />
for(init; test; update){<br />
...statements<br />
}<br />
Iterations 158
An Introduction To Programming With <strong>Processing</strong><br />
Of the main differences that separate one languages implementation of for loops<br />
from that of another, will generally not be anything structural by rather syntactic.<br />
For example some programming languages use comma's to separate init, test and<br />
update <strong>Processing</strong> uses a semi-colon implying that each is a statement on it's own.<br />
• The term init in the previous example is used to describe initialization. In<br />
a for() loop iteration init is used to declare a temporary variable that will<br />
usually be used in the iterations structure, test and update.<br />
• Test is used to describe a conditional, which like a normal conditional will<br />
evaluate to true or false. If the conditional evaluates to true the for()<br />
structure will run, if the conditional evaluates to false the entire for() loops<br />
structure is skipped and <strong>Processing</strong> will continue to the statement/s that<br />
follow the for() structure in the sketch.<br />
• Update is used to describe an expression that will determine how the value<br />
of the variable in the conditional is being changed. The value of the<br />
variable being evaluated in the conditional must change, by means of the<br />
update, or the loop will go on forever which will eventually cause<br />
<strong>Processing</strong> to crash. For example an increment statement is often used in<br />
update to increment the value of the variable initialized in init and<br />
evaluated in the conditional test.<br />
In programming it is common to use a for() loop iteration to get your program to<br />
count for you, as per the following example:<br />
for (int i = 0; i < 10; i++){<br />
println(i);<br />
}<br />
//prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 one digit at a time<br />
The previous example used a for() loop iteration to count from 0 to 9, lets have a<br />
look at how we did this. First we need to use the for keyword to indicate to<br />
<strong>Processing</strong> that we are about to create a for() loop iteration. A for loop iteration<br />
relies on three statements init, test and update within parenthesis so that they are<br />
specifically associated with the for() loop iteration structure. As you can see the<br />
three statements are separated with semi-colons, this is unique to a for() loop<br />
iteration in <strong>Processing</strong> and clearly differentiates these statements from being<br />
parameters.<br />
As init is used to initialize a variable within the for() loop iteration structure, the<br />
scope of this variable is limited to the for() structure. What this means is that the<br />
Iterations 159
An Introduction To Programming With <strong>Processing</strong><br />
variable i in our previous example will not be accessible in other places within<br />
our sketch and only be accessible within the for() structure. As a result this<br />
variable name is usually i or n and not very descriptive. It is actually more<br />
distracting to call a variable initialized within a for() loop anything other than i or<br />
n (some people might also use x but this can be a bit distracting from variables<br />
that use x to denote a position on the x axis). It is therefore advisable to not use a<br />
variable name that is any more descriptive than a single character such as i or n.<br />
Once we have the variable initialized we can then use it in a test, if the test<br />
evaluates to true the code within the for structure will be run. It is important to<br />
note that if the test evaluates to true the code within the for structure is run, and<br />
only after this code is run is the update statement executed.<br />
A graphical representation of how an iteration works<br />
The update statement in our example is an incremental statement, which adds one<br />
to the variable from init subsequently increasing the value of the variable with<br />
each iteration. On the tenth occasion that the loop repeats the variable is<br />
incremented to a value of 10, so when the conditional evaluates the test (10
An Introduction To Programming With <strong>Processing</strong><br />
beginShape();<br />
for(int i = 0; i < points; i++){<br />
vertex(numx[i], numy[i]);<br />
}<br />
endShape();<br />
Using this method we can let the user decide what the shape should look like. If<br />
you recall beginShape() and endShape() require the vertex() function between<br />
them. The difference with this sketch is that we have nested the vertex() function<br />
inside a for() loop iteration. The program will loop through the vertex() function<br />
as many times as the variable initialized within the for() loop called i, is less than<br />
the points variable declared earlier in global space. What this translates to is the<br />
the vertex() function will be run six times and on the seventh attempt to run the<br />
for() loop the conditional of the for() loop will evaluate to false as i will be equal<br />
to points (i == points) causing the loop to break and running the rest of the code<br />
that follows the for() loop structure, which would be the endShape() function.<br />
This creates a shape with six vertices in the positions that the user specified by<br />
clicking in the Display Window. The coordinates of these vertices are determined<br />
by extracting the values associated with each element in the arrays numx[] and<br />
numy[], as the index number of each element is referenced with the for() loop<br />
variable i. A full listing of the mystery shape program follows:<br />
int points = 10;<br />
int clicks;<br />
int[] numx = new int[points];<br />
int[] numy = new int[points];<br />
color randCol = color(random(255), random(255), random(255));<br />
void setup() {<br />
size(300,300);<br />
smooth();<br />
}<br />
void draw() {<br />
background(100);<br />
if (clicks
An Introduction To Programming With <strong>Processing</strong><br />
}else{<br />
fill(randCol);<br />
beginShape();<br />
for(int tempx = 0; tempx < points; tempx++){<br />
vertex(numx[tempx], numy[tempx]);<br />
}<br />
endShape();<br />
}<br />
}<br />
void mouseClicked(){<br />
clicks++;<br />
}<br />
Transforms<br />
<strong>Processing</strong> provides a convenient method for animating and interacting with<br />
components of a sketch that are transformed in various ways. The term transform<br />
when used in this context generally refers to any one of, or combinations of the<br />
following three actions:<br />
Translation, Scaling, Rotation.<br />
Translation is simply another way of saying “moving” but as the term moving can<br />
tend to be somewhat ambiguous when you consider that rotation also involves<br />
movement and so too does scaling (when you consider that the components<br />
making up an object such as it's vertices move when the object is scaled), we<br />
prefer to use the term translation as it specifically refers to positional data in terms<br />
of x, y and z of an entity. The function for applying translations within a sketch is<br />
translate() and it accepts parameters in the form of x and y with an optional third<br />
parameter for z (which we will discuss soon) when using a 3D renderer.<br />
Rotation is a transform that we have not discussed in any of our previous<br />
sketches, and as you will see can be a useful asset to creating certain types of<br />
animation within a sketch. Amongst the functions that provide us with access to<br />
rotation are rotate(), rotateX(), rotateY() and rotateZ() these functions accept<br />
values in radians.<br />
Scaling is a transform accessed with the scale() function and it accepts a single<br />
float value or two floats that relate to x and y or three floats that relate to x, y and<br />
Transforms 162
An Introduction To Programming With <strong>Processing</strong><br />
z for 3D sketches. Scaling creates the impression of making things appear to be<br />
bigger or smaller within a sketch.<br />
Let's have a look at an example of a static sketch using the translate() function.<br />
size(400,60);<br />
rect(0,0,50,50);<br />
translate(width/2, 0);<br />
fill(255,0,0);<br />
rect(0,0,50,50);<br />
A static sketch using transforms<br />
In the first line of the sketch, we simply defined the window in which the sketch<br />
is running as being very long horizontally and short, vertically. In the following<br />
line we drew a rectangle at the origin, and because the rectMode() function by<br />
default is set to CORNER, the rectangle sits perfectly flush with the top left hand<br />
corner of the Display Window. We then used the translate() function with a<br />
modification to the x parameter, and as you would expect the next time we draw a<br />
rectangle (after changing the fill color) it's position on the x axis reflects this<br />
translation we previously applied. However, if you have a look at the x parameter<br />
for the rect() function you will notice that things are a bit different to what you<br />
might expect as the X parameter reads 0 whereas the rectangle is drawn close to<br />
the center of the Display Window and to the right of the previously drawn<br />
rectangle. Shouldn't the rectangle be drawn at the origin if it's X parameter is 0?<br />
If you were thinking something along those lines then you are absolutely correct<br />
and in fact the rectangle is being drawn at the origin, the main difference here is<br />
that we have used the translate() function to move the origin, not of the rectangle<br />
but of the entire coordinate system. Let's have a look at how this came to be.<br />
Although the effect of what you are seeing in the Display Window creates the<br />
impression that <strong>Processing</strong> has moved the rectangle, the rectangle as it is<br />
Transforms 163
An Introduction To Programming With <strong>Processing</strong><br />
indicated by it's X parameter in both rect() function calls tells us something<br />
different. That is that the rectangle has in fact not moved. The reason that the<br />
rectangle has come to be drawn in this new location is due to the effect of the<br />
entire coordinate system moving.<br />
If you were for a moment to reflect back on the Cartesian graph system that we<br />
discussed earlier you would remember that everything in <strong>Processing</strong> works in a<br />
similar fashion to that of something drawn on graph paper. Bearing this in mind,<br />
what we have done in the previous sketch cannot accurately be described as<br />
moving the rectangle, but rather more akin to us moving the “graph paper”. For<br />
example if you were to draw a rectangle on a piece of graph paper, then move the<br />
graph paper around, you would in effect be creating the impression of the<br />
rectangle drawn on the graph paper moving around. The rectangle itself would not<br />
be what you are moving around, in terms of the fact that the rectangle's positional<br />
x and y data has not changed with relation to the origin of the coordinate system it<br />
was drawn relative to. We can therefore say that the rectangle has not moved,<br />
however the coordinate system associated with it has.<br />
An object drawn on graph paper does not move but the graph paper does<br />
This is the purpose of transforms in <strong>Processing</strong>, they move the coordinate system<br />
for us. We can still move the components of a sketch through their own positional<br />
data, which we usually supply in terms of X and Y parameters of a function, but<br />
bear in mind that mixing translation techniques like this will result in the<br />
component appearing to have “moved” by the sum of the two data sets. To put<br />
this in another way, the distance the entity would appear to have moved would be<br />
the sum of the translate() function plus the X, Y and Z parameters of the function<br />
to draw the entity.<br />
So if we still have the ability to modify components of a sketch via their own X<br />
and Y parameters what's the benefit of having transforms?<br />
Transforms can save us a lot of unnecessary work, make our code a lot easier to<br />
read and provide us with functionality that would not be possible without them.<br />
Transforms 164
An Introduction To Programming With <strong>Processing</strong><br />
Lets have a look at an example of how this works.<br />
In order to see the benefits that transforms have on our code we'll revisit the smile<br />
sketch from our static sketch examples at the beginning. If you recall, the<br />
purpose of the sketch was simply to draw a smiley face to the Display Window in<br />
static mode with some other components. We're only interested in the smiley face,<br />
so first we're going to adapt the sketch for active mode by including the drawing<br />
of the face within the draw() structure:<br />
void setup(){<br />
size(640,480);<br />
}<br />
void draw(){<br />
background(127);<br />
//Drawing the face<br />
fill(191,233,255);<br />
ellipse(width/2, height/2, 100, 100);<br />
//smile<br />
noFill();<br />
stroke(255,0,0);<br />
arc(width/2, height/2 + 10, 50, 50, 0, PI);<br />
//eyes<br />
stroke(0,0,0);<br />
fill(0,255,0);<br />
ellipse(width/2-15, height/2-15, 20, 30);<br />
ellipse(width/2+15, height/2-15, 20, 30);<br />
}<br />
The smile static sketch revisited and modified to fit an active mode sketch<br />
Transforms 165
An Introduction To Programming With <strong>Processing</strong><br />
As you can see nothing surprising about the sketch, but what if we wanted to<br />
animate the smiley face by moving it across the Display Window, or attaching it<br />
to the mouse?<br />
This could become quite a cumbersome task as every component of the smiley<br />
face that has X and Y parameters would have to be updated for every frame. To<br />
give you an indication of how much extra work this is we're going to have a look<br />
at what sort of changes in the sketch would need to be implemented if we wanted<br />
to attach the smiley face to the mouse:<br />
void setup(){<br />
size(640,480);<br />
}<br />
void draw(){<br />
background(127);<br />
//Drawing the face<br />
fill(191,233,255);<br />
ellipse(mouseX, mouseY, 100, 100);<br />
//smile<br />
noFill();<br />
stroke(255,0,0);<br />
arc(mouseX, mouseY + 10, 50, 50, 0, PI);<br />
//eyes<br />
stroke(0,0,0);<br />
fill(0,255,0);<br />
ellipse(mouseX-15, mouseY-15, 20, 30);<br />
ellipse(mouseX+15, mouseY-15, 20, 30);<br />
}<br />
As you can see almost every second line of code had to be updated within the<br />
draw() structure. Now imagine if you had a whole character you wanted to draw<br />
and how much additional work something like that could amount to?<br />
With transforms making a change like this to your code is easy:<br />
void setup(){<br />
size(640,480);<br />
}<br />
void draw(){<br />
background(127);<br />
//transform<br />
translate(mouseX-width/2, mouseY-height/2);<br />
Transforms 166
An Introduction To Programming With <strong>Processing</strong><br />
//Drawing the face<br />
fill(191,233,255);<br />
ellipse(width/2, height/2, 100, 100);<br />
//smile<br />
noFill();<br />
stroke(255,0,0);<br />
arc(width/2, height/2 + 10, 50, 50, 0, PI);<br />
//eyes<br />
stroke(0,0,0);<br />
fill(0,255,0);<br />
ellipse(width/2-15, height/2-15, 20, 30);<br />
ellipse(width/2+15, height/2-15, 20, 30);<br />
}<br />
Notice that only one additional line of code was needed to accommodate for this<br />
update, the rest of the code remained unchanged.<br />
The additional statement is:<br />
translate(mouseX-width/2, mouseY-height/2);<br />
This statement simply uses the translate() function, with two parameters relating<br />
to X and Y. The X parameter tells <strong>Processing</strong> to “move” the entire coordinate<br />
system to the position of the mouse's X value then to subtract half the width of the<br />
Display Window from this value. The reason we need to subtract half the width of<br />
the Display Window from the mouseX system variable is because our entire<br />
sketch was originally made to draw the smiley face in the center of the Display<br />
Window.<br />
Offset from the origin with<br />
mouseX<br />
Offset from the origin with<br />
mouseX - width/2<br />
As the coordinate system is transformed, it's origin can exist within the boundaries of the<br />
Display Window or outside of these boundaries.<br />
Transforms 167
An Introduction To Programming With <strong>Processing</strong><br />
As transforms effect everything below their implementation within a sketch, due<br />
to them transforming the entire coordinate system, there are times when you will<br />
find that this is not the effect that you want.<br />
The image below of a cart is made up of three separate images which are rendered<br />
in the following order the wheel in the background, the main cart and the wheel in<br />
the foreground. If our intention was to rotate the back wheel first, as the back<br />
wheel would have to be rendered before any of the other images. We run the risk<br />
of having the transforms applied to the back wheel effecting the main cart and the<br />
wheel in the foreground as they are rendered after the back wheel, and will<br />
therefore be effected by any scale(), translate() and/or rotate() function that is<br />
intended for the back wheel. This would create the impression of the cart orbiting<br />
around the back wheel, which is obviously not what we where trying to<br />
accomplish. Two functions in <strong>Processing</strong> called pushMatrix() and popMatrix()<br />
help us to solve this problem.<br />
Main Cart<br />
Background wheel<br />
Foreground wheel<br />
The template rendering of the cart.pde sketch<br />
The function pushMatrix() when called before a transform is executed will store<br />
the current position of the coordinate system. This means that if you call a<br />
pushMatrix() function at the start of the draw() structure it will remember the<br />
default position of the coordinate system (pre-transform). You are then free to<br />
apply transforms to the particular component of the sketch that you would like to<br />
scale, rotate or translate. Once you are satisfied with the transforms you have<br />
performed you can then render the component, for example by means of a call to<br />
Transforms 168
An Introduction To Programming With <strong>Processing</strong><br />
the image() function. Running the popMatrix() function at this point will then be<br />
necessary to restore the coordinate system back to the state it was in when the<br />
previous pushMatrix() was called. You can then proceed to run more<br />
pushMatrix(), transforms, render, popMatrix() combinations on other components<br />
of the sketch which will remain unaffected by the previous transforms. Using<br />
pushMatrix() and popMatrix() in this way allows us to apply multiple transforms<br />
to a component of a sketch ,and not have those transforms effect other<br />
components.<br />
Transforms 169
An Introduction To Programming With <strong>Processing</strong><br />
Lets have a look at how to use this technique to make the cart move across the<br />
Display Window and have the wheels of the cart rotate accordingly.<br />
We'll start as always with a template of what we want the final result should look<br />
like:<br />
PImage cart;<br />
PImage wheelFd;<br />
PImage wheelBd;<br />
PImage grass;<br />
void setup(){<br />
size(800,600);<br />
cart = loadImage("cartMain.png");<br />
wheelFd = loadImage("wheelFd.png");<br />
wheelBd = loadImage("wheelBd.png");<br />
grass = loadImage("grassLessBlur.jpg");<br />
}<br />
void draw(){<br />
background(grass);<br />
imageMode(CENTER);<br />
}<br />
image(wheelBd, -75, 25);<br />
image(cart, 0, 0);<br />
image(wheelFd, -95, 35);<br />
//println(mouseY);<br />
Out of interest you might be wondering how I came about selecting the X and Y<br />
parameters of the image() functions which render the wheels relative to the<br />
position of the cart. If you look at the last line you'll see a println() function that<br />
has been commented out. By replacing the image() function's X and Y parameters<br />
with mouseX then mouseY, respectively and one at a time, you can run the<br />
sketch with the image of the wheel attached to either the mouse's X or Y position.<br />
Place the wheel in the position it should be in, the println() function (when<br />
uncommented) will print out the position of your mouse, note this value and<br />
replace it with the mouseX or mouseY system variable in the wheel's image()<br />
function's corresponding X or Y parameter.<br />
Transforms 170
An Introduction To Programming With <strong>Processing</strong><br />
As the imageMode() function is set to CENTER in this example you will have to<br />
move the cart image to a location that is not the origin, so that the left and top<br />
halves of the image is not obscured by the boundaries of the Display Window.<br />
You will then need to subtract the value that you added to the X and Y parameters<br />
of the image() function to draw the cart from the respective values printed in the<br />
Text Area that will be used to place the wheels in the correct locations.<br />
Now that we have a template from which to start let's set up a temporary system<br />
that allows the cart to trail after the mouse with a bit of friction, we'll then modify<br />
this code to suit the needs of our sketch. This methodological approach to<br />
sketching by creating a rough idea then refining it will allow us to see results<br />
much sooner in the sketching process, rather than spending a lot of time on a<br />
sketch only to find out when it is almost done that the effect we were trying to<br />
achieve isn't quite working out.<br />
We'll start by adding the following global variables:<br />
float xPos;<br />
float difX;<br />
int drag = 30;<br />
If you recall from the imageScroll.pde sketch, we used the technique of creating<br />
the impression of friction with a similar set of global variables. The only<br />
difference is that in this sketch we are now using the same technique to create the<br />
impression of friction along the x axis. Next we'll need to add the following<br />
statements to the draw() structure after the imageMode() function call:<br />
image(wheelBd, -75, 25);<br />
image(cart, 0, 0);<br />
image(wheelFd, -95, 35);<br />
difX = mouseX - (xPos + cart.width/2);<br />
xPos += difX/drag;<br />
Since we want the cart to move with relation to the mouse moving past the end of<br />
the cart on the right hand side, we're going to divide the cart.width object variable<br />
by 2 and add it to the position of the cart which is now determined by the center<br />
of the cart object because we have set imageMode() to CENTER.<br />
To temporarily link these statements to the rendering of the cart, directly after the<br />
previous statements add the following code:<br />
Transforms 171
An Introduction To Programming With <strong>Processing</strong><br />
pushMatrix();<br />
translate(xPos, 250);<br />
image(wheelBd, -75, 25);<br />
image(cart, 0, 0);<br />
image(wheelFd, -95, 35);<br />
popMatrix();<br />
Notice that we just added three additional statements. The first new statement is<br />
pushMatrix() this tells <strong>Processing</strong> to store the current transformational data of the<br />
coordinate system in memory, we then use the translate() function to to modify<br />
the coordinate system along the x axis by the value of the variable xPos and the<br />
numerical constant of 250 for the Y parameter. the Y parameter is a numerical<br />
constant simply because it will not change throughout the duration that the sketch<br />
is running. Next we render the images without any changes to their parameters as<br />
all of their positional data remains the same, the transform will create the<br />
impression of movement for us. Then finally we use the popMatrix() function to<br />
restore the transformational data relating to the coordinate system when<br />
pushMatrix() was initially called.<br />
When using pushMatrix() it must always be coupled with popMatrix() or<br />
<strong>Processing</strong> will complain about there being too many calls to pushMatrix() and<br />
not enough to popMatrix(). The term matrix simply refers to a grid of numbers,<br />
which is how <strong>Processing</strong> stores information about the coordinate system in<br />
memory. For example a matrix can be represented as:<br />
1 2 3 4 5<br />
6 7 8 9 10<br />
11 12 13 14 15<br />
16 17 18 19 20<br />
We would call this a 4 x 5 matrix meaning that it is made up of 4 rows and 5<br />
columns. This is not an actual representation of a matrix that <strong>Processing</strong> uses to<br />
calculate transforms but simply an example of what a matrix could look like, in<br />
fact the matrices that <strong>Processing</strong> uses are simpler than the previous matrix<br />
example.<br />
You might hear the term transformation matrix used on occasion, this is just<br />
simply referring to the numbers that make up the matrix that the matrix<br />
representing the current coordinate system must be processed through in order to<br />
produce the representation of the coordinate system in it's transformed state.<br />
Although this might sound like a bit of a tongue twister, the concept is less<br />
Transforms 172
An Introduction To Programming With <strong>Processing</strong><br />
complicated when you think of it in graphical form. Following is an example of<br />
what this might look like as a graphical representation, remember the numbers are<br />
purely illustrative, and not intended to represent actual numerical data and<br />
patterns that <strong>Processing</strong> calculates:<br />
pushMatrix()<br />
Matrix representing<br />
current coordinate<br />
system<br />
Transformation matrix<br />
stores data about<br />
translation, rotation<br />
and scaling<br />
=<br />
Resulting matrix<br />
representing new<br />
coordinate system<br />
popMatrix()<br />
Now that we have an idea of what the cart is going to look like when it's moving,<br />
lets concentrate on getting the wheels to rotate and translate.<br />
pushMatrix();<br />
translate(xPos -75 , 250 +25);<br />
rotate(xPos/wheelBd.width);<br />
image(wheelBd, 0, 0);<br />
popMatrix();<br />
image(cart, 0, 0);<br />
image(wheelFd, -95, 35);<br />
As you can see we have removed the image() function that renders the wheelBd<br />
object and placed it between a pushMatrix() and popMatrix() function pair.<br />
Between pushMatrix() and popMatrix() we are free to use translate() and rotate()<br />
to modify the coordinate system before rendering wheelBd with a call to the<br />
image() function. When we originally rendered the three images making up the<br />
cart, we had to offset the back wheel and front wheel so that they we in the<br />
correct places in relation to the position of the main cart. When performing<br />
transformations to an image it's best the have the image transform from the origin.<br />
As a result the X and Y parameters of the image() function used to render the<br />
image should remain at 0, and translations should be used when the image's X and<br />
Y coordinates need to change. This is often the simplest and most logical<br />
approach to working with transforms as it ensures that the image's relative<br />
distance to the origin is not modified which could lead to unexpected results.<br />
Transforms 173
An Introduction To Programming With <strong>Processing</strong><br />
Transforms are more predictable when the image() function's parameters are set to 0, 0<br />
for X and Y. Offsets in these parameters will often result in undesirable transformations.<br />
By setting the imageMode() function to CENTER and the X and Y parameters for<br />
the image() function to 0 and 0 we can be assured that the image of the wheel is<br />
going to be rendered with it's center at the origin. This is important because all<br />
transformations are relative to the origin, so that when we rotate the wheel it will<br />
appear to rotate from it's center, this is also due to setting imageMode() to<br />
CENTER and not leaving it at it's default of CORNER which would have resulted<br />
in the wheel appearing to rotate from it's top left hand corner. Bearing this in<br />
mind it is also important that the images that we use for the wheels are square in<br />
shape, in other words the image's width should match the same image's height.<br />
This creates the impression of the wheels being flat on the ground when they start<br />
to rotate. The following statement, is how we remove the image() functions offset<br />
and are still able to match the position of the cart with the mouse's X value:<br />
translate(xPos -75 , 250 +25);<br />
The xPos variable has not changed in terms of how it is applied in this sketch, the<br />
difference is that the X and Y parameter values that were used in the image()<br />
function to render the wheel have now been added to the translate() function's X<br />
and Y parameters. The rotate() function follows:<br />
rotate(xPos/wheelBd.width);<br />
As the xPos variable changes relative to the distance the cart has moved we can<br />
use the changing properties of this variable to make the wheels rotate. We can<br />
then divide this number by the width of the wheel image which is also the<br />
diameter of the circular shape of the wheel. This expression is based on the<br />
formula for pi which is pi = circumference/diameter, but it is worth noting that the<br />
Transforms 174
An Introduction To Programming With <strong>Processing</strong><br />
value returned from our modified expression is not equal to pi, as this would be a<br />
constant value as a result xPos is substituted for the circumference of the circle as<br />
this will yield a value that changes relative to the distance that the cart has<br />
traveled.<br />
We can then render the image at the origin after the coordinate system has been<br />
transformed, so the image appears to have moved because the coordinate system<br />
it is rendered relative to has, by then, been transformed.<br />
image(wheelBd, 0, 0);<br />
Finally use popMatrix() to reset the coordinate system back to it's original<br />
transformations.<br />
We can then continue to render the main cart and foreground wheel using the<br />
same techniques, and not have transformations from one rendering effect another.<br />
In the final cart.pde example I've added a shadow, try to figure out how you<br />
would go about creating this effect before looking at the code. Here's a hint, I've<br />
added four additional images to the sketch.<br />
The completed cart.pde sketch<br />
Transforms 175
An Introduction To Programming With <strong>Processing</strong><br />
An Introduction to 3D in <strong>Processing</strong><br />
Up until now we have been using <strong>Processing</strong> to create 2D sketches, that is<br />
sketches with 2 measurable dimensions such as width and height, however<br />
<strong>Processing</strong> allows us easy access to another dimension that being depth. As width<br />
is usually associated with the X axis and height is usually associated with the Y<br />
axis, depth is usually associated with the Z axis.<br />
Y<br />
X<br />
Z<br />
Axes indicating 3 Dimensions<br />
In <strong>Processing</strong> we have access to two 3D renderers, P3D and OpenGL. The P3D<br />
renderer is used mainly for 3D sketches on the web, the OpenGL renderer<br />
requires that the machine running the sketch must have OpenGL acceleration<br />
capabilities. Many modern 3D games and most 3D content creation software uses<br />
OpenGL, as it is not specific to <strong>Processing</strong> and a set of features that abstract the<br />
details of hardware acceleration for software developers. Using the P3D renderer<br />
in a <strong>Processing</strong> sketch is easy, as this renderer is simply invoked by adding an<br />
extra parameter to the size() function. For example:<br />
size(800, 600, P3D);<br />
This would cause <strong>Processing</strong> to use the P3D renderer. Using the OpenGL renderer<br />
is slightly different as this requires that the OpenGL library is first imported:<br />
An Introduction to 3D in <strong>Processing</strong> 176
An Introduction To Programming With <strong>Processing</strong><br />
import processing.opengl.*;<br />
All import statements in a sketch should precede all other statements. You can<br />
then use the OPENGL mode as a third parameter for the size() function.<br />
size(800, 600, OPENGL);<br />
A typical example of a sketch using OpenGL might look something like this:<br />
import processing.opengl.*;<br />
void setup(){<br />
size(500,500,OPENGL);<br />
}<br />
void draw(){<br />
background(127);<br />
…<br />
}<br />
3D Primitives<br />
In a similar way that <strong>Processing</strong> has 2D primitives such as rectangles, ellipses,<br />
lines etc you will also find a set of 3D primitives such as a box or a sphere.<br />
However you are free to use 2D primitives in a 3D sketch, but not 3D Primitives<br />
in a 2D sketch. One of the fundamental differences that separates the way in<br />
which the functions used to render 3D primitives differs from rendering 2D<br />
primitives, is that 3D primitives do not have parameters for X, Y and Z<br />
coordinates. For example the function to draw a box which is box() can accept<br />
three parameters but these parameters relate to width, height and depth.<br />
So how to we place 3D primitives in a sketch and move them around?<br />
This is achieved with the transform functions we have been using in our 2D<br />
sketches. The main difference is that now we have an additional axis to consider<br />
the Z axis, as a result in a 3D sketch translate() can be used with either 2 or 3<br />
parameters for example:<br />
An Introduction to 3D in <strong>Processing</strong> 177
An Introduction To Programming With <strong>Processing</strong><br />
translate(X, Y);<br />
//or<br />
translate(X, Y ,Z);<br />
Where X, Y and Z would be the numerical values relating to how the coordinate<br />
system is translated. The rotate() function can also be used in the following<br />
context:<br />
rotateX(num);<br />
//or<br />
rotateY(num);<br />
//or<br />
rotateZ(num);<br />
Where num is the numerical value in radians that the coordinate system will be<br />
rotated around the corresponding axis.<br />
Using the box() function and translations here's an example of how we could go<br />
about drawing a simple robot character using OpenGL:<br />
import processing.opengl.*;<br />
void setup(){<br />
size(500,500,OPENGL);<br />
}<br />
void draw(){<br />
background(127);<br />
pushMatrix();<br />
translate(width/2, (height/2)-100);<br />
box(40);<br />
translate(0,80);<br />
scale(0.8,1);<br />
box(80);<br />
translate(70,0);<br />
scale(1,2);<br />
box(30);<br />
translate(-140,0);<br />
box(30);<br />
translate(50,50);<br />
scale(1,1.5);<br />
An Introduction to 3D in <strong>Processing</strong> 178
An Introduction To Programming With <strong>Processing</strong><br />
}<br />
box(30);<br />
translate(40,0);<br />
box(30);<br />
popMatrix();<br />
A simple robot character rendered in <strong>Processing</strong> using OpenGL<br />
Creating 3D sketches can be fun, but can also become exceedingly difficult for<br />
the beginner as you will often find that a firm grasp of trigonometry is necessary<br />
and depending on what you are wanting to achieve an understanding of vector<br />
math and matrices might also be a prerequisite. However if you are interested in<br />
learning more about creating 3D sketches the best place to start is to work your<br />
way up from creating 2D sketches, that make use of the transformation matrix and<br />
basic trigonometric functions, then try adapt these ideas to include three<br />
dimensions.<br />
Guess My Number Game<br />
Using the information you've learned, thus far you should be able to follow the<br />
code within the guess my number game. Have some fun by modifying the code<br />
and try to make your own!<br />
Guess My Number Game 179
An Introduction To Programming With <strong>Processing</strong><br />
One of the many possible implementations of The Guess My Number Game<br />
Guess My Number Game 180
An Introduction To Programming With <strong>Processing</strong><br />
Object Oriented Programming<br />
Object Oriented Programming is a modern day programming paradigm, meaning<br />
that it is a fundamental style that suits the task of creating modern software. Most<br />
popular modern programming languages support OOP (Object Oriented<br />
Programming), and as a result understanding the fundamental concepts that define<br />
it within <strong>Processing</strong> can help in implementing it, by means of adapting your<br />
knowledge to suite any programming language that supports Object Oriented<br />
Programming.<br />
Earlier we discussed that OOP can be contrasted with Procedural Programming if<br />
you consider that Procedural Programming is a style of programming where the<br />
program is tailored to suite the data as opposed to Object Oriented Programming<br />
which is more akin to a style of programming where the data is tailored to suite<br />
the program. To briefly recap on these concepts, typically when creating<br />
programs using the procedural programming paradigm we use the programming<br />
language's built-in API features and associate the data we are representing in our<br />
program with the features that are defined by the developers of the language. The<br />
data that is associated with the API features is what we then use in our main<br />
program. This is in contrast to the object oriented programming paradigm where<br />
we define new types of data (called classes) to categorize and associate the data<br />
we are representing in our programs with the programming languages built-in API<br />
features. We then use instantiations of the classes called software objects in our<br />
main program.<br />
From this description you can see that the results of both programming paradigms<br />
can eventually lead to the same thing, however the process of getting to that result<br />
is what distinguishes one programming paradigm from that of another.<br />
Object Oriented Programming 181
An Introduction To Programming With <strong>Processing</strong><br />
The Procedural Programming<br />
Paradigm<br />
Data to represent<br />
The Object Oriented<br />
Programming Paradigm<br />
Data to represent<br />
API features<br />
API features<br />
Class organizes data<br />
Data represented with<br />
API features<br />
Objects representing<br />
Class<br />
Main Program<br />
Main Program<br />
An graphical representation of how OOP works<br />
OOP as you are aware relies on classes, from which we instantiate objects. These<br />
objects are the reason why we refer to this programming paradigm as Object<br />
Oriented Programming, and emphasize the “Object” part. We have already been<br />
using classes that are a part of <strong>Processing</strong>'s API such as PImage from which we<br />
have instantiated object variables which we have given names, and those objects<br />
have inherited various properties and functions (called methods in OOP) from the<br />
classes from which they where instantiated. But what exactly is a class?<br />
The concept of a class<br />
A class is simply a body of code that, in a similar way to a function, exists<br />
independently of the main body of code from which it is referenced. However, a<br />
class does not only have a singular purpose like a function that checks the<br />
position of the mouse, or moves and image around in a specific way or has some<br />
other purpose that can be summarized by a singularly specific directive. A class<br />
can consist of many functions, which in the context of OOP we refer to as<br />
methods. These methods can be used like functions of your main program but<br />
with the inherited properties of the class from which it came. As a result you can<br />
think of a method as being a function of a class, that when used in your main<br />
Object Oriented Programming 182
An Introduction To Programming With <strong>Processing</strong><br />
program will, like a function, have a definition independent of the main program<br />
and also have properties that are specific to the class it was instantiated from. The<br />
benefit of this is that when multiple objects are instantiated from a single class<br />
they all inherit the methods of that class, this allows you to use certain methods<br />
with one object and certain other methods with another object. Thereby creating<br />
relationships between those objects (and ultimately the data you are representing<br />
with you main program) with other data or API features in ways that would be<br />
very difficult or maybe not practically possible without OOP.<br />
Branch 01<br />
Method 1<br />
Branch 02<br />
Class<br />
Method 1<br />
Method 2<br />
Method 3<br />
Object 1<br />
Object 2<br />
Method 3<br />
MAIN PROGRAM<br />
Method 2<br />
Function Call<br />
Function<br />
Definition<br />
Method 2<br />
Branch 04<br />
Branch 03<br />
One class can result in many different branches.<br />
The Blueprint Analogy<br />
By creating classes we categorize the data we are representing and give these<br />
representations a context by associating them with features in the programming<br />
languages API. However a class is never used in the main program, it must first<br />
Object Oriented Programming 183
An Introduction To Programming With <strong>Processing</strong><br />
be instantiated as an object and the object is what we would use in our main<br />
program. In this sense a class is more like a blueprint, that describes the complex<br />
relationships between the data we are representing, like the blueprint of a house<br />
can describe how tall a wall will be or how far a window will be from the ceiling.<br />
If you can imagine a class to be like a blueprint then a software object is like a<br />
house made from that blueprint. For example, a class only describes the possible<br />
objects that can be instantiated from it, taking the blueprint analogy further we<br />
cannot live in a blueprint yet it has all the information we need to build a house<br />
which would be something that we use as a functional object. In other words we<br />
use the blueprint to build a house, this is just like instantiating an object from a<br />
class. The class only describes the possibilities of an object that can be<br />
instantiated from it and when we finally do instantiate an object from the class, it<br />
is the object that we use in our main program.<br />
Just like a blueprint describes a structure it does not say anything about how the<br />
structure can be used for example a blueprint can be used to build somebody's<br />
home or the same blueprint can be used to build an office. The purposes the<br />
buildings serve are different, but the structure of the buildings remains the same.<br />
The relationship between classes and software objects is very similar, in that one<br />
object instantiated from class can serve a certain purpose and another object<br />
instantiated from the same class can serve a different purpose, but because both<br />
objects are instantiated from the same class the context in which they are used<br />
will tend to have similarities.<br />
A single blueprint could be used to make several derivatives<br />
Object Oriented Programming 184
An Introduction To Programming With <strong>Processing</strong><br />
Why use Object Oriented Programming<br />
One of the fundamental concepts that makes OOP so popular is known as data<br />
encapsulation. We have already discussed how a variable can have a greater or<br />
lesser scope depending on where it is declared, that is to say that when a variable<br />
is not declared within the global variable scope it can only be accessed in some<br />
parts of a program and not in others that are outside of the structure in which it<br />
was declared. The range over which the variable is accessible refers to the<br />
variable's scope. Data encapsulation is a similar concept, except that the concept<br />
of “hiding” data is emphasized as opposed to defining a variable in the global<br />
variable scope where the concept of “exposing” data is emphasized. Another<br />
major difference between the two concepts is that with data encapsulation as<br />
opposed to variable scope we are not referring to a single variable but can, in fact,<br />
be referring to entire structures. These structures that we make inaccessible to the<br />
main program are what form the body of code that defines a class. By defining a<br />
class we use a modular approach to designing software, in the sense that the class<br />
that we have defined is not necessarily specific to the program we initially wrote<br />
it for, and as a result an be used in our program or removed from our program<br />
without us having to rewrite the entire program this is an inherent design<br />
characteristic of data encapsulation.<br />
Amongst other applications, creating a class defines the behaviors that an object<br />
instantiated from it will inherit. In order to interact with an object in a program,<br />
and subsequently use that which it has inherited from a class, we interact with the<br />
object via it's behaviors which are more commonly referred to as methods. This is<br />
a form of data encapsulation, in that we do not have direct access to how that<br />
object works as that is defined within the class. However we can still have the<br />
object interact with our main program through it's methods. In this sense Object<br />
Oriented Programming can provide a level of abstraction, when working with<br />
objects in the main program.<br />
Creating a Class<br />
As previously mentioned a class typically consists of method definitions and<br />
various fields (which we also refer to as member variables) that store information<br />
about the current state of the object instantiated from the class. The term fields<br />
Object Oriented Programming 185
An Introduction To Programming With <strong>Processing</strong><br />
refers to variables that are members of a particular class, and as a result are<br />
encapsulated data that store information about the object itself and are sometimes<br />
referred to in <strong>Processing</strong> as class data.<br />
Typically in <strong>Processing</strong> creating a class is a four step process that involves,<br />
1)Class Name creation<br />
2)Field declarations<br />
3)Constructor creation<br />
4)Method definitions<br />
The structure of a class looks similar to setup() and draw() and user defined<br />
functions, but since a class is not a function, but may contain many functions<br />
(called methods) it's name is not followed by parenthesis. An object variable<br />
name which we will have a look at shortly, on the other hand is followed by<br />
parenthesis in order to provide a means of communicating with the object's<br />
internal structure.<br />
void setup(){<br />
}<br />
void draw(){<br />
}<br />
class ClassName{<br />
}<br />
As you can see a class definition usually finds it place at the very end of a sketch,<br />
this is sometimes referred to as an in-line class definition. This simply emphasizes<br />
that the class is directly related to the sketch that it is defined within. As defining<br />
a class at the end of a sketch, after user defined functions, mouse and keyboard<br />
functions etc can create a cluttered looking sketch <strong>Processing</strong> also provides us<br />
with Tabs in which we can place additional code that will be compiled with the<br />
sketch we are currently working on. You can create a new tab by clicking the<br />
arrow pointing to the right on the far right of the PDE and a fly-off menu relating<br />
to Tabs will appear.<br />
Object Oriented Programming 186
An Introduction To Programming With <strong>Processing</strong><br />
The Tab fly-off from the PDE<br />
<strong>Processing</strong> will then ask you to provide a name for the new tab.<br />
Creating a new Tab<br />
Once you supply a unique name and click OK <strong>Processing</strong> will create a new blank<br />
Tab next to the original Tab. What has actually happened is that <strong>Processing</strong> has<br />
created a new .pde file that has the name you specified for the Tab that was just<br />
created. This new .pde file resides in the same location as the sketch you are<br />
currently working on, as a result it can access anything in the data folder that you<br />
can access from the code of the original Tab. Although <strong>Processing</strong> has created<br />
another .pde file this file is only part of a sketch. In a similar way that the original<br />
pde file can be reliant on the contents of the data folder, the new .pde file in the<br />
same location as the original pde file can also be reliant on the original .pde and<br />
the contents of the data folder. As a result we refer to this collection of elements<br />
(i.e. pde files, txt files, spreadsheets, images and anything else that is in the data<br />
folder used in the sketch) collectively as the contents of a sketch.<br />
Using additional Tabs in a sketch provides us with a convenient location for<br />
placing classes. This is useful because it emphasizes the modular design of classes<br />
and clears the main pde file from becoming over-cluttered with code. Working<br />
with additional tabs is not synonymous to working with multiple sketches.<br />
Multiple tabs are a means of breaking up the current sketch you are working on<br />
Object Oriented Programming 187
An Introduction To Programming With <strong>Processing</strong><br />
into smaller manageable portions of code. As a result when a sketch with multiple<br />
Tabs is run all the code within all the Tabs of that sketch are compiled together.<br />
This means that only one of the Tabs should have setup() and draw() structures,<br />
the other Tabs should be used for class definitions, user defined functions or other<br />
elements of a sketch that exist outside of setup() and draw() structures.<br />
A Button Class<br />
If we wanted to create a class for a button, that we will call Button. This class will<br />
also have<br />
• fields that will contain certain information about the object instantiated<br />
from the class such as the color of the button, it's size and position.<br />
• The class will also have a constructor that will use the class's fields to<br />
create an initial state for the object.<br />
• Finally the class will have 2 methods, one that renders (or displays) the<br />
button and another that tests whether the user's mouse is over the button.<br />
The completed buttonClassExample file<br />
In order to give the class a name and let <strong>Processing</strong> know that we are about to<br />
create a class we must use the class keyword. The name of a class generally starts<br />
with an upper-case character. For example. We'll start by adding a new tab and<br />
calling it Button. In this tab add the following code:<br />
class Button{<br />
}<br />
This is how we create a class and name it in <strong>Processing</strong>. As you can see the class's<br />
A Button Class 188
An Introduction To Programming With <strong>Processing</strong><br />
name is Button which starts with an upper-case character, in-line with popular<br />
standardized coding practices.<br />
When we instantiate an object from this class there are several properties we'd<br />
like this object to inherit from the class, which we will have access to modifying<br />
from the main program but not be able to modify the definitions of these<br />
properties as this will be encapsulated within the Button class. A list of the these<br />
properties follow:<br />
1. the color of the rectangle that will visually represent the button object,<br />
2. the object's X coordinate<br />
3. the object's Y coordinate<br />
4. the object's width<br />
5. the object's height<br />
6. and a name for the object.<br />
As a result we will need at least all six of these properties represented in the<br />
class's fields as variables.<br />
Let's add those fields to the class, inside the braces of the Button class add the<br />
following declarations:<br />
color cB;<br />
float xLocB;<br />
float yLocB;<br />
float xSizeB;<br />
float ySizeB;<br />
String nameB;<br />
As you can see each of these variables will hold the information related to the<br />
previous list of six items. To give you an idea of how these fields (or variables)<br />
will be used we need to fast forward a few steps into the future and take a quick<br />
look at what happens when we instantiate the class. The process of creating an<br />
object is actually nothing new to you, as you have already instantiated objects<br />
from the PImage class. One of the main differences with our Button class is that<br />
we will be using it's constructor to initialize objects instantiated from it, so when<br />
we get to doing this we will use an initialization statement that will in part look<br />
like this:<br />
//this is simply for illustrative purposes<br />
Button(cB, xLocB, yLocB, xSizeB, ySizeB, nameB);<br />
A Button Class 189
An Introduction To Programming With <strong>Processing</strong><br />
From this partially complete code fragment, Button accepts the parameters the<br />
user has input, which will be assigned to the object's fields (which were inherited<br />
from the class's fields). These parameters will be used to initialize the the object<br />
instantiated from the Button class. However at the moment, these variables don't<br />
really do much, or store any information that will help in constructing the button<br />
object. This is why we need a constructor. The constructor is like a method that is<br />
automatically called every time a new object is instantiated from a particular<br />
class. The main purpose of a constructor is to determine a default state that an<br />
object will exist in as soon as it is instantiated. The constructor is defined below<br />
the fields declaration of a class and our constructor will look like this:<br />
Button(color tempcB, float tempxLocB, float tempyLocB, float<br />
tempxSizeB, float tempySizeB,String tempNameB){<br />
cB = tempcB;<br />
xLocB = tempxLocB;<br />
yLocB = tempyLocB;<br />
xSizeB = tempxSizeB;<br />
ySizeB = tempySizeB;<br />
nameB = tempNameB;<br />
}<br />
Note that the constructor has the same name as the class, this is a requirement for<br />
using a constructor. When we refer to Button() we are actually referring to the<br />
constructor of the class and not the class itself, which we simply refer to as<br />
Button.<br />
The first line of the constructor tells <strong>Processing</strong> how the Button class will accept<br />
parameters when a new object is instantiated from it. You might have also noticed<br />
that we have declared six new variables that will temporarily store the values that<br />
the user inputs as parameters when an object is instantiated. These values will<br />
then be assigned to the original member variables which will store the values that<br />
the user has input as parameters when instantiating the button. Using this<br />
approach to designing a constructor ensures that multiple objects can be<br />
instantiated using different parameters with the same constructor.<br />
At this stage in the design of the Button class we have fields declaring the<br />
member variables that will be used to store information about the button, and how<br />
we would like to use those fields to construct the button, but we have not told<br />
processing to actually draw the button to the Display Window so that the user can<br />
see a visual representation of the object and interact with it. This is amongst one<br />
A Button Class 190
An Introduction To Programming With <strong>Processing</strong><br />
of the many reasons why class's have methods. In order to render this visual<br />
representation we're going to create a method called disp() which will create a<br />
rectangle from the parameters the user inputs into the Button() constructor when<br />
instantiating a new object. Just like user defined functions methods must use the<br />
void keyword if they do not return a datatype. Here's what our disp() method<br />
(short for display method) will look like:<br />
void disp(){<br />
fill(cB);<br />
rect(xLocB, yLocB,xSizeB, ySizeB);<br />
fill(0);<br />
text(nameB, (xSizeB/2)+xLocB-((xSizeB/2)/2),<br />
(ySizeB/2)+yLocB+((ySizeB/2)/2));<br />
}<br />
Creating a method follows the same routine as creating a user defined function.<br />
Our disp() method is really quite simple all it does is accept the cB variable as a<br />
fill() color, draw a rectangle with the positional data from xLocB and yLocB and<br />
finish the rectangle by determining it's size from the xSizeB and ySizeB<br />
variables. The method then goes on to set the fill() to black and render the name<br />
of the button (nameB) in the center of the button.<br />
A class can be as simple or a complex as you want, and since we have all the<br />
“main ingredients” of our class we're going to return to our main program and<br />
have a look at how to instantiate an object from this class.<br />
Object Instantiation<br />
Object instantiation is not a new concept to you as you have already instantiated<br />
objects from the PImage class. The process of instantiating an object from our<br />
Button class will follow a very similar pattern.<br />
Since we want this object to be accessible from both setup(), draw() and user<br />
defined functions we are going to declare an object variable in the global variable<br />
scope by adding the following declaration outside of both setup() and draw():<br />
Button myButton;<br />
A Button Class 191
An Introduction To Programming With <strong>Processing</strong><br />
We now have a variable name that we can use to reference the object we just<br />
instantiated from the Button class, this name is myButton.<br />
Within the setup() structure we'll initialize the button:<br />
myButton = new Button(color(255), width/2, height/2, 100, 40,<br />
"myButton");<br />
myButton (the object variable) has inherited the properties of the Button class. If<br />
you were to compare this statement with the modified example of the class's<br />
constructor:<br />
//this is simply for illustrative purposes<br />
Button(cB, xLocB, yLocB, xSizeB, ySizeB, nameB);<br />
You will notice that this button is currently being constructed, but remember that<br />
you will not actually see the button at this stage as all we have done is told<br />
<strong>Processing</strong> how we would like the button to be constructed we have not told<br />
<strong>Processing</strong> to actually display the button. The use of the new keyword in the<br />
previous listed assignment statement is followed by the class's constructor which<br />
is why we are using Button() and not Button.<br />
Now that we have told <strong>Processing</strong> how we would like this new button constructed<br />
let's move onto the draw() structure and actually render the button.<br />
Using an object's method is easy, and is very similar to a function call. The main<br />
difference is that the name of the method is preceded by the name of the object<br />
itself. For example:<br />
myButton.disp();<br />
Add this statement to the draw() structure, and you'll finally see your button.<br />
The button instantiated and displayed by it's disp() method<br />
A Button Class 192
An Introduction To Programming With <strong>Processing</strong><br />
As you can see when working with OOP the main program looks less cluttered<br />
with code and the majority of the code exists in creating classes. This for many<br />
people creates a more readable interface for designing software, and once you get<br />
the hang of using OOP it can also help to localize problematic code that might be<br />
difficult to locate without a program adopting a modular design.<br />
The completed sketch ButonClassExample.pde also contains another method<br />
called over() which will identify if the users mouse is over the button, if you take<br />
some time to examine the sketch you should be able to add your own<br />
functionality to the button.<br />
Working with external data<br />
There are many ways of getting data into a <strong>Processing</strong> sketch from importing a<br />
simple image, 3D geometry or importing spread sheet data and the list goes on.<br />
But amongst the simplest and most versatile methods of getting external data into<br />
<strong>Processing</strong> is by means of a text file.<br />
A simple text file<br />
A text file imported into a sketch should have the file extension .txt. A word<br />
processor document might have additional formatting and as a result might<br />
produce unexpected results when used in a sketch. For this exercise it is<br />
recommended that you use the file called names.txt.<br />
Importing a text document into a sketch works in the same way that that images<br />
are imported into a sketch. Locate the file to be imported and click and drag it into<br />
Working with external data 193
An Introduction To Programming With <strong>Processing</strong><br />
the PDE with the sketch you are working on, open. The PDE will report that a file<br />
has been added successfully to the sketch and if you were to open the sketch's<br />
data folder you will find a copy of the file in there. In order to display the contents<br />
of the names.txt file in the Display Window we will use an array of Strings with<br />
each element of the String representing a line of characters in the names.txt file.<br />
Lets have a look at how to do this.<br />
In the global variable scope declare a new array of Strings and call it names:<br />
String[] names;<br />
Notice that declaring an array like this does not indicate to <strong>Processing</strong> how many<br />
elements will be in the array. This is because we want <strong>Processing</strong> to tell us how<br />
many elements are going to make up this array. In other words if we had a text<br />
document with many lines each of which was intended to be an element in an<br />
array, instead of counting the lines in the text document and creating the array like<br />
so:<br />
String[] names = new String[10560];<br />
We would use the former method where the number of elements is decided by<br />
<strong>Processing</strong> and if we wanted to know how many elements <strong>Processing</strong> has<br />
populated the array with, we would use the String object's variable length to find<br />
out. We'll have a look at how to do this a bit later.<br />
In setup() we're going to populate the array with the loadStrings() function, which<br />
will accept one parameter that is the name of the text file containing the data that<br />
will be used to populate the array.<br />
names = loadStrings("names.txt");<br />
We now have an array of Strings that we can refer to by it's variable name called<br />
names. This array has several elements each consisting of a String representing<br />
each individual line of the names.txt file.<br />
Finally to display the information contained within the elements of the names<br />
array we will use the text() function within a for loop:<br />
Working with external data 194
An Introduction To Programming With <strong>Processing</strong><br />
void draw() {<br />
for(int i = 0; i < names.length; i++){<br />
text(names[i], 20, i*20 + 20);<br />
}<br />
}<br />
The String object's variable, names.length stores the amount of elements in the<br />
names array, this information is important for creating the test of a for loop<br />
iteration. The text() function uses each element in the names array as a data input<br />
parameter, subsequently rendering each line of the text file one after the other and<br />
offset on the Y axis.<br />
The loadStringsExample.pde file<br />
Using this technique of loading external data does not have to be confined to<br />
working with the Strings datatype. Typecasting provides a convenient approach to<br />
converting String data into numerical data that can be calculated. Here's an<br />
example of the loadStringsExample.pde file that does just that with a file<br />
containing numbers. It is worth noting that although when you open the<br />
numbers.txt file it reveals a list of numbers to you, when this information is read<br />
into our sketch <strong>Processing</strong> identifies this data as String data. Which is why we<br />
must first typecast each element of the numbers array with the int() function into<br />
an int datatype before we can perform addition on the data.<br />
String[] names;<br />
String[] numbers;<br />
int tCast;<br />
Working with external data 195
An Introduction To Programming With <strong>Processing</strong><br />
void setup() {<br />
size(300,300);<br />
smooth();<br />
names = loadStrings("names.txt");<br />
numbers = loadStrings("numbers.txt");<br />
}<br />
void draw() {<br />
background(100);<br />
for(int i = 0; i < names.length; i++){<br />
text(names[i],20,i*20 + 20);<br />
}<br />
for(int i = 0; i < numbers.length; i++){<br />
tCast += int(numbers[i]); //typecasting int(numbers[i])<br />
}<br />
text(tCast,250,20);<br />
}<br />
Working with external data 196
An Introduction To Programming With <strong>Processing</strong><br />
Attribution<br />
Images<br />
Apollo Guidance Computer 10<br />
Copyright NASA<br />
NASA Manned Spacecraft Center 10<br />
Copyright NASA<br />
Japanese Rickshaws 11<br />
Public Domain<br />
Medical Equipment 14<br />
Copyright the owner of the image<br />
Gambling Machines 15<br />
Yamaguchi 先 生 /Wikipedia<br />
Alan Turing 16<br />
Copyright the owner of the image<br />
LOLCAT image 17<br />
M-J<br />
<strong>Processing</strong>.org image 41<br />
Copyright the owner of the image<br />
Star Wars ARC-170 Starfighter<br />
Guess My Number Game<br />
Cody Borst (Sqorck)<br />
Coat of Arms Icons Social Commentary Viz<br />
Copyright the owner/s of the images<br />
Attribution 197