<<

An Introduction To Programming With Processing

This publication is released under a Creative Commons Attribution- NonCommercial-NoDerivs 3.0 License. CC BY-NC-ND 2011

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

For additional information regrading this license please see http://creativecommons.org/licenses/by-nc-sa/3.0/legalcode

2 An Introduction To Programming With Processing

Table Of Contents

About This Guide 7 Hardware and Software Theory 7 What is Programming? 7 How does Programming relate to Hardware and Software? 8 Abstraction 10 Speed 11 Efficiency 12 Disambiguation 14 The Unique Qualities of a 17 Lower Level Languages and Higher Level Languages 20 An Analysis of a Computer Program 22 Commands 23 Expressions 23 A Scalable Software Development Model 25 Plan 25 Research 26 Mockup Designs 27 Data Acquisition: Sourcing The Data Needed For Your Project 28 Filter 29 Clustering and Data Mining 29 Parsing 32 Determining Flow of Control Through Stepwise Refinement 32 Implement, and Document. Repeat 34 Deliver 35 Why Learn Programming using Processing? 36 Code For Artists 36 Java Based 36 Open Source 37 PDE 38 Source Code Editor 40 Build Automation Tools 40 Compiler and/or Interpreter 41 Debugger 42 Active Online Community 43

Table Of Contents 3 An Introduction To Programming With Processing

Hello Processing 44 Install Processing 44 Sketches 44 Hello World Program 1.0 45 The println() Function 47 Syntax And Syntax Errors 48 Logical Errors 50 Display Window 50 Standardized Coding Practices 52 Comments 52 Whitespace 53 Program Notes 54 Cartesian Graph and the Processing Coordinate System 54 Hello Display Window: Hello World 1.1 56 text() 56 Program Notes 57 Formatting Text 58 Color 59 Drawing 62 2D Primitives 62 The Origin of an Ellipse 63 Aliasing 66 Smile 66 Angles in Processing 66 Editing the Smile 69 Adding Eyes 72 Drawing Irregular Shapes 73 Order, Order! 78 Finishing the Sketch 78 Programming Paradigms 80 Datatyping Categories 81 Primitive Data Types 81 Processing API Data Types 82 User Defined Complex Data Types 83 PImage 83 The Design and Layout Program 86 Program Notes for Interface01.pde 86

Table Of Contents 4 An Introduction To Programming With Processing

The PDE Tools Menu 86 Beyond Static Sketches and on to Active Mode 90 Methods, Functions and their contexts 91 The setup() function 92 The draw() function 94 Experimentation 96 Datatyping 101 Variables 102 Variable Scope 104 Interacting with Images 106 Friction Simulation 109 Variable Naming Conventions 111 Planning and Pre-debugging 112 Implementing a Programmatic Solution 114 Constraining Values 116 Branching 118 The if() structure 120 Relational Operators 121 Comparison 121 Extending the if() structure with else 124 Extending the if() construct with if else if else 126 Logical Operators 127 Interface Controls Setting up a Slider 128 User Defined Functions 130 Creating a User Defined Function 134 Datatyping a Function 134 Determining a Range 134 Returning Data from a Function 138 Dragging the Slider Button 140 Setting up Regional Constraints 142 Finishing the Slider 144 Mapping Values 144 The Mystery Shape Maker 148 Arrays 149 Program Notes 153 Dynamic Assignment for Elements in and Array 155 Iterations 158

Table Of Contents 5 An Introduction To Programming With Processing

Transforms 162 An Introduction to 3D in Processing 176 3D Primitives 177 Guess My Number Game 179 Object Oriented Programming 181 The Concept of a Class 182 The Blueprint Analogy 183 Why Use Object Oriented Programming 185 Creating a Class 185 A Button Class 188 Object Instantiation Working with External Data 193 Attribution 197 Images 197

Table Of Contents 6 An Introduction To Programming With Processing

About this Guide

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

Hardware and Software Theory

What is programming?

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

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

Hardware and Software Theory 7 An Introduction To Programming With Processing

How does programming relate to hardware and software?

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

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

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

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

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

Hardware and Software Theory 8 An Introduction To Programming With Processing

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

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

We interface with computers via software which allows us to work in an individual capacity, whenever applicable, in fields that would previously have required teams of people working together.

Hardware and Software Theory 9 An Introduction To Programming With Processing

Abstraction

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

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

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

“Computer, could you please draw a circle that has a diameter of 55 pixels and 's center is somewhere close to the top left of my screen, thanks?”

Instead we communicate with our computers like this: ellipse(56, 46, 55, 55);

Abstraction 10 An Introduction To Programming With Processing

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

Speed

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

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

Abstraction 11 An Introduction To Programming With Processing

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

Efficiency

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

“A human-powered two wheeled cart, that seats one or two people reserved for the social elite.”

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

Abstraction 12 An Introduction To Programming With Processing

“Rickshaw”

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

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

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

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

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

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

Disambiguation

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

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

Abstraction 14 An Introduction To Programming With Processing center is somewhere close to the top left of my screen...” would not be as effective as the statement: ellipse(56, 46, 55, 55);

The first statement although a perfectly acceptable command issued in English, would fail dismally when translated directly into computer-speak for several reasons relating to the ambiguity associated with it.

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

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

Finally I'm sure that if computers had a sense of humour, they would find our former description of the location of our circle “ somewhere close to the top

Abstraction 15 An Introduction To Programming With Processing left of my screen” to be somewhat uninformed and laughable, not to mention words such as “somewhere” and “my” which might condition a response equivalent to that of an existential dilemma for a computer. If you supply a computer program with specific screen positions in terms of x, y and z and dimensions in terms of width, height and depth either communicated explicitly or implicitly through an expression (which is something we will discuss in more detail later) you will find your programs to have more predictable and efficient results and would help to remove ambiguities that could lead to errors. Screen space and dimensions are concepts we will be dealing with in more detail in later chapters. Of course there are times when randomness and unpredictability are desirable qualities in a program, in which case no other resources available to man can produce a series of unpredictable results more efficiently than computers. This is a testament to why people devotedly invest in computers to provide the sequence of random digits that could potentially make casinos loose millions upon millions to gambling patrons.

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

Abstraction 16 An Introduction To Programming With Processing

The Unique Qualities of a Programming Language

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

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

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

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

The Unique Qualities of a Programming Language 17 An Introduction To Programming With Processing

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

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

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

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

The Unique Qualities of a Programming Language 18 An Introduction To Programming With Processing

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

LOLCODE is another example of an esoteric programing language that is based on the text within images. Lolcats are images of cats that circulate the Internet, often in cute and whimsical representations. These images are accompanied with text that is generally idiosyncratic and grammatically incorrect with the intent to contribute humour to the image.

An example of a typical image

An example of a Hello World program in LOLCODE follows:

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

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

The Unique Qualities of a Programming Language 19 An Introduction To Programming With Processing

Lower Level Languages and Higher Level Languages

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

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

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

Lower Level Languages and Higher Level Languages 20 An Introduction To Programming With Processing

Following is the C version of a “Hello World” Program:

#include int main(void) { ("hello, world\n"); return 0; }

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

Lower Level Languages and Higher Level Languages 21 An Introduction To Programming With Processing

An Analysis of a Computer Program

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

Statements can also be made up of many other parts not mentioned here, but for now we are most interested in two of these components making up a statement, commands and expressions, the rest we will get to later.

An Analysis of a Computer Program 22 An Introduction To Programming With Processing

Commands

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

“Run, as fast as you can!”

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

Expressions

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

An Analysis of a Computer Program 23 An Introduction To Programming With Processing println(5+3);

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

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

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

An Analysis of a Computer Program 24 An Introduction To Programming With Processing

A Scalable Software Development Model

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

1. Plan

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

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

A Scalable Software Development Model 25 An Introduction To Programming With Processing questions that need to be answered before the implementation of the project can begin. These questions that you derive from planning your project will form the basis for the research that follows planning.

Examples of an abstraction, followed by a deconstruction and finally a technical overview of a project plan.

2. Research

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

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

A Scalable Software Development Model 26 An Introduction To Programming With Processing adapting and modifying already existing code to suit the needs of their projects. Finally researching your project can also reveal useful sources for data acquisition, which will be particularly helpful in the fourth phase of your development model.

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

3. Mockup Designs

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

A Scalable Software Development Model 27 An Introduction To Programming With Processing solve how programmatic implementations of visualizing data might be addressed through various programming methodologies.

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

4. Data Acquisition: Sourcing the data needed for your project.

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

A Scalable Software Development Model 28 An Introduction To Programming With Processing seventh phase of the software development model.

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

5. Filter

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

6. Clustering and Data Mining

Data mining is the process of identifying patterns within the data you have acquired. The purpose of doing this is to place the relationships that exist between the various aspects of your data in a more mathematical context that can ultimately be used programmatically (in the program you are developing). Data mining can be done manually or it could be automated. When dealing with a

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

A Scalable Software Development Model 30 An Introduction To Programming With Processing

Raw Data

Manual Clustering

Digital Results

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

A Scalable Software Development Model 31 An Introduction To Programming With Processing

7. Parsing

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

8. Determining Flow of Control through Stepwise Refinement

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

A Scalable Software Development Model 32 An Introduction To Programming With Processing

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

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

Your list at this stage should start to read more like a program rather than a paragraph written in a natural language. This resemblance is no coincidence and forms the basis for the process programmers use for developing what is known as pseudo code. Pseudo Code is somewhere between a programming language and a natural language and forms the basis for stepwise refinement. During stepwise refinement rewrite your list so that it resembles something closer to the code of your program each time the pseudo code is refined. A Pseudo code example for a guess my number game might look something like this: choose a random number between 1 and 100 set the number of user guesses to 1 get the user's guess while the user's guess is not equal to the random number and less than 5 guesses if the guess is too high tell user “guess too high” increment user guesses else if the guess is too low tell the user “guess too low” increment user guesses if the number of guesses is 5 or greater user has lost else if the guess is equal to the random number user has won

A Scalable Software Development Model 33 An Introduction To Programming With Processing

9. Implement, Test and Document. Repeat.

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

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

A Scalable Software Development Model 34 An Introduction To Programming With Processing

10. Deliver

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

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

A Scalable Software Development Model 35 An Introduction To Programming With Processing

Why Learn Programming using Processing?

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

Code for Artists

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

Java Based

Processing was originally developed as an extension to the Programming language, Java and it's roots in Java are still evident today even though Processing is a language on it's own. Processing's relationship with Java has many benefits, the two languages share a similar syntax except that Processing can make visual representations of your code easier to create than Java can (which is more generic in it's scope of application). Java shares a lot of similarities with the programming

Why Learn Programming using Processing? 36 An Introduction To Programming With Processing language C (from which it was originally developed) and Java is also one of the most popular languages currently in use. If you are familiar with Java or C++ (which is closely based on C) learning Processing should come quite naturally to you.

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

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

Open Source

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

Why Learn Programming using Processing? 37 An Introduction To Programming With Processing of their products. Anybody can use Processing and the PDE, modify it, redistribute it and the GNU General Public License ensures that the Processing PDE will always remain free. So because Processing is free what about the content you create with Processing does that also have to be “free” and open source? The answer to this question is and will remain to be, no. The content you create with Processing belongs to you, the creator, and you are free to do with it whatever you please. If you wish to sell the software or code that you produce with Processing it is your right to do so. If, however, you do not wish to sell your work and subsequently do not choose to copyright your work there are various options available to you to protect you and your work. Amongst these licences is the GNU General Public Licence which protects the rights of developers of computer programs that wish to ensure that the software they develop remains free, including all derivatives that are made from the original software program. Another such licence is the Creative Commons Licence, this licence allows creators of media to reserve some rights of their work (if they choose to) and still legally allows the copying, redistribution and modification of such media if the author chooses to exercise these rights. Wikipedia is an example of a large scale organization that licenses it's contents under a Creative Commons Licence and is an example of popular software that is licensed under the GNU General Public Licence.

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

PDE

An IDE is an acronym for Integrated Development Environment, it refers to a software application that is used to develop code for a computer programming

Why Learn Programming using Processing? 38 An Introduction To Programming With Processing language. Processing has it's own IDE called the PDE or Processing Development Environment.

The PDE is a popular tool for developing Processing Sketches but the popular IDE Ellipse is also quite readily used too.

Of course all code is simply text, so why can't we call any text editor an IDE? An IDE such as the PDE generally has several special characteristics that separate it from other software applications.

1. Source Code Editor 2. Build Automation Tools 3. Compiler and/or Interpreter 4. Debugger

Why Learn Programming using Processing? 39 An Introduction To Programming With Processing

Source Code Editor

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

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

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

Build Automation Tools

Programming can involve many repetitive tasks, build automation tools help programmers perform these repetitive tasks by use of tools built into the IDE. They might include the IDE's ability to convert source code to machine readable code with the click of a single button (the button being the build automation tool) or the ability to export your source code to multiple platforms with a menu

Why Learn Programming using Processing? 40 An Introduction To Programming With Processing selection. In the PDE several build automation tools for creating Processing applications can be found under the Tools and Sketch menus more generic build automation tools can also be found in the other menu's in the PDE.

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

Compiler and /or Interpreter

Most modern day IDE's have a compiler and/or interpreter, as this is the feature within IDE's that enable the conversion of source code to machine readable code. It is in this feature that our code is given a “meaning” for a computer to implement and for us to observe, interact with and experience in what ever it's intended form of implementation. You might be wondering at this point what exactly is the difference between a compiler and an interpreter? The truth is that there is actually not much of a difference between what a compiler does and what an interpreter does. The terms stem from a “Compiled Language” and an “Interpreted Language”. As mentioned before in order for a computer to make any sense of our code it needs to convert this code into a machine readable format, this process of conversion is referred to as compiling. The process is specific because the code must be fed into a compiler in a specific language and then be compiled into another “language” which is no longer human-readable but machine readable and specific to a particular platform. A compiler is said to perform this task on the entirety of the source code once so that when the program is compiled there is no more conversion or compilation that needs to be performed there after. An interpreter differs in the sense that the source code is not compiled into a specific machine readable format. So how does the code run on a machine? The code is passed to an interpreter (which is another software application) that runs the code. The interpreter then determines how the code should be run continuously translating the code from a higher level to a machine readable level

Why Learn Programming using Processing? 41 An Introduction To Programming With Processing each time the code needs to be executed. Of course at some point in order for the code to be run on a computer it has to exist in a machine readable format regardless of whether it's compiled or interpreted, so theoretically the difference between the two methods is not inherently specific to the language you are creating the code with but rather more to do with how a language is implemented. What this means is that any language could be interpreted or compiled, it's how the code that you create is implemented that determines whether that code will be compiled or interpreted. Processing compiles to Java bytecode, and can subsequently run on any Java enabled machine it is estimated that there are currently over 4.5 billion Java- enabled machines. Java is said to be an interpreted language.

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

Debugger

A debugger in the context of an IDE is software that examines code either as a part of the compilation process or before compilation or interpretation in order to reduce the number of bugs within a program. The term bug in relation to computer programming is used to describe an error, fault or some means of a computer program acting in an unexpected or unintended way. The process of

Why Learn Programming using Processing? 42 An Introduction To Programming With Processing debugging a program is intended to identify these bugs and in some cases assist the programmer in rectifying them. In the PDE the debugger console can be found below the text editor and is used generally for debugging one's own program or allowing the PDE to determine bugs within a program.

The Debugger console (also known as Message and Text area) can be used to identify bugs and track program variables which can be useful in identifying logical errors.

Active Online Community

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

The Processing logo is a trademark of processing.org

Why Learn Programming using Processing? 43 An Introduction To Programming With Processing

Hello Processing

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

Install Processing

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

Sketches

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

File → Preferences → “Sketchbook location”

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

Hello Processing 44 An Introduction To Programming With Processing

Hello World Program 1.0

Programming can be simple or very complex depending on what you are hoping to achieve. Since this is our introduction to programming we'll be following programming tradition and starting with a simple Hello World program. A Hello World program is a program that simply prints the words “hello world” to a display, that display in our case in the “Hello World 1.0” program is going to be the debugging console in the PDE. The purpose of the Hello World program is not as much to impress but rather to get a firm grasp on the key points that make a successful program and then to later expand on this understanding.

If you have not already done so open the PDE and start a new sketch. You can do this by clicking

File → New

Save the sketch in your sketchbook folder

File → Save As...

Give the sketch a unique name that you will remember. In the text editor of the PDE create the Hello World 1.0 program by typing println("Hello World");

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

Hello World Program 1.0 45 An Introduction To Programming With Processing

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

If your console window has the phrase “Hello World” printed in it, congratulations you've successfully completed the Hello World 1.0 program! Like I said earlier, don't expect to be impressed right away, building a more useful program is going to take a little more practice. Nonetheless let's have a look at what is going on here.

Firstly you'll notice that the text editor has formatted the text we input in different colors. The colors denote specific meanings in Processing, for example in our Hello World 1.0 program:

Orange Orange is used to identify a command.

Black Black identifies syntax formatting characters such as parenthesis and a statement terminator.

Blue Blue identifies a string of data.

Hello World Program 1.0 46 An Introduction To Programming With Processing

IDE's such as the PDE that use syntax highlighting make reading code easier to decipher and once you get familiar with what the colors represent you'll find yourself separating the code you are reading into smaller manageable chunks by identifying the colors that serve specific functions.

We refer to the sentence typed in the text editor as a statement. Statements are easy to identify because they always end with a semi-colon and not with a period (like in English). Our entire Hello World 1.0 program consists of only one statement which in itself consists of only one command. Processing is a case sensitive language so it is very important that when you type a command you do not mix it's casing because println() and printLn() will not yield the same results, in fact the latter will cause an error.

The println() function println() is a special type of command called a function. Sometimes a function is also referred to as a subroutine so how the term is used from one language to another may vary but regardless of what you call it the purpose of a function is generally the same in any programming language, a portion of code (usually a single word followed immediately with parenthesis) that exists within a larger body of code (in our case this could be the sketch we are creating) and performs a specific task within the context of the program but is also independent of the program. As you are aware, we have not defined the function println() we are just simply using it as it has been defined by the people that developed Processing, in other words we have not told the computer what to do when it comes across println() in our Hello World 1.0 program. This means that the main body defining how println() acts in our program is not defined within our program but exists independently of our program, probably somewhere else on your hard disk drive where you installed Processing. If we were to take another look at the Hello World 1.0 program, we can see the function println() is telling the machine, that the sketch is running on, to print whatever is inside the parenthesis. We call data we input to a function through parenthesis, parameters and some other higher level languages might refer to parameters as arguments. The parameters our println() function accepts in this case is the string of characters that spell out the words “Hello World”.

Hello World Program 1.0 47 An Introduction To Programming With Processing

There are two points worth noting here, firstly we have input data into the println() function and secondly it has returned data back to us, that being what it has printed to the debugger console. When a function is used in this way we are said to be calling a function. Functions are the building blocks of Processing and we will be using them regularly and even creating our own.

The process of calling a function visualized.

Syntax and syntax errors

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

Hello World Program 1.0 48 An Introduction To Programming With Processing

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

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

Help → Reference

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

Hello World Program 1.0 49 An Introduction To Programming With Processing

Logical Errors

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

Display Window

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

The default Display window has dimensions 100 pixels in width by 100 pixels in height.

Hello World Program 1.0 50 An Introduction To Programming With Processing

Lets take a look at how we can control the Display window with the size() function. The size() function allows you to specify the dimensions of the Display window in pixels. You use the size() function by supplying two parameters to it, an x value which defines the horizontal dimension of the Display window and a y value which defines the vertical dimension of the Display window. Just like the println() function, parameters for the size() function are entered between the function's parenthesis. For example if we wanted the dimension of the Display window to be 640 pixels across by 480 pixels down we would type: size(640,480);

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

Add the second statement to your Hello World 1.0 program

Below the first statement type the second statement so that your code reads: println("Hello World"); size(640,480);

Hello World Program 1.0 51 An Introduction To Programming With Processing

Standardized Coding Practices

Comments and white space form a part of standardized coding practices. Standardized coding practices establish a consistency between different software languages. If you do not use them your software may or may not throw an exception or an error, but you can be certain that there are many people that might read your code who will find it non-user-friendly when you do not use standardized coding practices and try to invent your own.

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

Comments in Processing and many other higher level languages are indicated with two forward slashes:

// for a single line comment, that is a comment that is // only one line long, // but can also have one comment following another.

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

/** typing the multi-line comment ...... and ending it with */

Hello World Program 1.0 52 An Introduction To Programming With Processing

White space

White space is also sometimes referred to as negative space and is the space between the characters of text that make up the lines of your source code text file. For example a space, tab or enter/break are all referred to as white space. Processing unlike other programming languages (such as Python) completely ignores white space, just like it ignores comments. However just because Processing ignores white space doesn't mean you should. Using a consistent spacing and formatting of your code will make it easier to read. For example: println("Hello World");size(640,480); is valid code but less readable than the same program with white space: println("Hello World"); size(640,480);

You can probably imagine how unreadable code could quickly become when creating more complex programs with hundreds of statements.

Let's revisit our Hello World 1.0 program and retype it taking standardized coding practices into consideration.

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

//Determine the size of the Display window size(640,480);

//Print characters to the console println("Hello World");

Hello World Program 1.0 53 An Introduction To Programming With Processing

Program Notes

Firstly you'll notice that every line in the documentation comment except the first and last lines of this comment is started with an asterisk “*”. This is not necessary but, it does make the code look somewhat nicer and many programmers adopt this fashion of multi-line commenting so I've included it in this program. As mentioned earlier to Processing it makes absolutely no difference, but to us it makes the code easier to read.

It is standardized coding practice to include the following information in the documentation comment. • Name of the program, • The programmers name, • The date on which the program was released, • A brief description of what the program does.

Secondly you'll also note that I've changed the order in which the statements are executed (or run). Code written in this way resembles a procedural programming style meaning that the code is executed one line after the next starting at the top of the document and working down. Subsequently it makes more sense to define the size of the Display window before any other code is run. At a later stage you will see that when using the setup() function starting with the size() function, before any other functions following setup(), is mandatory.

Cartesian Graph and the Processing Coordinate System

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

Cartesian Graph and the Processing Coordinate System 54 An Introduction To Programming With Processing

The Display Window can be divided up into a grid.

The origin of the Display window is in the top left hand corner, being the origin it's coordinates will be (0,0) meaning 0 x and 0 y respectively. This type of layout might look familiar to you, that's because it's based on the Cartesian graph system. This is the name for the type of graph layout we use in Processing and many other programming languages that allow us to create and place components of a sketch within an area such as the Display Window. The main difference between the programmatic version of the Cartesian graph and the mathematical version of the Cartesian graph is that in the programmatic version the positive y axis runs downwards not upwards as is usually the case in the mathematical representation of this graph. This actually does not change anything about how the graph system is used, if you find this to be a bit odd you can think of it as if we were looking at a piece of graph paper rotated 180 degrees around the x axis so we're looking at the back of the graph paper and everything drawn on the paper now appears upside down. As you can imagine nothing drawn on the graph paper has changed just the way we are looking at it is different. Understanding how the Cartesian graph system is applied in programming is a lot easier when we have an example to work with, so lets add to our Hello World 1.0 program.

Cartesian Graph and the Processing Coordinate System 55 An Introduction To Programming With Processing

Hello Display Window: Hello World 1.1

In the revised version of our Hello World Program we will start using the Display Window, firstly to display the original character set “Hello World” then to display a few shapes too. text() The text() function is the first function we will use to make Processing draw something to the Display Window for us. The text() function accepts parameters in various formats of which the simplest format is: text(data, x, y);

The data parameter in this case will be the string of characters that spell the phrase “Hello World” and as you've probably already guessed the x and y parameters tells Processing where in the Display Window we would like to draw the text in terms of x and y coordinates. So let's give it a try, add the following line to the bottom your Hello World 1.0 sketch: text(“Hello World”, width/2, height/2);

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

Hello Display Window: Hello World 1.1 56 An Introduction To Programming With Processing

Program Notes You'll notice that your sketch is now making use of the Display Window, which is the first step towards creating visual representations of your code. We used the string of text “Hello World” in the data parameter, but the x and y parameters are looking a little different particularly if you were expecting them to be numbers. In fact they are numbers, instead of inputting a specific number for the x and y parameters we used an expression and in this case the expression evaluates to a number. It is this number that Processing reads and accepts as the parameter. But what exactly do the expressions mean? Amongst the many things that Processing is, it is also a very sophisticated calculator. It has the ability to calculate very complex mathematical formulae and also is able to do very simple math too. The expression: width/2 is asking Processing to get the width of the Display Window and divide (/) it by 2. The keyword width is a type of data known as a system variable. Basically the width system variable stores information set by the first parameter in the size() function, and as you are aware the first parameter in the size() function determines the width of the Display window. In our program we set the size() function to read: size(640,480);

How this relates to the width system variable is that every time Processing sees the keyword width it replaces it with whatever we set the width value to be in the size() function. In this case since we set the width to 640 the text statement as Processing reads it looks something like this: text(“Hello World”, 640/2, 480/2);

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

Hello Display Window: Hello World 1.1 57 An Introduction To Programming With Processing text(“Hello World”, 320, 240);

Although this is a perfectly valid methodology, it is not very versatile. Currently there is not too much maintenance involved in updating the code if we were to decide that the Display Window needs to be smaller, however when it comes to creating the rest of the sketch which is going to involve drawing shapes to the Display Window of which each shape will need to have it's own set of coordinates, if we had typed in a specific value for each x and y position, updating the code to reflect the change of dimensions of our Display Window would mean changing each statement where we input specific x and y values. That could mean a lot of extra and unnecessary work. By using an expression with the keywords width and height we can place whatever we are drawing relative to a position determined by the size() function. So all we need to do now is update the size() function and every place that we have used the keywords (width and height) relating to the size() function updates without us having to change anything more than a single statement. This is a programming methodology that is used often and referred to as implicit programming, and although it might not seem entirely obvious to you at this point why it is a recommended methodology it should become more clear as you delve deeper into the Hello World 1.2 program.

Formatting Text

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

If you were to re-run the sketch your updated version should have the text directly in the center of the Display Window. As we are using a procedural programming

Hello Display Window: Hello World 1.1 58 An Introduction To Programming With Processing style to create this sketch, Processing needs statements input in a particular order. We'll discuss procedural programming and other programming paradigms in more detail a bit later, but for now it's very important to note the order that statements are placed in. Placing the textAlign() function before the text() function ensures that the textAlign() function is run before the text() function thereby ensuring that by the time Processing gets to drawing the text in the Display Window it already knows that the coordinates within the text() function refer to the CENTER of the text.

Next we'll have a look at the size of the text. Currently the sketch looks like it's drowning the text in a sea of greyness, so lets make the text a little bigger. The textSize() function allows us to set the size of text in pixels. The size number is input as a parameter of the textSize() function. Add the following statement before the text statement: textSize(24);

Now we're starting to get somewhere, although white text on a grey background does not exactly jump out at you. So in keeping with the old Processing.org color scheme we're going to use a black background with light blue text.

Color

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

The background() function accepts up to three parameters, in our case the first parameter is the Red value followed by the Green value and finally by the Blue value. As we want a black background all of these values are set to 0 the minimum value for the current color mode of RGB, the maximum value for these parameters is 255, this gives you a total of 256 different color values for each

Hello Display Window: Hello World 1.1 59 An Introduction To Programming With Processing color (remember 0 is also a value). If we wanted a white background we would have to enter 255 for each of the three parameters of the background() function.

Back to the color of the text. The textAlign() and textSize() functions set parameters not just for the text currently displayed but for all text that is created thereafter. Until these functions are used again to change these parameters they will remain in Processing's memory and effect all text that is drawn to the Display Window following their execution. The fill() function acts in a similar fashion, it accepts color values and will effect everything that is drawn to the Display window that has a fill after the function is evoked. We will have a look at how to modify this behaviour a bit later, for now lets focus on getting the text to display in a light blue. In the PDE click:

Tools → Color Selector

The Color Selector is a build automation tool accessible within the PDE

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

Before the text() function type the following statement:

Hello Display Window: Hello World 1.1 60 An Introduction To Programming With Processing fill(191, 233, 255);

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

(height/4)*3

What this reads as is “height divided by four then multiplied by three”. Just like in mathematics anything within parenthesis is evaluated before that which is outside of parenthesis. So the expression height/4 is first evaluated, the answer of this expression is then multiplied by 3. Modify your text statement to look like this: text("Hello World", width/2, (height/4)*3);

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

Hello Display Window: Hello World 1.1 61 An Introduction To Programming With Processing

The new Hello World Program in Processing.

Drawing

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

2D Primitives

Drawing an ellipse in Processing is easy you just use the ellipse() function that accepts parameters in the following order: ellipse(x, y, width, height);

As you might have already guessed the x and y parameters indicate where the ellipse is to be drawn on the coordinate system, and the width and height parameters indicate the width and height of the ellipse. Please note that the terms width and height in this context have nothing to do with the system variables

Hello Display Window: Hello World 1.1 62 An Introduction To Programming With Processing width and height which store the information relating to the x and y dimensions of the Display Window. To draw an ellipse in the Display Window add the following statement to the end of your program: ellipse(width/2, height/2, 100, 100);

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

The Origin of an ellipse

Processing provides several different ways to draw an ellipse which modify what the x and y parameters of the ellipse() function refer to. These parameters of ellipse() define what is known as the origin of the ellipse, the function ellipseMode() is used to change where the origin of the ellipse is with regards to the x and y parameters of the ellipse() function. This relationship will determine where the ellipse is drawn within the Sketch. We use the function ellipseMode() which accepts the parameters CENTER, RADIUS, CORNER, or CORNERS to determine how the circle is to be created. Using the CENTER parameter tells Processing to use the x and y parameters of the ellipse() function to determine the center of the ellipse as it's origin. The CENTER parameter for ellipseMode() is the default mode, and is subsequently why we did not add the statement to our sketch. If you did want to use the CENTER creation mode for drawing ellipses after having overridden this setting with one of the other modes, to reactivate the CENTER mode parameter you would add the following statement to your sketch before using the ellipse() function:

Hello Display Window: Hello World 1.1 63 An Introduction To Programming With Processing ellipseMode(CENTER);

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

Drawing an ellipse with the CENTER parameter of ellipseMode()

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

Drawing and ellipse with the CORNER parameter of ellipseMode()

To use this creation method for ellipses type the following code: ellipseMode(CORNER);

Hello Display Window: Hello World 1.1 64 An Introduction To Programming With Processing

It's time to save your sketch if you haven't already done so. In the PDE click

File → Save As...

Change the name of your sketch and save it. Processing will create a new folder in your sketchbook folder with the new name of your sketch, it's also worth noting that if you have added any additional files to your sketch such as images or other files processing will also copy the data folder that it created automatically when you added external content to a sketch to the new sketch location. This is something to be aware of as you can inadvertently duplicate the amount of data on your hard disk drive if you are unaware of this feature in Processing. Adding external content to a sketch is something we will get into a bit later when we start adding images to our sketch.

Your sketch should read something like this:

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

//Determine the size of the display window size(640,480); background(0,0,0);

//Print characters to the console println("Hello World");

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

//Drawing the face ellipse(width/2, height/2, 100, 100);

Hello Display Window: Hello World 1.1 65 An Introduction To Programming With Processing

Aliasing

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

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

Smile

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

Angles in Processing

In mathematics angles are usually measured in either degrees or radians, Processing and many other programming languages generally accept and/or prefer the latter. One of the main reasons most programming languages accept a unit of

Hello Display Window: Hello World 1.1 66 An Introduction To Programming With Processing measuring angles in radians is because it allows us to work with the value known as PI (pronounced py rhymes with “try”) and represented mathematically as π. PI is a number that has the approximate value 3.1415927 (calculated to seven decimal places). The actual number that PI represents, in programming, is not quite as important as it's mathematical equivalent subsequently we will generally never need to remember what this number is in programming but rather what the language we are choosing to use it in, represents it as. In Processing the value of π is represented by the mathematical constant PI. To Processing and many other programming languages a constant is a value that does not change, as a result it makes sense for the Processing representation of pi to be a constant. Pi has always been the same value long before Archimedes approximated it's value in the 200's BC as it's implication in the construction of many architectural wonders of human ingenuity from as far back as the Egyptian pyramids and even further back in human history suggests, and it's highly unlikely that pi could be used to represent any other value. So what does it mean? Pi is the ratio of the circumference of a circle to it's diameter, and pi radians is also equal to approximately 180 degrees. Pi can be expressed mathematically as:

π = C/d

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

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

Hello Display Window: Hello World 1.1 67 An Introduction To Programming With Processing

PI + HALF_PI

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

(PI/180)270

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

One of the simplest methods of converting degrees to radians in Processing is to use the radians() function. If you know the value of the angle in degrees you can simply use the value in degrees as a parameter of the radians() functions. For example: radians(270);

This will convert 270 degrees to it's equivalent in radians. It is important that angles in Processing are converted to radians because all trigonometric functions that require angles accept this value in radians.

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

Hello Display Window: Hello World 1.1 68 An Introduction To Programming With Processing

The arc() function in processing accepts six parameters in the format x, y, width, height, start, stop. You are already familiar with the first four parameters x and y determine the point of origin of the arc and this can be further controlled with the ellipseMode() function. width and height represent the dimensions of the arc in much the same way that these parameters, determine the dimensions of an ellipse. The last two parameters you might not be familiar with start and stop determine the starting and ending values of the angle of the arc, so for example we are going to draw a half circle which you know has an angular value of 180 degrees, secondly because we want our smile to be straight we will start it at 0 and end it at PI (which is approximately 180 degrees). Add the following statement to your sketch following the ellipse statement: arc(width/2, height/2, 50, 50, 0, PI);

A Smile on the “Hello World” Program.

Editing the smile

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

Hello Display Window: Hello World 1.1 69 An Introduction To Programming With Processing statement is simply to place the comment tokens at the start of the statement so it looks like this:

//ellipse(width/2, height/2, 100, 100); you will notice that when you comment out a statement, syntax highlighting causes the statement to turn grey. This means we can now run the program and Processing will no longer draw our ellipse, until we uncomment the statement by deleting the comment tokens. Another way of commenting out a whole block of code is to select the lines of code you wish to comment out in the PDE click:

Edit → Comment/Uncomment

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

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

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

The order in which commands are issued to Processing is very important. Functions such as rectMode() and noFill() not only effect the command that directly follows them (such as the arc statement being effected by the noFill() function) but they also effect all statements that follow there after that rely on these special functions. So what that means is that if we were to place the noFill()

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

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

Now we have a smile floating above our text, so we're going to uncomment the ellipse statement and when we run the sketch our smile is restored to it's elliptical face.

Hello Display Window: Hello World 1.1 71 An Introduction To Programming With Processing

The smile is looking a little too high up on the face so we're going to move it down, this is easy enough as we already have the style of the smile we are looking for we just need to offset it's y position. To do this we are going to edit the arc() function once more to the following state: arc(width/2, height/2 + 10, 50, 50, 0, PI);

Notice that because we are using an inverted Cartesian graph adding 10 to the arc's current y value actually moves the arc down, inversely if we subtracted 10 we would move the smile up. At first getting used to this system might be a little tricky.

Adding Eyes

What's a smiley face without eyes. Add the following code to your sketch after the previous arc statement: stroke(0,0,0); fill(0,255,0); ellipse(width/2-15, height/2-15, 20, 30); ellipse(width/2+15, height/2-15, 20, 30);

As we changed the stroke to red in our previous statement to draw the smile, we need to change it back to black so we add the second stroke statement to our program to change the stroke color back to black. Having also turned the fill off for the arc statement we need to turn it back on and set it to green, we can conveniently achieve both of these tasks with one function in the form of our fill statement. The x and y parameters of the ellipse functions that actually draw the eyes have had their expressions added to. For the eye on the left's x parameter I've subtracted 15 and for the eye on the right' x parameter I've added 15. When working with expressions like this it's important to remember that certain mathematical operators have precedence over others. For example * and / have precedence over + and -, this means that the expression width/2-15 is actually being evaluated like so (width/2)-15. This effect is known as operator precedence. Finally I offset the y position of the ellipses by subtracting 15 and drew them as more oval shaped by making their height's greater than their widths.

Hello Display Window: Hello World 1.1 72 An Introduction To Programming With Processing

Drawing Irregular Shapes

Fortunately we are not limited to drawing only 2D primitives in Processing, but we can in fact draw any shape that we can imagine. We use two main functions in conjunction with several calls to another function in order to achieve this, and the main functions are beginShape() and endShape() issued in that particular order. We're going to start off by experimenting with this feature by drawing a speech bubble surrounding the “Hello World” text in our sketch. The beginShape() function tells Processing to start recording the following set of points that are given to it and the endShape() function tells Processing to stop recording, between these two functions we are going to supply Processing with a set of special coordinates in the form of the vertex() function. Since we are using the vertex() function to determine where the points of our irregularly shaped object will be drawn we cannot use any other function other than vertex() between beginShape() and endShape(). The vertex() function accepts parameters in the form of x and y, which determine where in terms of x and y the point (or vertex) is in the Display window. By adding the following statements in this particular order we will be able to draw our speech bubble: beginShape();

//Start the shape in the middle of //the Display Window's x axis vertex(width/2, (height/4)*3-35); vertex(width/2-70, (height/4)*3-35); vertex(width/2-80, (height/4)*3-25); vertex(width/2-80, (height/4)*3+5); vertex(width/2-70, (height/4)*3+15);

//The following statement marks the point //where the shape starts to mirror itself vertex(width/2, (height/4)*3+15); //The Previous statement marks the point //where the shape starts to mirror itself vertex(width/2+70, (height/4)*3+15); vertex(width/2+80, (height/4)*3+5); vertex(width/2+80, (height/4)*3-25); vertex(width/2+70, (height/4)*3-35);

Hello Display Window: Hello World 1.1 73 An Introduction To Programming With Processing

//this is the arrowhead that points out of the //speech bubble towards the smiley face vertex(width/2 + 50, (height/4)*3-35); vertex(width/2 + 40, (height/4)*3-55); vertex(width/2 + 30, (height/4)*3-35);

//the end of the shape is the same as //the beginning vertex(width/2, (height/4)*3-35); endShape();

Although at first this might appear to be a lot of typing, upon further inspection you will notice that it is in fact very repetitious and more of copy, pasted and modified code. So lets have a look at what's going on here.

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

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

Hello Display Window: Hello World 1.1 74 An Introduction To Programming With Processing vertex(320, 325);

But using this method of explicit programming does not leave much room for changes and could subsequently lead to the extremely time consuming task of changing each explicitly determined point in your program manually, if it is deemed that such a change is necessary at a later stage.

From the next vertex on we can use the Display Windows width and height system variables and the text's x and y position as a starting point from which we can place every vertex that follows relative to the position of the previous one and in relation to the other elements making up our program. Using this method of implicit programming also makes it easier for us to “mirror” the coordinates of the irregularly shaped speech bubble across the center of it's own Y axis. As you will notice once we get to the vertex marked as “the point where the shape starts to mirror itself” it's just a simple question of copying and pasting the previous code excluding the first vertex statement, changing the negative values associated with the vertices' x parameters to positive values, and reversing the order of the statements in a mirrored fashion.

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

Hello Display Window: Hello World 1.1 75 An Introduction To Programming With Processing

This can save us quite a bit of work as we don't have to work out the specific coordinate of each vertex individually all we need to work out is half of the coordinates that make up the shape and since we are mirroring the shape on the x axis we simply change the negative values associated with x to positive. Once we have all the vertices mirrored on the right hand side (excluding the last vertex) we can then start to plot the points of the arrow head of the speech bubble that points to the smiley face implying that it's saying “Hello World”. This part of the shape is pretty straight forward because we already know that we will need three points to make the triangular shape of the arrowhead and two of these points we already know the y positions of because they will be at the same height of the first and last vertices. So it's just a case of simple trail and error to determine what looks best in adding the remaining parameters to the next three vertex() functions. Once that's complete we can close the shape by placing the last vertex at the same location of the first vertex. Finally to end the shape you must use the endShape() function. You might have noticed that the image of my sketch has a speech bubble with a thick blue outline around it. This is the strokeWeight() function, and it controls how thick or thin the stroke is rendered and accepts a number as a parameter, I don't recommend setting this number too high as you might find it causing undesirable effects on your sketch. The higher the number input the thicker the line. Add the following statement before the statements that draw the speech bubble: strokeWeight(8);

You might remember that in order to have a black outline around the face's eyes we set the stroke to an RGB value of 0,0,0 (or black), so although the strokeWeight() function has done it's job the effects of it might not be so obvious. Changing the stroke and fill colors are functions that you might need to run several times within a single sketch to achieve the desired result. Add the following statement before the previous statement: stroke(50,127,255);

This changes the stroke color for the speech bubble to a little bit of red, about 50 percent green and full blue. The fill color of my speech bubble is white and if you want to change the fill color of your speech bubble you must add the fill() function before the drawing of the speech bubble. Your statement would look

Hello Display Window: Hello World 1.1 76 An Introduction To Programming With Processing something like this: fill(255,255,255); or fill(255);

Either option is perfectly acceptable, the latter is used for determining a gray scale value from 0 which is black to 255 which is white.

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

The section of the speech bubble where the first and last points of the shape overlap has an unsightly blemish caused by stroke caps. Stroke Caps determine how the end of a stroke is drawn and fortunately we have a function in Processing for controlling this feature, as you might have guessed the function is called strokeCaps() and it accepts the parameters ROUND, SQUARE or PROJECT.

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

Remember that Processing is case sensitive so you must type the parameters name with the correct casing. ROUND is the default parameter that causes strokes in

Hello Display Window: Hello World 1.1 77 An Introduction To Programming With Processing

Processing to have a beveled end, SQUARE will end the stroke with a flat end and PROJECT will tend to render the end of the stroke slightly past it's destined coordinates. We are going to use SQUARE to fix the speech bubble blemish. Add the following statement after the strokeWeight() function call: strokeCap(SQUARE);

Order, order!

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

Finishing the sketch

To add the final touches to the Hello World 1.2 Program we're going to get Processing to display an image for the sketches background instead of the black background. This exercise will also be our first introduction to the Object Oriented Programming and the concept of data typing. The first thing we need to do is set our sketch up to accept external data in the form of an image. With the PDE open, open a file browser via your operating system and locate the file named “smileBkg.png”. From your file browser click

Hello Display Window: Hello World 1.1 78 An Introduction To Programming With Processing and drag the file into the sketch you would like to use the image in.

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

When you have dropped the file to the sketch Processing, will confirm this in the debugging area by printing the phrase “One file added to the sketch”. If you get this message you are ready to start using the image in your sketch. In order for you to use external data such as an image in your Processing sketch the data has to exist in a folder called “data”, which must be a subdirectory of the location where your sketch is saved. For example, we set up Processing at the start to store all sketches in a single folder which I've called “Sketchbook”, within this folder will be located the sketches we create with the PDE. I've called my Hello World 1.2 Program “smile” so within the Sketchbook folder is another folder called “smile” and within the smile folder is the file smile.pde (which is my Hello World sketch) and another folder called “data”. When we dropped the image into the PDE Processing automatically created the data folder, and placed a copy of the smileBkg.png file in it. If you would like to view the contents of this folder you can access it quite easily from the PDE by clicking

Sketch → Show Sketch Folder

Hello Display Window: Hello World 1.1 79 An Introduction To Programming With Processing

When transporting your Processing sketches from one computer to another you must always retain this directory structure of having your data folder as a subdirectory of the location where you saved your processing sketch which should always have the extension .pde.

Programming Paradigms

A programming paradigm is a fundamental style of programming, the term is often confused with programming methodology which is a style of addressing a problem within a program. But perhaps a better way to understand what a programming paradigm is would be to look at some examples of it. Many modern day software languages offer at least two fundamental programming paradigms, most commonly amongst these two choices are the Objected Oriented Programming Model and Procedural Programming Model. Procedural programming is also sometimes referred to as imperative programming. Like the name implies imperative programming is a programing paradigm that is used to determine a set of commands and/or steps a computer program must take in order to reach a desired state. It's worth knowing that the Object oriented programming model is often contrasted to the procedural programming model because of the fundamental differences that separate these programming paradigms. Procedural Programming can be summarized as a style of programming where the program is tailored to suite the data as opposed to Object oriented programming which is more akin to a style of programming where the data is tailored to suite the program. So what exactly does that mean? As mentioned earlier, programs are made up of statements and one of the things statements are made up of is commands. As you might recall a command in programming, much like in a natural language, is used to communicate a directive. In this way procedural programming is a list of statements telling a computer what to do. At this point you could be thinking “Isn't that the purpose of all programming i.e. telling a computer what to do, so how then does procedural programming differ from any other programming paradigm?” In one way or another we use programming to represent data, whatever that data may be for example the amount of tea compared to the amount of coffee consumed over the past ten years world wide, or it could be determining the

Hello Display Window: Hello World 1.1 80 An Introduction To Programming With Processing choices a character has in a game then choosing to act on those choices or it could even be something as simple as representing a set of alpha numeric characters on the screen that spell your name. Whatever way you look at it creating a program requires data. In procedural programming we use the tools provided to us by the language we are programming in to break down that data into smaller data types that the language predetermines for us and then use those representations to create a program that ultimately represents the larger original data set programmatically. This can be contrasted to object oriented programming where we use the tools provided to us by the language we are programming in to create our own data types for which we determine their meanings and use these new data types to create a program that ultimately represents our original data set.

Datatyping Categories

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

Primitive Data Types

Primitive Data Types form the building blocks of all the other mentioned forms of data types, and as a result are immutable, meaning that what defines them cannot be modified by use of Processing.

Numbers can be represented as Primitive data types and most commonly fall into the primitive data type definition of int or float. An int data type is an

Hello Display Window: Hello World 1.1 81 An Introduction To Programming With Processing abbreviation of the word integer and is used to create categories of numbers within a program that represent whole values such as 0, 1, -58, 6000000 and so on. In Processing these values can range anywhere between 2,147,483,647 to -2,147,483,648. A float (or floating point number) is a data type used to categorize numbers that have a decimal point. Numbers such as 1.5, 3.0, -56.91 and even numbers such as 3.40282347E+38 in SI (the International System of Units) notation qualify to be a float primitive data type. Typographic characters such as 'A', 'b', '5', '@' etc can also be stored as primitive data types by use of the char data type which is an abbreviation for the term character. However, storing a sequence of typographic characters as a single unit requires a different data type that is more complex than a primitive.

Processing's API Data Types

In order to make languages fit more specifically to an environment certain repetitive tasks are often automated by the developers of the language's API. The acronym API stands for Application Programming Interface and it refers to the means by which you communicate with a program. Although you are creating programs (known as sketches) with Processing, Processing in itself is also a software program. We have been communicating with Processing through the PDE, and within the PDE we have been typing statements instructing Processing what we would like it to do with the data we have supplied it with. Those instructions such as functions, tokens, arithmetic operators etc that we are using to communicate with Processing are all defined within Processing's API. Processing's API Data Types are special data types defined within the Processing API that may or may not be found in other languages, but will make fulfilling the requirements of creating sketches (including data visualizations, end-user interactions and many other features commonly found in sketches) easier and less repetitive for the programmer by abstracting base-level computational interactions. The PImage data type is an example of a Processing specific API Data Type that makes the task of dealing with images much simpler for the programmer. The String data type is a Processing non-specific API Data Type, meaning that although this data type is common to many different programming languages it is not a primitive data type as it uses characteristics of both int and char primitive data types in it's implementation. Processing's API Data Types are usually quite easy to identify as the keyword used to invoke them usually starts

Hello Display Window: Hello World 1.1 82 An Introduction To Programming With Processing with an upper-case character, this is a common standardized programming practice that is used to identify Classes which are the fundamental building blocks of Object Oriented Programming and are an inherent quality of Processing's API Data Types.

User Defined Complex Data Types

In procedural based programming languages the programmer is supplied with a predetermined set of keywords that can be issued during the course of the program to communicate with the languages API, as a result no matter what the data that you are representing with your program is, that data must be tailored to fit those keywords. This means that your data will need to be fragmented, categorized and associated with the predetermined data types of the procedurally based language. This differs substantially from an object oriented approach to programming, in that you tailor the program you are creating to suit the data you are representing. In Object Oriented Programming you define your own data types by combining various Primitive data types and predetermined complex data types of the programming language's API into your own User Defined Complex Data Types that are referred to as Classes. These data types can then be instantiated throughout your program as often as necessary and used in a manner that is akin to how any other data type is used. The invocation or instantiation of a Class data type is known as a Software Object, and this is how the Object Oriented Programming (or OOP for short) paradigm evolved. Objects that are instantiated from the classes that make up an OOP program fall into the category of being user defined complex data types.

PImage

We are going to create a new software object from the PImage class, and we will give this new object a name. It is important that the name that we assign to the new object is unique so that when ever we want to use that object we can refer to it by it's name and Processing will know exactly which object we are referring to. The PImage Class contains useful information about the image we are loading into our sketch and allows us access to this information without having to understand how it has extracted this information from the image, such as it's width, height or how many pixels make up the image and what color each pixel is.

Hello Display Window: Hello World 1.1 83 An Introduction To Programming With Processing

This is one of the benefits of object oriented programming, being able to abstract complex code by referencing it with a single keyword, the name of the object. Amongst the prerequisites of using an image file as a background in Processing is that the image must be in either gif, jpg, png or tga format and must have the same dimensions as the sketch in which it will be displayed. If you have had a look at the smileBkg.png file you might have noticed that the dimensions do not match that of our current sketch. However, we are in luck because we have been using an implicit style of programming to specify the x and y parameters within our sketch so changing the dimensions of our sketch at this late point in the programming process is actually not going to cause a problem. If on the other hand we had used an explicit style of programming we would have a problem as all of our had work to keep the graphical components of our sketch in the center of the display window would now be lost and fixing it would mean having to go through every statement where x and y coordinates where used and changing them to accommodate for the new sketch size. Since we are loading our image as a background we are going to add the following statements before the background statement near the top of the sketch. To create a new object from the PImage class add the following statement before the background statement:

PImage img;

This statement tells Processing that we want to create a new software object which has all the properties of the PImage data type and we would like to call this new object “img”. Our new software object has inherited the properties of the PImage data type which allow us to access information about the image we would like to store within the object without us having to know how exactly it goes about accessing this information. However, what our new object does not know yet is what image exactly we would like to use in our sketch and refer to as img. Add the following statement after the previous PImage statement: img = loadImage("smileBkg.png");

This statement tells Processing the name and location of the image file we would like to use and refer to as img throughout the rest of our sketch. Because the image file has already been dropped into our sketch Processing has already placed a copy of the file in our data folder. Processing will expect to find whatever image files we are using in our sketch in this folder. The loadImage() function can also

Hello Display Window: Hello World 1.1 84 An Introduction To Programming With Processing accept a URL as a parameter if you wanted to load an image that is not located locally on the same station that your sketch is running from. So now that we have the image loaded into our sketch we need to tell Processing what we would like to do with and, where we want to place it and finally to draw the image to the Display Window. To display the image in our sketch we're going to modify the background statement and Processing will now draw the image to the Display Window when we run the sketch. Modify the background statement to read: background(img);

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

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

The completed “Hello World 1.2” Program

Hello Display Window: Hello World 1.1 85 An Introduction To Programming With Processing

The Design and Layout Program

Using what we've learned thus far from this guide, I've constructed a program that “sketches” a prototype for an interface to an online portfolio.

The Completed Design and Layout Program

Program Notes for Interface01.pde

The PDE Tools menu

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

Tools → Create Font..

The Design and Layout Program 86 An Introduction To Programming With Processing

The Create Font build automation tool can be used to ensure that users do not have to have the fonts you have installed on your computer in order for your sketch to display properly on their computers.

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

The Design and Layout Program 87 An Introduction To Programming With Processing that of loading and displaying images. Start by creating a new object that will serve as the container for your font, by adding the following statement:

PFont myFont;

PFont is a special data type in Processing used for storing fonts, in a similar way that PImage works with images. myfont is the name we have chosen to create an object that inherits the unique qualities of PFont. Next you will need to load the font into your sketch, to do so add the following statement: myFont = loadFont("FancyFont-Bold-42.vlw");

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

The textFont() function accepts two parameters, the name of the PFont object you have created (which is myFont in this case) and the size at which you would like the text that follows to be rendered at. All the calls to the text() function that follow this statement will use the parameters set in textFont() until textFont() is called again with a different set of parameters. Finally you can draw the text to the Display Window with the text() function: text("Welcome to my\nProcessing Portfolio", width/2, height/2);

You might notice something strange about the literal string parameter for the text() function. Between the characters “my” and “Processing” are the characters \ n. This is known as an escape character and is not rendered with the literal string. Escape characters are used to format text before they are drawn to the screen. In my Interface01 sketch there is a break between “Welcome to my” and “Processing Portfolio”, this is because the \n is known as a new line escape character and has the function of inserting a break between characters. This saves me having to use the text() function twice, first to render the text “Welcome to

The Design and Layout Program 88 An Introduction To Programming With Processing my” and adjust the y parameter in the next call to text() to render the rest of the sentence. Using a short-cut like this can save your program some overhead, but also comes with the expense of making your code look a little less readable, particularly if you have never seen an escape character before.

Another place where I've used a short-cut in my Interface01 Program is in the statement where I create the objects for storing the images that I will use in the rest of the sketch. The following statement demonstrates this:

PImage mGoat, banner, bkg, button;

The long version of this code would look like this:

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

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

The Design and Layout Program 89 An Introduction To Programming With Processing

Beyond Static Sketches and on to Active mode

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

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

90 An Introduction To Programming With Processing

Up until now our sketches have not been interactive or included any animation. The use of the active mode structure, including the addition of the setup() and draw() functions, allows us to truly access the powerful features that programming offers to developers and extend our sketches with interactivity, animation, logic and a host of other features that we shall explore.

We'll start by having a look at how setup() and draw() change our sketches and make them more dynamic.

Methods, functions and their contexts

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

PImage img;

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

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

91 An Introduction To Programming With Processing

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

The setup() function

Let's have a look at how the setup() function works and how it alters the structure of a program. Code that is cradled between the braces{} of the setup() function forms the code block of the setup() function and determines it's structure. This code will run only once, throughout the duration of the sketches life-cycle. Meaning that from the time the sketch is started to the point when you close the Display Window, the web page the sketch was running on, close the application the sketch was running through or do whatever is needed to end the sketch, the code block within the setup() function is never repeated until that sketch is run again. So how does that make the sketch more dynamic? Well in fact, when compared to the draw() function the setup() function does not contribute to significantly making the sketch more dynamic, but it does contribute to allowing the sketch to become dynamic. In programming the term dynamic is often used to describe the changing effects of a program. If we where to contrast this definition with our previous example of

The setup() function 92 An Introduction To Programming With Processing the interface01 program, we would see that this program is not dynamic as from the time that the sketch starts to the point when the sketch is terminated, the program does not change. However if we where to add animation to the images, or make the “buttons” of the interface clickable, then the program would be dynamic. So how does the setup() function contribute to this? One of setup()'s main forms of contribution to active mode sketches is in something we call assignment. Assignment is actually not a new concept to us as we have already used it several times in our previous sketches and is often invoked in most programming languages with an equals sign “=” which, in programming, is called an assignment operator. For example we have previously used assignment in the following context, when loading an image into a sketch in preparation for it to be rendered: img = loadImage(“myBitmap.png”);

The purpose of assignment is to make whatever the value on the left side of the operator, equal the value that is on the right side of the assignment operator. In this way assignment can be a relatively straight forward or complex procedure. For example if we have a simple value such as a number or typographic character on the right of the assignment operator, the assignment of that value to whatever exists on the left is relatively straightforward because we're just simply telling Processing to make whatever is on the left of the assignment operator be the same as that which is on the right and then store those values in the computer's memory. However if we have an expression, a command or both on the right of the assignment operator the task of assignment can become more complex not only for Processing but also for us to keep track of. In the previous example we are assigning the value of the bitmap image that exists in our data folder called myBitmap.png to img, by using the loadImage() function. But, what exactly is going on in this assignment statement, as the computer that is running the sketch sees it?

Firstly the computer running the sketch must process the call to the function loadImage() this requires processing power, and secondly the computer having realized what the loadImage() function requires after processing it now accepts the parameter “myBitmap.png”.

The setup() function 93 An Introduction To Programming With Processing

In order for it to accept this parameter it has to allocate a certain amount of it's memory to load the image. Computers have a limited amount of memory and the larger the bitmap image's size (in terms of kilobytes, megabytes, etc.) the more memory they require to be loaded into a sketch. As a result the computer must try to allocate memory that has not already been assigned to another value and does not request more memory than is necessary. All of this work performed by the computer is performed without us having to know anything about the steps it must take to display the image in our sketch. As you can see, although this assignment statement was relatively easy for us to create, the steps that our computers must take in order to make what we are requesting possible is actually not so straightforward. The setup() function can be very useful in a situation such as this, because the previous statement is so resource insensitive it is not the kind of statement we would like to have repeated throughout the duration of our running program. Doing this will simply cause a bottleneck effect on the resources of the computer running the sketch and ultimately cause the sketch's performance to drop, as the computer struggles to keep up with our requests. The setup() function as a result will run only once throughout the duration of a program, and is designed to keep system performance at optimal speeds so that our sketches can run more efficiently with the code that does need to be repeated such as that of the draw() function.

The draw() function

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

The draw() function 94 An Introduction To Programming With Processing

Using the setup() and draw() functions in Processing is actually quite easy, and in the following example we'll use them for the purpose of getting the user's mouse position in terms of x and y coordinates and then use the println() function to print these values to the debugging console. Enter the following code and run it. Don't be alarmed when Processing starts to print line after line of information to the console, this is actually the desired effect. Move your mouse around in the Display Window to see the values update in the console view then close the Display Window when you are done: void setup(){ size(510,300); } void draw(){ println("The Mouse's X position is " + mouseX + " The Mouse's Y position is " + mouseY ); }

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

95 An Introduction To Programming With Processing

Experimentation

The setup() function must always precede the draw() function, and is used to define the initial properties of the sketch such as the size of the sketch. The size() function when used within an active mode sketch must always follow the setup() function before any other statements. If we had images to display in our sketch assigning them to variables would generally be done within the setup() structure, we'll have a look at this technique a little later. The draw() function repeats once every 60th of a second by default, but this behaviour can be changed with the frameRate() function which would be called within the setup() structure too.

Within the println() function you might have noticed something a little different, two new commands, mouseX and mouseY are system variables in Processing that store the X and Y position of the mouse when it is over the window the sketch is running in. When used within a sketch they simply return a number that is either the respective X or Y coordinate of the user's mouse. It is also worth noting that it is necessary for the println() function to be repeated within the draw() structure because whenever the user moves the mouse within the Display Window a new value for the mouse's x and y position replaces the old value for the previous position of the user's mouse. If this command was within the setup() function Processing would only print the mouse's x and y values once and not again. Although this is perfectly valid code it, is not very useful to us because if the user has moved the mouse since the start of the program (when setup() ran for the first and only time) the current position of the user's mouse would not have been updated thereafter. The statement to update the mouse's x and y position would not have been repeated so according to Processing the x and y position of the mouse would be the same as when the program first started, this is obviously not the case if the user has moved the mouse.

The repetitious nature of an active mode sketch

Experimentation 96 An Introduction To Programming With Processing

The mouseX and mouseY system variables are important keywords in determining the interactive nature of many sketches so lets attempt to use them in another way that is more directly related to the visualization of sketches.

Add the following statement before the println() statement: line(0,0, mouseX, mouseY);

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

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

Experimentation 97 An Introduction To Programming With Processing stroke(mouseX/2);

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

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

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

Experimentation 98 An Introduction To Programming With Processing

More interactivity can be added to this sketch example quite easily

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

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

Experimentation 99 An Introduction To Programming With Processing

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

Ordering statements appropriately can contribute significantly to the readability of your code.

Experimentation 100 An Introduction To Programming With Processing

Datatyping

You might have noticed something else that's new about the active mode structure of a sketch, that being the usage of the void keyword preceding both the setup() and draw() functions. The keyword void is used for defining functions that do not return a value, all other user defined functions must return a value of a certain type of data. The setup() and draw() functions differ significantly from their roots in the C/C++ main() function in that they are not intended to return a value of any type of data to the main program, the mandatory usage of the void keyword ensures this. We'll have a look at user defined functions in more detail later. The process of assigning a type to data is known as datatyping. There are many different types of data within Processing we have already had a look at some of the categories that the different types of data within Processing can be broken down into, but what exactly are these different types of data and how do they assist us in programming?

One of the datatypes we're already familiar with is the PImage datatype. We know that if we want to use a bitmap image in our sketch we must first assign it to the object we created from PImage. That new object that we have then created has inherited all of the properties of the PImage data type amongst which is the ability to resize the image, get information about the pixels that make up the image and what the alpha and color values of each pixel making up the image is. We did not have to tell Processing what a pixel is or how we would like to use it, these definitions exist already predetermined within the PImage class, which will be a body of code that exists somewhere on your computer (probably in the location you installed the PDE). Now that we have a new object instantiated from the PImage class it has inherited all of the properties that define that particular type of data, in other words the new object we have created has been datatyped as PImage. But in order to understand what is really going on here we need to look a little deeper...

Datatyping 101 An Introduction To Programming With Processing

Variables

Variables are common to most programming languages as they provide us with a means of storing data within the memory of a computer without having to know the process the computer has taken to store that data and where exactly within the computers memory that data has been stored. This provides us with a convenient method for accessing data, without having to understand the complexities of manual memory management as might be the case in lower level languages. Lets have a look at how variables play a part in helping us store data. Using variables is pretty straight forward and can be thought of as a two step process, 1.) Declaration and 2.) Assignment. The second step we are already familiar with, which could imply that you might have already used variables in your previous sketches, and this is in fact correct. You have used both steps of variable creation in your previous programs as variable assignment relies on declaration. Declaration is the process of giving the data you are representing in your program a name, and is a process that involves datatyping (preformed by the programmer) and memory allocation (performed automatically in Processing). So lets have a look at a declaration in the following statement:

PImage img;

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

Datatyping 102 An Introduction To Programming With Processing int myVar;

The keyword int in this statement is used to datatype a variable with the properties of type integer. Integers are primitive datatypes that must be whole numbers, such as 0, 5, -1, 2430 and so on. They cannot have a decimal value. All we are doing at this stage is giving the variable a name, that being myVar, we have not given the variable a value yet the value would effectively be an integer, and associating the variable with a value is specifically what assignment is for. In the above statement we have declared a variable called myVar and datatyped it as an int. So when we want to use the variable and the data associated with it in our program we can simply refer to it by it's name for example: println(myVar);

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

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

Datatyping 103 An Introduction To Programming With Processing int x; //declaration x = 5; //assignment x is now 5 x = x + x; //assignment expression x is now 10 println(x); //Prints 10

The value you assign to a variable can be changed when ever you instruct your program to do so, usually through use of the assignment operator. As a result in the previous example although we started off with the variable we called x having a value of 5 assigned to it in the second statement, in the next line we added it's current value of 5 to itself then reassigned that new value of 5 + 5 (on the right of the assignment operator) back to itself (on the left of the assignment operator), making x = 10. Using this simple method we have represented two different values of 5 and 10 with only one variable, x. That does not mean that x could be either 5 or 10 it simply means that at the start of the program x was 5 and by the end of the program x ended up being 10. By having one variable that can be used to represent many different values we can save on memory as at any given time that variable can only have one value associated with it, meaning that if a new value is assigned to it like in our previous example that new value will replace the old one and so on. Not only does this make our program run more efficiently but it also makes keeping track of the representations of the different data in your program more manageable.

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

Datatyping 104 An Introduction To Programming With Processing

Erroneous code is produced from a lack of considering variable scope

As you can see in the previous image x cannot be accessed from within draw() because it has been initialized within the setup() function. Initialization is the process of combining variable declaration and assignment into one statement. For example the following declaration and assignment statements can be written as such: int x; //declaration x = 20; //assignment or the statements could be combined in one statement and written as such: int x = 20; //initialization is both declaration and assignment

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

Datatyping 105 An Introduction To Programming With Processing

Basically, what this boils down to is that where you choose to declare your variables is your choice, but there are also certain rules in place that if you are aware of, can make this decision somewhat easier for you. Lets restructure the previous example using a more readable format that takes variable scope into consideration: int x; //declare variable only once in global //variable scope void setup(){ //assign a starting value to the x = 20; //variable. Note: accessible within } //setup()structure void draw(){ //access the variable from elsewhere in println(x); //the program. Note: also accessible } //within draw() structure

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

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

//declare global variables

Interacting with images 106 An Introduction To Programming With Processing

PImage doors; void setup(){ //size() always first in setup size(800,600);

//use setup() for assignment where ever possible doors = loadImage("doorsClosed.png"); } void draw(){ //draw the image image(doors,0, 0); }

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

Making the image follow the mouse's Y position is actually quite easy, modify the image statement to read: image(doors, 0, mouseY);

Now when you run the sketch your image will start to move up and down in the

Interacting with images 107 An Introduction To Programming With Processing

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

Streaking

The streaking effect

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

Now when you run the sketch it should act in a more predictable fashion. I've chosen black as a background color but you can choose any color. There are however several areas that can be improved on, • firstly the way in which the image moves in relation to the mouse is not

Interacting with images 108 An Introduction To Programming With Processing

very interesting to interact with. It would seem that the image appears to be stuck to the mouse. In order to fix this we will make the image lag slightly behind the mouse and then slowly catch up to the position of the mouse by creating a new variable that we can use to control the speed at which the image moves. This will create the impression of the image's movement being affected by friction. • Secondly because the image's origin is it's top left hand corner, when we move the mouse down we tend to expose the background above the image, so we'll also make the image react to the mouse's y position in relation to the center of the image and not it's top left hand corner. This reduces the possibility of exposing the background and makes the image more of a focal point. • Finally we will constrain how far the image can move along the Y axis so as to completely eliminate the possibility of exposing the background.

Friction simulation

Friction is the force that resists the relative motion of something else (like an object, a gas, a liquid, etc), and is the effect that we will be attempting to simulate (in a simplified form) in this sketch. By moving the mouse up and down within the Display Window the image should try to follow the mouse and slow down as it approaches the mouse, this will create the impression of friction. We'll start by creating three new variables. Add the following statements at the top of the sketch, below the PImage statement: float yPos; //declaration related to image Y position float difY; //declaration related to difference between //mouse and image's Y position int frict = 30; //initialization, friction. high values make //image move slower float is a keyword for declaring floating point variables. Floating point values are numbers that have a fractional part, that is to say they are numbers with a decimal value such as 1.0, -2.9865, 10000.423, 0.0000001 and so on. Floating point numbers will tend to require more memory for storage so if you can get away

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

Interacting with images 110 An Introduction To Programming With Processing

Variable naming conventions

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

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

Interacting with images 111 An Introduction To Programming With Processing

Planning and Pre-Debugging

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

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

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

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

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

Interacting with images 112 An Introduction To Programming With Processing

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

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

Interacting with images 113 An Introduction To Programming With Processing

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

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

Implementing a Programmatic Solution

To summarize we are dividing the difference between the mouse's Y position and the center of the image with the frict value, then adding this value to the images current position. We can express this programmatically with the following two statements, which you can add to your sketch before the image statement: difY = mouseY - (yPos + doors.height/2); yPos += difY/drag;

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

Interacting with images 114 An Introduction To Programming With Processing which is the process of condensing a statement that uses the common technique of using a variable in an expression, then assigning the value of the expression back to the same variable. For example the statement: x = x + 5;

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

Both statements evaluate to the same answer, the latter is a more commonly used method for this type of statement, as this kind of statement is so commonly implemented in programming. Some other examples of augmented assignment follow: x = x -5; //Can be expressed in augmented assignment form as: x-=5; x = x * 7; //Can be expressed in augmented assignment form as: x*=7;

/= and %= can also be used in augmented assignment. As you can see the following statement used in our sketch is an example of augmented assignment: yPos += difY/drag; //Can also be expressed as: yPos = yPos + difY/drag;

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

Interacting with images 115 An Introduction To Programming With Processing to move beyond it's boundaries and display the sketches background. Fortunately we have a function in Processing that allows us to stop values from getting too high or too low.

Constraining Values

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

At first this statement could look a little intimidating, but in fact you already know what's going on in most of the statement and it's only the Y parameter of the image() function that is somewhat different. As you are aware the image() function accepts three parameters, firstly the object variable containing the image (doors), secondly the value of the X position you would like the image rendered at and finally the images Y position. This statement is in the draw() structure and as a result will be repeated throughout the program's run-cycle, this means that every time the user moves the mouse the difY variable will change and as a result so too will the yPos variable. It is therefore necessary for this statement to be within the draw() structure, or these changes will never be seen. The Y parameter of the image() function accepts an expression in this example, the expression consisting of the constrain() function: constrain(yPos, height - doors.height, 0)

This expression when evaluated, returns the value of the image() function's Y parameter. The constrain() function clamps the yPos value so that the image is never raised above the value returned from height – doors.height and never

Interacting with images 116 An Introduction To Programming With Processing lowered below 0, this will be the point where the image's origin matches the Display Window's origin.

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

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

... float imageY; void setup(){ ... doors = loadImage("doorsClosed.png"); ... } void draw(){ … imageY = constrain(yPos, height- doors.height, 0); image(doors,0, imageY); }

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

Interacting with images 117 An Introduction To Programming With Processing

Branching

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

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

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

Branching 118 An Introduction To Programming With Processing

Multiple if statements can be used within the same program and even within the same draw() structure. They are identified by the if keyword followed by parenthesis containing a conditional. The conditional for an if() statement will always return a value that is true or false through the process of evaluation which can be based on a comparison expression. We'll have a look at the process of comparison a bit later, for now we'll focus on the boolean datatype.

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

Type casting errors

Branching 119 An Introduction To Programming With Processing

If we were to declare a boolean variable and use it in an if statement, it might look something like this: boolean myValue = true; //initialization if(myValue){ //if conditional returns true … run these statements //statements within if() structure } //are run

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

In the previous example we have used initialization to declare a variable of type boolean and assign the value of true to it. We then used the new variable in an if() statement conditional (the part between parenthesis following the if keyword). The way that an if statement works is the program will evaluate the expression within the conditional, if the conditional evaluates to true the code delimited within the if() statements braces will be run. However if the conditional evaluates and a value of false is returned, it will skip the code within the if() statement's braces and proceed to the statements that follows, for example: boolean myValue = false; //variable initialized to //false if(myValue){ //conditional evaluates to … don't run these statements //false }

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

Using this method of programming we have allowed our program to make a decision based on certain conditions, in a real world situation the conditions the program would evaluate would usually be dynamic for example a user interaction or some other dynamic feature.

Branching 120 An Introduction To Programming With Processing

Relational Operators

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

Using a single expression within a conditional

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

Comparison

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

Branching 121 An Introduction To Programming With Processing

< less than > greater than == equality <= is less than or equal to >= is greater than or equal to != inequality

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

(5>1)

This is a conditional extracted from an if() statement, it consists of a single comparison. The comparison returns a value of true and would be read as “ five is greater than one”. The next example demonstrates a comparison that returns a value of false:

(5<1)

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

(mouseY > height/2)

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

Branching 122 An Introduction To Programming With Processing void setup() { size(300,300); } void draw() { if( mouseY >= height/2){ println("Mouse is in the bottom half of the sketch"); println(mouseY); } println("Mouse could be in either half"); }

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

Branching 123 An Introduction To Programming With Processing of the code within the draw() structure that once again tells it to print "Mouse could be in either half".

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

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

Extending the if() structure with else

In our previous example, we where able to run statements based on whether the mouse was in the bottom half of the Display Window, if we change the conditional to read:

(mouseY <= height/2) then we could get Processing to run a set of statements based on whether the mouse is in the upper half of the Display Window. But what if we wanted Processing to run a specific set of statements when the mouse is in the upper half

Branching 124 An Introduction To Programming With Processing of the Display Window and a different set of statements when the mouse is in the other half of the Display Window? Using an if statement to do this by itself would not be possible, but fortunately we can extend the if() structure with the else keyword. Use of the else keyword within an if() structure ensures that even if the conditional returns a value of false that the code that follows else (which is still within the if() structure) will be run, before the program exits the if() structure and moves on to the rest of the statements making up the program. This can effectively provide us with a fail safe method of ensuring that code is run within an if() structure before the program exits the structure. For example if we wanted to get our sketch to tell us whether the mouse is specifically in the upper or lower half of the Display Window we would modify the previous sketch to look like this: void setup() { size(300,300); } void draw() { if( mouseY >= height/2){ println("Mouse is in the bottom half of the sketch"); println(mouseY); }else{ println("Mouse is in the upper half of the sketch"); println(mouseY); } println("Mouse could be in either half"); }

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

Branching 125 An Introduction To Programming With Processing

Extending the if() construct with if else if else There are many times when you will require more than the two branches that an if else construct will permit, and in that case you can use the process of nesting multiple if else structures within others. For example, in our previous sketch when our program started and our mouse was not hovering over the Display Window, Processing rightfully skipped the first if() control structure and went to the else structure. However we could capture this possibility in a condition and associate it with it's own code block. An if else if else construct generally follows this pattern: if(condition){ ...statements }else if(condition){ ..statements }else{ ...statements }

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

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

Branching 126 An Introduction To Programming With Processing

Logical Operators

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

&& logical AND || logical OR ! logical NOT

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

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

(5>3 && 3<1) //Returned as False, because the //expression in the right is false logical OR returns a value of true if at least one of the expressions on either side of it is true, for example:

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

(5>3 || 3<1) //Returned as True, because the //expression on the left is true

(5<3 || 3<1) //Returned as False, because both //expressions are false logical NOT (also traditionally referred to as “bang”) works in a somewhat different manner to that of it's counterparts. It will return a value that is the opposite of the expression it is evaluating. For example if an expression such as x>1 evaluates to true, then !(x>1) will evaluate to false. However, be cautious of how you choose to use this operator as you can often express the meaning of your code in another format that might be easier to read, for example:

Branching 127 An Introduction To Programming With Processing if (!(x>1)) ... //can also be expressed as, if (x<=1) ...

However the logical NOT operator can be useful, for toggling the boolean value of an expression when that expression is required in several places in a certain state and only once in the opposite state. For example: boolean x = true; ellipseMode(CORNER); if (x) { rect(25, 25, 50, 50); }else{ ellipse(25, 25, 50, 50); } if (!x) { rect(25, 25, 50, 50); }else{ ellipse(25, 25, 50, 50); } println(x); //x still has the value of true associated with it

Interface Controls: Setting up a Slider

Now that we understand the theory behind branching lets use what we have learned in a sketch to create a slider that can return a numerical value, which we will map to the tinting of an image.

The best place to start with a program is always doing what your are already most familiar with so lets start by loading all the images into the sketch:

Interface Controls: Setting up a Slider 128 An Introduction To Programming With Processing

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

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

The template from which the sketch will evolve.

Interface Controls: Setting up a Slider 129 An Introduction To Programming With Processing

User Defined Functions

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

Slider Button

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

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

User Defined Functions 131 An Introduction To Programming With Processing language beyond the definition or philosophy of it's environment, but if that is your intention then you would more than likely consider abstracting a far greater degree of the languages built-in features within a library consisting of multiple classes. The definitions for user defined functions must exist outside of both setup() and draw() structures if they are to have a greater scope. Our function definition will reside at the bottom of the sketch and contain three main characteristics.

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

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

Then within the context of draw(): void draw(){ ..statements defining draw() structure }

Now as a user defined function, applicable to our sketch: boolean myFunction(){ ...statements defining myFunction }

As you can see, not a lot has changed in terms of how a user defined function is structured in comparison to the previous example using draw(). The fundamental

User Defined Functions 132 An Introduction To Programming With Processing difference is that statements delimited within the braces associated with draw() define it's structure and not the function, as the definition of the draw() function exists outside of the sketch we are creating and is something that the developers of Processing have determined. In contrast statements delimited within a user defined function form a function definition, within it's braces. In order to use the function we will then need to include a call to the function from within our main program. This is very similar to the method used to call built-in functions such as rect(), ellipse(), println() and many other functions we have already used. Let's revise our previous example to demonstrate the process of defining a function then calling it from within the draw() structure: void setup(){ ...statements } void draw(){ ...statements myFunction(); } boolean myFunction(){ ...statements defining myFunction }

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

User Defined Functions 133 An Introduction To Programming With Processing

Creating a user defined function

Datatyping a function

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

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

Determining a range

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

User Defined Functions 134 An Introduction To Programming With Processing

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

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

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

Eventually I'd like to replace the X parameter for the image() function rendering sliderFd in the X position determined by buttonXPos. As we are aware what the variable buttonXPos is going to represent we're going to set it up with a

User Defined Functions 135 An Introduction To Programming With Processing temporary value within our sketch to test our user defined function. So we're going to add a temporary statement for testing and debugging purposes to the draw() function which assigns a value to buttonXPos and then changes the image() function of which sliderFd is associated with to reflect this assignment statement. Once the buttonXPos variable is declared in global space, you can edit the draw() structure to include the first command and update the appropriate image command:

... //temp for debugging buttonXPos = width/2 - sliderBk.width/2; ... image(sliderFd,buttonXPos ,margin);

Once we are sure that our function is working we will return to the temporary statement that we adding for debugging and testing purposes and include the buttonXPos variable assignment statement within an if() structure.

We are now ready to proceed with setting up our function. To briefly recap our function has been declared as type boolean and given the name overButton(), setting up the range will occur within a conditional consisting of multiple comparisons and will look like this: boolean overButton(){ if (mouseX >= buttonXPos && mouseX <= buttonXPos + sliderFd.width && mouseY >= margin && mouseY <= margin + sliderFd.height) { …

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

User Defined Functions 136 An Introduction To Programming With Processing

1. mouseX >= buttonXPos, this checks if the mouse is anywhere in the highlighted area. If the mouse is then a value of true is returned and Processing will continue to evaluate the rest of the conditional.

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

User Defined Functions 137 An Introduction To Programming With Processing

3. mouseY >= margin, once again this comparison is only evaluated if the previous comparison was true because both comparisons are separated with &&. This comparison returns a value of true only if the mouse is below the top of the slider button.

4. mouseY <= margin + sliderFd.height, another && precedes this comparison which will finally only return true and determine if the entire compound conditional evaluates to true if the mouse's Y value is less than the bottom of the slider button.

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

Returning data from a function

Every function declared in a sketch that does not use void, must return data matching the type that the function has been datatyped as. In our example our function has been datatyped as a boolean and as a result we need a means of returning boolean data back to the program in a useful way. This boolean value that is returned back to the program, is what we will use in our main program to

User Defined Functions 138 An Introduction To Programming With Processing let us know that when the value returned from the function is true that the mouse is over the button and when the value is returned as false we can safely conclude from this information that the mouse is not hovering over the button. First we are going to declare another variable in the global scope and datatype it as a boolean, add the following variable to the global space of your sketch: boolean mouseOverButton;

Now we'll use this variable in our user defined function to return a boolean back to the main program. boolean overButton(){ if (mouseX >= buttonXPos && mouseX <= buttonXPos + sliderFd.width && mouseY >= margin && mouseY <= margin + sliderFd.height){ mouseOverButton = true; cursor(HAND); //Returns true back to main program return mouseOverButton; }else{ mouseOverButton = false; cursor(ARROW); //Returns false back to main program return mouseOverButton; } }

Returning data back to the main program is actually really easy and is simply a means of using the return keyword followed by the data you want to return which must match the same type as that of the function. Basically, our function is checking in the conditional if the mouse is within the range defined therein, if it is then it sets the mouseOverButton variable which has been declared in global space and data typed as boolean to true with a simple assignment statement. We then use the cursor function to change the mouse icon from the default ARROW to a HAND. This function also accepts parameters CROSS, MOVE, TEXT, and can also accept a PImage as a parameter. Now when the cursor is over the slider button it will change to a hand icon, giving the user a visual clue that they are hovering over a clickable element. If we where to leave the function at this point and not add an else structure, Processing would give us an error when trying to compile this sketch. This is because every function must at return a

User Defined Functions 139 An Introduction To Programming With Processing datatype if it is datatyped, meaning that in our case when the mouse is not over the slider button and we did not have an else structure capturing this possibility at that point our function would not be returning any data back to the main program. This is why it is important that we add an else structure to this if() construct, so that we can set the mouseOverButton variable to false, and subsequently return he correct data back to the main program. This also gives us an opportunity to change the cursor back to an arrow, indicating to the user that their mouse is no longer over a clickable element.

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

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

Dragging the slider button mouseDragged() is a function that provides a structure to which we can add statements each time the mouse is dragged. A dragging operation qualifies as a user clicking and dragging a mouse button anywhere in the Display Window, when this happens the mouseDragged() function will be called once, and it's structure will be executed. As a result because the mouseDragged() function is not called repeatedly for each frame that the mouse is begin dragged, we will use the function to set a variable called buttonDrag to true indicating that the mouse is currently being dragged, this variable will then be used in the draw() structure, within an if() statement which causes the slider button to follow the mouse when the variable is true and remain stationary when it is false. When the user then releases the mouse we will use a call to the mouseReleased() function (which structurally works in a similar way to the mouseDragged() function) to set the variable, buttonDrag to false within the mouseReleased() structure. What this means is that when the if() statement in draw() checks the status of this variable it

User Defined Functions 140 An Introduction To Programming With Processing will now be returned as false causing the slider button to remain stationary. In other words, we already have a function that tells us if the mouse is over the button or not, we will now add two more functions that will tell us whether the user's mouse is attempting to drag the button and whether it has been released. Mouse related functions usually follow the end of the draw() structure and should not be mixed amongst user defined functions. We'll start by declaring the buttonDrag boolean in global space: boolean buttonDrag;

Then using it within a mouseDragged() function, remember to place all mouse related functions together and not between user defined functions: void mouseDragged(){ if (mouseOverButton){ buttonDrag = true; } }

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

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

The following statement will replace it: if(buttonDrag){ buttonXPos = mouseX - sliderFd.width/2; }

User Defined Functions 141 An Introduction To Programming With Processing

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

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

Setting up regional constraints

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

sliderBd.width SliderFd CORNER

The slider button is dragged too far right

As you can see the slider button has gone too far past the right edge of the sliderBd image, subtracting the sliderFd's width from the right edge of sliderBd will solve this.

User Defined Functions 142 An Introduction To Programming With Processing

Modify the if() statement to include the following if else clause: else{ buttonXPos = constrain(buttonXPos, width/2 - sliderBk.width/2, width/2 + sliderBk.width/2 - sliderFd.width); }

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

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

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

User Defined Functions 143 An Introduction To Programming With Processing

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

Finishing the slider

The Third issue with the slider is to get it to stop dragging once the mouse has been released. For this we're going to use the mouseReleased() function. The mouseReleased() function should be placed directly below the mouseDragged() function for the purpose of readability. However to Processing it does not make a difference if the function is before or after mouseDragged(). The mouseReleased() function is pretty simple, all it does is run the function once every time the mouse button is released in the Display Window. In our case the function will check if buttonDrag is set to true, if it is then we can be sure that the slider button is being dragged. As the function is run when the mouse has been released, we can be certain that the user no longer wants to drag the button, as a result the function then sets the buttonDrag variable back to false. This means that the conditional using this variable in the draw() structure will evaluate to false, so that mouseX will no longer be used to determine the value of buttonXPos. The mouseReleased() function should look like the following code listing: void mouseReleased(){ if(buttonDrag){ buttonDrag = false; } }

Mapping Values

Now that we have the slider moving correctly we can use the values of buttonXPos and map them to any values that we choose, for example we cold

User Defined Functions 144 An Introduction To Programming With Processing map the range of values that buttonXPos returns to the amount we would like an image to scale on it's x axis, how far or fast an image moves across the screen, or just about anything that can accept a range of values as an input. We're going to map the buttonXPos range to the tint of an image, making the image appear to fade in from black. Mapping one range of values to another is done with the map() function. The map() function accepts parameters in the following format: map(mValue, oldLow, oldHigh, newLow, newHigh);

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

The oldHigh value is the maximum value of the original range, and in the context of our program: width/2 + sliderBk.width/2 – sliderFd.width

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

User Defined Functions 145 An Introduction To Programming With Processing declaring a new variable in the global scope. Add the following variable to your sketch: float imgTint;

As you can see this variable is datatyped as float, this is because the map() function returns floats. Remember that this does not mean that the parameters themselves have to be floats, nonetheless it is worth noting that in order to perform true division if the parameters you supply Processing with for the map() function are of type int Processing will typecast them to floats for the purpose of the map() function. What this means is that once those values have been evaluated by the map() function, the answer will be returned as a float. Since this is the variable that we will assign the return value of the map() function to, and as just stated this value will be a float it makes sense to datatype this variable as a float. If we try to use another datatype, such as an int, we will get a “type miss-match” error. With our new variable, imgTint, we will use assignment in the if() construct we created earlier within the draw() function, to determine it's value as the slider is dragged. Add the following statement to the if() construct, directly under the assignment statement for buttonXPos: imgTint = map(buttonXPos, width/2 - sliderBk.width/2, width/2 + sliderBk.width/2 - sliderFd.width, 0, 255);

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

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

User Defined Functions 146 An Introduction To Programming With Processing

draw()

If the slider button is being dragged Update variables

Else leave everything as it is

render the images

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

draw()

If the slider button is being dragged Update variables render the images

Else leave everything as it is render the images end draw()

How this new structure is implemented in our program will follow this pattern: buttonXPos //update variable imgTint //update variable tint() //set the tint value img //render main image now effected by tint noTint() //Turn tint off so slider images are not

User Defined Functions 147 An Introduction To Programming With Processing

//effected by it sliderBk //render slider background image sliderFd //render slider button image

This is the order within the first code block of the if else construct the second code block will follow the same order. For a full listing of the code it's best to look at the sketch itself which is named slider.pde. Finally to end off the example I've added another image to the sketch which I've associated with the object I've called star and mapped it's Y movement to the slider. Like I said the mapping of one value with a range to another range can lead to in infinite array of possibilities, and is largely the premise on which more complex applications are built upon. Why not try your own custom mappings you'll soon come to realize that with this simple function, the sky is definitely not the limit.

The final slider.pde sketch The mystery shape maker

In this next sketch we will discover two new fundamental programming concepts arrays and iterations, learn how to work with random numbers and try out a new datatype called color. The mystery shape maker is a sketch that allows the user to make several clicks in the Display Window, and by capturing and storing the

The mystery shape maker 148 An Introduction To Programming With Processing coordinates of each click constructs a new shape for the user in a randomly generated color. The shapes can be as simple or complex as you want, as you determine how many times the user gets to click in the Display Window before the mystery shape is drawn.

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

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

An everyday list:

My Shopping List //name of the list 1. Tea //element1 2. Soy Milk //element2 3. Vegan Cookie //element3

Arrays 149 An Introduction To Programming With Processing

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

Index values for arrays start at 0 and can go as high as the number of elements in an array minus 1, for example if an array has 15 elements, the index value of the last element in the array is 14. Element No. 1 Element No.3 has an index has an index value of 0 value of 2 int[] myArray = {20, 30, 40};

Element No.2 has an index value of 1

Understandably at first this system of numbering might seem a bit strange, so in order to simplify things you can think of an index number as a means of referring to an element within an array without having to know what it's value is. This concept should not be new to you as it does not differentiate very much from that which defines a variable, the main difference being that instead of using a variable name we are now using an index number within an array to reference that specific value. The syntax for referencing an element within an array follows: int[] myArray = {20, 30, 40}; //initialize array myArray[0]; //reference array element with //index number 0, which has a value //of 20.

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

Arrays 150 An Introduction To Programming With Processing

Index Number 0 1 2 int[] myArray = {20, 30, 40}; //initialize array int x = myArray[0] + myArray[2]; //sets x to 20 + 40 i.e. 60

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

With all the similarities between variables and array elements you might be wondering what the purpose of an array is? Unlike variables storing one value followed by another value of the same type within the same variable, the array does not have to replace the previous value in order to store a new value. For example, what if I wanted to store the x position of the mouse when the user clicks in the Display Window. This would be easy enough, I'd just create a variable and assign it the value of the mouseX system variable. This is fine if all I need to know is the current x position of the mouse when the user clicks. However, what if I need to know the previous x coordinate of the mouse, or the one before that and so on. Retrieving this information with a simple variable would not be possible because each time the user clicks the mouse the current value of mouseX replaces the previous value.

Arrays 151 An Introduction To Programming With Processing int mXPos; //declare variable to store mouse x //position if(userClicked){ //hypothetical conditional to test if //user has clicked mXPos = mouseX; //sets variable to current X position of //mouse }

//user moves the mouse around and clicks again if(userClicked){ //hypothetical conditional repeats to //test if user has clicked mXPos = mouseX; //replaces the previous value for mXPos //with the new X position of the mouse, //and the previous value of mXPos can no //longer be retrieved. }

With arrays this information becomes accessible to us. By using the elements of an array we can store the first x coordinate of the mouse at index 0, the second coordinate at index 1 and so on. Lets have a look at an example of this in a sketch. int[] myArray = new int[4]; //declare array with four //elements int clicks; //counts the number of clicks void draw() { //makes the program repeat } void mouseClicked(){ if(clicks<4){ //check that the user has not //clicked more than 4 times. myArray[clicks] = mouseX; //Sets the mouse x coord to //the index number in an //array that matches the //amount of times the user //has clicked. println(myArray[0]); //print the value of the //first x coordinate println(myArray[1]); //print the value of the //second x coordinate

Arrays 152 An Introduction To Programming With Processing

println(myArray[2]); //print the value of the //third x coordinate println(myArray[3]); //print the value of the last //x coordinate clicks++; //increment the click value //by 1 } }

Program Notes

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

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

Arrays 153 An Introduction To Programming With Processing

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

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

In a similar way that we used augmented assignment to shorten an expression that is commonly used in programming, we have used an increment operator in the previous example to shorten this statement. The increment operator works by adding 1 to the current value of the particular variable it is used with, then assigning this new value back to the original variable. This is a common method of getting a program to count for you as each time the variable is used with the increment operator it will return a value that is one more than it's previous value. Writing this statement without the increment operator would look like this: clicks = clicks + 1;

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

The result of this statement is that the clicks variable will now be one more than it's previous value by the time the program repeats. For example the clicks variable was initially 0, but at the end of the if() statement the clicks variable will have a value of 1. This is important because the next time the user clicks a mouse

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

Dynamic assignment for elements in an Array

For the mystery shape maker sketch we are going to use two arrays, one will store the mouse's X positional values and the other will store the mouse's Y positional values, each time the user clicks in the Display Window. As there is no way of knowing exactly where the user is going to click in the Display Window we will need to populate these arrays with the aforementioned values, dynamically. This means each element of the array must have values assigned that relate to the values of the user's mouse's X and Y positional data while the program is running and the user has clicked in the Display Window. We then need to make sure those values are not overwritten but stored in memory and can be accessed through their index numbers of the arrays they are associated with. Finally when the user has clicked the last point contributing to the mysterious shape the conditional that was

Arrays 155 An Introduction To Programming With Processing evaluating to true and subsequently assigning positional data to the elements in the array, will now evaluate to false as the number of clicks increases in value. We will then use the beginShape() and endShape() functions and combine each one of the two arrays' corresponding elements into a coordinate for the vertex() function, which will be embedded within a loop that cycles through the two arrays extracting the information from them and subsequently drawing the mystery shape. Although this might sound like a handful, you already know how to create two thirds of this program. Nonetheless, lets recap on these fundamental programming topics as they will more than likely prove to be a useful asset in many a sketch.

First we are going to start by declaring and/or initializing the following global variables: int points = 6; //number of points int clicks; //click counter int[] numx = new int[points]; //array for mouse x //coordinates int[] numy = new int[points]; //array for mouse y //coordinates

//generate a random color for the shape's fill color randCol = color(random(256), random(256), random(256));

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

It is worth noting that in the actual sketch we have not used a numerical constant

Arrays 156 An Introduction To Programming With Processing but rather a variable to determine how many elements will populate the array, this is because if we decided we want to use more or less points making up the mystery shape, it would be easier to implement this change by means of modifying the initialization statement for the points variable rather than having to change numerical values scattered throughout the sketch.

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

Where color is the keyword used to declare variables of type color, varName is the name of the variable, and the assignment operator is used to assign a color value in R (red), G (green) and B (blue) values. RGB values range from 0 to 255 each. Note the expression used for each of the R, G and B values: random(256) random() is a function that is used to return a random number, that is between 0 and the number specified, but not including the specified number. As a result the parameter 256 is used so that Processing will include values between 0 up to and including 255. random() also accepts parameters in the form of: random(Low, High);

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

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

if (clicks

Arrays 157 An Introduction To Programming With Processing

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

void mouseClicked(){ clicks++; }

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

Iterations

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

Iterations 158 An Introduction To Programming With Processing

Of the main differences that separate one languages implementation of for loops from that of another, will generally not be anything structural by rather syntactic. For example some programming languages use comma's to separate init, test and update Processing uses a semi-colon implying that each is a statement on it's own. • The term init in the previous example is used to describe initialization. In a for() loop iteration init is used to declare a temporary variable that will usually be used in the iterations structure, test and update. • Test is used to describe a conditional, which like a normal conditional will evaluate to true or false. If the conditional evaluates to true the for() structure will run, if the conditional evaluates to false the entire for() loops structure is skipped and Processing will continue to the statement/s that follow the for() structure in the sketch. • Update is used to describe an expression that will determine how the value of the variable in the conditional is being changed. The value of the variable being evaluated in the conditional must change, by means of the update, or the loop will go on forever which will eventually cause Processing to crash. For example an increment statement is often used in update to increment the value of the variable initialized in init and evaluated in the conditional test.

In programming it is common to use a for() loop iteration to get your program to count for you, as per the following example: for (int i = 0; i < 10; i++){ println(i); } //prints 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 one digit at a time

The previous example used a for() loop iteration to count from 0 to 9, lets have a look at how we did this. First we need to use the for keyword to indicate to Processing that we are about to create a for() loop iteration. A for loop iteration relies on three statements init, test and update within parenthesis so that they are specifically associated with the for() loop iteration structure. As you can see the three statements are separated with semi-colons, this is unique to a for() loop iteration in Processing and clearly differentiates these statements from being parameters. As init is used to initialize a variable within the for() loop iteration structure, the scope of this variable is limited to the for() structure. What this means is that the

Iterations 159 An Introduction To Programming With Processing variable i in our previous example will not be accessible in other places within our sketch and only be accessible within the for() structure. As a result this variable name is usually i or n and not very descriptive. It is actually more distracting to call a variable initialized within a for() loop anything other than i or n (some people might also use x but this can be a bit distracting from variables that use x to denote a position on the x axis). It is therefore advisable to not use a variable name that is any more descriptive than a single character such as i or n. Once we have the variable initialized we can then use it in a test, if the test evaluates to true the code within the for structure will be run. It is important to note that if the test evaluates to true the code within the for structure is run, and only after this code is run is the update statement executed.

A graphical representation of how an iteration works

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

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

Iterations 160 An Introduction To Programming With Processing beginShape(); for(int i = 0; i < points; i++){ vertex(numx[i], numy[i]); } endShape();

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

if (clicks

Iterations 161 An Introduction To Programming With Processing

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

void mouseClicked(){ clicks++; }

Transforms

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

Translation, Scaling, Rotation.

Translation is simply another way of saying “moving” but as the term moving can tend to be somewhat ambiguous when you consider that rotation also involves movement and so too does scaling (when you consider that the components making up an object such as it's vertices move when the object is scaled), we prefer to use the term translation as it specifically refers to positional data in terms of x, y and z of an entity. The function for applying translations within a sketch is translate() and it accepts parameters in the form of x and y with an optional third parameter for z (which we will discuss soon) when using a 3D renderer. Rotation is a transform that we have not discussed in any of our previous sketches, and as you will see can be a useful asset to creating certain types of animation within a sketch. Amongst the functions that provide us with access to rotation are rotate(), rotateX(), rotateY() and rotateZ() these functions accept values in radians. Scaling is a transform accessed with the scale() function and it accepts a single float value or two floats that relate to x and y or three floats that relate to x, y and

Transforms 162 An Introduction To Programming With Processing z for 3D sketches. Scaling creates the impression of making things appear to be bigger or smaller within a sketch.

Let's have a look at an example of a static sketch using the translate() function. size(400,60); rect(0,0,50,50); translate(width/2, 0); fill(255,0,0); rect(0,0,50,50);

A static sketch using transforms

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

Although the effect of what you are seeing in the Display Window creates the impression that Processing has moved the rectangle, the rectangle as it is

Transforms 163 An Introduction To Programming With Processing indicated by it's X parameter in both rect() function calls tells us something different. That is that the rectangle has in fact not moved. The reason that the rectangle has come to be drawn in this new location is due to the effect of the entire coordinate system moving. If you were for a moment to reflect back on the Cartesian graph system that we discussed earlier you would remember that everything in Processing works in a similar fashion to that of something drawn on graph paper. Bearing this in mind, what we have done in the previous sketch cannot accurately be described as moving the rectangle, but rather more akin to us moving the “graph paper”. For example if you were to draw a rectangle on a piece of graph paper, then move the graph paper around, you would in effect be creating the impression of the rectangle drawn on the graph paper moving around. The rectangle itself would not be what you are moving around, in terms of the fact that the rectangle's positional x and y data has not changed with relation to the origin of the coordinate system it was drawn relative to. We can therefore say that the rectangle has not moved, however the coordinate system associated with it has.

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

This is the purpose of transforms in Processing, they move the coordinate system for us. We can still move the components of a sketch through their own positional data, which we usually supply in terms of X and Y parameters of a function, but bear in mind that mixing translation techniques like this will result in the component appearing to have “moved” by the sum of the two data sets. To put this in another way, the distance the entity would appear to have moved would be the sum of the translate() function plus the X, Y and Z parameters of the function to draw the entity. So if we still have the ability to modify components of a sketch via their own X and Y parameters what's the benefit of having transforms? Transforms can save us a lot of unnecessary work, make our code a lot easier to read and provide us with functionality that would not be possible without them.

Transforms 164 An Introduction To Programming With Processing

Lets have a look at an example of how this works. In order to see the benefits that transforms have on our code we'll revisit the smile sketch from our static sketch examples at the beginning. If you recall, the purpose of the sketch was simply to draw a smiley face to the Display Window in static mode with some other components. We're only interested in the smiley face, so first we're going to adapt the sketch for active mode by including the drawing of the face within the draw() structure: void setup(){ size(640,480); } void draw(){ background(127); //Drawing the face fill(191,233,255); ellipse(width/2, height/2, 100, 100); //smile noFill(); stroke(255,0,0); arc(width/2, height/2 + 10, 50, 50, 0, PI); //eyes stroke(0,0,0); fill(0,255,0); ellipse(width/2-15, height/2-15, 20, 30); ellipse(width/2+15, height/2-15, 20, 30); }

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

Transforms 165 An Introduction To Programming With Processing

As you can see nothing surprising about the sketch, but what if we wanted to animate the smiley face by moving it across the Display Window, or attaching it to the mouse? This could become quite a cumbersome task as every component of the smiley face that has X and Y parameters would have to be updated for every frame. To give you an indication of how much extra work this is we're going to have a look at what sort of changes in the sketch would need to be implemented if we wanted to attach the smiley face to the mouse: void setup(){ size(640,480); } void draw(){ background(127); //Drawing the face fill(191,233,255); ellipse(mouseX, mouseY, 100, 100); //smile noFill(); stroke(255,0,0); arc(mouseX, mouseY + 10, 50, 50, 0, PI); //eyes stroke(0,0,0); fill(0,255,0); ellipse(mouseX-15, mouseY-15, 20, 30); ellipse(mouseX+15, mouseY-15, 20, 30); }

As you can see almost every second line of code had to be updated within the draw() structure. Now imagine if you had a whole character you wanted to draw and how much additional work something like that could amount to? With transforms making a change like this to your code is easy: void setup(){ size(640,480); } void draw(){ background(127); //transform translate(mouseX-width/2, mouseY-height/2);

Transforms 166 An Introduction To Programming With Processing

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

Notice that only one additional line of code was needed to accommodate for this update, the rest of the code remained unchanged. The additional statement is: translate(mouseX-width/2, mouseY-height/2);

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

Offset from the origin with mouseX

Offset from the origin with mouseX - width/2

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

Transforms 167 An Introduction To Programming With Processing

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

Main Cart

Background wheel Foreground wheel

The template rendering of the cart.pde sketch

The function pushMatrix() when called before a transform is executed will store the current position of the coordinate system. This means that if you call a pushMatrix() function at the start of the draw() structure it will remember the default position of the coordinate system (pre-transform). You are then free to apply transforms to the particular component of the sketch that you would like to scale, rotate or translate. Once you are satisfied with the transforms you have performed you can then render the component, for example by means of a call to

Transforms 168 An Introduction To Programming With Processing the image() function. Running the popMatrix() function at this point will then be necessary to restore the coordinate system back to the state it was in when the previous pushMatrix() was called. You can then proceed to run more pushMatrix(), transforms, render, popMatrix() combinations on other components of the sketch which will remain unaffected by the previous transforms. Using pushMatrix() and popMatrix() in this way allows us to apply multiple transforms to a component of a sketch ,and not have those transforms effect other components.

Transforms 169 An Introduction To Programming With Processing

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

PImage cart; PImage wheelFd; PImage wheelBd; PImage grass; void setup(){ size(800,600); cart = loadImage("cartMain.png"); wheelFd = loadImage("wheelFd.png"); wheelBd = loadImage("wheelBd.png"); grass = loadImage("grassLessBlur.jpg");

} void draw(){ background(grass); imageMode(CENTER);

image(wheelBd, -75, 25); image(cart, 0, 0); image(wheelFd, -95, 35); //println(mouseY);

}

Out of interest you might be wondering how I came about selecting the X and Y parameters of the image() functions which render the wheels relative to the position of the cart. If you look at the last line you'll see a println() function that has been commented out. By replacing the image() function's X and Y parameters with mouseX then mouseY, respectively and one at a time, you can run the sketch with the image of the wheel attached to either the mouse's X or Y position. Place the wheel in the position it should be in, the println() function (when uncommented) will print out the position of your mouse, note this value and replace it with the mouseX or mouseY system variable in the wheel's image() function's corresponding X or Y parameter.

Transforms 170 An Introduction To Programming With Processing

As the imageMode() function is set to CENTER in this example you will have to move the cart image to a location that is not the origin, so that the left and top halves of the image is not obscured by the boundaries of the Display Window. You will then need to subtract the value that you added to the X and Y parameters of the image() function to draw the cart from the respective values printed in the Text Area that will be used to place the wheels in the correct locations.

Now that we have a template from which to start let's set up a temporary system that allows the cart to trail after the mouse with a bit of friction, we'll then modify this code to suit the needs of our sketch. This methodological approach to sketching by creating a rough idea then refining it will allow us to see results much sooner in the sketching process, rather than spending a lot of time on a sketch only to find out when it is almost done that the effect we were trying to achieve isn't quite working out. We'll start by adding the following global variables: float xPos; float difX; int drag = 30;

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

image(wheelBd, -75, 25); image(cart, 0, 0); image(wheelFd, -95, 35);

difX = mouseX - (xPos + cart.width/2); xPos += difX/drag;

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

Transforms 171 An Introduction To Programming With Processing

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

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

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

We would call this a 4 x 5 matrix meaning that it is made up of 4 rows and 5 columns. This is not an actual representation of a matrix that Processing uses to calculate transforms but simply an example of what a matrix could look like, in fact the matrices that Processing uses are simpler than the previous matrix example. You might hear the term transformation matrix used on occasion, this is just simply referring to the numbers that make up the matrix that the matrix representing the current coordinate system must be processed through in order to produce the representation of the coordinate system in it's transformed state. Although this might sound like a bit of a tongue twister, the concept is less

Transforms 172 An Introduction To Programming With Processing

complicated when you think of it in graphical form. Following is an example of what this might look like as a graphical representation, remember the numbers are purely illustrative, and not intended to represent actual numerical data and patterns that Processing calculates:

Matrix representing Transformation matrix Resulting matrix current coordinate stores data about representing new system translation, rotation coordinate system and scaling pushMatrix() = popMatrix()

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

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

image(cart, 0, 0); image(wheelFd, -95, 35);

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

Transforms 173 An Introduction To Programming With Processing

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

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

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

As the xPos variable changes relative to the distance the cart has moved we can use the changing properties of this variable to make the wheels rotate. We can then divide this number by the width of the wheel image which is also the diameter of the circular shape of the wheel. This expression is based on the formula for pi which is pi = circumference/diameter, but it is worth noting that the

Transforms 174 An Introduction To Programming With Processing value returned from our modified expression is not equal to pi, as this would be a constant value as a result xPos is substituted for the circumference of the circle as this will yield a value that changes relative to the distance that the cart has traveled.

We can then render the image at the origin after the coordinate system has been transformed, so the image appears to have moved because the coordinate system it is rendered relative to has, by then, been transformed. image(wheelBd, 0, 0);

Finally use popMatrix() to reset the coordinate system back to it's original transformations. We can then continue to render the main cart and foreground wheel using the same techniques, and not have transformations from one rendering effect another.

In the final cart.pde example I've added a shadow, try to figure out how you would go about creating this effect before looking at the code. Here's a hint, I've added four additional images to the sketch.

The completed cart.pde sketch

Transforms 175 An Introduction To Programming With Processing

An Introduction to 3D in Processing

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

Y

X Z

Axes indicating 3 Dimensions

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

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

An Introduction to 3D in Processing 176 An Introduction To Programming With Processing import processing.opengl.*;

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

A typical example of a sketch using OpenGL might look something like this: import processing.opengl.*; void setup(){ size(500,500,OPENGL); } void draw(){ background(127); … }

3D Primitives

In a similar way that Processing has 2D primitives such as rectangles, ellipses, lines etc you will also find a set of 3D primitives such as a box or a sphere. However you are free to use 2D primitives in a 3D sketch, but not 3D Primitives in a 2D sketch. One of the fundamental differences that separates the way in which the functions used to render 3D primitives differs from rendering 2D primitives, is that 3D primitives do not have parameters for X, Y and Z coordinates. For example the function to draw a box which is box() can accept three parameters but these parameters relate to width, height and depth. So how to we place 3D primitives in a sketch and move them around? This is achieved with the transform functions we have been using in our 2D sketches. The main difference is that now we have an additional axis to consider the Z axis, as a result in a 3D sketch translate() can be used with either 2 or 3 parameters for example:

An Introduction to 3D in Processing 177 An Introduction To Programming With Processing translate(X, Y); //or translate(X, Y ,Z);

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

Where num is the numerical value in radians that the coordinate system will be rotated around the corresponding axis.

Using the box() function and translations here's an example of how we could go about drawing a simple robot character using OpenGL: import processing.opengl.*; void setup(){ size(500,500,OPENGL); } void draw(){ background(127);

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

An Introduction to 3D in Processing 178 An Introduction To Programming With Processing

box(30); translate(40,0); box(30); popMatrix();

}

A simple robot character rendered in Processing using OpenGL

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

Guess My Number Game

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

Guess My Number Game 179 An Introduction To Programming With Processing

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

Guess My Number Game 180 An Introduction To Programming With Processing

Object Oriented Programming

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

Object Oriented Programming 181 An Introduction To Programming With Processing

The Procedural Programming The Object Oriented Paradigm Programming Paradigm Data to represent Data to represent

API features API features Class organizes data

Data represented with Objects representing API features Class

Main Program Main Program

An graphical representation of how OOP works

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

The concept of a class

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

Object Oriented Programming 182 An Introduction To Programming With Processing program will, like a function, have a definition independent of the main program and also have properties that are specific to the class it was instantiated from. The benefit of this is that when multiple objects are instantiated from a single class they all inherit the methods of that class, this allows you to use certain methods with one object and certain other methods with another object. Thereby creating relationships between those objects (and ultimately the data you are representing with you main program) with other data or API features in ways that would be very difficult or maybe not practically possible without OOP.

Branch 01

Method 1 Branch 02

Class Object 1 Method 3 Method 1 Method 2 MAIN PROGRAM Method 3 Object 2 Method 2 Function Call Function Definition

Method 2

Branch 04

Branch 03

One class can result in many different branches.

The Blueprint Analogy

By creating classes we categorize the data we are representing and give these representations a context by associating them with features in the programming languages API. However a class is never used in the main program, it must first

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

A single blueprint could be used to make several derivatives

Object Oriented Programming 184 An Introduction To Programming With Processing

Why use Object Oriented Programming

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

Creating a Class

As previously mentioned a class typically consists of method definitions and various fields (which we also refer to as member variables) that store information about the current state of the object instantiated from the class. The term fields

Object Oriented Programming 185 An Introduction To Programming With Processing refers to variables that are members of a particular class, and as a result are encapsulated data that store information about the object itself and are sometimes referred to in Processing as class data. Typically in Processing creating a class is a four step process that involves,

1)Class Name creation 2)Field declarations 3)Constructor creation 4)Method definitions

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

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

Object Oriented Programming 186 An Introduction To Programming With Processing

The Tab fly-off from the PDE

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

Creating a new Tab

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

Object Oriented Programming 187 An Introduction To Programming With Processing into smaller manageable portions of code. As a result when a sketch with multiple Tabs is run all the code within all the Tabs of that sketch are compiled together. This means that only one of the Tabs should have setup() and draw() structures, the other Tabs should be used for class definitions, user defined functions or other elements of a sketch that exist outside of setup() and draw() structures.

A Button Class

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

The completed buttonClassExample file

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

This is how we create a class and name it in Processing. As you can see the class's

A Button Class 188 An Introduction To Programming With Processing name is Button which starts with an upper-case character, in-line with popular standardized coding practices. When we instantiate an object from this class there are several properties we'd like this object to inherit from the class, which we will have access to modifying from the main program but not be able to modify the definitions of these properties as this will be encapsulated within the Button class. A list of the these properties follow: 1. the color of the rectangle that will visually represent the button object, 2. the object's X coordinate 3. the object's Y coordinate 4. the object's width 5. the object's height 6. and a name for the object.

As a result we will need at least all six of these properties represented in the class's fields as variables. Let's add those fields to the class, inside the braces of the Button class add the following declarations: color cB; float xLocB; float yLocB; float xSizeB; float ySizeB; String nameB;

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

//this is simply for illustrative purposes Button(cB, xLocB, yLocB, xSizeB, ySizeB, nameB);

A Button Class 189 An Introduction To Programming With Processing

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

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

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

A Button Class 190 An Introduction To Programming With Processing of the many reasons why class's have methods. In order to render this visual representation we're going to create a method called disp() which will create a rectangle from the parameters the user inputs into the Button() constructor when instantiating a new object. Just like user defined functions methods must use the void keyword if they do not return a datatype. Here's what our disp() method (short for display method) will look like:

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

Creating a method follows the same routine as creating a user defined function. Our disp() method is really quite simple all it does is accept the cB variable as a fill() color, draw a rectangle with the positional data from xLocB and yLocB and finish the rectangle by determining it's size from the xSizeB and ySizeB variables. The method then goes on to set the fill() to black and render the name of the button (nameB) in the center of the button.

A class can be as simple or a complex as you want, and since we have all the “main ingredients” of our class we're going to return to our main program and have a look at how to instantiate an object from this class.

Object Instantiation

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

Button myButton;

A Button Class 191 An Introduction To Programming With Processing

We now have a variable name that we can use to reference the object we just instantiated from the Button class, this name is myButton. Within the setup() structure we'll initialize the button: myButton = new Button(color(255), width/2, height/2, 100, 40, "myButton"); myButton (the object variable) has inherited the properties of the Button class. If you were to compare this statement with the modified example of the class's constructor:

//this is simply for illustrative purposes Button(cB, xLocB, yLocB, xSizeB, ySizeB, nameB);

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

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

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

A Button Class 192 An Introduction To Programming With Processing

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

Working with external data

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

A simple text file

A text file imported into a sketch should have the file extension .txt. A word processor document might have additional formatting and as a result might produce unexpected results when used in a sketch. For this exercise it is recommended that you use the file called names.txt. Importing a text document into a sketch works in the same way that that images are imported into a sketch. Locate the file to be imported and click and drag it into

Working with external data 193 An Introduction To Programming With Processing the PDE with the sketch you are working on, open. The PDE will report that a file has been added successfully to the sketch and if you were to open the sketch's data folder you will find a copy of the file in there. In order to display the contents of the names.txt file in the Display Window we will use an array of Strings with each element of the String representing a line of characters in the names.txt file. Lets have a look at how to do this.

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

String[] names;

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

String[] names = new String[10560];

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

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

Working with external data 194 An Introduction To Programming With Processing void draw() { for(int i = 0; i < names.length; i++){ text(names[i], 20, i*20 + 20); } }

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

The loadStringsExample.pde file

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

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

Working with external data 195 An Introduction To Programming With Processing void setup() { size(300,300); smooth(); names = loadStrings("names.txt"); numbers = loadStrings("numbers.txt"); } void draw() { background(100); for(int i = 0; i < names.length; i++){ text(names[i],20,i*20 + 20); } for(int i = 0; i < numbers.length; i++){ tCast += int(numbers[i]); //typecasting int(numbers[i]) } text(tCast,250,20); }

Working with external data 196 An Introduction To Programming With Processing

Attribution

Images

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

Attribution 197