From fc3d75abf6bab4602d7c3559d8b85d9e6894e722 Mon Sep 17 00:00:00 2001 From: zach lieberman Date: Sun, 22 Mar 2015 17:59:00 -0400 Subject: [PATCH 1/4] change all smart quotes, worth a thorough review --- chapters/OOPs!/outline.md | 2 +- chapters/animation/chapter.md | 2 +- chapters/cplusplus_basics/chapter.md | 10 +- chapters/cplusplus_basics/unabridged.md | 14 +-- .../data_vis/MichaelHadleyChapterFeedback.md | 14 +-- chapters/data_vis/chapter.md | 24 ++-- chapters/game_design/chapter.md | 106 ++++++++--------- chapters/game_design/old drafts/oscchapter.md | 108 +++++++++--------- chapters/hardware/chapter.md | 14 +-- .../chapter.md | 2 +- .../installation_up_4evr_macosx/chapter.md | 70 ++++++------ chapters/intro_to_graphics/Cut Material.md | 2 +- chapters/ios/chapter.md | 2 +- chapters/ios/outline.md | 2 +- chapters/math/brannon_edits_chapter.md | 2 +- chapters/project_elliot/chapter.md | 4 +- chapters/project_joel/chapter.md | 4 +- chapters/project_joel/unabridged.md | 4 +- .../setup_and_project_structure/outline.md | 2 +- 19 files changed, 194 insertions(+), 194 deletions(-) diff --git a/chapters/OOPs!/outline.md b/chapters/OOPs!/outline.md index 0a5b8dec..bca15b54 100644 --- a/chapters/OOPs!/outline.md +++ b/chapters/OOPs!/outline.md @@ -22,4 +22,4 @@ http://www.openframeworks.cc/tutorials/first%20steps/003_ooops_object_oriented_p -What is it / what does it mean ? - example of basic class and object (polymorphism) - make a simple class (simple particle?) - - make different objects from the same class \ No newline at end of file + - make different objects from the same class diff --git a/chapters/animation/chapter.md b/chapters/animation/chapter.md index 0452f7ee..63b2a7d9 100644 --- a/chapters/animation/chapter.md +++ b/chapters/animation/chapter.md @@ -6,7 +6,7 @@ ## Background -The word animation is a medieval term stemming from the Latin animare, which means ‘instill with life’. In modern terms, it's used to describe the process of creating movement from still, sequential images. Early creators of animation used spinning discs (phenakistoscopes) and cylinders (zoetropes) with successive frames to create the illusion of a smooth movement from persistence of vision. In modern times, we're quite used to other techniques such as flip books and cinematic techniques like stop motion. Increasingly, artists have been using computational techniques to create animation -- using code to "bring life" to objects on the screen over successive frames. This chapter is going to look at these techniques and specifically try to address a central question: how can we create compelling, organic, and even absurd movement through code? +The word animation is a medieval term stemming from the Latin animare, which means 'instill with life'. In modern terms, it's used to describe the process of creating movement from still, sequential images. Early creators of animation used spinning discs (phenakistoscopes) and cylinders (zoetropes) with successive frames to create the illusion of a smooth movement from persistence of vision. In modern times, we're quite used to other techniques such as flip books and cinematic techniques like stop motion. Increasingly, artists have been using computational techniques to create animation -- using code to "bring life" to objects on the screen over successive frames. This chapter is going to look at these techniques and specifically try to address a central question: how can we create compelling, organic, and even absurd movement through code? As a side note, I studied fine arts, painting and printmaking, and it was accidental that I started using computers. The moment I saw how you could write code to move something across the screen, even as simple as silly rectangle, I was hooked. I began during the first dot-com era working with flash / actionscript and lingo / director and have never looked back. diff --git a/chapters/cplusplus_basics/chapter.md b/chapters/cplusplus_basics/chapter.md index 6ac90b75..2a683307 100644 --- a/chapters/cplusplus_basics/chapter.md +++ b/chapters/cplusplus_basics/chapter.md @@ -151,16 +151,16 @@ Let's do an experiment. In the code editor, please comment out the include direc The syntax coloring will change to all green, meaning it's now just a comment. Run the code by pressing the big green button at the bottom right, and you'll see something new in the output pane. ``` -prog.cpp: In function ‘int main()’: -prog.cpp:5:2: error: ‘cout’ was not declared in this scope +prog.cpp: In function 'int main()': +prog.cpp:5:2: error: 'cout' was not declared in this scope cout << "Hello World" << endl; ^ -prog.cpp:5:27: error: ‘endl’ was not declared in this scope +prog.cpp:5:27: error: 'endl' was not declared in this scope cout << "Hello World" << endl; ^ ``` -The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function ‘int main()’`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: ‘cout’ was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. +The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function 'int main()'`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: ‘cout’ was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. ```cpp #include @@ -187,7 +187,7 @@ It's a very similar error as before, where it cannot find `cout` or `endl`, but ``` prog.cpp:5:2: note: suggested alternative: In file included from prog.cpp:1:0: -/usr/include/c++/4.8/iostream:61:18: note: ‘std::cout’ +/usr/include/c++/4.8/iostream:61:18: note: 'std::cout' extern ostream cout; /// Linked to standard output ^ ``` diff --git a/chapters/cplusplus_basics/unabridged.md b/chapters/cplusplus_basics/unabridged.md index e2ea7e33..d574d75f 100644 --- a/chapters/cplusplus_basics/unabridged.md +++ b/chapters/cplusplus_basics/unabridged.md @@ -149,16 +149,16 @@ Let's do an experiment. In the code editor, please comment out the include direc The syntax coloring will change to all green, meaning it's now just a comment. Run the code by pressing the big green button at the bottom right, and you'll see something new in the output pane. ``` -prog.cpp: In function ‘int main()’: -prog.cpp:5:2: error: ‘cout’ was not declared in this scope +prog.cpp: In function 'int main()': +prog.cpp:5:2: error: 'cout' was not declared in this scope cout << "Hello World" << endl; ^ -prog.cpp:5:27: error: ‘endl’ was not declared in this scope +prog.cpp:5:27: error: 'endl' was not declared in this scope cout << "Hello World" << endl; ^ ``` -The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function ‘int main()’`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: ‘cout’ was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. +The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function 'int main()'`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: ‘cout’ was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. ```cpp #include @@ -185,7 +185,7 @@ It's a very similar error as before, where it cannot find `cout` or `endl`, but ``` prog.cpp:5:2: note: suggested alternative: In file included from prog.cpp:1:0: -/usr/include/c++/4.8/iostream:61:18: note: ‘std::cout’ +/usr/include/c++/4.8/iostream:61:18: note: 'std::cout' extern ostream cout; /// Linked to standard output ^ ``` @@ -2158,8 +2158,8 @@ int main() { The output is a compiler error. ``` -prog.cpp: In function ‘void addOne()’: -prog.cpp:5:10: error: ‘i’ was not declared in this scope +prog.cpp: In function 'void addOne()': +prog.cpp:5:10: error: 'i' was not declared in this scope cout << i; ^ ``` diff --git a/chapters/data_vis/MichaelHadleyChapterFeedback.md b/chapters/data_vis/MichaelHadleyChapterFeedback.md index 7964714c..508385dd 100644 --- a/chapters/data_vis/MichaelHadleyChapterFeedback.md +++ b/chapters/data_vis/MichaelHadleyChapterFeedback.md @@ -9,7 +9,7 @@ It is a very brief overview of dealing with data in OF. It overviews how to load **[mh: you can omit the second sentence from the title]** -Computation has driven a huge increase in our capacity to collect, sort and store data. Yet our ability to perceive and understand this data remains limited by the human body’s sensory and cognitive abilities. Data visualisation aims to aid in the interpretation and presentation of data so it can be understood as information and potentially applied as knowledge. Spanning science, art, design, computation and (as some theorists argue) also philosophy, data visualisation is a way of presenting large and complex datasets graphically that can reveal trends and patterns that might otherwise remain invisible. +Computation has driven a huge increase in our capacity to collect, sort and store data. Yet our ability to perceive and understand this data remains limited by the human body's sensory and cognitive abilities. Data visualisation aims to aid in the interpretation and presentation of data so it can be understood as information and potentially applied as knowledge. Spanning science, art, design, computation and (as some theorists argue) also philosophy, data visualisation is a way of presenting large and complex datasets graphically that can reveal trends and patterns that might otherwise remain invisible. **[mh: since you haven't defined data at this point, maybe you could start off with talking about recording observations rather than saying "data"]** @@ -33,7 +33,7 @@ These definitions may need to be further refined. Ben Fry is a data artist and the author of Visualizing Data (2008), a well-known text outlining data visualisation approaches for the Processing programming environment. This an excellent reference text for anyone who wishes to dive deeper into thinking and working with data visualisation techniques. In it, Fry describes seven stages for visualising data that are useful for structuring a general process of working with data. These steps are: * Acquire: Obtain the data, whether from a file on a disk or a source over a network. -* Parse: Provide some structure for the data’s meaning, and order it into categories. +* Parse: Provide some structure for the data's meaning, and order it into categories. * Filter: Remove all but the data of interest. * Mine: Apply methods from statistics or data mining as a way to discern patterns or place the data in mathematical context. * Represent: Choose a basic visual model, such as a bar graph, list, or tree. @@ -59,7 +59,7 @@ Your dataset is likely to contain extra information not relevant to your visuali ###Mine As Fry (2008) outlines, the mining stage of visualising data involves applying statistical methods and math to your dataset to analyse patterns and trends within it. This might be as simple as identifying the minimum and maximum values so that you know the range of variation in your data. Depending on your data, you may wish to calculate an average or a median value. -Once you have completed this step, it is now time to load and visualise your data in OF. We will return to the last three stages of Fry’s data visualisation steps following this example. +Once you have completed this step, it is now time to load and visualise your data in OF. We will return to the last three stages of Fry's data visualisation steps following this example. ##2.1 Quick overview of some common file structures. tsv, csv, xml, json Data is available and stored in specific file types that have particular structures and syntax. The following file types are some of the most common forms of structuring data. @@ -78,7 +78,7 @@ Data is available and stored in specific file types that have particular structu Reading an XML file in OF requires the use of an OF addon called ofXmlSettings. **[mh: your xml isn't being rendered in md]** -* JSON: JSON stands for ‘javascript object notation’. This is a human readable file that is built on two structures, a collection of name/value pairs which can be realised in OF as a struct and an ordered list of values, realised as a vector. Json files also are parsed using an OF addon called ofxJSON, see example 2.XX for how to implement this. +* JSON: JSON stands for 'javascript object notation'. This is a human readable file that is built on two structures, a collection of name/value pairs which can be realised in OF as a struct and an ordered list of values, realised as a vector. Json files also are parsed using an OF addon called ofxJSON, see example 2.XX for how to implement this. ##2.2 Loading and saving data @@ -88,7 +88,7 @@ FIGURE OF FILE STRUCTURE HERE ###2.2.2 ofBuffer Once you have done this you will load this file into your OF program using the ofBuffer class. ofBuffer will read the data into a buffer (a temporary storage for our data as we write code to restructure and process it). -ofBuffer is what is known as a convenience class, and provides easy methods for reading from and writing to files. A convenience class simply means that this is a class that doesn’t do anything by itself but wraps or allows access to the functionality of a group of other classes. +ofBuffer is what is known as a convenience class, and provides easy methods for reading from and writing to files. A convenience class simply means that this is a class that doesn't do anything by itself but wraps or allows access to the functionality of a group of other classes. ###2.2.2 Buffer Functions @@ -96,7 +96,7 @@ ofBufferFromFile(); is a function that allows you to load your data file. ofBuffer file = ofBufferFromFile("weather.tsv"); cout << buffer.getText(); -So here our weather tsv file has been loaded into a variable called ‘file’. +So here our weather tsv file has been loaded into a variable called 'file'. ```cpp getFirstLine(); @@ -227,6 +227,6 @@ To finish this example here JSON validation tools like: http://jsonlint.com/ ##References -Fry, B. (2008). *Visualizing Data,* O’Reilly Media. +Fry, B. (2008). *Visualizing Data,* O'Reilly Media. Ackoff, R. L. (1989). *From Data to Wisdom. Journal of Applied Systems Analysis,* 16, 3–9. diff --git a/chapters/data_vis/chapter.md b/chapters/data_vis/chapter.md index 9075ca6a..656820fd 100644 --- a/chapters/data_vis/chapter.md +++ b/chapters/data_vis/chapter.md @@ -18,8 +18,8 @@ Ben Fry is a data artist and the author of Visualizing Data (2008), a well-known *Acquire: Obtain the data. Data is commonly made available in files downloadable from online sources such as weather services, newspapers, census records and from social media platforms. However there are also times when you may need to compile and format data from hardware or sensors. Real-time data is often available via an Application Programming Interfaces (API), which is an interface or a set of rules that define the process of how other applications can communicate with it. Every API is designed differently and therefore can be communicated with in different ways. This chapter presents two examples of visualising a static dataset imported into OF from external files, and an example that reads data from the New York Times API. -*Parse: Provide some structure for the data’s meaning, and order it into categories. -Once you have obtained your data, before you load it into OpenFrameworks it is important to parse the data. Parsing means checking the file’s format. Is the dataset tagged correctly? Check that each line of your data is broken up consistently across columns. This can be done in a number of ways such as, printing your file out in the terminal or opening your file in a text editor or spreadsheet program and checking for inconsistencies or gaps. +*Parse: Provide some structure for the data's meaning, and order it into categories. +Once you have obtained your data, before you load it into OpenFrameworks it is important to parse the data. Parsing means checking the file's format. Is the dataset tagged correctly? Check that each line of your data is broken up consistently across columns. This can be done in a number of ways such as, printing your file out in the terminal or opening your file in a text editor or spreadsheet program and checking for inconsistencies or gaps. *Filter: Remove all but the data of interest. Your dataset is likely to contain extra information not relevant to your visualisation. For example in the tab separated (.tsv) file shown in figure 1, the file has columns like station ID and latitude and longitude that are not relevant to the first visualisation example. As the data is from only one location, location information can be removed so that they do not interfere with the your visualisation process. @@ -53,7 +53,7 @@ Data is available and stored in specific file types that have particular structu Reading an XML file in OF requires the use of an OF addon called ofXmlSettings. -*JSON: JSON stands for ‘javascript object notation’. This is a human readable file that is built on two structures, a collection of name/value pairs which can be realised in OF as a struct and an ordered list of values, realised as a vector. Json files also are parsed using an OF addon called ofxJSON, see example 2.XX for how to implement this. +*JSON: JSON stands for 'javascript object notation'. This is a human readable file that is built on two structures, a collection of name/value pairs which can be realised in OF as a struct and an ordered list of values, realised as a vector. Json files also are parsed using an OF addon called ofxJSON, see example 2.XX for how to implement this. ###Example - Visualising Time Series Plot @@ -74,7 +74,7 @@ Save your file as a tsv file. Loading Your file into an OF Project -Firstly generate a new project remembering to include the add-ons if your data is in csv or json format. Then save the parsed population data file to the ‘bin’ folder of your OF project. +Firstly generate a new project remembering to include the add-ons if your data is in csv or json format. Then save the parsed population data file to the 'bin' folder of your OF project. Once your project file is set up, we will now work through writing the code. @@ -203,7 +203,7 @@ We will now load the data file into OF using the ofBuffer class. ####ofBuffer Class ofBuffer will read the data into a buffer which is temporary storage for it as we write code to restructure and process it. -ofBuffer is what is known as a convenience class, and provides easy methods for reading from and writing to files. A convenience class simply means that this is a class that doesn’t do anything by itself but wraps or allows access to the functionality of a group of other classes. +ofBuffer is what is known as a convenience class, and provides easy methods for reading from and writing to files. A convenience class simply means that this is a class that doesn't do anything by itself but wraps or allows access to the functionality of a group of other classes. ####Buffer Functions ofBufferFromFile(); is a function that allows you to load your data file. @@ -211,8 +211,8 @@ ofBufferFromFile(); is a function that allows you to load your data file. ofBuffer file = ofBufferFromFile(“population.tsv"); cout << file.getText(); ``` -This loads the population.tsv file into a variable called ‘file’. -Then we have printed out the contents of the variable ‘file’ using getText() which allows us to check the file has loaded correctly. +This loads the population.tsv file into a variable called 'file'. +Then we have printed out the contents of the variable 'file' using getText() which allows us to check the file has loaded correctly. getFirstLine(); Returns all text up to the first new line which ends at the first carriage return. @@ -221,7 +221,7 @@ getFirstLine(); Returns all text up to the first new line which ends at the firs string nameLine = file.getFirstLine(); ``` -We have used getFirstLine(); to copy the first line of the file containing the labels into a string called ‘nameLine’. +We have used getFirstLine(); to copy the first line of the file containing the labels into a string called 'nameLine'. getNextLine(); Returns the next row of the data file as marked by `\n` or `\r` (new line characters). @@ -407,14 +407,14 @@ Here we have a for loop generating values for i that range from 0 to maxValue. S **Step 6 Interact.** -Finally we can add interactivity by creating clickable tabs that will switch between the different datasets in our file. This section turns our code into a state machine, where we define a variable called ‘which’ which is toggled between the values 0,1 and 2. The value of ‘which’, dictates what dataset will be displayed. +Finally we can add interactivity by creating clickable tabs that will switch between the different datasets in our file. This section turns our code into a state machine, where we define a variable called 'which' which is toggled between the values 0,1 and 2. The value of ‘which’, dictates what dataset will be displayed. In testApp.h, declare which: ```cpp int which; ``` -Then insert this block of code to the mousePressed part of the openFrameworks template. These conditionals define regions around the title labels and turns them into buttons. When the button is clicked, ‘which’ changes state to the value shown. +Then insert this block of code to the mousePressed part of the openFrameworks template. These conditionals define regions around the title labels and turns them into buttons. When the button is clicked, 'which' changes state to the value shown. ```cpp @@ -466,7 +466,7 @@ to this: } ``` -We have created a new float ‘value’ to hold each data point. Depending on the value of ‘which’, value is assigned data from one of the three data sets in the tsp file. +We have created a new float 'value' to hold each data point. Depending on the value of ‘which’, value is assigned data from one of the three data sets in the tsp file. Finally the last step here is to draw the titles to the screen which is done by adding the last block of code underneath the for loop we just changed. @@ -522,7 +522,7 @@ You can write programs in OpenFrameworks so that data an be pulled from an API a JSON validation tools like: http://jsonlint.com/ ##References -Fry, B. (2008). *Visualizing Data,* O’Reilly Media. +Fry, B. (2008). *Visualizing Data,* O'Reilly Media. Ackoff, R. L. (1989). *From Data to Wisdom. Journal of Applied Systems Analysis,* 16, 3–9. diff --git a/chapters/game_design/chapter.md b/chapters/game_design/chapter.md index 31d50ec6..b3a5a339 100644 --- a/chapters/game_design/chapter.md +++ b/chapters/game_design/chapter.md @@ -59,7 +59,7 @@ Here's what our game will have: ![Space Game in action!](images/game.png "Space Game in action!") -With all that written out, let’s use OSC to affect the following: +With all that written out, let's use OSC to affect the following: * The horizontal movement of our enemies--whether they move in a more exaggerated sin wave, or whether they move in more of a straight line * The frequency with which our enemies shoot @@ -68,11 +68,11 @@ With all that written out, let’s use OSC to affect the following: These three parameters will allow the developer to, second-by-second, tailor the difficulty of the game to the individual playing it. -Let’s start with our testApp. There are a few things we definitely know we’ll want classes for, so make corresponding .h and .cpp files for Player, Bullet, Life, Enemy, and LevelController. Remember to `#include "ofMain.h"` in each of those classes, and to include the .h file of each of those classes in `testApp.h`. +Let's start with our testApp. There are a few things we definitely know we’ll want classes for, so make corresponding .h and .cpp files for Player, Bullet, Life, Enemy, and LevelController. Remember to `#include "ofMain.h"` in each of those classes, and to include the .h file of each of those classes in `testApp.h`. ###Gamestates -First let’s create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we’re in, which we’ll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are `"start"`, `"game"`, and `"end"`. Let’s add a score and a player at this point as well. +First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we’re in, which we’ll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are `"start"`, `"game"`, and `"end"`. Let’s add a score and a player at this point as well. 
 ```cpp string game_state; @@ -80,7 +80,7 @@ int score; Player player_1; ``` -We’ll then divide up `testApp`’s `update()` and `draw()` loops between those game states: +We'll then divide up `testApp`’s `update()` and `draw()` loops between those game states: ```cpp //-------------------------------------------------------------- @@ -102,7 +102,7 @@ void testApp::draw(){ } ``` -Let’s set the initial value of `game_state` to `"start"` right when the app begins. +Let's set the initial value of `game_state` to `"start"` right when the app begins. ```cpp //-------------------------------------------------------------- @@ -112,7 +112,7 @@ void testApp::setup(){ } ``` -Finally, let’s make sure that we can move forward from the start screen. In this example, when the player is on the start screen and releases the space key, they’ll be taken to the game. +Finally, let's make sure that we can move forward from the start screen. In this example, when the player is on the start screen and releases the space key, they’ll be taken to the game. ```cpp //-------------------------------------------------------------- @@ -128,7 +128,7 @@ void testApp::keyReleased(int key){ ###Player movement -Great! Let’s move onto our player. Our player’s class looks like this: +Great! Let's move onto our player. Our player’s class looks like this: ```cpp class Player { @@ -155,19 +155,19 @@ public: Taking this one step at a time: -* Our player’s position will be stored in an `ofPoint` called `pos`. ofPoints are handy datatypes that contain `x` and `y` values, letting us access our player’s position through `pos.x` and `pos.y`. -* Our player will have `width`, `height`, and `speed` variables (which we’ll use for collision detection and movement, respectively). -* Our player will have an integer number of lives (since it wouldn’t make any sense for them to have 4.33333333333 lives). +* Our player's position will be stored in an `ofPoint` called `pos`. ofPoints are handy datatypes that contain `x` and `y` values, letting us access our player’s position through `pos.x` and `pos.y`. +* Our player will have `width`, `height`, and `speed` variables (which we'll use for collision detection and movement, respectively). +* Our player will have an integer number of lives (since it wouldn't make any sense for them to have 4.33333333333 lives). * Our player will keep track of what movement keys are currently pressed in separate booleans. * Our player will have `setup`, `update`, `draw`, `shoot`, and `calculate_movement` methods. -* Finally, our player will have a pointer to the image we’re using for the player. +* Finally, our player will have a pointer to the image we're using for the player. -You may be wondering why we’re using all these booleans--why not just check and see which keys are pressed? +You may be wondering why we're using all these booleans--why not just check and see which keys are pressed? The problem is that, in openFrameworks, `keyPressed()` does not return all the keys currently being pressed--just the last key that was pressed. That means that if the player presses up and left (intending to move diagonally), openFrameworks will only report one of the keys being pressed. You can try printing out the result of keyPressed to see this in action. -
What we’ll do to avoid this is instead base the player’s movement on the booleans we wrote earlier. If the player presses a certain key, that boolean will be true; if they release that key, that boolean will be false. That way, if the player presses up and left, we’ll report up and left as being true until those keys are released. +
What we'll do to avoid this is instead base the player’s movement on the booleans we wrote earlier. If the player presses a certain key, that boolean will be true; if they release that key, that boolean will be false. That way, if the player presses up and left, we’ll report up and left as being true until those keys are released. -Here’s what our new `keyPressed()` and `keyReleased()` functions look like: +Here's what our new `keyPressed()` and `keyReleased()` functions look like: ```cpp //-------------------------------------------------------------- @@ -216,7 +216,7 @@ void testApp::keyReleased(int key){ ``` -Add `ofImage player_image` to `testApp.h`, then load the player’s image and instantiate the player in `testApp`’s `setup()`: +Add `ofImage player_image` to `testApp.h`, then load the player's image and instantiate the player in `testApp`’s `setup()`: ```cpp void testApp::setup(){ @@ -254,7 +254,7 @@ void testApp::draw(){ You should have a player who moves around on-screen. Sweet!
 ###Player bullets -Let’s make our bullets next. In order to have a variable number of bullets on screen at a time, we need to add a `vector bullets;` to testApp.h. Let’s also create a `void update_bullets();` function, which will update our vector of bullets (and, shortly, trigger the check for bullet collisions). We also want our player and enemy bullets to look different, so we’ll add `ofImage enemy_bullet_image;` and `ofImage player_bullet_image;` to our `testApp.h` file. +Let's make our bullets next. In order to have a variable number of bullets on screen at a time, we need to add a `vector bullets;` to testApp.h. Let’s also create a `void update_bullets();` function, which will update our vector of bullets (and, shortly, trigger the check for bullet collisions). We also want our player and enemy bullets to look different, so we’ll add `ofImage enemy_bullet_image;` and `ofImage player_bullet_image;` to our `testApp.h` file. Our bullet class will look a lot like the player class, having a position, speed, width, pointer to an image, and various functions. The big difference is that the bullets will keep track of who they came from (since that will affect who they can hurt and which direction they move). @@ -301,7 +301,7 @@ void Bullet::draw() { Again, this is much like the code for the player. The two differences are: * We keep track of where the bullet comes from, and alter the code based on that variable (meaning we can keep all the bullets in the same vector) -* When instantiating a bullet, we check to see the position of the shooter, as well as the shooter’s current speed (so it will always move faster than the thing that shot it) +* When instantiating a bullet, we check to see the position of the shooter, as well as the shooter's current speed (so it will always move faster than the thing that shot it) Now that our bullet class is implemented, we can go back to `testApp::setup()` and add in `enemy_bullet_image.loadImage("enemy_bullet.png");` and `player_bullet_image.loadImage("player_bullet.png");` right underneath where we loaded in our `player_image`. 
 @@ -316,7 +316,7 @@ void testApp::update_bullets() { bullets.erase(bullets.begin()+i); } } - // we’ll call a collision check function here shortly + // we'll call a collision check function here shortly } ``` @@ -349,7 +349,7 @@ void testApp::draw(){ } ``` -Finally, let’s add an if-statement to our `keyPressed()` so that when we press the spacebar during the game, we spawn a player bullet: +Finally, let's add an if-statement to our `keyPressed()` so that when we press the spacebar during the game, we spawn a player bullet: ```cpp //-------------------------------------------------------------- @@ -380,11 +380,11 @@ void testApp::keyPressed(int key){ } ``` -Remember, the first parameter in the bullet’s setup is whether it comes from the player (which, in this case, is always true). Run your app and fly around shooting for a bit to see how it feels. +Remember, the first parameter in the bullet's setup is whether it comes from the player (which, in this case, is always true). Run your app and fly around shooting for a bit to see how it feels. ###Adding adversaries -Let’s move on to our enemy. This process should be familiar by now. Add an `ofImage enemy_image;` and a `vector enemies;` to `testApp.h`. Additionally, add `float max_enemy_amplitude;` and `float max_enemy_shoot_interval;` to `testApp.h`--these are two of the enemy parameters we’ll affect with OSC. +Let's move on to our enemy. This process should be familiar by now. Add an `ofImage enemy_image;` and a `vector enemies;` to `testApp.h`. Additionally, add `float max_enemy_amplitude;` and `float max_enemy_shoot_interval;` to `testApp.h`--these are two of the enemy parameters we’ll affect with OSC. 
Your enemy class will look like this: ```cpp @@ -407,7 +407,7 @@ public: }; ``` -Our enemy’s horizontal movement will be shaped by the values fed to a sine wave (which we’ll see in a moment). We’ll keep track of our amplitude variable (so different enemies can have different amplitudes). We’ll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the start_shoot and shoot_interval variables. Both of these variables will actually be set in our setup() function. Finally, we’ll have a boolean function that will tell us whether the enemy can shoot this frame or not. +Our enemy's horizontal movement will be shaped by the values fed to a sine wave (which we’ll see in a moment). We’ll keep track of our amplitude variable (so different enemies can have different amplitudes). We’ll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the start_shoot and shoot_interval variables. Both of these variables will actually be set in our setup() function. Finally, we’ll have a boolean function that will tell us whether the enemy can shoot this frame or not. 
Our enemy class will look like this: ```cpp @@ -437,10 +437,10 @@ bool Enemy::time_to_shoot() { } ``` -In update, we’re using the current elapsed time in frames to give us a constantly increasing number to feed to the sine function, which in turn returns a value between -1 and 1. We multiply it by the amplitude of the wave, making this curve more or less exaggerated. +In update, we're using the current elapsed time in frames to give us a constantly increasing number to feed to the sine function, which in turn returns a value between -1 and 1. We multiply it by the amplitude of the wave, making this curve more or less exaggerated. -In `time_to_shoot()`, we check to see whether the difference between the current time and the time this enemy last shot is greater than the enemy’s shooting interval. If it is, we set `start_shoot` to the current time, and return true. If not, we return false. -
Let’s integrate our enemies into the rest of our `testApp.cpp`: +In `time_to_shoot()`, we check to see whether the difference between the current time and the time this enemy last shot is greater than the enemy's shooting interval. If it is, we set `start_shoot` to the current time, and return true. If not, we return false. +
Let's integrate our enemies into the rest of our `testApp.cpp`: ```cpp //-------------------------------------------------------------- @@ -495,7 +495,7 @@ void testApp::draw(){ ###Collisions -Let’s implement our bullet collision checks. Add a void `check_bullet_collisions();` to your `testApp.h`, then write the following function: +Let's implement our bullet collision checks. Add a void `check_bullet_collisions();` to your `testApp.h`, then write the following function: ```cpp //-------------------------------------------------------------- @@ -523,10 +523,10 @@ void testApp::check_bullet_collisions() { } ``` -This code is a bit nested, but actually pretty simple. First, it goes through each bullet in the vector and checks to see whether it’s from the player. If it’s from the player, it starts a for-loop for all the enemies, so we can compare the player bullet position against all the enemy positions. We use `ofDist()` to see whether the distance between a given bullet and a given enemy is less than the sum of their radii--if it is, they’re overlapping. -
If a bullet is not from the player, the function does a distance calculation against the player, to see whether a given enemy bullet and the player are close enough to count it as a hit. If there is a hit, we subtract a player’s life and erase that bullet. If the player has less than or equal to 0 lives, we change the game state to the end. +This code is a bit nested, but actually pretty simple. First, it goes through each bullet in the vector and checks to see whether it's from the player. If it’s from the player, it starts a for-loop for all the enemies, so we can compare the player bullet position against all the enemy positions. We use `ofDist()` to see whether the distance between a given bullet and a given enemy is less than the sum of their radii--if it is, they’re overlapping. +
If a bullet is not from the player, the function does a distance calculation against the player, to see whether a given enemy bullet and the player are close enough to count it as a hit. If there is a hit, we subtract a player's life and erase that bullet. If the player has less than or equal to 0 lives, we change the game state to the end. -Don’t forget to call `check_bullet_collisions()` as part of `update_bullets()`: +Don't forget to call `check_bullet_collisions()` as part of `update_bullets()`: ```cpp //-------------------------------------------------------------- @@ -543,7 +543,7 @@ void testApp::update_bullets() { ###Our game's brain -Great! Except… we don’t have any enemies yet! Definitely an oversight. This is where our level controller comes in. Add `LevelController level_controller;` to your `testApp.h`. +Great! Except… we don't have any enemies yet! Definitely an oversight. This is where our level controller comes in. Add `LevelController level_controller;` to your `testApp.h`. 
Our level controller class is super-simple: ```cpp @@ -557,7 +557,7 @@ public: }; ``` -As you might guess, all it’ll really do is keep track of whether it’s time to spawn another enemy yet. +As you might guess, all it'll really do is keep track of whether it’s time to spawn another enemy yet. Inside our `LevelController.cpp`: @@ -575,9 +575,9 @@ bool LevelController::should_spawn() { } ``` -When we set up our level controller, we’ll give it a starting time. It’ll use this time as a baseline for the first enemy spawn. The should_spawn code should look familiar from the enemy bullet section. +When we set up our level controller, we'll give it a starting time. It’ll use this time as a baseline for the first enemy spawn. The should_spawn code should look familiar from the enemy bullet section. -We’ll wait to set up our level controller until the game actually starts--namely, when the game state changes from `"start"` to `"game"`. +We'll wait to set up our level controller until the game actually starts--namely, when the game state changes from `"start"` to `"game"`. ```cpp void testApp::keyReleased(int key){ @@ -590,7 +590,7 @@ void testApp::keyReleased(int key){ } ``` -Next we’ll integrate it into our `testApp::update()`: +Next we'll integrate it into our `testApp::update()`: ```cpp //-------------------------------------------------------------- @@ -619,11 +619,11 @@ void testApp::update(){ } ``` -Awesome! We’re close to done! +Awesome! We're close to done! ###Bonus lives -Before we finish, let’s add in our last OSC feature: the ability to throw in bonus lives on the fly. Add `vector bonuses;` and `ofImage life_image;` to your `testApp.h`. To keep our code modular, let’s also add `void update_bonuses();` in the same place. Don’t forget to `life_image.loadImage("life_image.png");` in `testApp::setup()`. +Before we finish, let's add in our last OSC feature: the ability to throw in bonus lives on the fly. Add `vector bonuses;` and `ofImage life_image;` to your `testApp.h`. To keep our code modular, let’s also add `void update_bonuses();` in the same place. Don’t forget to `life_image.loadImage("life_image.png");` in `testApp::setup()`. `Life.h` should look like this: @@ -642,7 +642,7 @@ public: }; ``` -And it’ll function like this--a lot like the bullet: +And it'll function like this--a lot like the bullet: ```cpp void Life::setup(ofImage * _img) { @@ -679,7 +679,7 @@ void testApp::update_bonuses() { } ``` -All that’s left for our lives functionality is to alter `testApp::update()` and `testApp::draw()`. +All that's left for our lives functionality is to alter `testApp::update()` and `testApp::draw()`. ```cpp //-------------------------------------------------------------- @@ -736,7 +736,7 @@ void testApp::draw(){ ###Let's get visual -Finally, we’ve been a bit stingy with visual feedback, so let’s add in a start screen, a score, a visual representation of the lives left, and an end screen. Add `ofImage start_screen;`, `ofImage end_screen;`, `void draw_lives();`, and `void draw_score();` to `testApp.h`. +Finally, we've been a bit stingy with visual feedback, so let’s add in a start screen, a score, a visual representation of the lives left, and an end screen. Add `ofImage start_screen;`, `ofImage end_screen;`, `void draw_lives();`, and `void draw_score();` to `testApp.h`. Change `testApp::setup()` to load in those assets: @@ -776,19 +776,19 @@ void testApp::draw_score() { By using `stringWidth()`, we can calculate the width of a string and shift the text over--handy for centering it. -All that’s left after that is to call `draw_score();` and `draw_lives();` during the `testApp::draw()`’s game state, and to call `draw_score();` during the end state. +All that's left after that is to call `draw_score();` and `draw_lives();` during the `testApp::draw()`’s game state, and to call `draw_score();` during the end state. Congrats--you made a game! ###Linking oF and OSC -Now let’s add in the OSC functionality. We are going to set our application up to receive messages from our iPad and then make changes in real-time while our game is running to test some possible player scenarios. As mentioned before, this can trump going into your application and making manual changes because you skip the need to recompile your game and playtest live. In fact, you can use Touch OSC to even open up new ways to interact with your players. +Now let's add in the OSC functionality. We are going to set our application up to receive messages from our iPad and then make changes in real-time while our game is running to test some possible player scenarios. As mentioned before, this can trump going into your application and making manual changes because you skip the need to recompile your game and playtest live. In fact, you can use Touch OSC to even open up new ways to interact with your players. ![Nightgame developer interface by Phoenix Perry](images/touchGame.png "Nightgame developer interface by Phoenix Perry") *Touch OSC is used to switch game levels on the fly and to run challenges.* To accomplish this we are going to create a new class that will contain our OSC functionality. Create a .cpp and .h file for this class now and name it LiveTesting. Open `LiveTesting.h` -And let’s add the line to import the OSC at the top of your file after your preprocessor directives and also a line for using iostream for testing purposes. As we add the code we will explain in inline in the code comments. +And let's add the line to import the OSC at the top of your file after your preprocessor directives and also a line for using iostream for testing purposes. As we add the code we will explain in inline in the code comments. Add the following: @@ -797,7 +797,7 @@ Add the following: #include "ofxOsc.h" ``` -Next let’s set up all of our variables we are going to use to receive OSC data and map it to in game values. Add the following code into your class. +Next let's set up all of our variables we are going to use to receive OSC data and map it to in game values. Add the following code into your class. ```cpp class LiveTesting @@ -829,13 +829,13 @@ public: }; ``` -Now let’s jump over to the `LiveTesting.cpp` file. In this file we are going to set up our network address and the ports we are sending and receiving data on as the first order of business. However, to go any further we are going to need to do some housekeeping and install additional software. For OSC to work it will need a local wifi network to send the messages across. Note this tactic may not work for a network outside of your own because often a sysadmin will stop this kind of traffic from being transmitted on a very public network. We suggest brining an Airport Express or similar with you so you can quickly and wirelessly establish a local network for playtesting. +Now let's jump over to the `LiveTesting.cpp` file. In this file we are going to set up our network address and the ports we are sending and receiving data on as the first order of business. However, to go any further we are going to need to do some housekeeping and install additional software. For OSC to work it will need a local wifi network to send the messages across. Note this tactic may not work for a network outside of your own because often a sysadmin will stop this kind of traffic from being transmitted on a very public network. We suggest brining an Airport Express or similar with you so you can quickly and wirelessly establish a local network for playtesting. For the purpose of this chapter and to allow us to create an experience that will work on both Android and iOS we are going to use a piece of software called TouchOSC from this URL: http://hexler.net/software/touchosc -The desktop editor software is free however the matching software for your device will be $4.99. Get both now. As a mater of principle, we endorse building your own tools and you could easily build a second oF project to be your OSC sender and receiver on your mobile device. With that said, nothing beats TouchOSC for speed, ease of use and complete, platform independent flexibility. If you are someone who often moves between an iOS and Android device on both Windows and Mac, this tool will become indispensible to you. As a games designer it can open up possibilities like changing levels on the fly, updating game variables, adjusting for player feedback and adding new features into and taking them out of your game as it’s running. We highly endorse using it and support the continued advancement of the tool. You can also use it with music production tools like Ableton Live and it comes with great presets for things like DJing and mixing music live. Go to the app store of your device and purchase the mobile version now if you would like to continue down this route. +The desktop editor software is free however the matching software for your device will be $4.99. Get both now. As a mater of principle, we endorse building your own tools and you could easily build a second oF project to be your OSC sender and receiver on your mobile device. With that said, nothing beats TouchOSC for speed, ease of use and complete, platform independent flexibility. If you are someone who often moves between an iOS and Android device on both Windows and Mac, this tool will become indispensible to you. As a games designer it can open up possibilities like changing levels on the fly, updating game variables, adjusting for player feedback and adding new features into and taking them out of your game as it's running. We highly endorse using it and support the continued advancement of the tool. You can also use it with music production tools like Ableton Live and it comes with great presets for things like DJing and mixing music live. Go to the app store of your device and purchase the mobile version now if you would like to continue down this route. -After we get all of the tools downloaded and installed. Let’s start setting everything up. You are going to need two bits of information. You are going to need to know the IP address of your computer and the ip address of your laptop. If you are on a mac, just open up your System Preferences. Go to the Network setting and click on your wifi connection in the left sidebar. On the right side it will display your IP address. You can also get this setting by opening up Terminal and entering in the command ifconfig. Terminal will list of every network that’s a possible connection for your machine from the past, even if it’s not currently active. For example, if you have ever connected your phone, it will be in the list with some flag and listed as inactive. Look for the connection that’s currently active. It will look something like this: +After we get all of the tools downloaded and installed. Let's start setting everything up. You are going to need two bits of information. You are going to need to know the IP address of your computer and the ip address of your laptop. If you are on a mac, just open up your System Preferences. Go to the Network setting and click on your wifi connection in the left sidebar. On the right side it will display your IP address. You can also get this setting by opening up Terminal and entering in the command ifconfig. Terminal will list of every network that’s a possible connection for your machine from the past, even if it’s not currently active. For example, if you have ever connected your phone, it will be in the list with some flag and listed as inactive. Look for the connection that’s currently active. It will look something like this: ``` en1: flags=8863 mtu 1500 @@ -847,7 +847,7 @@ en1: flags=8863 mtu 1500 ``` The inet address is your current IP. -On windows, open the `charms` bar. In search type `cmd` and open the command prompt. Type in `ipconfig`. This information is much clearer than the data dump from terminal. The connected listed as your Wireless LAM adapter Wi-Fi will list your current IPV4 address. This is your IP address. Finally, obtain your mobile device’s IP address as well from your device settings. Make a note of your IPAddress for the next section. +On windows, open the `charms` bar. In search type `cmd` and open the command prompt. Type in `ipconfig`. This information is much clearer than the data dump from terminal. The connected listed as your Wireless LAM adapter Wi-Fi will list your current IPV4 address. This is your IP address. Finally, obtain your mobile device's IP address as well from your device settings. Make a note of your IPAddress for the next section. At this point, go ahead and launch TouchOSC on your device and the Touch OSC desktop editor on your computer. If you are on Windows, you will need to make sure you have java installed first. Once the software is open, click the open icon in the top tool bar. In the file containing the code for this chapter you will see a file called `ofBook.touchosc`. @@ -863,11 +863,11 @@ bool triggerBonus; ![](images/controls.png) -To build the app, let’s start by adding our first knob. Right click in the black empty space to the right. Choose to make a `rotaryH`. Next make two `labelH` objects. The first one will be the name of our knob. The second one will be for displaying the value of the current variable in our game. Place one label above the knob and one below. It should look like the below image: +To build the app, let's start by adding our first knob. Right click in the black empty space to the right. Choose to make a `rotaryH`. Next make two `labelH` objects. The first one will be the name of our knob. The second one will be for displaying the value of the current variable in our game. Place one label above the knob and one below. It should look like the below image: ![](images/label1_label2.png) -Now look to the left side of the app. At this point, it’s time to set all of the values this knob will be sending and what the labels will display. Let’s start with `label1`. We will name our knob on screen to make things easier to read. The first value in our game we want to control, level controller interval time, should be what this label reads onscreen. Changing the name field in the app interface will do little. However, note under the name field you can change the color of the label. For this example, use yellow. Next, jump down to the next to last field on screen called `Text`. You will want to set this to level controller interval time. +Now look to the left side of the app. At this point, it's time to set all of the values this knob will be sending and what the labels will display. Let’s start with `label1`. We will name our knob on screen to make things easier to read. The first value in our game we want to control, level controller interval time, should be what this label reads onscreen. Changing the name field in the app interface will do little. However, note under the name field you can change the color of the label. For this example, use yellow. Next, jump down to the next to last field on screen called `Text`. You will want to set this to level controller interval time. Moving on, select the knob. This one will require more set up because it will actually be sending values to our game. Color it yellow first. In the dark grey OSC box set all of the values we need to receive for the game. If auto is checked, uncheck it. Now customize the text in that box to `/game/interval_time`. In the `From` fields set the parameters to a range of values to try out in the game during a playtest. We will use from 0 to 300. These two elements, the tag and the parameters will get packed up into a message and sent over our OSC network to our game when values change. @@ -927,7 +927,7 @@ We are going to add one more but this one will be a Push Button verses a RotaryH * Color: Pink * OSC: /updatedVals/triggerBouns -Save your file to your hard drive desktop and name it `PlaytestInterface`. You are done building your interface for play testing. Now let’s deploy it. On your mobile device, launch Touch OSC. It will launch and open a settings screen. +Save your file to your hard drive desktop and name it `PlaytestInterface`. You are done building your interface for play testing. Now let's deploy it. On your mobile device, launch Touch OSC. It will launch and open a settings screen. This is when we need the network address of your computer we retrieved earlier. Under Connections touch OSC: and set it to the IPAddress of your computer to link the two. This should be something like `192.165.0.3` @@ -946,7 +946,7 @@ Now click on `Layout`. Then tap `Add`. It will start to search for your computer Switch back to your device. You should see your computer listed under FOUND HOSTS. Select it. It will pop back to the settings screen. Scroll down and find PlaytestInterface in the list of interfaces. Select it and it will take you back to the main menu. Press Done in the upper left corner and your interface will now launch. If you want to get back to the settings screen at any point the white dot in the upper right hand corner will return the user interface to that screen. -Finally, TouchOSC is set up. Let’s link it to our game and run our very first playtest. Go back to the programming IDE. Open up `LiveTesting.cpp`. In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer’s network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren’t going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You’ll need a separate port for each activity in this scenario. If a port isn’t used by your operating system, you can send and receive data there. We are going to use `8000` and `8001`. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: +Finally, TouchOSC is set up. Let's link it to our game and run our very first playtest. Go back to the programming IDE. Open up `LiveTesting.cpp`. In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer’s network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren’t going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You’ll need a separate port for each activity in this scenario. If a port isn’t used by your operating system, you can send and receive data there. We are going to use `8000` and `8001`. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: ```cpp #include "LiveTesting.h" @@ -972,9 +972,9 @@ LiveTesting::LiveTesting(){ } ``` -In the above code we simply set up our network address, incoming and out going ports and created a default address pattern. From here we should be good to go to set up the messages we’d like to send and receive in our code. +In the above code we simply set up our network address, incoming and out going ports and created a default address pattern. From here we should be good to go to set up the messages we'd like to send and receive in our code. -Let’s move on to the next major function we want to write. We need to run an update function in this class to update every frame so we can make sure that if we move a slider on our ipad that change becomes reflected within the game. Also, we might want to send that value back out once we receive it so we can get some visual feedback on our tablet to let us know what our current settings are. +Let's move on to the next major function we want to write. We need to run an update function in this class to update every frame so we can make sure that if we move a slider on our ipad that change becomes reflected within the game. Also, we might want to send that value back out once we receive it so we can get some visual feedback on our tablet to let us know what our current settings are. Each time we make a change on our device, it will send over the updates to our code via Touch OSC. We want to make sure we get all of the incoming messages that are being sent so we will create a simple while loop. We will loop through the whole list of messages that came into our game that frame and match it to the corresponding variable in our game via if statements. diff --git a/chapters/game_design/old drafts/oscchapter.md b/chapters/game_design/old drafts/oscchapter.md index fa6cc419..c17edb98 100644 --- a/chapters/game_design/old drafts/oscchapter.md +++ b/chapters/game_design/old drafts/oscchapter.md @@ -51,7 +51,7 @@ Here's what our game will have: * Bullets (for the player and the enemies), which have an on-screen position, images to represent them, a way to keep track of where they come from (player or enemy), and a speed * Bonuses (that give extra lives), which have an on-screen position, an image to represent them, and a speed -With all that written out, let’s use OSC to affect the following: +With all that written out, let's use OSC to affect the following: * The horizontal movement of our enemies--whether they move in a more exaggerated sin wave, or whether they move in more of a straight line * The frequency with which our enemies shoot @@ -60,18 +60,18 @@ With all that written out, let’s use OSC to affect the following: These three parameters will allow the developer to, second-by-second, tailor the difficulty of the game to the individual playing it. -Let’s start with our testApp. There are a few things we definitely know we’ll want classes for, so make corresponding .h and .cpp files for `Player`, `Bullet`, `Life`, `Enemy`, and `LevelController`. Remember to `#include` `ofMain.h` in each of those classes, and to include the .h file of each of those classes in `testApp.h`. +Let's start with our testApp. There are a few things we definitely know we’ll want classes for, so make corresponding .h and .cpp files for `Player`, `Bullet`, `Life`, `Enemy`, and `LevelController`. Remember to `#include` `ofMain.h` in each of those classes, and to include the .h file of each of those classes in `testApp.h`. ###Gamestates -First let’s create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we’re in, which we’ll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are “start”, “game”, and “end”. Let’s add a score and a player at this point as well.
 +First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we’re in, which we’ll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are “start”, “game”, and “end”. Let’s add a score and a player at this point as well.
 ``` string game_state; int score; Player player_1; ``` -We’ll then divide up testApp’s `update()` and `draw()` loops between those game states: +We'll then divide up testApp’s `update()` and `draw()` loops between those game states: ``` //-------------------------------------------------------------- @@ -96,7 +96,7 @@ void testApp::draw(){ } ``` -Let’s set the initial value of `game_state` to ` "start" ` right when the app begins. +Let's set the initial value of `game_state` to ` "start" ` right when the app begins. ``` //-------------------------------------------------------------- @@ -106,7 +106,7 @@ void testApp::setup(){ } ``` -Finally, let’s make sure that we can move forward from the start screen. In this example, when the player is on the start screen and releases the space key, they’ll be taken to the game. +Finally, let's make sure that we can move forward from the start screen. In this example, when the player is on the start screen and releases the space key, they’ll be taken to the game. ``` //-------------------------------------------------------------- @@ -119,11 +119,11 @@ void testApp::keyReleased(int key){ } ``` -Great! Let’s move onto our player. +Great! Let's move onto our player. ###Player movement -Our player’s class looks like this: +Our player's class looks like this: ``` class Player { @@ -150,22 +150,22 @@ public: Taking this one step at a time: -* Our player’s position will be stored in an `ofPoint` called `pos`. `ofPoint`s are handy datatypes that contain `x` and `y` values, letting us access our player’s position through `pos.x` and `pos.y`. +* Our player's position will be stored in an `ofPoint` called `pos`. `ofPoint`s are handy datatypes that contain `x` and `y` values, letting us access our player’s position through `pos.x` and `pos.y`. -* Our player will have `width`, `height`, and `speed` variables (which we’ll use for collision detection and movement, respectively). +* Our player will have `width`, `height`, and `speed` variables (which we'll use for collision detection and movement, respectively). -* Our player will have an integer number of lives (since it wouldn’t make any sense for them to have 4.33333333333 lives) +* Our player will have an integer number of lives (since it wouldn't make any sense for them to have 4.33333333333 lives) * Our player will keep track of what movement keys are currently pressed in separate booleans * Our player will have `setup`, `update`, `draw`, `shoot`, and `calculate_movement` methods. - * Finally, our player will have a pointer to the image we’re using for the player. + * Finally, our player will have a pointer to the image we're using for the player. -You may be wondering why we’re using all these booleans--why not just check and see which keys are pressed? +You may be wondering why we're using all these booleans--why not just check and see which keys are pressed? The problem is that, in openFrameworks, `keyPressed()` does not return all the keys currently being pressed--just the last key that was pressed. That means that if the player presses up and left (intending to move diagonally), openFrameworks will only report one of the keys being pressed. You can try printing out the result of keyPressed to see this in action. -
What we’ll do to avoid this is instead base the player’s movement on the booleans we wrote earlier. If the player presses a certain key, that boolean will be true; if they release that key, that boolean will be false. That way, if the player presses up and left, we’ll report up and left as being true until those keys are released. +
What we'll do to avoid this is instead base the player’s movement on the booleans we wrote earlier. If the player presses a certain key, that boolean will be true; if they release that key, that boolean will be false. That way, if the player presses up and left, we’ll report up and left as being true until those keys are released. -Here’s what our new `keyPressed()` and `keyReleased()` functions look like: +Here's what our new `keyPressed()` and `keyReleased()` functions look like: ``` //-------------------------------------------------------------- @@ -213,7 +213,7 @@ void testApp::keyReleased(int key){ } ``` -Add `ofImage player_image` to `testApp.h`, then load the player’s image and instantiate the player in `testApp`’s `setup()`: +Add `ofImage player_image` to `testApp.h`, then load the player's image and instantiate the player in `testApp`’s `setup()`: ``` void testApp::setup(){ @@ -252,7 +252,7 @@ You should have a player who moves around on-screen. Sweet! ###Player bullets -Let’s make our bullets next. In order to have a variable number of bullets on screen at a time, we need to add a `vector bullets` to `testApp.h`. Let’s also create a `void update_bullets();` function, which will update our vector of bullets (and, shortly, trigger the check for bullet collisions). We also want our player and enemy bullets to look different, so we’ll add `ofImage enemy_bullet_image;` and `ofImage player_bullet_image;` to our `testApp.h` file. +Let's make our bullets next. In order to have a variable number of bullets on screen at a time, we need to add a `vector bullets` to `testApp.h`. Let’s also create a `void update_bullets();` function, which will update our vector of bullets (and, shortly, trigger the check for bullet collisions). We also want our player and enemy bullets to look different, so we’ll add `ofImage enemy_bullet_image;` and `ofImage player_bullet_image;` to our `testApp.h` file. Our bullet class will look a lot like the player class, having a position, speed, width, pointer to an image, and various functions. The big difference is that the bullets will keep track of who they came from (since that will affect who they can hurt and which direction they move). @@ -296,7 +296,7 @@ void Bullet::draw() { Again, this is much like the code for the player. The two differences are: * We keep track of where the bullet comes from, and alter the code based on that variable (meaning we can keep all the bullets in the same vector) -* When instantiating a bullet, we check to see the position of the shooter, as well as the shooter’s current speed (so it will always move faster than the thing that shot it) +* When instantiating a bullet, we check to see the position of the shooter, as well as the shooter's current speed (so it will always move faster than the thing that shot it) Now that our bullet class is implemented, we can go back to `testApp::setup() `and add in `enemy_bullet_image.loadImage("enemy_bullet.png");` and `player_bullet_image.loadImage("player_bullet.png");` right underneath where we loaded in our `player_image`. @@ -311,7 +311,7 @@ void testApp::update_bullets() {            bullets.erase(bullets.begin()+i);        }    } -   // we’ll call a collision check function here shortly +   // we'll call a collision check function here shortly } ``` @@ -344,7 +344,7 @@ void testApp::draw(){ } ``` -Finally, let’s add an if-statement to our `keyPressed()` so that when we press the spacebar during the game, we spawn a player bullet: +Finally, let's add an if-statement to our `keyPressed()` so that when we press the spacebar during the game, we spawn a player bullet: ``` //-------------------------------------------------------------- @@ -375,13 +375,13 @@ void testApp::keyPressed(int key){ } ``` -Remember, the first parameter in the bullet’s setup is whether it comes from the player (which, in this case, is always true). Run your app and fly around shooting for a bit to see how it feels. +Remember, the first parameter in the bullet's setup is whether it comes from the player (which, in this case, is always true). Run your app and fly around shooting for a bit to see how it feels. -Let’s move on to our enemy. +Let's move on to our enemy. ###Adding adversaries -This process should be familiar by now. Add an `ofImage enemy_image;` and a `vector enemies;` to `testApp.h`. Additionally, add `float max_enemy_amplitude;` and `float max_enemy_shoot_interval;` to `testApp.h`--these are two of the enemy parameters we’ll affect with OSC. +This process should be familiar by now. Add an `ofImage enemy_image;` and a `vector enemies;` to `testApp.h`. Additionally, add `float max_enemy_amplitude;` and `float max_enemy_shoot_interval;` to `testApp.h`--these are two of the enemy parameters we'll affect with OSC. 
Your enemy class will look like this: ``` @@ -404,7 +404,7 @@ public: }; ``` -Our enemy’s horizontal position is shaped by the values fed to a sine wave (which we’ll see in a moment). We’ll keep track of each enemy's amplitude variable, so different enemies can have different amplitudes. We’ll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the `start_shoot` and `shoot_interval `variables. Both of these variables will actually be set in our `setup()` function. Finally, we’ll have a boolean function that will tell us whether the enemy can shoot this frame or not. +Our enemy's horizontal position is shaped by the values fed to a sine wave (which we’ll see in a moment). We’ll keep track of each enemy's amplitude variable, so different enemies can have different amplitudes. We’ll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the `start_shoot` and `shoot_interval `variables. Both of these variables will actually be set in our `setup()` function. Finally, we’ll have a boolean function that will tell us whether the enemy can shoot this frame or not. 
Our enemy class will look like this: ``` @@ -435,10 +435,10 @@ bool Enemy::time_to_shoot() { } ``` -In update, we’re using the current elapsed time in frames to give us a constantly increasing number to feed to the sine function, which in turn returns a value between -1 and 1. We multiply it by the amplitude of the wave, making this curve more or less exaggerated. +In update, we're using the current elapsed time in frames to give us a constantly increasing number to feed to the sine function, which in turn returns a value between -1 and 1. We multiply it by the amplitude of the wave, making this curve more or less exaggerated. -In `time_to_shoot`, we check to see whether the difference between the current time and the time this enemy last shot is greater than the enemy’s shooting interval. If it is, we set `start_shoot` to the current time, and return `true`. If not, we return `false`. -
Let’s integrate our enemies into the rest of our `testApp.cpp`: +In `time_to_shoot`, we check to see whether the difference between the current time and the time this enemy last shot is greater than the enemy's shooting interval. If it is, we set `start_shoot` to the current time, and return `true`. If not, we return `false`. +
Let's integrate our enemies into the rest of our `testApp.cpp`: ``` //-------------------------------------------------------------- @@ -499,7 +499,7 @@ void testApp::draw(){ ###Collisions -Let’s implement our bullet collision checks. Add a `void check_bullet_collisions();` to your `testApp.h`, then write the following function: +Let's implement our bullet collision checks. Add a `void check_bullet_collisions();` to your `testApp.h`, then write the following function: ``` //-------------------------------------------------------------- @@ -527,9 +527,9 @@ void testApp::check_bullet_collisions() { } ``` -This code is a bit nested, but actually pretty simple. First, it goes through each bullet in the vector and checks to see whether it’s from the player. If it’s from the player, it starts a for-loop for all the enemies, so we can compare the player bullet position against all the enemy positions. We use `ofDist()` to see whether the distance between a given bullet and a given enemy is less than the sum of their radii--if it is, they’re overlapping. -
If a bullet is not from the player, the function does a distance calculation against the player, to see whether a given enemy bullet and the player are close enough to count it as a hit. If there is a hit, we subtract a player’s life and erase that bullet. If the player has less than or equal to 0 lives, we change the game state to the end. -
Don’t forget to call `check_bullet_collisions()` as part of `update_bullets()`: +This code is a bit nested, but actually pretty simple. First, it goes through each bullet in the vector and checks to see whether it's from the player. If it’s from the player, it starts a for-loop for all the enemies, so we can compare the player bullet position against all the enemy positions. We use `ofDist()` to see whether the distance between a given bullet and a given enemy is less than the sum of their radii--if it is, they’re overlapping. +
If a bullet is not from the player, the function does a distance calculation against the player, to see whether a given enemy bullet and the player are close enough to count it as a hit. If there is a hit, we subtract a player's life and erase that bullet. If the player has less than or equal to 0 lives, we change the game state to the end. +
Don't forget to call `check_bullet_collisions()` as part of `update_bullets()`: ``` //-------------------------------------------------------------- @@ -544,7 +544,7 @@ void testApp::update_bullets() { } ``` -Great! Except… we don’t have any enemies yet! Definitely an oversight. This is where our level controller comes in. +Great! Except… we don't have any enemies yet! Definitely an oversight. This is where our level controller comes in. ###Our game's brain @@ -562,7 +562,7 @@ public: }; ``` -As you might've guessed, all it’ll really do is keep track of whether it’s time to spawn another enemy yet. +As you might've guessed, all it'll really do is keep track of whether it’s time to spawn another enemy yet. Inside our `LevelController.cpp`: @@ -580,9 +580,9 @@ bool LevelController::should_spawn() { } ``` -When we set up our level controller, we’ll give it a starting time. It’ll use this time as a baseline for the first enemy spawn. The `should_spawn` code should look familiar from the enemy bullet section. +When we set up our level controller, we'll give it a starting time. It’ll use this time as a baseline for the first enemy spawn. The `should_spawn` code should look familiar from the enemy bullet section. -We’ll wait to set up our level controller until the game actually starts--namely, when the game state changes from ` “start” ` to ` “game” `. +We'll wait to set up our level controller until the game actually starts--namely, when the game state changes from ` “start” ` to ` “game” `. ``` void testApp::keyReleased(int key){ @@ -594,7 +594,7 @@ void testApp::keyReleased(int key){ } ``` -Next we’ll integrate it into our `testApp::update()`: +Next we'll integrate it into our `testApp::update()`: ``` //-------------------------------------------------------------- @@ -623,11 +623,11 @@ void testApp::update(){ } ``` -Awesome! We’re close to done! +Awesome! We're close to done! ###Bonus lives -Before we finish, let’s add in our last OSC feature: the ability to throw in bonus lives on the fly. Add `vector bonuses;` and `ofImage life_image;` to your `testApp.h`. To keep our code modular, let’s also add `void update_bonuses();` in the same place. Don’t forget to `life_image.loadImage("life_image.png");` in `testApp::setup()`. +Before we finish, let's add in our last OSC feature: the ability to throw in bonus lives on the fly. Add `vector bonuses;` and `ofImage life_image;` to your `testApp.h`. To keep our code modular, let’s also add `void update_bonuses();` in the same place. Don’t forget to `life_image.loadImage("life_image.png");` in `testApp::setup()`. `Life.h` should look like this: @@ -646,7 +646,7 @@ public: }; ``` -And it’ll function like this--a lot like the bullet: +And it'll function like this--a lot like the bullet: ``` void Life::setup(ofImage * _img) { @@ -683,7 +683,7 @@ void testApp::update_bonuses() { } ``` -All that’s left for our lives functionality is to alter `testApp::update()` and `testApp::draw()`. +All that's left for our lives functionality is to alter `testApp::update()` and `testApp::draw()`. ``` //-------------------------------------------------------------- @@ -739,7 +739,7 @@ void testApp::draw(){ ###Let's get visual -Finally, we’ve been a bit stingy with visual feedback, so let’s add in a start screen, a score, a visual representation of the lives left, and an end screen. Add `ofImage start_screen;`, `ofImage end_screen;`, `void draw_lives();`, and `void draw_score();` to `testApp.h`. +Finally, we've been a bit stingy with visual feedback, so let’s add in a start screen, a score, a visual representation of the lives left, and an end screen. Add `ofImage start_screen;`, `ofImage end_screen;`, `void draw_lives();`, and `void draw_score();` to `testApp.h`. Change `testApp::setup()` to load in those assets: @@ -780,20 +780,20 @@ void testApp::draw_score() { By using `stringWidth()`, we can calculate the width of a string--handy for centering it. -All that’s left after that is to call `draw_score();` and `draw_lives();` during the `testApp::draw()`’s game state, and to call `draw_score();` during the end state. +All that's left after that is to call `draw_score();` and `draw_lives();` during the `testApp::draw()`’s game state, and to call `draw_score();` during the end state. Congrats--you made a game! ###Linking oF and OSC -Now let’s add in the OSC functionality. We are going to set our application up to receive messages from our iPad and then make changes in real-time while our game is running to test some possible player scenarios. As mentioned before, this can trump going into your application and making manual changes because you skip the need to recompile your game and playtest live. -To accomplish this we are going to create a new class that will contain our OSC functionality. Create a .cpp and .h file for this class now and name it LiveTesting. Open LiveTesting.h And let’s add the line to import the OSC at the top of your file after your preprocessor directives and also a line for using iostream for testing purposes. As we add the code we will explain in inline in the code comments. +Now let's add in the OSC functionality. We are going to set our application up to receive messages from our iPad and then make changes in real-time while our game is running to test some possible player scenarios. As mentioned before, this can trump going into your application and making manual changes because you skip the need to recompile your game and playtest live. +To accomplish this we are going to create a new class that will contain our OSC functionality. Create a .cpp and .h file for this class now and name it LiveTesting. Open LiveTesting.h And let's add the line to import the OSC at the top of your file after your preprocessor directives and also a line for using iostream for testing purposes. As we add the code we will explain in inline in the code comments. Add the following: #include #include "ofxOsc.h" -Next let’s set up all of our variables we are going to use to receive OSC data and map it to in game values. Add the following code into your class. +Next let's set up all of our variables we are going to use to receive OSC data and map it to in game values. Add the following code into your class. class LiveTesting { @@ -824,9 +824,9 @@ public: Jump over to the LiveTesting.cpp file. In this file we are going to set up our network address and the ports we are sending and receiving data on as the first order of business. However, to go any further we are going to need to do some housekeeping and install additional software. For OSC to work it will need a local wifi network to send the messages across. Note this tactic may not work for a network outside of your own because often a sysadmin will stop this kind of traffic from being transmitted on a very public network. We suggest brining an Airport Express or similar with you so you can quickly and wirelessly establish a local network for playtesting. For the purpose of this chapter and to allow us to create an experience that will work on both Android and iOS we are going to use a piece of software called TouchOSC from this URL: http://hexler.net/software/touchosc -The desktop editor software is free however the matching software for your device will be $4.99. Get both now. As a mater of principle, we endorse building your own tools and you could easily build a second oF project to be your OSC sender and receiver on your mobile device. With that said, nothing beats TouchOSC for speed, ease of use and complete, platform independent flexibility. If you are someone who often moves between an iOS and Android device on both Windows and Mac, this tool will become indispensible to you. As a games designer it can open up possibilities like changing levels on the fly, updating game variables, adjusting for player feedback and adding new features into and taking them out of your game as it’s running. We highly endorse using it and support the continued advancement of the tool. You can also use it with music production tools like Ableton Live and it comes with great presets for things like DJing and mixing music live. Go to the app store of your device and purchase the mobile version now if you would like to continue down this route. +The desktop editor software is free however the matching software for your device will be $4.99. Get both now. As a mater of principle, we endorse building your own tools and you could easily build a second oF project to be your OSC sender and receiver on your mobile device. With that said, nothing beats TouchOSC for speed, ease of use and complete, platform independent flexibility. If you are someone who often moves between an iOS and Android device on both Windows and Mac, this tool will become indispensible to you. As a games designer it can open up possibilities like changing levels on the fly, updating game variables, adjusting for player feedback and adding new features into and taking them out of your game as it's running. We highly endorse using it and support the continued advancement of the tool. You can also use it with music production tools like Ableton Live and it comes with great presets for things like DJing and mixing music live. Go to the app store of your device and purchase the mobile version now if you would like to continue down this route. -After we get all of the tools downloaded and installed, we can start setting everything up. You are going to need two bits of information. You are going to need to know the IP address of your computer and the ip address of your laptop. If you are on a mac, just open up your System Preferences. Go to the Network setting and click on your wifi connection in the left sidebar. On the right side it will display your IP address. You can also get this setting by opening up Terminal and entering in the command ifconfig. Terminal will list of every network that’s a possible connection for your machine from the past, even if it’s not currently active. For example, if you have ever connected your phone, it will be in the list with some flag and listed as inactive. Look for the connection that’s currently active. It will look something like this: +After we get all of the tools downloaded and installed, we can start setting everything up. You are going to need two bits of information. You are going to need to know the IP address of your computer and the ip address of your laptop. If you are on a mac, just open up your System Preferences. Go to the Network setting and click on your wifi connection in the left sidebar. On the right side it will display your IP address. You can also get this setting by opening up Terminal and entering in the command ifconfig. Terminal will list of every network that's a possible connection for your machine from the past, even if it’s not currently active. For example, if you have ever connected your phone, it will be in the list with some flag and listed as inactive. Look for the connection that’s currently active. It will look something like this: en1: flags=8863 mtu 1500 ether 60:33:4b:12:e5:3b @@ -836,7 +836,7 @@ en1: flags=8863 mtu 1500 status: active The inet address is your current IP. -On windows, open the charms bar. In search type cmd and open the command prompt. Type in ipconfig. This information is much clearer than the data dump from terminal. The connected listed as your Wireless LAM adapter Wi-Fi will list your current IPV4 address. This is your IP address. Finally, obtain your mobile device’s IP address as well from your device settings. Make a note of your IPAddress for the next section. +On windows, open the charms bar. In search type cmd and open the command prompt. Type in ipconfig. This information is much clearer than the data dump from terminal. The connected listed as your Wireless LAM adapter Wi-Fi will list your current IPV4 address. This is your IP address. Finally, obtain your mobile device's IP address as well from your device settings. Make a note of your IPAddress for the next section. At this point, go ahead and launch TouchOSC on your device and the Touch OSC desktop editor on your computer. If you are on Windows, you will need to make sure you have java installed first. Once the software is open, click the open icon in the top tool bar. In the file containing the code for this chapter you will see a file called ofBook.touchosc. @@ -849,11 +849,11 @@ We are going to make this interface now and deploy it to our phone. We will make float max_enemy_shoot_interval; bool triggerBonus; [image touchOSCsetup.png] -To build the app, let’s start by adding our first knob. Right click in the black empty space to the right. Choose to make a rotaryH. Next make two labelH objects. The first one will be the name of our knob. The second one will be for displaying the value of the current variable in our game. Place one label above the knob and one below. It should look like the below image: +To build the app, let's start by adding our first knob. Right click in the black empty space to the right. Choose to make a rotaryH. Next make two labelH objects. The first one will be the name of our knob. The second one will be for displaying the value of the current variable in our game. Place one label above the knob and one below. It should look like the below image: [image labels.png] -Now look to the left side of the app. At this point, it’s time to set all of the values this knob will be sending and what the labels will display. Let’s start with label1. We will name our knob on screen to make things easier to read. The first value in our game we want to control, level controller interval time, should be what this label reads onscreen. Changing the name field in the app interface will do little. However, note under the name field you can change the color of the label. For this example, use yellow. Next, jump down to the next to last field on screen called Text: +Now look to the left side of the app. At this point, it's time to set all of the values this knob will be sending and what the labels will display. Let’s start with label1. We will name our knob on screen to make things easier to read. The first value in our game we want to control, level controller interval time, should be what this label reads onscreen. Changing the name field in the app interface will do little. However, note under the name field you can change the color of the label. For this example, use yellow. Next, jump down to the next to last field on screen called Text: You will want to set this to level controller interval time. Moving on, select the knob. This one will require more set up because it will actually be sending values to our game. Color it yellow first. In the dark grey OSC box set all of the values we need to receive for the game. If auto is checked, uncheck it. Now customize the text in that box to /game/interval_time. In the From fields set the parameters to a range of values to try out in the game during a playtest. We will use from 0 to 300. These two elements, the tag and the parameters will get packed up into a message and sent over our OSC network to our game when values change. @@ -921,7 +921,7 @@ Label H Color: Pink OSC: /updatedVals/triggerBouns -Save your file to your hard drive desktop and name it PlaytestInterface. You are done building your interface for play testing. Now let’s deploy it. On your mobile device, launch Touch OSC. It will launch and open a settings screen. +Save your file to your hard drive desktop and name it PlaytestInterface. You are done building your interface for play testing. Now let's deploy it. On your mobile device, launch Touch OSC. It will launch and open a settings screen. This is when we need the network address of your computer we retrieved earlier. Under Connections touch OSC: and set it to the IPAddress of your computer to link the two. This should be something like 192.165.0.3 The ports should also get set. Tap each one an set them up to these values: @@ -933,7 +933,7 @@ Now click on Layout. Then tap Add. It will start to search for your computer. Sw Switch back to your device. You should see your computer listed under FOUND HOSTS. Select it. It will pop back to the settings screen. Scroll down and find PlaytestInterface in the list of interfaces. Select it and it will take you back to the main menu. Press Done in the upper left corner and your interface will now launch. If you want to get back to the settings screen at any point the white dot in the upper right hand corner will return the user interface to that screen. -Finally, TouchOSC is set up. Let’s link it to our game and run our very first playtest. Go back to the programming IDE. Open up LiveTesting.cpp In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer’s network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren’t going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You’ll need a separate port for each activity in this scenario. If a port isn’t used by your operating system, you can send and receive data there. We are going to use 8000 and 8001. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: +Finally, TouchOSC is set up. Let's link it to our game and run our very first playtest. Go back to the programming IDE. Open up LiveTesting.cpp In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer’s network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren’t going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You’ll need a separate port for each activity in this scenario. If a port isn’t used by your operating system, you can send and receive data there. We are going to use 8000 and 8001. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: #include "LiveTesting.h" @@ -950,9 +950,9 @@ LiveTesting::LiveTesting(){ */ } -In the above code we simply set up our network address, incoming and out going ports and created a default address pattern. From here we should be good to go to set up the messages we’d like to send and receive in our code. +In the above code we simply set up our network address, incoming and out going ports and created a default address pattern. From here we should be good to go to set up the messages we'd like to send and receive in our code. -Let’s move on to the next major function we want to write. We need to run an update function in this class to update every frame so we can make sure that if we move a slider on our ipad that change becomes reflected within the game. Also, we might want to send that value back out once we receive it so we can get some visual feedback on our tablet to let us know what our current settings are. +Let's move on to the next major function we want to write. We need to run an update function in this class to update every frame so we can make sure that if we move a slider on our ipad that change becomes reflected within the game. Also, we might want to send that value back out once we receive it so we can get some visual feedback on our tablet to let us know what our current settings are. Each time we make a change on our device, it will send over the changes to our code via Touch OSC. We want to make sure we get all of the incoming messages that are being sent so we will create a simple while loop. Every incoming message will come in with its address tag and also the arguments we are setting. You can test for the address tag string to match up the incoming argument with the matching variables in your game. diff --git a/chapters/hardware/chapter.md b/chapters/hardware/chapter.md index dcac999a..706ceb24 100644 --- a/chapters/hardware/chapter.md +++ b/chapters/hardware/chapter.md @@ -9,11 +9,11 @@ This chapter will give you an introduction to working with openFrameworks outsid There are a number of ways of taking your openFrameworks app out of the frame of your own personal computer and getting it to interact with the outside world. Largely this involves some kind of communication from openFrameworks to whatever hardware you've decided to hook up to. The different types of computer based communications (or protocols) vary, but the most common is what's known as 'serial' communication, so called because each bit of data sent is transferred one after the other (as opposed to multiple bits being sent in parallel). -The first hardware that we’ll look at interfacing with is the excellent **Arduino** prototyping platform. Arduino is, in its own words, an *“open-source electronics prototyping platform based on flexible, easy-to-use hardware and software… intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments.*” It’s easy to see why there’s a lot of overlap between communities of people interested in using openFrameworks and Arduino! With Arduino, it’s quick to get your openFrameworks app hooked up to sensors (like light sensors, proximity sensors, or other methods of environmental input), actuators (like lights, motors, and other outputs), and real-time interaction. You're free to move out of the realm of pixels and into the physical world. +The first hardware that we'll look at interfacing with is the excellent **Arduino** prototyping platform. Arduino is, in its own words, an *“open-source electronics prototyping platform based on flexible, easy-to-use hardware and software… intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments.*” It’s easy to see why there’s a lot of overlap between communities of people interested in using openFrameworks and Arduino! With Arduino, it’s quick to get your openFrameworks app hooked up to sensors (like light sensors, proximity sensors, or other methods of environmental input), actuators (like lights, motors, and other outputs), and real-time interaction. You're free to move out of the realm of pixels and into the physical world. This chapter assumes that you have the Arduino IDE installed, in addition to the environment that you normally use for working with openFrameworks. If not, you can download it from the Arduino website (arduino.cc) or the Arduino github (github.com/arduino). -Additionally, following along with the examples in this chapter requires you to have a few pieces of basic hardware. You’ll need an Arduino (any generation; an Uno, Leonardo, or Duemilanove will look the most like the graphics in this chapter but any USB-connected Arduino will work just fine) and the appropriate USB cable to connect to your computer. +Additionally, following along with the examples in this chapter requires you to have a few pieces of basic hardware. You'll need an Arduino (any generation; an Uno, Leonardo, or Duemilanove will look the most like the graphics in this chapter but any USB-connected Arduino will work just fine) and the appropriate USB cable to connect to your computer. [** Callout - The Leonardo differs from earlier boards in that it has built-in USB communication, eliminating the need for a secondary processor. This allows the Leonardo to appear to a connected computer as a mouse and keyboard, in addition to a virtual serial port. This makes setting up interactive applications a very simple procedure - in your openFrameworks app all you need to do is check for a key press! **] @@ -22,7 +22,7 @@ Additionally, following along with the examples in this chapter requires you to **SERIAL: ONE AFTER THE OTHER** -Serial, in the most basic language sense, refers to things that come one after another; it’s a term often used to describe magazines, crimes, and television programs. That meaning also applies when talking about serial data: “serial communication” means that all information between two entities is being sent one piece at a time, following in a single stream. One piece of data, or one bit, is just a binary piece of information: you’re either sending a 0 or a 1. Using the terminology of digital electronics, these are frequently referred to as “high” and “low”; 0 is low (like turning a light off) and 1 is high (flipping it back on). 8 bits (for example the stream 01000001, which represents the letter A) are sometimes packaged together to create a single byte. +Serial, in the most basic language sense, refers to things that come one after another; it's a term often used to describe magazines, crimes, and television programs. That meaning also applies when talking about serial data: “serial communication” means that all information between two entities is being sent one piece at a time, following in a single stream. One piece of data, or one bit, is just a binary piece of information: you’re either sending a 0 or a 1. Using the terminology of digital electronics, these are frequently referred to as “high” and “low”; 0 is low (like turning a light off) and 1 is high (flipping it back on). 8 bits (for example the stream 01000001, which represents the letter A) are sometimes packaged together to create a single byte. Serial communication is actually a very broad topic and there are many serial protocols, including audio-visual protocols such as DMX (based on RS-485) and MIDI (serial at 31,250 bits per second) which we'll briefly cover in this chapter. The most common serial protocol is called RS-232 and computers used to be equipped with RS-232 serial ports (remember them?) but today they are rarely present, which is why serial communications involving a computer will typically require an RS-232 to USB adaptor (found on-line or at your local electronics store). @@ -160,7 +160,7 @@ There's a good, heavily commented demonstration of this in the communications fo **USING FIRMATA AS A SERIAL PROTOCOL** -Though it’s possible to navigate all serial communication manually, you’ll reach the limitations of what you’re able to do fairly quickly - as soon as you start wanting to address different devices or have multiple inputs, you’ll fall into a spiral of packet management and be much more prone to getting corrupt packets or inaccurate and scrambled data. Rather than deal with this manually, it’s much simpler to use Firmata, an open source protocol for managing multiple Serial streams. +Though it's possible to navigate all serial communication manually, you’ll reach the limitations of what you’re able to do fairly quickly - as soon as you start wanting to address different devices or have multiple inputs, you’ll fall into a spiral of packet management and be much more prone to getting corrupt packets or inaccurate and scrambled data. Rather than deal with this manually, it’s much simpler to use Firmata, an open source protocol for managing multiple Serial streams. **OFARDUINO** @@ -169,11 +169,11 @@ ofArduino, the built-in Arduino communication class for openFrameworks, is based **EXAMPLE**: Work through the same LED blink sketch as done previously with only Arduino, but with OF. -The basic flow of what we’re going to do looks like this: (graphic missing) +The basic flow of what we're going to do looks like this: (graphic missing) * Make an ofArduino object * Connect to the Arduino object at the correct port and baud rate -* Set up an event listener to determine whether we’re successfully connected to the Arduino +* Set up an event listener to determine whether we're successfully connected to the Arduino * Set up a pin to communicate with, and specify whether that communication is analog or digital * Poll for data from the serial port * Send HIGH and LOW (or analog value) arguments to that pin @@ -200,7 +200,7 @@ In the setup() of testApp.cpp, use the ofArduino `connect()` function to set up ard.connect("/dev/tty.usbserial-a700fiyD", 57600); ``` -**Set up an event listener to determine whether we’ve successfully connected to the Arduino** +**Set up an event listener to determine whether we've successfully connected to the Arduino** If you're working only within the Arduino IDE, it's easy to have functions (like setting up the pin modes) called only once at the start of the program -- you can just call those functions from within `setup()` with the confidence that they'll always be run once when the device initializes. When you're communicating with other software like openFrameworks, however, it's important to have a checking system to ensure that any setup functions only occur after a connection has been established. openFrameworks uses the ofEventUtils class to make this easier, relying on the default `ofAddListener()` and `ofRemoveListener()` functions to check for the connection event. diff --git a/chapters/image_processing_computer_vision/chapter.md b/chapters/image_processing_computer_vision/chapter.md index 08d4e118..e0ec9602 100644 --- a/chapters/image_processing_computer_vision/chapter.md +++ b/chapters/image_processing_computer_vision/chapter.md @@ -633,7 +633,7 @@ I sometimes assign my students the project of copying a well-known work of inter #### Text Rain by Camille Utterback and Romy Achituv (1999). -*[Text Rain](http://camilleutterback.com/projects/text-rain/)* is a now-classic work of interactive art in which virtual letters appear to "fall" on the visitor's "silhouette". Utterback writes: "In the Text Rain installation, participants stand or move in front of a large projection screen. On the screen they see a mirrored video projection of themselves in black and white, combined with a color animation of falling letters. Like rain or snow, the letters appears to land on participants’ heads and arms. The letters respond to the participants’ motions and can be caught, lifted, and then let fall again. The falling text will 'land' on anything darker than a certain threshold, and 'fall' whenever that obstacle is removed." +*[Text Rain](http://camilleutterback.com/projects/text-rain/)* is a now-classic work of interactive art in which virtual letters appear to "fall" on the visitor's "silhouette". Utterback writes: "In the Text Rain installation, participants stand or move in front of a large projection screen. On the screen they see a mirrored video projection of themselves in black and white, combined with a color animation of falling letters. Like rain or snow, the letters appears to land on participants' heads and arms. The letters respond to the participants’ motions and can be caught, lifted, and then let fall again. The falling text will 'land' on anything darker than a certain threshold, and 'fall' whenever that obstacle is removed." ![Camille Utterback and Romy Achituv, Text Rain (1999)](images/text-rain.jpg) diff --git a/chapters/installation_up_4evr_macosx/chapter.md b/chapters/installation_up_4evr_macosx/chapter.md index efe59727..9b4fb6d3 100644 --- a/chapters/installation_up_4evr_macosx/chapter.md +++ b/chapters/installation_up_4evr_macosx/chapter.md @@ -7,33 +7,33 @@ The original version of the article is [here](http://blairneal.com/blog/installa Edited the article with https://stackedit.io/# for help with rendering Github Flavored Markup --------- -At work I recently had to set up a four installations of different configurations that would need to run all day, every day, 24 hours a day for a couple months with as few crashes or glitches as possible and without anyone going to check on them. This is something that a lot of media artists need to do all the time, and there are a bunch of different tricks and tips to keeping things up for an extended period, I figured I’d share my findings. There are alternate ways to do many of these tasks and this is only one road so please share some tips you’ve picked up out in the field down in the comments box below. +At work I recently had to set up a four installations of different configurations that would need to run all day, every day, 24 hours a day for a couple months with as few crashes or glitches as possible and without anyone going to check on them. This is something that a lot of media artists need to do all the time, and there are a bunch of different tricks and tips to keeping things up for an extended period, I figured I'd share my findings. There are alternate ways to do many of these tasks and this is only one road so please share some tips you’ve picked up out in the field down in the comments box below. -I had to do several searches in a couple different places to find all the information I needed to keep everything consistently up and bug free. Luckily most of the installations I was dealing with this time were fairly light in terms of resources and complications, but it’s always best practices to have a safety net. +I had to do several searches in a couple different places to find all the information I needed to keep everything consistently up and bug free. Luckily most of the installations I was dealing with this time were fairly light in terms of resources and complications, but it's always best practices to have a safety net. I usually run these off brand new, unboxed computers so this is sort of starting from scratch. Most of the things I point out are set to the opposite by default. -Tip: if you’re doing multiple computers, do these prep steps on one of them and just boot the others into target disk mode and use something like [Carbon Copy Cloner](http://www.bombich.com/) to mirror the first one on the next so everything is as consistent as possible. +Tip: if you're doing multiple computers, do these prep steps on one of them and just boot the others into target disk mode and use something like [Carbon Copy Cloner](http://www.bombich.com/) to mirror the first one on the next so everything is as consistent as possible. **Step 1: Prep your software and the computer** ----------------------------------------------- -When building your software or whatever it might be, always keep the long running installation in mind. Plan which things will need to be adjusted by whoever is watching over the installation from the beginning (or at least don’t save it for the end). In my experience, keep it as simple as possible, so that it’s easy for the caretaker to get in there to fix or adjust what they need without opening Xcode and compiling or even exiting out of your app. Time you spend now to make things simple will save you hours of remote debugging when something breaks. +When building your software or whatever it might be, always keep the long running installation in mind. Plan which things will need to be adjusted by whoever is watching over the installation from the beginning (or at least don't save it for the end). In my experience, keep it as simple as possible, so that it’s easy for the caretaker to get in there to fix or adjust what they need without opening Xcode and compiling or even exiting out of your app. Time you spend now to make things simple will save you hours of remote debugging when something breaks. -You’ll need to go through and turn off or disable several different automatic settings to keep things from popping up over top of your application. This can differ depending on whether you’re running 10.7, 10.8, 10.9, 10.10 etc etc. +You'll need to go through and turn off or disable several different automatic settings to keep things from popping up over top of your application. This can differ depending on whether you’re running 10.7, 10.8, 10.9, 10.10 etc etc. Nick Hardeman has made a utility application for setting all of these attributes and more from one location - [check it out here](http://nickhardeman.com/610/openframeworks-configuring-osx-for-a-long-term-installation/) In System Preferences: - - **Desktop and Screensaver:** Disable your screensaver. Set it’s time to “Never." I also suggest changing your desktop background to either black/a screenshot of your app/you client's logo - you can even set these to change automatically - remember - **it's not broken until someone notices** :) + - **Desktop and Screensaver:** Disable your screensaver. Set it's time to “Never." I also suggest changing your desktop background to either black/a screenshot of your app/you client's logo - you can even set these to change automatically - remember - **it's not broken until someone notices** :) - **Energy Saver:** Turn Display Sleep and Computer Sleep to Never. Enable “Start up automatically after power failure” and “Restart automatically if the computer freezes” (these are only available in 10.7 and later) - **Users and Groups:** Go to Login Options (above the padlock) and enable "Automatic Login" - **Software update:** Disable automatic updates. - - **Sharing:** If you are running your main computer without a monitor or in an inaccessible area, don’t forget to turn on File sharing and Screen sharing. This will allow you to access the computer and control it if you're on the same network (optional if you’re concerned about security). - - **Network:** If you don’t need remote access or don’t need Internet access for the installation, it’s not a bad idea to disable the Wifi so the “please select a wireless network” window doesn’t pop up when you least expect it. You can also turn off the option to ask you to join a new network if the proper one isn't found. - - **Bluetooth** If running without a mouse or keyboard plugged in, sometimes you can get the annoying ”Bluetooth keyboard/mouse setup” pop up over your application. You can temporality disable these by going to the advanced settings within the Bluetooth Preferences. See below for it’s location in 10.6. - - **Security:** I would make sure that "Disable Automatic Login" is unchecked so you don't hit any surprises on reboots. If you’re really paranoid, you can even disable things like the IR remote receiver that still exists on some macs and definitely on Macbooks. This would keep pranksters with Apple TV remotes from “Front Rowing” your installation. To disable, go to Security->General->Advanced (in >10.8) and “Disable remote control IR receiver”. + - **Sharing:** If you are running your main computer without a monitor or in an inaccessible area, don't forget to turn on File sharing and Screen sharing. This will allow you to access the computer and control it if you're on the same network (optional if you’re concerned about security). + - **Network:** If you don't need remote access or don’t need Internet access for the installation, it’s not a bad idea to disable the Wifi so the “please select a wireless network” window doesn’t pop up when you least expect it. You can also turn off the option to ask you to join a new network if the proper one isn't found. + - **Bluetooth** If running without a mouse or keyboard plugged in, sometimes you can get the annoying ”Bluetooth keyboard/mouse setup” pop up over your application. You can temporality disable these by going to the advanced settings within the Bluetooth Preferences. See below for it's location in 10.6. + - **Security:** I would make sure that "Disable Automatic Login" is unchecked so you don't hit any surprises on reboots. If you're really paranoid, you can even disable things like the IR remote receiver that still exists on some macs and definitely on Macbooks. This would keep pranksters with Apple TV remotes from “Front Rowing” your installation. To disable, go to Security->General->Advanced (in >10.8) and “Disable remote control IR receiver”. - **Notification Center:** You can either [disable Notification Center completely](http://www.tekrevue.com/tip/how-to-completely-disable-notification-center-in-mac-os-x/), or set your "Do Not Disturb" to basically on be on forever by setting it with overlapping times like the screenshot below ![BluetoothSettings](images/Bluetooth_settings.png) @@ -72,7 +72,7 @@ defaults write com.apple.finder CreateDesktop -bool false **Step 2: Boot into your software** ------------------------------- -Things get unplugged, power goes out, not everyone has budget or space for a battery backup etc etc. Above, I covered how to have everything reboot automatically after power failures or freezes, but you’ll also need your app to be ready to go from boot and not leave the desktop open to prying eyes. There are many ways to have your application load automatically - the simplest is using OSX's built in tools: In the System Preferences “Accounts” panel, select “Login Items” and drag your application into there to have it open automatically on launch. +Things get unplugged, power goes out, not everyone has budget or space for a battery backup etc etc. Above, I covered how to have everything reboot automatically after power failures or freezes, but you'll also need your app to be ready to go from boot and not leave the desktop open to prying eyes. There are many ways to have your application load automatically - the simplest is using OSX's built in tools: In the System Preferences “Accounts” panel, select “Login Items” and drag your application into there to have it open automatically on launch. ![Login Items](images/Login_items.png) @@ -83,11 +83,11 @@ There are several ways to make sure your application goes up and stays up - **Launchd** -Using Launch Daemons is an alternate way to get apps to load on boot and to continuously re-open them if they go down. Launchd plists are very useful alternatives to cron jobs and can be used to run things on a periodic basis or on calendar days. You could achieve similar results with a combination of automator and iCal, but it depends on what you’re comfortable with. +Using Launch Daemons is an alternate way to get apps to load on boot and to continuously re-open them if they go down. Launchd plists are very useful alternatives to cron jobs and can be used to run things on a periodic basis or on calendar days. You could achieve similar results with a combination of automator and iCal, but it depends on what you're comfortable with. Here is an [Apple Doc](http://developer.apple.com/library/mac/#documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html) on using Launch Agents and Launch Daemons in various ways. -The [difference between a Launch Daemon and a Launch Agent](http://techjournal.318.com/general-technology/launchdaemons-vs-launchagents/) (Basically whether you need it to run when a user is logged in or not…for most simple options like launching a regular app, you’ll just want a Launch Agent) +The [difference between a Launch Daemon and a Launch Agent](http://techjournal.318.com/general-technology/launchdaemons-vs-launchagents/) (Basically whether you need it to run when a user is logged in or not…for most simple options like launching a regular app, you'll just want a Launch Agent) Also note (!) that you may need to point your launch daemon to a file within your .app package, not just the app itself - you have to point it to the file in the MacOS folder inside the .app package (right-click your app and select "Show package Contents") Otherwise you might be wondering why the launchdaemon isn't launching your app. @@ -100,14 +100,14 @@ In Lingon, hit the + to create a new launchd plist. Just make it a standard laun ![LingonSetup](images/LingonSetup.png) -One additional/optional thing you can add to this is to put an additional key in the plist for a “Successful Exit”. By adding this, your app won’t re-open when it has detected that it closed normally (ie You just hit escape intentionally, it didn’t crash). Can be useful if you’re trying to check something and OS X won’t stop re-opening the app on you. To easily add this to the key, click the advanced tab and click the checkbox for "Successful exit" - or just add it manually as it in the above screenshot. +One additional/optional thing you can add to this is to put an additional key in the plist for a “Successful Exit”. By adding this, your app won't re-open when it has detected that it closed normally (ie You just hit escape intentionally, it didn’t crash). Can be useful if you’re trying to check something and OS X won’t stop re-opening the app on you. To easily add this to the key, click the advanced tab and click the checkbox for "Successful exit" - or just add it manually as it in the above screenshot. **Shell script+Cron Job method** (I got the following super helpful tip from [Kyle McDonald](http://kylemcdonald.net/)) ) -This method is sort of deprecated in relation to the launchd method - you can run shell scripts with Lingon and launchd in the same manner as what we've got here. Shell scripting is your best friend. With the help of the script below and an application called CronniX (or use Lingon) , you will be able to use a cronjob to check the system’s list of currently running processes. If your app does not appear on the list, then the script will open it again, otherwise it won’t do anything. Either download the script or type the following into a text editor, replacing Twitter.app with your app’s name and filepath. Don’t forget the “.app” extension in the if statement!: +This method is sort of deprecated in relation to the launchd method - you can run shell scripts with Lingon and launchd in the same manner as what we've got here. Shell scripting is your best friend. With the help of the script below and an application called CronniX (or use Lingon) , you will be able to use a cronjob to check the system's list of currently running processes. If your app does not appear on the list, then the script will open it again, otherwise it won’t do anything. Either download the script or type the following into a text editor, replacing Twitter.app with your app’s name and filepath. Don’t forget the “.app” extension in the if statement!: \#!/bin/sh if [ $(ps ax | grep -v grep | grep "Twitter.app" | wc -l) -eq 0 ] then @@ -118,12 +118,12 @@ This method is sort of deprecated in relation to the launchd method - you can ru Save that file as something like “KeepOpen.sh” and keep it next to your application or somewhere convenient. -After creating that file, you’ll need to make it executable. To do this, open the Terminal and in a new window type “chmod +x ” and then enter the path to the shell script you just created (you can either drag the shell script into the terminal window or manually type it). It would look something like this: +After creating that file, you'll need to make it executable. To do this, open the Terminal and in a new window type “chmod +x ” and then enter the path to the shell script you just created (you can either drag the shell script into the terminal window or manually type it). It would look something like this: 4Evr-MacBook-Pro:~ Forever4Evr$ chmod +x /Users/Forever4Evr/Desktop/KeepOpen.sh -After you have made it executable, you’re now ready to set it up as a cronjob. Tip: to test the script, you can change the extension at the end to KeepOpen.command as an alternative to opening it with Terminal, but the same thing gets done. +After you have made it executable, you're now ready to set it up as a cronjob. Tip: to test the script, you can change the extension at the end to KeepOpen.command as an alternative to opening it with Terminal, but the same thing gets done. Cronjobs are just low level system tasks that are set to run on a timer. The syntax for cronjobs is outside of the scope of this walkthrough, but there are many sites available for that. Instead, the application CronniX can do a lot of the heavy lifting for you. @@ -131,7 +131,7 @@ After downloading CronniX, open it up and create a new cronjob. In the window th ![Cronnix_link](images/Cronnix-settings.png) -Now just hit “New” and then make sure to hit “Save” to save it into the system’s crontab. Now if you just wait a minute then it should open your app every minute on the minute. Maybe save this one for the very end if you have more to do :) +Now just hit “New” and then make sure to hit “Save” to save it into the system's crontab. Now if you just wait a minute then it should open your app every minute on the minute. Maybe save this one for the very end if you have more to do :) This is a great tool if there is an unintended crash because the app will never be down longer than a minute. @@ -156,7 +156,7 @@ Applescript is also a very solid choice for doing some more OS specific work in **Step 4: Reboot periodically** --------------------------- -This one is a little more preventative, or maybe superstitious so hopefully someone can point out a concrete reason why this is a good idea. Depending on your app and the amount of stuff it reaches into, there could be some memory leaks or other OS bugs that you haven’t accounted for. Rebooting every day or week is a good idea to keep everything tidy, system wise. +This one is a little more preventative, or maybe superstitious so hopefully someone can point out a concrete reason why this is a good idea. Depending on your app and the amount of stuff it reaches into, there could be some memory leaks or other OS bugs that you haven't accounted for. Rebooting every day or week is a good idea to keep everything tidy, system wise. The simplest option by far would be to go to System Preferences->Energy Saver and then click “Schedule…” and enter in some values if you need to turn the computer off to rest for a longer period of time to save it some stress when it might not be used at night time or something. Heat can do funny things sometimes, so if you have a chance to get your computer to rest and the time to test it, definitely give this a shot…saves some energy too which is nice. @@ -164,13 +164,13 @@ The simplest option by far would be to go to System Preferences->Energy Saver an You could also set up another shell script with a crontab as above with CronniX that reboots the system with as often as you specify. -Another option (if you don’t want to deal with the terminal and shell scripting) is to use iCal to call an Automator iCal event. This method is perhaps a little easier to schedule and visualize when you will reboot. Within Automator, create a new file with the iCal event template to do something like this: +Another option (if you don't want to deal with the terminal and shell scripting) is to use iCal to call an Automator iCal event. This method is perhaps a little easier to schedule and visualize when you will reboot. Within Automator, create a new file with the iCal event template to do something like this: ![Automator Shell Script](images/Automator_example2.png) -Run it to see if it does what you expect and then save it out. When you save,it will open in iCal as an action that gets opened. Just set it to repeat as often as you’d like. You can also set things like having it email you when it reboots or runs the script. +Run it to see if it does what you expect and then save it out. When you save,it will open in iCal as an action that gets opened. Just set it to repeat as often as you'd like. You can also set things like having it email you when it reboots or runs the script. -If you’d like to just close your programs and re-open them and there is a background and foreground do something like this (pauses are so the quitting and re-opening stuff has time to actually execute): +If you'd like to just close your programs and re-open them and there is a background and foreground do something like this (pauses are so the quitting and re-opening stuff has time to actually execute): ![AutomatorPause](images/Automator_example.png) @@ -187,15 +187,15 @@ Step 6: Test, test, test. ------------------------- -You’ve already tested and perfected your software for the installation, so make sure to test all of the above methods and automatic scripts in as realistic manner as you can before you leave it alone for the first day at school. +You've already tested and perfected your software for the installation, so make sure to test all of the above methods and automatic scripts in as realistic manner as you can before you leave it alone for the first day at school. -You can’t account for everything, so don’t beat yourself up if something does eventually happen, but this list will hopefully alleviate a little bit of frustration. Good luck! +You can't account for everything, so don’t beat yourself up if something does eventually happen, but this list will hopefully alleviate a little bit of frustration. Good luck! Additional Tips: Logging ------------------------ -If you have an installation that runs for weeks or months, you might want a way to keep tabs on it that doesn’t involve remotely logging in and checking on it. A good thing to have would be to have something on the system that writes certain info to a text file (kept on a linked Dropbox), or better write that file to a web server that you can then check. +If you have an installation that runs for weeks or months, you might want a way to keep tabs on it that doesn't involve remotely logging in and checking on it. A good thing to have would be to have something on the system that writes certain info to a text file (kept on a linked Dropbox), or better write that file to a web server that you can then check. There are a couple things you can do depending on what you want to know about the state of your installation. @@ -203,7 +203,7 @@ There is a terminal command you can use to get a list of all of the currently ru ps aux (or ps ax) -(more info above ps commands [here](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/ps.1.html))) – Further more you can filter this list to only return applications you’re interested in learning about: +(more info above ps commands [here](https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/ps.1.html))) – Further more you can filter this list to only return applications you're interested in learning about: ps aux | grep "TweetDeck" @@ -221,15 +221,15 @@ All that is left is to write this output to a text file, which you can do with a This line basically says - tell me the open processes (px aux) - only give me the lines that have "Tweetdeck" in them (grep Tweetdeck) - and then append them to a text file located at this location ( >> path_to_text_file) -Now we just need to make this an executable shell script and set it up as a launch daemon or cron job – see above at Step 3 to learn how to run the shell script at a regular interval using Lingon and launchd. If the app isn’t running, it will only return the “grep YourAppName” process which is a good thing to log because if your app isn’t open you won’t know how long it’s been out (nothing will be logged), but having the grep process logged will at least tell you it was checking for it. Grep will also more accurately tell you what time it checked – the other app will only give you a start time and up time. +Now we just need to make this an executable shell script and set it up as a launch daemon or cron job – see above at Step 3 to learn how to run the shell script at a regular interval using Lingon and launchd. If the app isn't running, it will only return the “grep YourAppName” process which is a good thing to log because if your app isn’t open you won’t know how long it’s been out (nothing will be logged), but having the grep process logged will at least tell you it was checking for it. Grep will also more accurately tell you what time it checked – the other app will only give you a start time and up time. -Let’s also take this one step further and say, hypothetically, that the Triplehead2Go display adapter you have is fairly wonky and you don’t always get the displays or projectors to connect after reboot – or maybe a projector is shutting itself off and disrupting things. Well we can log the currently available resolutions too! Try entering the line below in your own terminal: +Let's also take this one step further and say, hypothetically, that the Triplehead2Go display adapter you have is fairly wonky and you don’t always get the displays or projectors to connect after reboot – or maybe a projector is shutting itself off and disrupting things. Well we can log the currently available resolutions too! Try entering the line below in your own terminal: system_profiler SPDisplaysDataType This will return a list of connected displays and some metadata about them including resolution and names. -Let’s say you want to make sure you’re running a resolution of 3840×720 at all times…or you want a log of resolution changes. You would do something like: +Let's say you want to make sure you’re running a resolution of 3840×720 at all times…or you want a log of resolution changes. You would do something like: system_profiler SPDisplaysDataType | grep Resolution @@ -239,15 +239,15 @@ This will return “Resolution: 3840×720″ which you can combine with the abov ps aux | grep 'YourAppName' >> /Users/you/filepath/Install6ProcessLog.txt system_profiler SPDisplaysDataType | grep Resolution >> /Users/you/Dropbox/Install6ProcessLog.txt -And now you’re feeling excited, maybe you want to grab a fullscreen screenshot at a regular interval too, just to make sure there is no funkiness happening that you can’t see…well you could add this line to the above as well: +And now you're feeling excited, maybe you want to grab a fullscreen screenshot at a regular interval too, just to make sure there is no funkiness happening that you can’t see…well you could add this line to the above as well: screencapture ~/Desktop/$(date +%Y%m%d-%H%M%S).png -This will save a screenshot to the desktop (specify your own file path) with a formatted date and time. You may want to do this every hour instead of every 5 minutes since it’s a big chunk of data and it may cause some issue with your screens. As usual – test before deploying! +This will save a screenshot to the desktop (specify your own file path) with a formatted date and time. You may want to do this every hour instead of every 5 minutes since it's a big chunk of data and it may cause some issue with your screens. As usual – test before deploying! Bonus points would be to create an auto-generated table and webpage that takes all of this info and puts it into a nice view that you can use to check all of your installations at a glance. -If the process logger isn’t enough, we can use what we learned in that process to actually set up a system to email you if something is amiss so you don’t have to manually check it. We can do this all with the command line and internal tools, it’s just a more involved setup. This is going to be fairly general and will need some tuning in your specific case. +If the process logger isn't enough, we can use what we learned in that process to actually set up a system to email you if something is amiss so you don’t have to manually check it. We can do this all with the command line and internal tools, it’s just a more involved setup. This is going to be fairly general and will need some tuning in your specific case. First you will need to configure postfix so you can easily send emails from the terminal – [follow the instructions here as closely as possible](http://benjaminrojas.net/configuring-postfix-to-send-mail-from-mac-os-x-mountain-lion/) @@ -261,7 +261,7 @@ The line in the passwd file mentioned in the article would be: smtp.gmail.com:58 Now send a test email to yourself by running: echo “Hello” | mail -s “test” “InstallationSupport@gmail.com” -Second step is to combine this new found ability to send emails from the Terminal with a process to check if your application is still running…something like the below would work with some tweaking for what you’re looking to do: +Second step is to combine this new found ability to send emails from the Terminal with a process to check if your application is still running…something like the below would work with some tweaking for what you're looking to do: \#!/bin/sh if [ $(ps ax | grep -v grep | grep "YourApp.app" | wc -l) -eq 0 ] ; #Replace YourApp.app with your own app's name @@ -279,7 +279,7 @@ Second step is to combine this new found ability to send emails from the Termina echo "YourApp is running" fi -Now you just need to follow the instructions from Step 3 above to set this shell script up to run with launchd – you can check it every 5 minutes and have it email you if it crashed. You could also adapt the If statement to email you if the resolution isn’t right or some other process condition. +Now you just need to follow the instructions from Step 3 above to set this shell script up to run with launchd – you can check it every 5 minutes and have it email you if it crashed. You could also adapt the If statement to email you if the resolution isn't right or some other process condition. Memory leak murderer -------------------- @@ -310,7 +310,7 @@ Nick Hardeman's [ofxMacUtils](https://github.com/NickHardeman/ofxMacUtils) [https://sfpc.hackpad.com/rPi-run-4-ever-qFgafqYPM54](https://sfpc.hackpad.com/rPi-run-4-ever-qFgafqYPM54) **WINDOWS:** -If you’re looking for help with this task with Windows, check out this awesome script [StayUp](http://www.bantherewind.com/stayup) from Stephen Schieberl. Also for Windows: http://www.softpedia.com/get/System/File-Management/Restart-on-Crash.shtml and this tool for scripting OS operations on windows http://www.nirsoft.net/utils/nircmd.html +If you're looking for help with this task with Windows, check out this awesome script [StayUp](http://www.bantherewind.com/stayup) from Stephen Schieberl. Also for Windows: http://www.softpedia.com/get/System/File-Management/Restart-on-Crash.shtml and this tool for scripting OS operations on windows http://www.nirsoft.net/utils/nircmd.html Check out this great step by step from EVSC: http://www.evsc.net/home/prep-windows-machine-for-fulltime-exhibition-setup diff --git a/chapters/intro_to_graphics/Cut Material.md b/chapters/intro_to_graphics/Cut Material.md index ddf76d89..93283cc7 100644 --- a/chapters/intro_to_graphics/Cut Material.md +++ b/chapters/intro_to_graphics/Cut Material.md @@ -167,4 +167,4 @@ So we need is to reset the coordinate system using [`ofPushMatrix()`](http://www **[paragraph needs work]** ~~There are plenty of reasons why we might want to create visuals using code rather than with pencil and paper. Code allows for easy repetition. We can design a simple rule for making a mark on screen, and then we can repeat that rule and cover the screen in milliseconds. Code allows for animation - from simple shapes wiggling on our screen to movies like Pixar's Monsters, Inc. Code allows for interactivity, which ranges from games to web browsing. Most importantly to me, code allows us to engage with digital information. We can visualize and explore data. We can take digital imagery and reimagine it.~~ -**[insert images of the works of artists making inspiring generative visuals]** \ No newline at end of file +**[insert images of the works of artists making inspiring generative visuals]** diff --git a/chapters/ios/chapter.md b/chapters/ios/chapter.md index cb88a693..e9c34760 100644 --- a/chapters/ios/chapter.md +++ b/chapters/ios/chapter.md @@ -477,4 +477,4 @@ https://itunes.apple.com/au/app/snake-the-planet!/id528414021?mt=8 https://itunes.apple.com/au/app/horizons/id391748891?mt=8 -https://itunes.apple.com/us/app/spelltower/id476500832?mt=8 \ No newline at end of file +https://itunes.apple.com/us/app/spelltower/id476500832?mt=8 diff --git a/chapters/ios/outline.md b/chapters/ios/outline.md index f1530da6..8305e8e3 100644 --- a/chapters/ios/outline.md +++ b/chapters/ios/outline.md @@ -18,4 +18,4 @@ iOS Advanced sidebars ----------------- - GCD, blocks, "the main queue" -- ARC and C++ \ No newline at end of file +- ARC and C++ diff --git a/chapters/math/brannon_edits_chapter.md b/chapters/math/brannon_edits_chapter.md index 0b5ce43f..c2213948 100644 --- a/chapters/math/brannon_edits_chapter.md +++ b/chapters/math/brannon_edits_chapter.md @@ -676,4 +676,4 @@ In the 'Advanced Graphics' chapter you'll learn about two similar matrices: ##### Thanks -Thanks to Prof. Ken Perlin and Prof. Bo'az Klartag for your ideas on teaching mathematics. \ No newline at end of file +Thanks to Prof. Ken Perlin and Prof. Bo'az Klartag for your ideas on teaching mathematics. diff --git a/chapters/project_elliot/chapter.md b/chapters/project_elliot/chapter.md index 68987cb6..35718204 100644 --- a/chapters/project_elliot/chapter.md +++ b/chapters/project_elliot/chapter.md @@ -20,9 +20,9 @@ An architectural web of threads spans a gallery space. It hangs abstract and und A 2D canvas is reduced from a surface piece into a line segment, but then constructed into another dimension, a volume. Light creates contrast and order on the lines to articulate digital matter. Digital forms inhabit the interconnected boundaries of space, moulding visual mass, -The artists reference Picasso’s light painting, and Reticuláreas of Gego who’s work offers a contemplation of the material and immaterial, time and space, origin and encounter and art and technology. +The artists reference Picasso's light painting, and Reticuláreas of Gego who’s work offers a contemplation of the material and immaterial, time and space, origin and encounter and art and technology. -Kimchi and Chips create technology which paints into different dimensions, bringing new canvases and expanding the possibilities for artists to articulate form. These technologies become a corpus of code, offered without restriction on the internet. Their code is adopted by other artists and corporations, spreading values and ideas implicit with the artists’ work into shared cultural idea space. *Line Segments Space* lives both as a dynamic gallery object, and as an encapsulation of the techniques as new computer code and tools on the internet. +Kimchi and Chips create technology which paints into different dimensions, bringing new canvases and expanding the possibilities for artists to articulate form. These technologies become a corpus of code, offered without restriction on the internet. Their code is adopted by other artists and corporations, spreading values and ideas implicit with the artists' work into shared cultural idea space. *Line Segments Space* lives both as a dynamic gallery object, and as an encapsulation of the techniques as new computer code and tools on the internet. **[BD: This artist statement may be better at the top. It feels a bit weird to go from talking about the work in the forward, to a brief technical overview, and then an artist statement.]** diff --git a/chapters/project_joel/chapter.md b/chapters/project_joel/chapter.md index 6ecd7fda..ee13e7a4 100644 --- a/chapters/project_joel/chapter.md +++ b/chapters/project_joel/chapter.md @@ -302,13 +302,13 @@ Kieran and Bafic were the people who ran the show for the general public, below *Did you have a routine before show time?* -Before the first show of the day we’d double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we’d dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we’d turn the beanbags upright so as to ’set the scene’. Then, as people started to walk in we’d raise the lights as though they were walking on stage. And then before we pressed play we’d dim the lights to black. +Before the first show of the day we'd double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we’d dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we’d turn the beanbags upright so as to ’set the scene’. Then, as people started to walk in we’d raise the lights as though they were walking on stage. And then before we pressed play we’d dim the lights to black. *Any problems during shows? Crashes? Funny stories?* A couple of times the connection between the Kinect and the laptop failed due to the cable being under tension so we just had to let the show run to the end before we could fix it. The main problem we had was the projector overheating and displaying a lamp warning which involved having to find the technician to sort it. At one point the projector overheated so badly that we had to leave it switched off for 40 minutes before we could run the show again. -Off the top of my head I can’t think of anything I’d like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we’d mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn’t have to be manned at all times. +Off the top of my head I can't think of anything I’d like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we’d mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn’t have to be manned at all times. Following is Bafic's post show report: diff --git a/chapters/project_joel/unabridged.md b/chapters/project_joel/unabridged.md index 20db6921..c05d47a7 100644 --- a/chapters/project_joel/unabridged.md +++ b/chapters/project_joel/unabridged.md @@ -302,13 +302,13 @@ Kieran and Bafic were the people who ran the show for the general public, below *Did you have a routine before show time?* -Before the first show of the day we’d double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we’d dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we’d turn the beanbags upright so as to ’set the scene’. Then, as people started to walk in we’d raise the lights as though they were walking on stage. And then before we pressed play we’d dim the lights to black. +Before the first show of the day we'd double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we’d dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we’d turn the beanbags upright so as to ’set the scene’. Then, as people started to walk in we’d raise the lights as though they were walking on stage. And then before we pressed play we’d dim the lights to black. *Any problems during shows? Crashes? Funny stories?* A couple of times the connection between the Kinect and the laptop failed due to the cable being under tension so we just had to let the show run to the end before we could fix it. The main problem we had was the projector overheating and displaying a lamp warning which involved having to find the technician to sort it. At one point the projector overheated so badly that we had to leave it switched off for 40 minutes before we could run the show again. -Off the top of my head I can’t think of anything I’d like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we’d mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn’t have to be manned at all times. +Off the top of my head I can't think of anything I’d like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we’d mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn’t have to be manned at all times. Following is Bafic's post show report: diff --git a/chapters/setup_and_project_structure/outline.md b/chapters/setup_and_project_structure/outline.md index 922dc1e0..af88c234 100644 --- a/chapters/setup_and_project_structure/outline.md +++ b/chapters/setup_and_project_structure/outline.md @@ -29,4 +29,4 @@ I've have had some success explaining this things to my students by making a dir - How these files are structured (in OF) - Peeking at others files, OF's files in search for some help. - Some basic OOP, related to the idea of making a lot of the same recipe, how to deal with it. Link to the other chapters where OOP is covered. - \ No newline at end of file + From d05357484151b847e3d613264789005050ded9fe Mon Sep 17 00:00:00 2001 From: zach lieberman Date: Sun, 22 Mar 2015 18:05:57 -0400 Subject: [PATCH 2/4] more changes --- chapters/cplusplus_basics/chapter.md | 2 +- chapters/cplusplus_basics/unabridged.md | 2 +- chapters/data_vis/chapter.md | 4 +- chapters/game_design/chapter.md | 40 +++++++++---------- chapters/game_design/old drafts/oscchapter.md | 36 ++++++++--------- chapters/hardware/chapter.md | 6 +-- .../chapter.md | 2 +- .../installation_up_4evr_macosx/chapter.md | 26 ++++++------ chapters/project_elliot/chapter.md | 2 +- chapters/project_joel/chapter.md | 4 +- chapters/project_joel/unabridged.md | 4 +- 11 files changed, 64 insertions(+), 64 deletions(-) diff --git a/chapters/cplusplus_basics/chapter.md b/chapters/cplusplus_basics/chapter.md index 2a683307..ccefce35 100644 --- a/chapters/cplusplus_basics/chapter.md +++ b/chapters/cplusplus_basics/chapter.md @@ -160,7 +160,7 @@ prog.cpp:5:27: error: 'endl' was not declared in this scope ^ ``` -The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function 'int main()'`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: ‘cout’ was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. +The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function 'int main()'`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: ‘cout' was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. ```cpp #include diff --git a/chapters/cplusplus_basics/unabridged.md b/chapters/cplusplus_basics/unabridged.md index d574d75f..cfd74b57 100644 --- a/chapters/cplusplus_basics/unabridged.md +++ b/chapters/cplusplus_basics/unabridged.md @@ -158,7 +158,7 @@ prog.cpp:5:27: error: 'endl' was not declared in this scope ^ ``` -The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function 'int main()'`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: ‘cout’ was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. +The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function 'int main()'`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: ‘cout' was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. ```cpp #include diff --git a/chapters/data_vis/chapter.md b/chapters/data_vis/chapter.md index 656820fd..c714676b 100644 --- a/chapters/data_vis/chapter.md +++ b/chapters/data_vis/chapter.md @@ -407,7 +407,7 @@ Here we have a for loop generating values for i that range from 0 to maxValue. S **Step 6 Interact.** -Finally we can add interactivity by creating clickable tabs that will switch between the different datasets in our file. This section turns our code into a state machine, where we define a variable called 'which' which is toggled between the values 0,1 and 2. The value of ‘which’, dictates what dataset will be displayed. +Finally we can add interactivity by creating clickable tabs that will switch between the different datasets in our file. This section turns our code into a state machine, where we define a variable called 'which' which is toggled between the values 0,1 and 2. The value of ‘which', dictates what dataset will be displayed. In testApp.h, declare which: ```cpp @@ -466,7 +466,7 @@ to this: } ``` -We have created a new float 'value' to hold each data point. Depending on the value of ‘which’, value is assigned data from one of the three data sets in the tsp file. +We have created a new float 'value' to hold each data point. Depending on the value of ‘which', value is assigned data from one of the three data sets in the tsp file. Finally the last step here is to draw the titles to the screen which is done by adding the last block of code underneath the for loop we just changed. diff --git a/chapters/game_design/chapter.md b/chapters/game_design/chapter.md index b3a5a339..c0de2fa1 100644 --- a/chapters/game_design/chapter.md +++ b/chapters/game_design/chapter.md @@ -68,11 +68,11 @@ With all that written out, let's use OSC to affect the following: These three parameters will allow the developer to, second-by-second, tailor the difficulty of the game to the individual playing it. -Let's start with our testApp. There are a few things we definitely know we’ll want classes for, so make corresponding .h and .cpp files for Player, Bullet, Life, Enemy, and LevelController. Remember to `#include "ofMain.h"` in each of those classes, and to include the .h file of each of those classes in `testApp.h`. +Let's start with our testApp. There are a few things we definitely know we'll want classes for, so make corresponding .h and .cpp files for Player, Bullet, Life, Enemy, and LevelController. Remember to `#include "ofMain.h"` in each of those classes, and to include the .h file of each of those classes in `testApp.h`. ###Gamestates -First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we’re in, which we’ll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are `"start"`, `"game"`, and `"end"`. Let’s add a score and a player at this point as well. +First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we're in, which we'll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are `"start"`, `"game"`, and `"end"`. Let’s add a score and a player at this point as well. 
 ```cpp string game_state; @@ -80,7 +80,7 @@ int score; Player player_1; ``` -We'll then divide up `testApp`’s `update()` and `draw()` loops between those game states: +We'll then divide up `testApp`'s `update()` and `draw()` loops between those game states: ```cpp //-------------------------------------------------------------- @@ -112,7 +112,7 @@ void testApp::setup(){ } ``` -Finally, let's make sure that we can move forward from the start screen. In this example, when the player is on the start screen and releases the space key, they’ll be taken to the game. +Finally, let's make sure that we can move forward from the start screen. In this example, when the player is on the start screen and releases the space key, they'll be taken to the game. ```cpp //-------------------------------------------------------------- @@ -128,7 +128,7 @@ void testApp::keyReleased(int key){ ###Player movement -Great! Let's move onto our player. Our player’s class looks like this: +Great! Let's move onto our player. Our player's class looks like this: ```cpp class Player { @@ -155,7 +155,7 @@ public: Taking this one step at a time: -* Our player's position will be stored in an `ofPoint` called `pos`. ofPoints are handy datatypes that contain `x` and `y` values, letting us access our player’s position through `pos.x` and `pos.y`. +* Our player's position will be stored in an `ofPoint` called `pos`. ofPoints are handy datatypes that contain `x` and `y` values, letting us access our player's position through `pos.x` and `pos.y`. * Our player will have `width`, `height`, and `speed` variables (which we'll use for collision detection and movement, respectively). * Our player will have an integer number of lives (since it wouldn't make any sense for them to have 4.33333333333 lives). * Our player will keep track of what movement keys are currently pressed in separate booleans. @@ -165,7 +165,7 @@ Taking this one step at a time: You may be wondering why we're using all these booleans--why not just check and see which keys are pressed? The problem is that, in openFrameworks, `keyPressed()` does not return all the keys currently being pressed--just the last key that was pressed. That means that if the player presses up and left (intending to move diagonally), openFrameworks will only report one of the keys being pressed. You can try printing out the result of keyPressed to see this in action. -
What we'll do to avoid this is instead base the player’s movement on the booleans we wrote earlier. If the player presses a certain key, that boolean will be true; if they release that key, that boolean will be false. That way, if the player presses up and left, we’ll report up and left as being true until those keys are released. +
What we'll do to avoid this is instead base the player's movement on the booleans we wrote earlier. If the player presses a certain key, that boolean will be true; if they release that key, that boolean will be false. That way, if the player presses up and left, we'll report up and left as being true until those keys are released. Here's what our new `keyPressed()` and `keyReleased()` functions look like: @@ -216,7 +216,7 @@ void testApp::keyReleased(int key){ ``` -Add `ofImage player_image` to `testApp.h`, then load the player's image and instantiate the player in `testApp`’s `setup()`: +Add `ofImage player_image` to `testApp.h`, then load the player's image and instantiate the player in `testApp`'s `setup()`: ```cpp void testApp::setup(){ @@ -254,7 +254,7 @@ void testApp::draw(){ You should have a player who moves around on-screen. Sweet!
 ###Player bullets -Let's make our bullets next. In order to have a variable number of bullets on screen at a time, we need to add a `vector bullets;` to testApp.h. Let’s also create a `void update_bullets();` function, which will update our vector of bullets (and, shortly, trigger the check for bullet collisions). We also want our player and enemy bullets to look different, so we’ll add `ofImage enemy_bullet_image;` and `ofImage player_bullet_image;` to our `testApp.h` file. +Let's make our bullets next. In order to have a variable number of bullets on screen at a time, we need to add a `vector bullets;` to testApp.h. Let's also create a `void update_bullets();` function, which will update our vector of bullets (and, shortly, trigger the check for bullet collisions). We also want our player and enemy bullets to look different, so we'll add `ofImage enemy_bullet_image;` and `ofImage player_bullet_image;` to our `testApp.h` file. Our bullet class will look a lot like the player class, having a position, speed, width, pointer to an image, and various functions. The big difference is that the bullets will keep track of who they came from (since that will affect who they can hurt and which direction they move). @@ -384,7 +384,7 @@ Remember, the first parameter in the bullet's setup is whether it comes from the ###Adding adversaries -Let's move on to our enemy. This process should be familiar by now. Add an `ofImage enemy_image;` and a `vector enemies;` to `testApp.h`. Additionally, add `float max_enemy_amplitude;` and `float max_enemy_shoot_interval;` to `testApp.h`--these are two of the enemy parameters we’ll affect with OSC. +Let's move on to our enemy. This process should be familiar by now. Add an `ofImage enemy_image;` and a `vector enemies;` to `testApp.h`. Additionally, add `float max_enemy_amplitude;` and `float max_enemy_shoot_interval;` to `testApp.h`--these are two of the enemy parameters we'll affect with OSC. 
Your enemy class will look like this: ```cpp @@ -407,7 +407,7 @@ public: }; ``` -Our enemy's horizontal movement will be shaped by the values fed to a sine wave (which we’ll see in a moment). We’ll keep track of our amplitude variable (so different enemies can have different amplitudes). We’ll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the start_shoot and shoot_interval variables. Both of these variables will actually be set in our setup() function. Finally, we’ll have a boolean function that will tell us whether the enemy can shoot this frame or not. +Our enemy's horizontal movement will be shaped by the values fed to a sine wave (which we'll see in a moment). We'll keep track of our amplitude variable (so different enemies can have different amplitudes). We’ll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the start_shoot and shoot_interval variables. Both of these variables will actually be set in our setup() function. Finally, we’ll have a boolean function that will tell us whether the enemy can shoot this frame or not. 
Our enemy class will look like this: ```cpp @@ -523,7 +523,7 @@ void testApp::check_bullet_collisions() { } ``` -This code is a bit nested, but actually pretty simple. First, it goes through each bullet in the vector and checks to see whether it's from the player. If it’s from the player, it starts a for-loop for all the enemies, so we can compare the player bullet position against all the enemy positions. We use `ofDist()` to see whether the distance between a given bullet and a given enemy is less than the sum of their radii--if it is, they’re overlapping. +This code is a bit nested, but actually pretty simple. First, it goes through each bullet in the vector and checks to see whether it's from the player. If it's from the player, it starts a for-loop for all the enemies, so we can compare the player bullet position against all the enemy positions. We use `ofDist()` to see whether the distance between a given bullet and a given enemy is less than the sum of their radii--if it is, they're overlapping. 
If a bullet is not from the player, the function does a distance calculation against the player, to see whether a given enemy bullet and the player are close enough to count it as a hit. If there is a hit, we subtract a player's life and erase that bullet. If the player has less than or equal to 0 lives, we change the game state to the end. Don't forget to call `check_bullet_collisions()` as part of `update_bullets()`: @@ -557,7 +557,7 @@ public: }; ``` -As you might guess, all it'll really do is keep track of whether it’s time to spawn another enemy yet. +As you might guess, all it'll really do is keep track of whether it's time to spawn another enemy yet. Inside our `LevelController.cpp`: @@ -575,7 +575,7 @@ bool LevelController::should_spawn() { } ``` -When we set up our level controller, we'll give it a starting time. It’ll use this time as a baseline for the first enemy spawn. The should_spawn code should look familiar from the enemy bullet section. +When we set up our level controller, we'll give it a starting time. It'll use this time as a baseline for the first enemy spawn. The should_spawn code should look familiar from the enemy bullet section. We'll wait to set up our level controller until the game actually starts--namely, when the game state changes from `"start"` to `"game"`. @@ -623,7 +623,7 @@ Awesome! We're close to done! ###Bonus lives -Before we finish, let's add in our last OSC feature: the ability to throw in bonus lives on the fly. Add `vector bonuses;` and `ofImage life_image;` to your `testApp.h`. To keep our code modular, let’s also add `void update_bonuses();` in the same place. Don’t forget to `life_image.loadImage("life_image.png");` in `testApp::setup()`. +Before we finish, let's add in our last OSC feature: the ability to throw in bonus lives on the fly. Add `vector bonuses;` and `ofImage life_image;` to your `testApp.h`. To keep our code modular, let's also add `void update_bonuses();` in the same place. Don't forget to `life_image.loadImage("life_image.png");` in `testApp::setup()`. `Life.h` should look like this: @@ -736,7 +736,7 @@ void testApp::draw(){ ###Let's get visual -Finally, we've been a bit stingy with visual feedback, so let’s add in a start screen, a score, a visual representation of the lives left, and an end screen. Add `ofImage start_screen;`, `ofImage end_screen;`, `void draw_lives();`, and `void draw_score();` to `testApp.h`. +Finally, we've been a bit stingy with visual feedback, so let's add in a start screen, a score, a visual representation of the lives left, and an end screen. Add `ofImage start_screen;`, `ofImage end_screen;`, `void draw_lives();`, and `void draw_score();` to `testApp.h`. Change `testApp::setup()` to load in those assets: @@ -776,7 +776,7 @@ void testApp::draw_score() { By using `stringWidth()`, we can calculate the width of a string and shift the text over--handy for centering it. -All that's left after that is to call `draw_score();` and `draw_lives();` during the `testApp::draw()`’s game state, and to call `draw_score();` during the end state. +All that's left after that is to call `draw_score();` and `draw_lives();` during the `testApp::draw()`'s game state, and to call `draw_score();` during the end state. Congrats--you made a game! @@ -835,7 +835,7 @@ For the purpose of this chapter and to allow us to create an experience that wil The desktop editor software is free however the matching software for your device will be $4.99. Get both now. As a mater of principle, we endorse building your own tools and you could easily build a second oF project to be your OSC sender and receiver on your mobile device. With that said, nothing beats TouchOSC for speed, ease of use and complete, platform independent flexibility. If you are someone who often moves between an iOS and Android device on both Windows and Mac, this tool will become indispensible to you. As a games designer it can open up possibilities like changing levels on the fly, updating game variables, adjusting for player feedback and adding new features into and taking them out of your game as it's running. We highly endorse using it and support the continued advancement of the tool. You can also use it with music production tools like Ableton Live and it comes with great presets for things like DJing and mixing music live. Go to the app store of your device and purchase the mobile version now if you would like to continue down this route. -After we get all of the tools downloaded and installed. Let's start setting everything up. You are going to need two bits of information. You are going to need to know the IP address of your computer and the ip address of your laptop. If you are on a mac, just open up your System Preferences. Go to the Network setting and click on your wifi connection in the left sidebar. On the right side it will display your IP address. You can also get this setting by opening up Terminal and entering in the command ifconfig. Terminal will list of every network that’s a possible connection for your machine from the past, even if it’s not currently active. For example, if you have ever connected your phone, it will be in the list with some flag and listed as inactive. Look for the connection that’s currently active. It will look something like this: +After we get all of the tools downloaded and installed. Let's start setting everything up. You are going to need two bits of information. You are going to need to know the IP address of your computer and the ip address of your laptop. If you are on a mac, just open up your System Preferences. Go to the Network setting and click on your wifi connection in the left sidebar. On the right side it will display your IP address. You can also get this setting by opening up Terminal and entering in the command ifconfig. Terminal will list of every network that's a possible connection for your machine from the past, even if it's not currently active. For example, if you have ever connected your phone, it will be in the list with some flag and listed as inactive. Look for the connection that’s currently active. It will look something like this: ``` en1: flags=8863 mtu 1500 @@ -867,7 +867,7 @@ To build the app, let's start by adding our first knob. Right click in the black ![](images/label1_label2.png) -Now look to the left side of the app. At this point, it's time to set all of the values this knob will be sending and what the labels will display. Let’s start with `label1`. We will name our knob on screen to make things easier to read. The first value in our game we want to control, level controller interval time, should be what this label reads onscreen. Changing the name field in the app interface will do little. However, note under the name field you can change the color of the label. For this example, use yellow. Next, jump down to the next to last field on screen called `Text`. You will want to set this to level controller interval time. +Now look to the left side of the app. At this point, it's time to set all of the values this knob will be sending and what the labels will display. Let's start with `label1`. We will name our knob on screen to make things easier to read. The first value in our game we want to control, level controller interval time, should be what this label reads onscreen. Changing the name field in the app interface will do little. However, note under the name field you can change the color of the label. For this example, use yellow. Next, jump down to the next to last field on screen called `Text`. You will want to set this to level controller interval time. Moving on, select the knob. This one will require more set up because it will actually be sending values to our game. Color it yellow first. In the dark grey OSC box set all of the values we need to receive for the game. If auto is checked, uncheck it. Now customize the text in that box to `/game/interval_time`. In the `From` fields set the parameters to a range of values to try out in the game during a playtest. We will use from 0 to 300. These two elements, the tag and the parameters will get packed up into a message and sent over our OSC network to our game when values change. @@ -946,7 +946,7 @@ Now click on `Layout`. Then tap `Add`. It will start to search for your computer Switch back to your device. You should see your computer listed under FOUND HOSTS. Select it. It will pop back to the settings screen. Scroll down and find PlaytestInterface in the list of interfaces. Select it and it will take you back to the main menu. Press Done in the upper left corner and your interface will now launch. If you want to get back to the settings screen at any point the white dot in the upper right hand corner will return the user interface to that screen. -Finally, TouchOSC is set up. Let's link it to our game and run our very first playtest. Go back to the programming IDE. Open up `LiveTesting.cpp`. In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer’s network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren’t going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You’ll need a separate port for each activity in this scenario. If a port isn’t used by your operating system, you can send and receive data there. We are going to use `8000` and `8001`. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: +Finally, TouchOSC is set up. Let's link it to our game and run our very first playtest. Go back to the programming IDE. Open up `LiveTesting.cpp`. In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer's network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren't going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You’ll need a separate port for each activity in this scenario. If a port isn’t used by your operating system, you can send and receive data there. We are going to use `8000` and `8001`. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: ```cpp #include "LiveTesting.h" diff --git a/chapters/game_design/old drafts/oscchapter.md b/chapters/game_design/old drafts/oscchapter.md index c17edb98..6f715bda 100644 --- a/chapters/game_design/old drafts/oscchapter.md +++ b/chapters/game_design/old drafts/oscchapter.md @@ -60,18 +60,18 @@ With all that written out, let's use OSC to affect the following: These three parameters will allow the developer to, second-by-second, tailor the difficulty of the game to the individual playing it. -Let's start with our testApp. There are a few things we definitely know we’ll want classes for, so make corresponding .h and .cpp files for `Player`, `Bullet`, `Life`, `Enemy`, and `LevelController`. Remember to `#include` `ofMain.h` in each of those classes, and to include the .h file of each of those classes in `testApp.h`. +Let's start with our testApp. There are a few things we definitely know we'll want classes for, so make corresponding .h and .cpp files for `Player`, `Bullet`, `Life`, `Enemy`, and `LevelController`. Remember to `#include` `ofMain.h` in each of those classes, and to include the .h file of each of those classes in `testApp.h`. ###Gamestates -First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we’re in, which we’ll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are “start”, “game”, and “end”. Let’s add a score and a player at this point as well.
 +First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we're in, which we'll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are “start”, “game”, and “end”. Let’s add a score and a player at this point as well.
 ``` string game_state; int score; Player player_1; ``` -We'll then divide up testApp’s `update()` and `draw()` loops between those game states: +We'll then divide up testApp's `update()` and `draw()` loops between those game states: ``` //-------------------------------------------------------------- @@ -106,7 +106,7 @@ void testApp::setup(){ } ``` -Finally, let's make sure that we can move forward from the start screen. In this example, when the player is on the start screen and releases the space key, they’ll be taken to the game. +Finally, let's make sure that we can move forward from the start screen. In this example, when the player is on the start screen and releases the space key, they'll be taken to the game. ``` //-------------------------------------------------------------- @@ -150,7 +150,7 @@ public: Taking this one step at a time: -* Our player's position will be stored in an `ofPoint` called `pos`. `ofPoint`s are handy datatypes that contain `x` and `y` values, letting us access our player’s position through `pos.x` and `pos.y`. +* Our player's position will be stored in an `ofPoint` called `pos`. `ofPoint`s are handy datatypes that contain `x` and `y` values, letting us access our player's position through `pos.x` and `pos.y`. * Our player will have `width`, `height`, and `speed` variables (which we'll use for collision detection and movement, respectively). @@ -163,7 +163,7 @@ Taking this one step at a time: You may be wondering why we're using all these booleans--why not just check and see which keys are pressed? The problem is that, in openFrameworks, `keyPressed()` does not return all the keys currently being pressed--just the last key that was pressed. That means that if the player presses up and left (intending to move diagonally), openFrameworks will only report one of the keys being pressed. You can try printing out the result of keyPressed to see this in action. -
What we'll do to avoid this is instead base the player’s movement on the booleans we wrote earlier. If the player presses a certain key, that boolean will be true; if they release that key, that boolean will be false. That way, if the player presses up and left, we’ll report up and left as being true until those keys are released. +
What we'll do to avoid this is instead base the player's movement on the booleans we wrote earlier. If the player presses a certain key, that boolean will be true; if they release that key, that boolean will be false. That way, if the player presses up and left, we'll report up and left as being true until those keys are released. Here's what our new `keyPressed()` and `keyReleased()` functions look like: @@ -213,7 +213,7 @@ void testApp::keyReleased(int key){ } ``` -Add `ofImage player_image` to `testApp.h`, then load the player's image and instantiate the player in `testApp`’s `setup()`: +Add `ofImage player_image` to `testApp.h`, then load the player's image and instantiate the player in `testApp`'s `setup()`: ``` void testApp::setup(){ @@ -252,7 +252,7 @@ You should have a player who moves around on-screen. Sweet! ###Player bullets -Let's make our bullets next. In order to have a variable number of bullets on screen at a time, we need to add a `vector bullets` to `testApp.h`. Let’s also create a `void update_bullets();` function, which will update our vector of bullets (and, shortly, trigger the check for bullet collisions). We also want our player and enemy bullets to look different, so we’ll add `ofImage enemy_bullet_image;` and `ofImage player_bullet_image;` to our `testApp.h` file. +Let's make our bullets next. In order to have a variable number of bullets on screen at a time, we need to add a `vector bullets` to `testApp.h`. Let's also create a `void update_bullets();` function, which will update our vector of bullets (and, shortly, trigger the check for bullet collisions). We also want our player and enemy bullets to look different, so we'll add `ofImage enemy_bullet_image;` and `ofImage player_bullet_image;` to our `testApp.h` file. Our bullet class will look a lot like the player class, having a position, speed, width, pointer to an image, and various functions. The big difference is that the bullets will keep track of who they came from (since that will affect who they can hurt and which direction they move). @@ -404,7 +404,7 @@ public: }; ``` -Our enemy's horizontal position is shaped by the values fed to a sine wave (which we’ll see in a moment). We’ll keep track of each enemy's amplitude variable, so different enemies can have different amplitudes. We’ll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the `start_shoot` and `shoot_interval `variables. Both of these variables will actually be set in our `setup()` function. Finally, we’ll have a boolean function that will tell us whether the enemy can shoot this frame or not. +Our enemy's horizontal position is shaped by the values fed to a sine wave (which we'll see in a moment). We'll keep track of each enemy's amplitude variable, so different enemies can have different amplitudes. We’ll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the `start_shoot` and `shoot_interval `variables. Both of these variables will actually be set in our `setup()` function. Finally, we’ll have a boolean function that will tell us whether the enemy can shoot this frame or not. 
Our enemy class will look like this: ``` @@ -527,7 +527,7 @@ void testApp::check_bullet_collisions() { } ``` -This code is a bit nested, but actually pretty simple. First, it goes through each bullet in the vector and checks to see whether it's from the player. If it’s from the player, it starts a for-loop for all the enemies, so we can compare the player bullet position against all the enemy positions. We use `ofDist()` to see whether the distance between a given bullet and a given enemy is less than the sum of their radii--if it is, they’re overlapping. +This code is a bit nested, but actually pretty simple. First, it goes through each bullet in the vector and checks to see whether it's from the player. If it's from the player, it starts a for-loop for all the enemies, so we can compare the player bullet position against all the enemy positions. We use `ofDist()` to see whether the distance between a given bullet and a given enemy is less than the sum of their radii--if it is, they're overlapping. 
If a bullet is not from the player, the function does a distance calculation against the player, to see whether a given enemy bullet and the player are close enough to count it as a hit. If there is a hit, we subtract a player's life and erase that bullet. If the player has less than or equal to 0 lives, we change the game state to the end. 
Don't forget to call `check_bullet_collisions()` as part of `update_bullets()`: @@ -562,7 +562,7 @@ public: }; ``` -As you might've guessed, all it'll really do is keep track of whether it’s time to spawn another enemy yet. +As you might've guessed, all it'll really do is keep track of whether it's time to spawn another enemy yet. Inside our `LevelController.cpp`: @@ -580,7 +580,7 @@ bool LevelController::should_spawn() { } ``` -When we set up our level controller, we'll give it a starting time. It’ll use this time as a baseline for the first enemy spawn. The `should_spawn` code should look familiar from the enemy bullet section. +When we set up our level controller, we'll give it a starting time. It'll use this time as a baseline for the first enemy spawn. The `should_spawn` code should look familiar from the enemy bullet section. We'll wait to set up our level controller until the game actually starts--namely, when the game state changes from ` “start” ` to ` “game” `. @@ -627,7 +627,7 @@ Awesome! We're close to done! ###Bonus lives -Before we finish, let's add in our last OSC feature: the ability to throw in bonus lives on the fly. Add `vector bonuses;` and `ofImage life_image;` to your `testApp.h`. To keep our code modular, let’s also add `void update_bonuses();` in the same place. Don’t forget to `life_image.loadImage("life_image.png");` in `testApp::setup()`. +Before we finish, let's add in our last OSC feature: the ability to throw in bonus lives on the fly. Add `vector bonuses;` and `ofImage life_image;` to your `testApp.h`. To keep our code modular, let's also add `void update_bonuses();` in the same place. Don't forget to `life_image.loadImage("life_image.png");` in `testApp::setup()`. `Life.h` should look like this: @@ -739,7 +739,7 @@ void testApp::draw(){ ###Let's get visual -Finally, we've been a bit stingy with visual feedback, so let’s add in a start screen, a score, a visual representation of the lives left, and an end screen. Add `ofImage start_screen;`, `ofImage end_screen;`, `void draw_lives();`, and `void draw_score();` to `testApp.h`. +Finally, we've been a bit stingy with visual feedback, so let's add in a start screen, a score, a visual representation of the lives left, and an end screen. Add `ofImage start_screen;`, `ofImage end_screen;`, `void draw_lives();`, and `void draw_score();` to `testApp.h`. Change `testApp::setup()` to load in those assets: @@ -780,7 +780,7 @@ void testApp::draw_score() { By using `stringWidth()`, we can calculate the width of a string--handy for centering it. -All that's left after that is to call `draw_score();` and `draw_lives();` during the `testApp::draw()`’s game state, and to call `draw_score();` during the end state. +All that's left after that is to call `draw_score();` and `draw_lives();` during the `testApp::draw()`'s game state, and to call `draw_score();` during the end state. Congrats--you made a game! @@ -826,7 +826,7 @@ Jump over to the LiveTesting.cpp file. In this file we are going to set up our n For the purpose of this chapter and to allow us to create an experience that will work on both Android and iOS we are going to use a piece of software called TouchOSC from this URL: http://hexler.net/software/touchosc The desktop editor software is free however the matching software for your device will be $4.99. Get both now. As a mater of principle, we endorse building your own tools and you could easily build a second oF project to be your OSC sender and receiver on your mobile device. With that said, nothing beats TouchOSC for speed, ease of use and complete, platform independent flexibility. If you are someone who often moves between an iOS and Android device on both Windows and Mac, this tool will become indispensible to you. As a games designer it can open up possibilities like changing levels on the fly, updating game variables, adjusting for player feedback and adding new features into and taking them out of your game as it's running. We highly endorse using it and support the continued advancement of the tool. You can also use it with music production tools like Ableton Live and it comes with great presets for things like DJing and mixing music live. Go to the app store of your device and purchase the mobile version now if you would like to continue down this route. -After we get all of the tools downloaded and installed, we can start setting everything up. You are going to need two bits of information. You are going to need to know the IP address of your computer and the ip address of your laptop. If you are on a mac, just open up your System Preferences. Go to the Network setting and click on your wifi connection in the left sidebar. On the right side it will display your IP address. You can also get this setting by opening up Terminal and entering in the command ifconfig. Terminal will list of every network that's a possible connection for your machine from the past, even if it’s not currently active. For example, if you have ever connected your phone, it will be in the list with some flag and listed as inactive. Look for the connection that’s currently active. It will look something like this: +After we get all of the tools downloaded and installed, we can start setting everything up. You are going to need two bits of information. You are going to need to know the IP address of your computer and the ip address of your laptop. If you are on a mac, just open up your System Preferences. Go to the Network setting and click on your wifi connection in the left sidebar. On the right side it will display your IP address. You can also get this setting by opening up Terminal and entering in the command ifconfig. Terminal will list of every network that's a possible connection for your machine from the past, even if it's not currently active. For example, if you have ever connected your phone, it will be in the list with some flag and listed as inactive. Look for the connection that's currently active. It will look something like this: en1: flags=8863 mtu 1500 ether 60:33:4b:12:e5:3b @@ -853,7 +853,7 @@ To build the app, let's start by adding our first knob. Right click in the black [image labels.png] -Now look to the left side of the app. At this point, it's time to set all of the values this knob will be sending and what the labels will display. Let’s start with label1. We will name our knob on screen to make things easier to read. The first value in our game we want to control, level controller interval time, should be what this label reads onscreen. Changing the name field in the app interface will do little. However, note under the name field you can change the color of the label. For this example, use yellow. Next, jump down to the next to last field on screen called Text: +Now look to the left side of the app. At this point, it's time to set all of the values this knob will be sending and what the labels will display. Let's start with label1. We will name our knob on screen to make things easier to read. The first value in our game we want to control, level controller interval time, should be what this label reads onscreen. Changing the name field in the app interface will do little. However, note under the name field you can change the color of the label. For this example, use yellow. Next, jump down to the next to last field on screen called Text: You will want to set this to level controller interval time. Moving on, select the knob. This one will require more set up because it will actually be sending values to our game. Color it yellow first. In the dark grey OSC box set all of the values we need to receive for the game. If auto is checked, uncheck it. Now customize the text in that box to /game/interval_time. In the From fields set the parameters to a range of values to try out in the game during a playtest. We will use from 0 to 300. These two elements, the tag and the parameters will get packed up into a message and sent over our OSC network to our game when values change. @@ -933,7 +933,7 @@ Now click on Layout. Then tap Add. It will start to search for your computer. Sw Switch back to your device. You should see your computer listed under FOUND HOSTS. Select it. It will pop back to the settings screen. Scroll down and find PlaytestInterface in the list of interfaces. Select it and it will take you back to the main menu. Press Done in the upper left corner and your interface will now launch. If you want to get back to the settings screen at any point the white dot in the upper right hand corner will return the user interface to that screen. -Finally, TouchOSC is set up. Let's link it to our game and run our very first playtest. Go back to the programming IDE. Open up LiveTesting.cpp In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer’s network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren’t going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You’ll need a separate port for each activity in this scenario. If a port isn’t used by your operating system, you can send and receive data there. We are going to use 8000 and 8001. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: +Finally, TouchOSC is set up. Let's link it to our game and run our very first playtest. Go back to the programming IDE. Open up LiveTesting.cpp In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer's network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren't going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You’ll need a separate port for each activity in this scenario. If a port isn’t used by your operating system, you can send and receive data there. We are going to use 8000 and 8001. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: #include "LiveTesting.h" diff --git a/chapters/hardware/chapter.md b/chapters/hardware/chapter.md index 706ceb24..37debc12 100644 --- a/chapters/hardware/chapter.md +++ b/chapters/hardware/chapter.md @@ -9,7 +9,7 @@ This chapter will give you an introduction to working with openFrameworks outsid There are a number of ways of taking your openFrameworks app out of the frame of your own personal computer and getting it to interact with the outside world. Largely this involves some kind of communication from openFrameworks to whatever hardware you've decided to hook up to. The different types of computer based communications (or protocols) vary, but the most common is what's known as 'serial' communication, so called because each bit of data sent is transferred one after the other (as opposed to multiple bits being sent in parallel). -The first hardware that we'll look at interfacing with is the excellent **Arduino** prototyping platform. Arduino is, in its own words, an *“open-source electronics prototyping platform based on flexible, easy-to-use hardware and software… intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments.*” It’s easy to see why there’s a lot of overlap between communities of people interested in using openFrameworks and Arduino! With Arduino, it’s quick to get your openFrameworks app hooked up to sensors (like light sensors, proximity sensors, or other methods of environmental input), actuators (like lights, motors, and other outputs), and real-time interaction. You're free to move out of the realm of pixels and into the physical world. +The first hardware that we'll look at interfacing with is the excellent **Arduino** prototyping platform. Arduino is, in its own words, an *“open-source electronics prototyping platform based on flexible, easy-to-use hardware and software… intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments.*” It's easy to see why there's a lot of overlap between communities of people interested in using openFrameworks and Arduino! With Arduino, it’s quick to get your openFrameworks app hooked up to sensors (like light sensors, proximity sensors, or other methods of environmental input), actuators (like lights, motors, and other outputs), and real-time interaction. You're free to move out of the realm of pixels and into the physical world. This chapter assumes that you have the Arduino IDE installed, in addition to the environment that you normally use for working with openFrameworks. If not, you can download it from the Arduino website (arduino.cc) or the Arduino github (github.com/arduino). @@ -22,7 +22,7 @@ Additionally, following along with the examples in this chapter requires you to **SERIAL: ONE AFTER THE OTHER** -Serial, in the most basic language sense, refers to things that come one after another; it's a term often used to describe magazines, crimes, and television programs. That meaning also applies when talking about serial data: “serial communication” means that all information between two entities is being sent one piece at a time, following in a single stream. One piece of data, or one bit, is just a binary piece of information: you’re either sending a 0 or a 1. Using the terminology of digital electronics, these are frequently referred to as “high” and “low”; 0 is low (like turning a light off) and 1 is high (flipping it back on). 8 bits (for example the stream 01000001, which represents the letter A) are sometimes packaged together to create a single byte. +Serial, in the most basic language sense, refers to things that come one after another; it's a term often used to describe magazines, crimes, and television programs. That meaning also applies when talking about serial data: “serial communication” means that all information between two entities is being sent one piece at a time, following in a single stream. One piece of data, or one bit, is just a binary piece of information: you're either sending a 0 or a 1. Using the terminology of digital electronics, these are frequently referred to as “high” and “low”; 0 is low (like turning a light off) and 1 is high (flipping it back on). 8 bits (for example the stream 01000001, which represents the letter A) are sometimes packaged together to create a single byte. Serial communication is actually a very broad topic and there are many serial protocols, including audio-visual protocols such as DMX (based on RS-485) and MIDI (serial at 31,250 bits per second) which we'll briefly cover in this chapter. The most common serial protocol is called RS-232 and computers used to be equipped with RS-232 serial ports (remember them?) but today they are rarely present, which is why serial communications involving a computer will typically require an RS-232 to USB adaptor (found on-line or at your local electronics store). @@ -160,7 +160,7 @@ There's a good, heavily commented demonstration of this in the communications fo **USING FIRMATA AS A SERIAL PROTOCOL** -Though it's possible to navigate all serial communication manually, you’ll reach the limitations of what you’re able to do fairly quickly - as soon as you start wanting to address different devices or have multiple inputs, you’ll fall into a spiral of packet management and be much more prone to getting corrupt packets or inaccurate and scrambled data. Rather than deal with this manually, it’s much simpler to use Firmata, an open source protocol for managing multiple Serial streams. +Though it's possible to navigate all serial communication manually, you'll reach the limitations of what you're able to do fairly quickly - as soon as you start wanting to address different devices or have multiple inputs, you’ll fall into a spiral of packet management and be much more prone to getting corrupt packets or inaccurate and scrambled data. Rather than deal with this manually, it’s much simpler to use Firmata, an open source protocol for managing multiple Serial streams. **OFARDUINO** diff --git a/chapters/image_processing_computer_vision/chapter.md b/chapters/image_processing_computer_vision/chapter.md index e0ec9602..44fda1b5 100644 --- a/chapters/image_processing_computer_vision/chapter.md +++ b/chapters/image_processing_computer_vision/chapter.md @@ -633,7 +633,7 @@ I sometimes assign my students the project of copying a well-known work of inter #### Text Rain by Camille Utterback and Romy Achituv (1999). -*[Text Rain](http://camilleutterback.com/projects/text-rain/)* is a now-classic work of interactive art in which virtual letters appear to "fall" on the visitor's "silhouette". Utterback writes: "In the Text Rain installation, participants stand or move in front of a large projection screen. On the screen they see a mirrored video projection of themselves in black and white, combined with a color animation of falling letters. Like rain or snow, the letters appears to land on participants' heads and arms. The letters respond to the participants’ motions and can be caught, lifted, and then let fall again. The falling text will 'land' on anything darker than a certain threshold, and 'fall' whenever that obstacle is removed." +*[Text Rain](http://camilleutterback.com/projects/text-rain/)* is a now-classic work of interactive art in which virtual letters appear to "fall" on the visitor's "silhouette". Utterback writes: "In the Text Rain installation, participants stand or move in front of a large projection screen. On the screen they see a mirrored video projection of themselves in black and white, combined with a color animation of falling letters. Like rain or snow, the letters appears to land on participants' heads and arms. The letters respond to the participants' motions and can be caught, lifted, and then let fall again. The falling text will 'land' on anything darker than a certain threshold, and 'fall' whenever that obstacle is removed." ![Camille Utterback and Romy Achituv, Text Rain (1999)](images/text-rain.jpg) diff --git a/chapters/installation_up_4evr_macosx/chapter.md b/chapters/installation_up_4evr_macosx/chapter.md index 9b4fb6d3..d1267a2c 100644 --- a/chapters/installation_up_4evr_macosx/chapter.md +++ b/chapters/installation_up_4evr_macosx/chapter.md @@ -7,7 +7,7 @@ The original version of the article is [here](http://blairneal.com/blog/installa Edited the article with https://stackedit.io/# for help with rendering Github Flavored Markup --------- -At work I recently had to set up a four installations of different configurations that would need to run all day, every day, 24 hours a day for a couple months with as few crashes or glitches as possible and without anyone going to check on them. This is something that a lot of media artists need to do all the time, and there are a bunch of different tricks and tips to keeping things up for an extended period, I figured I'd share my findings. There are alternate ways to do many of these tasks and this is only one road so please share some tips you’ve picked up out in the field down in the comments box below. +At work I recently had to set up a four installations of different configurations that would need to run all day, every day, 24 hours a day for a couple months with as few crashes or glitches as possible and without anyone going to check on them. This is something that a lot of media artists need to do all the time, and there are a bunch of different tricks and tips to keeping things up for an extended period, I figured I'd share my findings. There are alternate ways to do many of these tasks and this is only one road so please share some tips you've picked up out in the field down in the comments box below. I had to do several searches in a couple different places to find all the information I needed to keep everything consistently up and bug free. Luckily most of the installations I was dealing with this time were fairly light in terms of resources and complications, but it's always best practices to have a safety net. @@ -18,9 +18,9 @@ Tip: if you're doing multiple computers, do these prep steps on one of them and **Step 1: Prep your software and the computer** ----------------------------------------------- -When building your software or whatever it might be, always keep the long running installation in mind. Plan which things will need to be adjusted by whoever is watching over the installation from the beginning (or at least don't save it for the end). In my experience, keep it as simple as possible, so that it’s easy for the caretaker to get in there to fix or adjust what they need without opening Xcode and compiling or even exiting out of your app. Time you spend now to make things simple will save you hours of remote debugging when something breaks. +When building your software or whatever it might be, always keep the long running installation in mind. Plan which things will need to be adjusted by whoever is watching over the installation from the beginning (or at least don't save it for the end). In my experience, keep it as simple as possible, so that it's easy for the caretaker to get in there to fix or adjust what they need without opening Xcode and compiling or even exiting out of your app. Time you spend now to make things simple will save you hours of remote debugging when something breaks. -You'll need to go through and turn off or disable several different automatic settings to keep things from popping up over top of your application. This can differ depending on whether you’re running 10.7, 10.8, 10.9, 10.10 etc etc. +You'll need to go through and turn off or disable several different automatic settings to keep things from popping up over top of your application. This can differ depending on whether you're running 10.7, 10.8, 10.9, 10.10 etc etc. Nick Hardeman has made a utility application for setting all of these attributes and more from one location - [check it out here](http://nickhardeman.com/610/openframeworks-configuring-osx-for-a-long-term-installation/) @@ -30,8 +30,8 @@ In System Preferences: - **Energy Saver:** Turn Display Sleep and Computer Sleep to Never. Enable “Start up automatically after power failure” and “Restart automatically if the computer freezes” (these are only available in 10.7 and later) - **Users and Groups:** Go to Login Options (above the padlock) and enable "Automatic Login" - **Software update:** Disable automatic updates. - - **Sharing:** If you are running your main computer without a monitor or in an inaccessible area, don't forget to turn on File sharing and Screen sharing. This will allow you to access the computer and control it if you're on the same network (optional if you’re concerned about security). - - **Network:** If you don't need remote access or don’t need Internet access for the installation, it’s not a bad idea to disable the Wifi so the “please select a wireless network” window doesn’t pop up when you least expect it. You can also turn off the option to ask you to join a new network if the proper one isn't found. + - **Sharing:** If you are running your main computer without a monitor or in an inaccessible area, don't forget to turn on File sharing and Screen sharing. This will allow you to access the computer and control it if you're on the same network (optional if you're concerned about security). + - **Network:** If you don't need remote access or don't need Internet access for the installation, it's not a bad idea to disable the Wifi so the “please select a wireless network” window doesn’t pop up when you least expect it. You can also turn off the option to ask you to join a new network if the proper one isn't found. - **Bluetooth** If running without a mouse or keyboard plugged in, sometimes you can get the annoying ”Bluetooth keyboard/mouse setup” pop up over your application. You can temporality disable these by going to the advanced settings within the Bluetooth Preferences. See below for it's location in 10.6. - **Security:** I would make sure that "Disable Automatic Login" is unchecked so you don't hit any surprises on reboots. If you're really paranoid, you can even disable things like the IR remote receiver that still exists on some macs and definitely on Macbooks. This would keep pranksters with Apple TV remotes from “Front Rowing” your installation. To disable, go to Security->General->Advanced (in >10.8) and “Disable remote control IR receiver”. - **Notification Center:** You can either [disable Notification Center completely](http://www.tekrevue.com/tip/how-to-completely-disable-notification-center-in-mac-os-x/), or set your "Do Not Disturb" to basically on be on forever by setting it with overlapping times like the screenshot below @@ -100,14 +100,14 @@ In Lingon, hit the + to create a new launchd plist. Just make it a standard laun ![LingonSetup](images/LingonSetup.png) -One additional/optional thing you can add to this is to put an additional key in the plist for a “Successful Exit”. By adding this, your app won't re-open when it has detected that it closed normally (ie You just hit escape intentionally, it didn’t crash). Can be useful if you’re trying to check something and OS X won’t stop re-opening the app on you. To easily add this to the key, click the advanced tab and click the checkbox for "Successful exit" - or just add it manually as it in the above screenshot. +One additional/optional thing you can add to this is to put an additional key in the plist for a “Successful Exit”. By adding this, your app won't re-open when it has detected that it closed normally (ie You just hit escape intentionally, it didn't crash). Can be useful if you're trying to check something and OS X won’t stop re-opening the app on you. To easily add this to the key, click the advanced tab and click the checkbox for "Successful exit" - or just add it manually as it in the above screenshot. **Shell script+Cron Job method** (I got the following super helpful tip from [Kyle McDonald](http://kylemcdonald.net/)) ) -This method is sort of deprecated in relation to the launchd method - you can run shell scripts with Lingon and launchd in the same manner as what we've got here. Shell scripting is your best friend. With the help of the script below and an application called CronniX (or use Lingon) , you will be able to use a cronjob to check the system's list of currently running processes. If your app does not appear on the list, then the script will open it again, otherwise it won’t do anything. Either download the script or type the following into a text editor, replacing Twitter.app with your app’s name and filepath. Don’t forget the “.app” extension in the if statement!: +This method is sort of deprecated in relation to the launchd method - you can run shell scripts with Lingon and launchd in the same manner as what we've got here. Shell scripting is your best friend. With the help of the script below and an application called CronniX (or use Lingon) , you will be able to use a cronjob to check the system's list of currently running processes. If your app does not appear on the list, then the script will open it again, otherwise it won't do anything. Either download the script or type the following into a text editor, replacing Twitter.app with your app's name and filepath. Don’t forget the “.app” extension in the if statement!: \#!/bin/sh if [ $(ps ax | grep -v grep | grep "Twitter.app" | wc -l) -eq 0 ] then @@ -189,7 +189,7 @@ Step 6: Test, test, test. You've already tested and perfected your software for the installation, so make sure to test all of the above methods and automatic scripts in as realistic manner as you can before you leave it alone for the first day at school. -You can't account for everything, so don’t beat yourself up if something does eventually happen, but this list will hopefully alleviate a little bit of frustration. Good luck! +You can't account for everything, so don't beat yourself up if something does eventually happen, but this list will hopefully alleviate a little bit of frustration. Good luck! Additional Tips: Logging @@ -221,15 +221,15 @@ All that is left is to write this output to a text file, which you can do with a This line basically says - tell me the open processes (px aux) - only give me the lines that have "Tweetdeck" in them (grep Tweetdeck) - and then append them to a text file located at this location ( >> path_to_text_file) -Now we just need to make this an executable shell script and set it up as a launch daemon or cron job – see above at Step 3 to learn how to run the shell script at a regular interval using Lingon and launchd. If the app isn't running, it will only return the “grep YourAppName” process which is a good thing to log because if your app isn’t open you won’t know how long it’s been out (nothing will be logged), but having the grep process logged will at least tell you it was checking for it. Grep will also more accurately tell you what time it checked – the other app will only give you a start time and up time. +Now we just need to make this an executable shell script and set it up as a launch daemon or cron job – see above at Step 3 to learn how to run the shell script at a regular interval using Lingon and launchd. If the app isn't running, it will only return the “grep YourAppName” process which is a good thing to log because if your app isn't open you won't know how long it’s been out (nothing will be logged), but having the grep process logged will at least tell you it was checking for it. Grep will also more accurately tell you what time it checked – the other app will only give you a start time and up time. -Let's also take this one step further and say, hypothetically, that the Triplehead2Go display adapter you have is fairly wonky and you don’t always get the displays or projectors to connect after reboot – or maybe a projector is shutting itself off and disrupting things. Well we can log the currently available resolutions too! Try entering the line below in your own terminal: +Let's also take this one step further and say, hypothetically, that the Triplehead2Go display adapter you have is fairly wonky and you don't always get the displays or projectors to connect after reboot – or maybe a projector is shutting itself off and disrupting things. Well we can log the currently available resolutions too! Try entering the line below in your own terminal: system_profiler SPDisplaysDataType This will return a list of connected displays and some metadata about them including resolution and names. -Let's say you want to make sure you’re running a resolution of 3840×720 at all times…or you want a log of resolution changes. You would do something like: +Let's say you want to make sure you're running a resolution of 3840×720 at all times…or you want a log of resolution changes. You would do something like: system_profiler SPDisplaysDataType | grep Resolution @@ -239,7 +239,7 @@ This will return “Resolution: 3840×720″ which you can combine with the abov ps aux | grep 'YourAppName' >> /Users/you/filepath/Install6ProcessLog.txt system_profiler SPDisplaysDataType | grep Resolution >> /Users/you/Dropbox/Install6ProcessLog.txt -And now you're feeling excited, maybe you want to grab a fullscreen screenshot at a regular interval too, just to make sure there is no funkiness happening that you can’t see…well you could add this line to the above as well: +And now you're feeling excited, maybe you want to grab a fullscreen screenshot at a regular interval too, just to make sure there is no funkiness happening that you can't see…well you could add this line to the above as well: screencapture ~/Desktop/$(date +%Y%m%d-%H%M%S).png @@ -247,7 +247,7 @@ This will save a screenshot to the desktop (specify your own file path) with a f Bonus points would be to create an auto-generated table and webpage that takes all of this info and puts it into a nice view that you can use to check all of your installations at a glance. -If the process logger isn't enough, we can use what we learned in that process to actually set up a system to email you if something is amiss so you don’t have to manually check it. We can do this all with the command line and internal tools, it’s just a more involved setup. This is going to be fairly general and will need some tuning in your specific case. +If the process logger isn't enough, we can use what we learned in that process to actually set up a system to email you if something is amiss so you don't have to manually check it. We can do this all with the command line and internal tools, it's just a more involved setup. This is going to be fairly general and will need some tuning in your specific case. First you will need to configure postfix so you can easily send emails from the terminal – [follow the instructions here as closely as possible](http://benjaminrojas.net/configuring-postfix-to-send-mail-from-mac-os-x-mountain-lion/) diff --git a/chapters/project_elliot/chapter.md b/chapters/project_elliot/chapter.md index 35718204..de6d4d3e 100644 --- a/chapters/project_elliot/chapter.md +++ b/chapters/project_elliot/chapter.md @@ -20,7 +20,7 @@ An architectural web of threads spans a gallery space. It hangs abstract and und A 2D canvas is reduced from a surface piece into a line segment, but then constructed into another dimension, a volume. Light creates contrast and order on the lines to articulate digital matter. Digital forms inhabit the interconnected boundaries of space, moulding visual mass, -The artists reference Picasso's light painting, and Reticuláreas of Gego who’s work offers a contemplation of the material and immaterial, time and space, origin and encounter and art and technology. +The artists reference Picasso's light painting, and Reticuláreas of Gego who's work offers a contemplation of the material and immaterial, time and space, origin and encounter and art and technology. Kimchi and Chips create technology which paints into different dimensions, bringing new canvases and expanding the possibilities for artists to articulate form. These technologies become a corpus of code, offered without restriction on the internet. Their code is adopted by other artists and corporations, spreading values and ideas implicit with the artists' work into shared cultural idea space. *Line Segments Space* lives both as a dynamic gallery object, and as an encapsulation of the techniques as new computer code and tools on the internet. diff --git a/chapters/project_joel/chapter.md b/chapters/project_joel/chapter.md index ee13e7a4..698480fd 100644 --- a/chapters/project_joel/chapter.md +++ b/chapters/project_joel/chapter.md @@ -302,13 +302,13 @@ Kieran and Bafic were the people who ran the show for the general public, below *Did you have a routine before show time?* -Before the first show of the day we'd double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we’d dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we’d turn the beanbags upright so as to ’set the scene’. Then, as people started to walk in we’d raise the lights as though they were walking on stage. And then before we pressed play we’d dim the lights to black. +Before the first show of the day we'd double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we'd dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we'd turn the beanbags upright so as to ’set the scene’. Then, as people started to walk in we’d raise the lights as though they were walking on stage. And then before we pressed play we’d dim the lights to black. *Any problems during shows? Crashes? Funny stories?* A couple of times the connection between the Kinect and the laptop failed due to the cable being under tension so we just had to let the show run to the end before we could fix it. The main problem we had was the projector overheating and displaying a lamp warning which involved having to find the technician to sort it. At one point the projector overheated so badly that we had to leave it switched off for 40 minutes before we could run the show again. -Off the top of my head I can't think of anything I’d like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we’d mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn’t have to be manned at all times. +Off the top of my head I can't think of anything I'd like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we'd mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn’t have to be manned at all times. Following is Bafic's post show report: diff --git a/chapters/project_joel/unabridged.md b/chapters/project_joel/unabridged.md index c05d47a7..54fb07eb 100644 --- a/chapters/project_joel/unabridged.md +++ b/chapters/project_joel/unabridged.md @@ -302,13 +302,13 @@ Kieran and Bafic were the people who ran the show for the general public, below *Did you have a routine before show time?* -Before the first show of the day we'd double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we’d dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we’d turn the beanbags upright so as to ’set the scene’. Then, as people started to walk in we’d raise the lights as though they were walking on stage. And then before we pressed play we’d dim the lights to black. +Before the first show of the day we'd double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we'd dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we'd turn the beanbags upright so as to ’set the scene’. Then, as people started to walk in we’d raise the lights as though they were walking on stage. And then before we pressed play we’d dim the lights to black. *Any problems during shows? Crashes? Funny stories?* A couple of times the connection between the Kinect and the laptop failed due to the cable being under tension so we just had to let the show run to the end before we could fix it. The main problem we had was the projector overheating and displaying a lamp warning which involved having to find the technician to sort it. At one point the projector overheated so badly that we had to leave it switched off for 40 minutes before we could run the show again. -Off the top of my head I can't think of anything I’d like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we’d mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn’t have to be manned at all times. +Off the top of my head I can't think of anything I'd like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we'd mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn’t have to be manned at all times. Following is Bafic's post show report: From 8f49bdbb82b5d43a861c56bddbaad993b784a2a9 Mon Sep 17 00:00:00 2001 From: zach lieberman Date: Sun, 22 Mar 2015 18:07:01 -0400 Subject: [PATCH 3/4] again more changes on this same front --- chapters/cplusplus_basics/chapter.md | 2 +- chapters/cplusplus_basics/unabridged.md | 2 +- chapters/data_vis/chapter.md | 4 ++-- chapters/game_design/chapter.md | 8 ++++---- chapters/game_design/old drafts/oscchapter.md | 6 +++--- chapters/hardware/chapter.md | 4 ++-- chapters/installation_up_4evr_macosx/chapter.md | 8 ++++---- chapters/project_joel/chapter.md | 4 ++-- chapters/project_joel/unabridged.md | 4 ++-- 9 files changed, 21 insertions(+), 21 deletions(-) diff --git a/chapters/cplusplus_basics/chapter.md b/chapters/cplusplus_basics/chapter.md index ccefce35..8bef8fc4 100644 --- a/chapters/cplusplus_basics/chapter.md +++ b/chapters/cplusplus_basics/chapter.md @@ -160,7 +160,7 @@ prog.cpp:5:27: error: 'endl' was not declared in this scope ^ ``` -The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function 'int main()'`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: ‘cout' was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. +The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function 'int main()'`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: 'cout' was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. ```cpp #include diff --git a/chapters/cplusplus_basics/unabridged.md b/chapters/cplusplus_basics/unabridged.md index cfd74b57..55c56bb1 100644 --- a/chapters/cplusplus_basics/unabridged.md +++ b/chapters/cplusplus_basics/unabridged.md @@ -158,7 +158,7 @@ prog.cpp:5:27: error: 'endl' was not declared in this scope ^ ``` -The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function 'int main()'`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: ‘cout' was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. +The compiler found an error and did not run the program. Instead, in attempt to help you fix it, the compiler is showing you where it got confused in attempt to help you fix it. The first part, *prog.cpp*: tells you the file that contains the error. In this case, ideone.com saved your code into that default file name. Next, it says `In function 'int main()'`: file showing you the specific section of the code that contains the error, in this case, between the {curly brace} of a function called *main*. (We will talk about functions and curly braces later). On the next line, we see `prog.cpp:5:2:`. The 5 is how many lines from the top of the file, and 2 is how many characters rightward from the beginning of the line. Next, we see `error: 'cout' was not declared in this scope`. That is a message describing what it believes it wrong in the code. In this case, it's fairly correct. iostream.h is gone, and therefore no `cout` is provided to us, and so when we try to send "Hello World", the compile fails. On the next couple of lines, you see the line of code containing the fallacious `cout`, plus an extra little up-caret character on the line beneath it, and that is supposed to be an arrow pointing at a character in the code. In this case, the arrow should be sitting beneath the 'c' in `cout`. The system is showing you visually which token is at fault. A second error is shown, and this time, the compiler complains that there is no endl. Of course, we know that in order to fix the error, we need to include `` so let us do that now. Please un-comment line 1 and re-run the code. ```cpp #include diff --git a/chapters/data_vis/chapter.md b/chapters/data_vis/chapter.md index c714676b..4b163214 100644 --- a/chapters/data_vis/chapter.md +++ b/chapters/data_vis/chapter.md @@ -407,7 +407,7 @@ Here we have a for loop generating values for i that range from 0 to maxValue. S **Step 6 Interact.** -Finally we can add interactivity by creating clickable tabs that will switch between the different datasets in our file. This section turns our code into a state machine, where we define a variable called 'which' which is toggled between the values 0,1 and 2. The value of ‘which', dictates what dataset will be displayed. +Finally we can add interactivity by creating clickable tabs that will switch between the different datasets in our file. This section turns our code into a state machine, where we define a variable called 'which' which is toggled between the values 0,1 and 2. The value of 'which', dictates what dataset will be displayed. In testApp.h, declare which: ```cpp @@ -466,7 +466,7 @@ to this: } ``` -We have created a new float 'value' to hold each data point. Depending on the value of ‘which', value is assigned data from one of the three data sets in the tsp file. +We have created a new float 'value' to hold each data point. Depending on the value of 'which', value is assigned data from one of the three data sets in the tsp file. Finally the last step here is to draw the titles to the screen which is done by adding the last block of code underneath the for loop we just changed. diff --git a/chapters/game_design/chapter.md b/chapters/game_design/chapter.md index c0de2fa1..73a1e9b0 100644 --- a/chapters/game_design/chapter.md +++ b/chapters/game_design/chapter.md @@ -72,7 +72,7 @@ Let's start with our testApp. There are a few things we definitely know we'll wa ###Gamestates -First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we're in, which we'll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are `"start"`, `"game"`, and `"end"`. Let’s add a score and a player at this point as well. +First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we're in, which we'll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are `"start"`, `"game"`, and `"end"`. Let's add a score and a player at this point as well. 
 ```cpp string game_state; @@ -407,7 +407,7 @@ public: }; ``` -Our enemy's horizontal movement will be shaped by the values fed to a sine wave (which we'll see in a moment). We'll keep track of our amplitude variable (so different enemies can have different amplitudes). We’ll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the start_shoot and shoot_interval variables. Both of these variables will actually be set in our setup() function. Finally, we’ll have a boolean function that will tell us whether the enemy can shoot this frame or not. +Our enemy's horizontal movement will be shaped by the values fed to a sine wave (which we'll see in a moment). We'll keep track of our amplitude variable (so different enemies can have different amplitudes). We'll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the start_shoot and shoot_interval variables. Both of these variables will actually be set in our setup() function. Finally, we'll have a boolean function that will tell us whether the enemy can shoot this frame or not. 
Our enemy class will look like this: ```cpp @@ -835,7 +835,7 @@ For the purpose of this chapter and to allow us to create an experience that wil The desktop editor software is free however the matching software for your device will be $4.99. Get both now. As a mater of principle, we endorse building your own tools and you could easily build a second oF project to be your OSC sender and receiver on your mobile device. With that said, nothing beats TouchOSC for speed, ease of use and complete, platform independent flexibility. If you are someone who often moves between an iOS and Android device on both Windows and Mac, this tool will become indispensible to you. As a games designer it can open up possibilities like changing levels on the fly, updating game variables, adjusting for player feedback and adding new features into and taking them out of your game as it's running. We highly endorse using it and support the continued advancement of the tool. You can also use it with music production tools like Ableton Live and it comes with great presets for things like DJing and mixing music live. Go to the app store of your device and purchase the mobile version now if you would like to continue down this route. -After we get all of the tools downloaded and installed. Let's start setting everything up. You are going to need two bits of information. You are going to need to know the IP address of your computer and the ip address of your laptop. If you are on a mac, just open up your System Preferences. Go to the Network setting and click on your wifi connection in the left sidebar. On the right side it will display your IP address. You can also get this setting by opening up Terminal and entering in the command ifconfig. Terminal will list of every network that's a possible connection for your machine from the past, even if it's not currently active. For example, if you have ever connected your phone, it will be in the list with some flag and listed as inactive. Look for the connection that’s currently active. It will look something like this: +After we get all of the tools downloaded and installed. Let's start setting everything up. You are going to need two bits of information. You are going to need to know the IP address of your computer and the ip address of your laptop. If you are on a mac, just open up your System Preferences. Go to the Network setting and click on your wifi connection in the left sidebar. On the right side it will display your IP address. You can also get this setting by opening up Terminal and entering in the command ifconfig. Terminal will list of every network that's a possible connection for your machine from the past, even if it's not currently active. For example, if you have ever connected your phone, it will be in the list with some flag and listed as inactive. Look for the connection that's currently active. It will look something like this: ``` en1: flags=8863 mtu 1500 @@ -946,7 +946,7 @@ Now click on `Layout`. Then tap `Add`. It will start to search for your computer Switch back to your device. You should see your computer listed under FOUND HOSTS. Select it. It will pop back to the settings screen. Scroll down and find PlaytestInterface in the list of interfaces. Select it and it will take you back to the main menu. Press Done in the upper left corner and your interface will now launch. If you want to get back to the settings screen at any point the white dot in the upper right hand corner will return the user interface to that screen. -Finally, TouchOSC is set up. Let's link it to our game and run our very first playtest. Go back to the programming IDE. Open up `LiveTesting.cpp`. In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer's network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren't going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You’ll need a separate port for each activity in this scenario. If a port isn’t used by your operating system, you can send and receive data there. We are going to use `8000` and `8001`. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: +Finally, TouchOSC is set up. Let's link it to our game and run our very first playtest. Go back to the programming IDE. Open up `LiveTesting.cpp`. In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer's network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren't going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You'll need a separate port for each activity in this scenario. If a port isn't used by your operating system, you can send and receive data there. We are going to use `8000` and `8001`. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: ```cpp #include "LiveTesting.h" diff --git a/chapters/game_design/old drafts/oscchapter.md b/chapters/game_design/old drafts/oscchapter.md index 6f715bda..c11ba0e5 100644 --- a/chapters/game_design/old drafts/oscchapter.md +++ b/chapters/game_design/old drafts/oscchapter.md @@ -64,7 +64,7 @@ Let's start with our testApp. There are a few things we definitely know we'll wa ###Gamestates -First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we're in, which we'll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are “start”, “game”, and “end”. Let’s add a score and a player at this point as well.
 +First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we're in, which we'll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are “start”, “game”, and “end”. Let's add a score and a player at this point as well.
 ``` string game_state; int score; @@ -404,7 +404,7 @@ public: }; ``` -Our enemy's horizontal position is shaped by the values fed to a sine wave (which we'll see in a moment). We'll keep track of each enemy's amplitude variable, so different enemies can have different amplitudes. We’ll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the `start_shoot` and `shoot_interval `variables. Both of these variables will actually be set in our `setup()` function. Finally, we’ll have a boolean function that will tell us whether the enemy can shoot this frame or not. +Our enemy's horizontal position is shaped by the values fed to a sine wave (which we'll see in a moment). We'll keep track of each enemy's amplitude variable, so different enemies can have different amplitudes. We'll also want to keep track of whether enough time has passed for this enemy to shoot again, necessitating the `start_shoot` and `shoot_interval `variables. Both of these variables will actually be set in our `setup()` function. Finally, we'll have a boolean function that will tell us whether the enemy can shoot this frame or not. 
Our enemy class will look like this: ``` @@ -933,7 +933,7 @@ Now click on Layout. Then tap Add. It will start to search for your computer. Sw Switch back to your device. You should see your computer listed under FOUND HOSTS. Select it. It will pop back to the settings screen. Scroll down and find PlaytestInterface in the list of interfaces. Select it and it will take you back to the main menu. Press Done in the upper left corner and your interface will now launch. If you want to get back to the settings screen at any point the white dot in the upper right hand corner will return the user interface to that screen. -Finally, TouchOSC is set up. Let's link it to our game and run our very first playtest. Go back to the programming IDE. Open up LiveTesting.cpp In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer's network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren't going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You’ll need a separate port for each activity in this scenario. If a port isn’t used by your operating system, you can send and receive data there. We are going to use 8000 and 8001. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: +Finally, TouchOSC is set up. Let's link it to our game and run our very first playtest. Go back to the programming IDE. Open up LiveTesting.cpp In our default constructor, we will now set up our game to send and receive values over the network. To do this we will need to know which Ip address and port on our device we will send to as well as set up a port on our local computer's network to receive incoming data. Your computer will have only one IP address but it can send and receive data on thousands of ports. While we aren't going too deep into ports there, you can think of the IP address like a boat pier. Lots of boats can be docked at a single pier. This is no different. Your ports are your docks and your IP address is your pier. You can think of the data like the people departing and arriving. You'll need a separate port for each activity in this scenario. If a port isn't used by your operating system, you can send and receive data there. We are going to use 8000 and 8001. The final thing to establish is the Address Pattern. It will look like a file path and it will allow us to specify the address pattern match our messages to their right values. Add this code: #include "LiveTesting.h" diff --git a/chapters/hardware/chapter.md b/chapters/hardware/chapter.md index 37debc12..8a3e3d09 100644 --- a/chapters/hardware/chapter.md +++ b/chapters/hardware/chapter.md @@ -9,7 +9,7 @@ This chapter will give you an introduction to working with openFrameworks outsid There are a number of ways of taking your openFrameworks app out of the frame of your own personal computer and getting it to interact with the outside world. Largely this involves some kind of communication from openFrameworks to whatever hardware you've decided to hook up to. The different types of computer based communications (or protocols) vary, but the most common is what's known as 'serial' communication, so called because each bit of data sent is transferred one after the other (as opposed to multiple bits being sent in parallel). -The first hardware that we'll look at interfacing with is the excellent **Arduino** prototyping platform. Arduino is, in its own words, an *“open-source electronics prototyping platform based on flexible, easy-to-use hardware and software… intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments.*” It's easy to see why there's a lot of overlap between communities of people interested in using openFrameworks and Arduino! With Arduino, it’s quick to get your openFrameworks app hooked up to sensors (like light sensors, proximity sensors, or other methods of environmental input), actuators (like lights, motors, and other outputs), and real-time interaction. You're free to move out of the realm of pixels and into the physical world. +The first hardware that we'll look at interfacing with is the excellent **Arduino** prototyping platform. Arduino is, in its own words, an *“open-source electronics prototyping platform based on flexible, easy-to-use hardware and software… intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments.*” It's easy to see why there's a lot of overlap between communities of people interested in using openFrameworks and Arduino! With Arduino, it's quick to get your openFrameworks app hooked up to sensors (like light sensors, proximity sensors, or other methods of environmental input), actuators (like lights, motors, and other outputs), and real-time interaction. You're free to move out of the realm of pixels and into the physical world. This chapter assumes that you have the Arduino IDE installed, in addition to the environment that you normally use for working with openFrameworks. If not, you can download it from the Arduino website (arduino.cc) or the Arduino github (github.com/arduino). @@ -160,7 +160,7 @@ There's a good, heavily commented demonstration of this in the communications fo **USING FIRMATA AS A SERIAL PROTOCOL** -Though it's possible to navigate all serial communication manually, you'll reach the limitations of what you're able to do fairly quickly - as soon as you start wanting to address different devices or have multiple inputs, you’ll fall into a spiral of packet management and be much more prone to getting corrupt packets or inaccurate and scrambled data. Rather than deal with this manually, it’s much simpler to use Firmata, an open source protocol for managing multiple Serial streams. +Though it's possible to navigate all serial communication manually, you'll reach the limitations of what you're able to do fairly quickly - as soon as you start wanting to address different devices or have multiple inputs, you'll fall into a spiral of packet management and be much more prone to getting corrupt packets or inaccurate and scrambled data. Rather than deal with this manually, it's much simpler to use Firmata, an open source protocol for managing multiple Serial streams. **OFARDUINO** diff --git a/chapters/installation_up_4evr_macosx/chapter.md b/chapters/installation_up_4evr_macosx/chapter.md index d1267a2c..c0548f77 100644 --- a/chapters/installation_up_4evr_macosx/chapter.md +++ b/chapters/installation_up_4evr_macosx/chapter.md @@ -31,7 +31,7 @@ In System Preferences: - **Users and Groups:** Go to Login Options (above the padlock) and enable "Automatic Login" - **Software update:** Disable automatic updates. - **Sharing:** If you are running your main computer without a monitor or in an inaccessible area, don't forget to turn on File sharing and Screen sharing. This will allow you to access the computer and control it if you're on the same network (optional if you're concerned about security). - - **Network:** If you don't need remote access or don't need Internet access for the installation, it's not a bad idea to disable the Wifi so the “please select a wireless network” window doesn’t pop up when you least expect it. You can also turn off the option to ask you to join a new network if the proper one isn't found. + - **Network:** If you don't need remote access or don't need Internet access for the installation, it's not a bad idea to disable the Wifi so the “please select a wireless network” window doesn't pop up when you least expect it. You can also turn off the option to ask you to join a new network if the proper one isn't found. - **Bluetooth** If running without a mouse or keyboard plugged in, sometimes you can get the annoying ”Bluetooth keyboard/mouse setup” pop up over your application. You can temporality disable these by going to the advanced settings within the Bluetooth Preferences. See below for it's location in 10.6. - **Security:** I would make sure that "Disable Automatic Login" is unchecked so you don't hit any surprises on reboots. If you're really paranoid, you can even disable things like the IR remote receiver that still exists on some macs and definitely on Macbooks. This would keep pranksters with Apple TV remotes from “Front Rowing” your installation. To disable, go to Security->General->Advanced (in >10.8) and “Disable remote control IR receiver”. - **Notification Center:** You can either [disable Notification Center completely](http://www.tekrevue.com/tip/how-to-completely-disable-notification-center-in-mac-os-x/), or set your "Do Not Disturb" to basically on be on forever by setting it with overlapping times like the screenshot below @@ -100,14 +100,14 @@ In Lingon, hit the + to create a new launchd plist. Just make it a standard laun ![LingonSetup](images/LingonSetup.png) -One additional/optional thing you can add to this is to put an additional key in the plist for a “Successful Exit”. By adding this, your app won't re-open when it has detected that it closed normally (ie You just hit escape intentionally, it didn't crash). Can be useful if you're trying to check something and OS X won’t stop re-opening the app on you. To easily add this to the key, click the advanced tab and click the checkbox for "Successful exit" - or just add it manually as it in the above screenshot. +One additional/optional thing you can add to this is to put an additional key in the plist for a “Successful Exit”. By adding this, your app won't re-open when it has detected that it closed normally (ie You just hit escape intentionally, it didn't crash). Can be useful if you're trying to check something and OS X won't stop re-opening the app on you. To easily add this to the key, click the advanced tab and click the checkbox for "Successful exit" - or just add it manually as it in the above screenshot. **Shell script+Cron Job method** (I got the following super helpful tip from [Kyle McDonald](http://kylemcdonald.net/)) ) -This method is sort of deprecated in relation to the launchd method - you can run shell scripts with Lingon and launchd in the same manner as what we've got here. Shell scripting is your best friend. With the help of the script below and an application called CronniX (or use Lingon) , you will be able to use a cronjob to check the system's list of currently running processes. If your app does not appear on the list, then the script will open it again, otherwise it won't do anything. Either download the script or type the following into a text editor, replacing Twitter.app with your app's name and filepath. Don’t forget the “.app” extension in the if statement!: +This method is sort of deprecated in relation to the launchd method - you can run shell scripts with Lingon and launchd in the same manner as what we've got here. Shell scripting is your best friend. With the help of the script below and an application called CronniX (or use Lingon) , you will be able to use a cronjob to check the system's list of currently running processes. If your app does not appear on the list, then the script will open it again, otherwise it won't do anything. Either download the script or type the following into a text editor, replacing Twitter.app with your app's name and filepath. Don't forget the “.app” extension in the if statement!: \#!/bin/sh if [ $(ps ax | grep -v grep | grep "Twitter.app" | wc -l) -eq 0 ] then @@ -221,7 +221,7 @@ All that is left is to write this output to a text file, which you can do with a This line basically says - tell me the open processes (px aux) - only give me the lines that have "Tweetdeck" in them (grep Tweetdeck) - and then append them to a text file located at this location ( >> path_to_text_file) -Now we just need to make this an executable shell script and set it up as a launch daemon or cron job – see above at Step 3 to learn how to run the shell script at a regular interval using Lingon and launchd. If the app isn't running, it will only return the “grep YourAppName” process which is a good thing to log because if your app isn't open you won't know how long it’s been out (nothing will be logged), but having the grep process logged will at least tell you it was checking for it. Grep will also more accurately tell you what time it checked – the other app will only give you a start time and up time. +Now we just need to make this an executable shell script and set it up as a launch daemon or cron job – see above at Step 3 to learn how to run the shell script at a regular interval using Lingon and launchd. If the app isn't running, it will only return the “grep YourAppName” process which is a good thing to log because if your app isn't open you won't know how long it's been out (nothing will be logged), but having the grep process logged will at least tell you it was checking for it. Grep will also more accurately tell you what time it checked – the other app will only give you a start time and up time. Let's also take this one step further and say, hypothetically, that the Triplehead2Go display adapter you have is fairly wonky and you don't always get the displays or projectors to connect after reboot – or maybe a projector is shutting itself off and disrupting things. Well we can log the currently available resolutions too! Try entering the line below in your own terminal: diff --git a/chapters/project_joel/chapter.md b/chapters/project_joel/chapter.md index 698480fd..bc5d9595 100644 --- a/chapters/project_joel/chapter.md +++ b/chapters/project_joel/chapter.md @@ -302,13 +302,13 @@ Kieran and Bafic were the people who ran the show for the general public, below *Did you have a routine before show time?* -Before the first show of the day we'd double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we'd dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we'd turn the beanbags upright so as to ’set the scene’. Then, as people started to walk in we’d raise the lights as though they were walking on stage. And then before we pressed play we’d dim the lights to black. +Before the first show of the day we'd double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we'd dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we'd turn the beanbags upright so as to 'set the scene'. Then, as people started to walk in we'd raise the lights as though they were walking on stage. And then before we pressed play we'd dim the lights to black. *Any problems during shows? Crashes? Funny stories?* A couple of times the connection between the Kinect and the laptop failed due to the cable being under tension so we just had to let the show run to the end before we could fix it. The main problem we had was the projector overheating and displaying a lamp warning which involved having to find the technician to sort it. At one point the projector overheated so badly that we had to leave it switched off for 40 minutes before we could run the show again. -Off the top of my head I can't think of anything I'd like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we'd mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn’t have to be manned at all times. +Off the top of my head I can't think of anything I'd like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we'd mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn't have to be manned at all times. Following is Bafic's post show report: diff --git a/chapters/project_joel/unabridged.md b/chapters/project_joel/unabridged.md index 54fb07eb..d7237210 100644 --- a/chapters/project_joel/unabridged.md +++ b/chapters/project_joel/unabridged.md @@ -302,13 +302,13 @@ Kieran and Bafic were the people who ran the show for the general public, below *Did you have a routine before show time?* -Before the first show of the day we'd double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we'd dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we'd turn the beanbags upright so as to ’set the scene’. Then, as people started to walk in we’d raise the lights as though they were walking on stage. And then before we pressed play we’d dim the lights to black. +Before the first show of the day we'd double check the connection between the laptop and the Kinect and test with the skeleton tracking that everything was working correctly. Before show time we'd dim the lights, make sure the sound was turned on, switch to the point cloud setting so people could see themselves as they walked in and then we'd turn the beanbags upright so as to 'set the scene'. Then, as people started to walk in we'd raise the lights as though they were walking on stage. And then before we pressed play we'd dim the lights to black. *Any problems during shows? Crashes? Funny stories?* A couple of times the connection between the Kinect and the laptop failed due to the cable being under tension so we just had to let the show run to the end before we could fix it. The main problem we had was the projector overheating and displaying a lamp warning which involved having to find the technician to sort it. At one point the projector overheated so badly that we had to leave it switched off for 40 minutes before we could run the show again. -Off the top of my head I can't think of anything I'd like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we'd mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn’t have to be manned at all times. +Off the top of my head I can't think of anything I'd like to change about it, the GUI had quite a steep learning curve so it took a while to remember all the keys to press to hide each part of the interface but once we'd mastered that everything was fine. I guess the only thing that would be good but most likely ultimately un-achieveable would be full automation in the sense that the station wouldn't have to be manned at all times. Following is Bafic's post show report: From 44f3b469234d3d41a2d7117418777d2c92939c08 Mon Sep 17 00:00:00 2001 From: zach lieberman Date: Sun, 22 Mar 2015 18:34:15 -0400 Subject: [PATCH 4/4] goodbye curly quotes --- chapters/cplusplus_basics/chapter.md | 6 ++-- chapters/cplusplus_basics/unabridged.md | 6 ++-- .../data_vis/MichaelHadleyChapterFeedback.md | 6 ++-- chapters/data_vis/chapter.md | 12 +++---- chapters/game_design/old drafts/oscchapter.md | 8 ++--- chapters/hardware/chapter.md | 6 ++-- .../installation_up_4evr_macosx/chapter.md | 34 +++++++++---------- chapters/intro_to_graphics/Cut Material.md | 2 +- 8 files changed, 40 insertions(+), 40 deletions(-) diff --git a/chapters/cplusplus_basics/chapter.md b/chapters/cplusplus_basics/chapter.md index 8bef8fc4..d942ef89 100644 --- a/chapters/cplusplus_basics/chapter.md +++ b/chapters/cplusplus_basics/chapter.md @@ -70,7 +70,7 @@ You will see a slightly different editing configuration but the same template co // your code goes here . ``` -A line beginning with a double forward slash is called a comment. You may type anything you need to in order to annotate your code in a way you understand. Sometimes a it's useful to “comment out code” by placing two forward-slashes before it, because that deactivates the C++ code without deleting it. Comments in C++ can also take up multiple lines, or insert like a tag. The syntax for beginning and ending comment-mode is different. Everything between the `/* and the */` becomes a comment: +A line beginning with a double forward slash is called a comment. You may type anything you need to in order to annotate your code in a way you understand. Sometimes a it's useful to "comment out code" by placing two forward-slashes before it, because that deactivates the C++ code without deleting it. Comments in C++ can also take up multiple lines, or insert like a tag. The syntax for beginning and ending comment-mode is different. Everything between the `/* and the */` becomes a comment: ```cpp @@ -104,7 +104,7 @@ int main(){ } ``` -Now press the green *ideone it!* button at the bottom right corner and watch the output console, which is the bottom half of the code editor, just above that green button. You will see orange status messages saying things like “Waiting for compilation,” “Compilation,” and “Running”. Shortly after, the program will execute in the cloud and the standard output should show up on that web page. You should see the new message in Figure 8. +Now press the green *ideone it!* button at the bottom right corner and watch the output console, which is the bottom half of the code editor, just above that green button. You will see orange status messages saying things like "Waiting for compilation," "Compilation," and "Running". Shortly after, the program will execute in the cloud and the standard output should show up on that web page. You should see the new message in Figure 8. ![Figure 8](images/hello-world.png "Figure 8: Hello World appears in output window") @@ -303,7 +303,7 @@ There are a few advantages to using C++ over the other options (mostly scripting ## Variables (part 1) -> A “thing” is a “think”, a unit of thought +> A "thing" is a "think", a unit of thought > > -- Alan Watts diff --git a/chapters/cplusplus_basics/unabridged.md b/chapters/cplusplus_basics/unabridged.md index 55c56bb1..f849e818 100644 --- a/chapters/cplusplus_basics/unabridged.md +++ b/chapters/cplusplus_basics/unabridged.md @@ -68,7 +68,7 @@ You will see a slightly different editing configuration but the same template co // your code goes here . ``` -A line beginning with a double forward slash is called a comment. You may type anything you need to in order to annotate your code in a way you understand. Sometimes a it's useful to “comment out code” by placing two forward-slashes before it, because that deactivates the C++ code without deleting it. Comments in C++ can also take up multiple lines, or insert like a tag. The syntax for beginning and ending comment-mode is different. Everything between the `/* and the */` becomes a comment: +A line beginning with a double forward slash is called a comment. You may type anything you need to in order to annotate your code in a way you understand. Sometimes a it's useful to "comment out code" by placing two forward-slashes before it, because that deactivates the C++ code without deleting it. Comments in C++ can also take up multiple lines, or insert like a tag. The syntax for beginning and ending comment-mode is different. Everything between the `/* and the */` becomes a comment: ```cpp @@ -102,7 +102,7 @@ int main(){ } ``` -Now press the green *ideone it!* button at the bottom right corner and watch the output console, which is the bottom half of the code editor, just above that green button. You will see orange status messages saying things like “Waiting for compilation,” “Compilation,” and “Running”. Shortly after, the program will execute in the cloud and the standard output should show up on that web page. You should see the new message in Figure 8. +Now press the green *ideone it!* button at the bottom right corner and watch the output console, which is the bottom half of the code editor, just above that green button. You will see orange status messages saying things like "Waiting for compilation," "Compilation," and "Running". Shortly after, the program will execute in the cloud and the standard output should show up on that web page. You should see the new message in Figure 8. ![Figure 8](images/hello-world.png "Figure 8: Hello World appears in output window") @@ -334,7 +334,7 @@ Sometimes I say C, and sometimes I say C++. Since they are closely related, perh ## Variables (part 1) -> A “thing” is a “think”, a unit of thought +> A "thing" is a "think", a unit of thought > > -- Alan Watts diff --git a/chapters/data_vis/MichaelHadleyChapterFeedback.md b/chapters/data_vis/MichaelHadleyChapterFeedback.md index 508385dd..5f6be395 100644 --- a/chapters/data_vis/MichaelHadleyChapterFeedback.md +++ b/chapters/data_vis/MichaelHadleyChapterFeedback.md @@ -23,7 +23,7 @@ This chapter introduces some basic ways to work with data and visualise datasets ###1.2 Definition of terms and chapter structure -Data is produced from processes of observation. It is symbols or numerical interpretations that “represent the properties of objects, events or environments” (Ackoff, 1989). Information comes from understanding and analysing the context and descriptive qualities of the data, it relates to why the data was collected. Although these terms are often used loosely and interchangeably, in the field of information science data is generally thought of as a raw material from which information is produced through analytical processes. +Data is produced from processes of observation. It is symbols or numerical interpretations that "represent the properties of objects, events or environments" (Ackoff, 1989). Information comes from understanding and analysing the context and descriptive qualities of the data, it relates to why the data was collected. Although these terms are often used loosely and interchangeably, in the field of information science data is generally thought of as a raw material from which information is produced through analytical processes. These definitions may need to be further refined. **[mh: the second to last sentence is quite nice, and I don't think these definitions need to be further refined.]** @@ -151,7 +151,7 @@ Vectors are also an important data structure for storing lists of data in OF. In Conversion functions enable the manipulation of each line of data in the buffer. They allow each line to be split and for parts of it to be placed into string or integer variables. ```cpp -ofSplitString(line, “\t” ); +ofSplitString(line, "\t" ); ``` This function splits a string at a specified character. It has two arguments, the first is the name of the string to be split and the second is the character at which it is to be split. (\t indicates split at a tab) ```cpp @@ -199,7 +199,7 @@ vector < weatherData > dataPoints; IN THE TESTAPP FILE: We load the data into the buffer and then run through each line of the buffer, placing the values into the struct called data. ```cpp -ofBuffer buffer = ofBufferFromFile(“weather.csv"); +ofBuffer buffer = ofBufferFromFile("weather.csv"); string temp = buffer.getNextLine(); diff --git a/chapters/data_vis/chapter.md b/chapters/data_vis/chapter.md index 4b163214..d4fe2026 100644 --- a/chapters/data_vis/chapter.md +++ b/chapters/data_vis/chapter.md @@ -60,7 +60,7 @@ Reading an XML file in OF requires the use of an OF addon called ofXmlSettings. **Step 1 Acquire:** This section works through an example of a data visualisation of US population data downloaded from the United States Census service here: http://www.nber.org/data/census-decennial-population.html -**Step 2 Parse and Filter:** Open this file in a spreadsheet program and inspect its contents. You will see that there is an population data for all the regions of the USA from 1900-1990. This example visualises the total population data and data from New York, Louisiana and Alabama so we must construct the data file with only the data from those particular states. You will want to copy and past the selected data into a new spreadsheet so that you are working with a file structure that looks like Figure 1. If you are working in Excel to parse the data, this program has a useful way of transposing the table. Copy a row from the original spreadsheet, and then paste it into your new file by selecting the “Paste Special” option in the Edit menu and selecting “Transpose” before hitting ok. +**Step 2 Parse and Filter:** Open this file in a spreadsheet program and inspect its contents. You will see that there is an population data for all the regions of the USA from 1900-1990. This example visualises the total population data and data from New York, Louisiana and Alabama so we must construct the data file with only the data from those particular states. You will want to copy and past the selected data into a new spreadsheet so that you are working with a file structure that looks like Figure 1. If you are working in Excel to parse the data, this program has a useful way of transposing the table. Copy a row from the original spreadsheet, and then paste it into your new file by selecting the "Paste Special" option in the Edit menu and selecting "Transpose" before hitting ok. IMAGE HERE. @@ -208,7 +208,7 @@ ofBuffer is what is known as a convenience class, and provides easy methods for ####Buffer Functions ofBufferFromFile(); is a function that allows you to load your data file. ```cpp -ofBuffer file = ofBufferFromFile(“population.tsv"); +ofBuffer file = ofBufferFromFile("population.tsv"); cout << file.getText(); ``` This loads the population.tsv file into a variable called 'file'. @@ -421,17 +421,17 @@ Then insert this block of code to the mousePressed part of the openFrameworks te void testApp::mousePressed(int x, int y, int button){ -ofRectangle rect = font.getStringBoundingBox(“NewYork”, dimensions.x, dimensions.y-15); +ofRectangle rect = font.getStringBoundingBox("NewYork", dimensions.x, dimensions.y-15); if (rect.inside(ofPoint(x,y))){ which = 0; } - rect = font.getStringBoundingBox(“Louisiana”, dimensions.x + 80, dimensions.y-15); + rect = font.getStringBoundingBox("Louisiana", dimensions.x + 80, dimensions.y-15); if (rect.inside(ofPoint(x,y))){ which = 1; } - rect = font.getStringBoundingBox(“Alabama”, dimensions.x + 160, dimensions.y-15); + rect = font.getStringBoundingBox("Alabama", dimensions.x + 160, dimensions.y-15); if (rect.inside(ofPoint(x,y))){ which = 2; } @@ -492,7 +492,7 @@ Finally the last step here is to draw the titles to the screen which is done by ###Conversion functions (ofSplitString, ofToString, ofToInt) Conversion functions enable the manipulation of each line of data in the buffer. They allow each line to be split and for parts of it to be placed into string or integer variables. ```cpp -ofSplitString(line, “\t” ); +ofSplitString(line, "\t" ); ``` This function splits a string at a specified character. It has two arguments, the first is the name of the string to be split and the second is the character at which it is to be split. (\t indicates split at a tab) ```cpp diff --git a/chapters/game_design/old drafts/oscchapter.md b/chapters/game_design/old drafts/oscchapter.md index c11ba0e5..fcdcc790 100644 --- a/chapters/game_design/old drafts/oscchapter.md +++ b/chapters/game_design/old drafts/oscchapter.md @@ -64,7 +64,7 @@ Let's start with our testApp. There are a few things we definitely know we'll wa ###Gamestates -First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we're in, which we'll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are “start”, “game”, and “end”. Let's add a score and a player at this point as well.
 +First let's create the basic structure of our game. Games typically have at least three parts: a start screen, the game itself, and an end screen. We need to keep track of which section of the game we're in, which we'll do using a variable called a game state. In this example, our game state variable is a string, and the three parts of our game are "start", "game", and "end". Let's add a score and a player at this point as well.
 ``` string game_state; int score; @@ -80,7 +80,7 @@ void testApp::update(){ 
    } else if (game_state == "game") {     -   } else if (game_state == “end”) { +   } else if (game_state == "end") { 
    } } @@ -90,7 +90,7 @@ void testApp::draw(){     } else if (game_state == "game") {     -   } else if (game_state == “end”) { +   } else if (game_state == "end") { 
    } } @@ -582,7 +582,7 @@ bool LevelController::should_spawn() { When we set up our level controller, we'll give it a starting time. It'll use this time as a baseline for the first enemy spawn. The `should_spawn` code should look familiar from the enemy bullet section. -We'll wait to set up our level controller until the game actually starts--namely, when the game state changes from ` “start” ` to ` “game” `. +We'll wait to set up our level controller until the game actually starts--namely, when the game state changes from ` "start" ` to ` "game" `. ``` void testApp::keyReleased(int key){ diff --git a/chapters/hardware/chapter.md b/chapters/hardware/chapter.md index 8a3e3d09..1776cd42 100644 --- a/chapters/hardware/chapter.md +++ b/chapters/hardware/chapter.md @@ -9,7 +9,7 @@ This chapter will give you an introduction to working with openFrameworks outsid There are a number of ways of taking your openFrameworks app out of the frame of your own personal computer and getting it to interact with the outside world. Largely this involves some kind of communication from openFrameworks to whatever hardware you've decided to hook up to. The different types of computer based communications (or protocols) vary, but the most common is what's known as 'serial' communication, so called because each bit of data sent is transferred one after the other (as opposed to multiple bits being sent in parallel). -The first hardware that we'll look at interfacing with is the excellent **Arduino** prototyping platform. Arduino is, in its own words, an *“open-source electronics prototyping platform based on flexible, easy-to-use hardware and software… intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments.*” It's easy to see why there's a lot of overlap between communities of people interested in using openFrameworks and Arduino! With Arduino, it's quick to get your openFrameworks app hooked up to sensors (like light sensors, proximity sensors, or other methods of environmental input), actuators (like lights, motors, and other outputs), and real-time interaction. You're free to move out of the realm of pixels and into the physical world. +The first hardware that we'll look at interfacing with is the excellent **Arduino** prototyping platform. Arduino is, in its own words, an *"open-source electronics prototyping platform based on flexible, easy-to-use hardware and software… intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments.*" It's easy to see why there's a lot of overlap between communities of people interested in using openFrameworks and Arduino! With Arduino, it's quick to get your openFrameworks app hooked up to sensors (like light sensors, proximity sensors, or other methods of environmental input), actuators (like lights, motors, and other outputs), and real-time interaction. You're free to move out of the realm of pixels and into the physical world. This chapter assumes that you have the Arduino IDE installed, in addition to the environment that you normally use for working with openFrameworks. If not, you can download it from the Arduino website (arduino.cc) or the Arduino github (github.com/arduino). @@ -22,7 +22,7 @@ Additionally, following along with the examples in this chapter requires you to **SERIAL: ONE AFTER THE OTHER** -Serial, in the most basic language sense, refers to things that come one after another; it's a term often used to describe magazines, crimes, and television programs. That meaning also applies when talking about serial data: “serial communication” means that all information between two entities is being sent one piece at a time, following in a single stream. One piece of data, or one bit, is just a binary piece of information: you're either sending a 0 or a 1. Using the terminology of digital electronics, these are frequently referred to as “high” and “low”; 0 is low (like turning a light off) and 1 is high (flipping it back on). 8 bits (for example the stream 01000001, which represents the letter A) are sometimes packaged together to create a single byte. +Serial, in the most basic language sense, refers to things that come one after another; it's a term often used to describe magazines, crimes, and television programs. That meaning also applies when talking about serial data: "serial communication" means that all information between two entities is being sent one piece at a time, following in a single stream. One piece of data, or one bit, is just a binary piece of information: you're either sending a 0 or a 1. Using the terminology of digital electronics, these are frequently referred to as "high" and "low"; 0 is low (like turning a light off) and 1 is high (flipping it back on). 8 bits (for example the stream 01000001, which represents the letter A) are sometimes packaged together to create a single byte. Serial communication is actually a very broad topic and there are many serial protocols, including audio-visual protocols such as DMX (based on RS-485) and MIDI (serial at 31,250 bits per second) which we'll briefly cover in this chapter. The most common serial protocol is called RS-232 and computers used to be equipped with RS-232 serial ports (remember them?) but today they are rarely present, which is why serial communications involving a computer will typically require an RS-232 to USB adaptor (found on-line or at your local electronics store). @@ -220,7 +220,7 @@ void testApp::setupArduino(const int & version) { The argument that's being passed to the function, `const int & version`, is a default return from the listener we're about to set up, which always responds to a connection event by sending back an argument with the connected firmware version. That can stay as it is. -In the `setup()` of testApp.cpp, create a listener using `ofAddListener()`. `ofAddListener()` is a function of ofEventUtils, which takes the arguments (event object, callback object, callback function). When the event object happens (in this case, when the ofArduino EInitialized event is triggered), ofAddListener tells the callback object (here, a pointer to the testApp itself, referred to as “this”) to perform the setupArduino function that we created in the last step. +In the `setup()` of testApp.cpp, create a listener using `ofAddListener()`. `ofAddListener()` is a function of ofEventUtils, which takes the arguments (event object, callback object, callback function). When the event object happens (in this case, when the ofArduino EInitialized event is triggered), ofAddListener tells the callback object (here, a pointer to the testApp itself, referred to as "this") to perform the setupArduino function that we created in the last step. ```cpp ofAddListener(myArduino.EInitialized, this, &testApp.setupArduino); diff --git a/chapters/installation_up_4evr_macosx/chapter.md b/chapters/installation_up_4evr_macosx/chapter.md index c0548f77..a43b7967 100644 --- a/chapters/installation_up_4evr_macosx/chapter.md +++ b/chapters/installation_up_4evr_macosx/chapter.md @@ -26,14 +26,14 @@ Nick Hardeman has made a utility application for setting all of these attributes In System Preferences: - - **Desktop and Screensaver:** Disable your screensaver. Set it's time to “Never." I also suggest changing your desktop background to either black/a screenshot of your app/you client's logo - you can even set these to change automatically - remember - **it's not broken until someone notices** :) - - **Energy Saver:** Turn Display Sleep and Computer Sleep to Never. Enable “Start up automatically after power failure” and “Restart automatically if the computer freezes” (these are only available in 10.7 and later) + - **Desktop and Screensaver:** Disable your screensaver. Set it's time to "Never." I also suggest changing your desktop background to either black/a screenshot of your app/you client's logo - you can even set these to change automatically - remember - **it's not broken until someone notices** :) + - **Energy Saver:** Turn Display Sleep and Computer Sleep to Never. Enable "Start up automatically after power failure" and "Restart automatically if the computer freezes" (these are only available in 10.7 and later) - **Users and Groups:** Go to Login Options (above the padlock) and enable "Automatic Login" - **Software update:** Disable automatic updates. - **Sharing:** If you are running your main computer without a monitor or in an inaccessible area, don't forget to turn on File sharing and Screen sharing. This will allow you to access the computer and control it if you're on the same network (optional if you're concerned about security). - - **Network:** If you don't need remote access or don't need Internet access for the installation, it's not a bad idea to disable the Wifi so the “please select a wireless network” window doesn't pop up when you least expect it. You can also turn off the option to ask you to join a new network if the proper one isn't found. - - **Bluetooth** If running without a mouse or keyboard plugged in, sometimes you can get the annoying ”Bluetooth keyboard/mouse setup” pop up over your application. You can temporality disable these by going to the advanced settings within the Bluetooth Preferences. See below for it's location in 10.6. - - **Security:** I would make sure that "Disable Automatic Login" is unchecked so you don't hit any surprises on reboots. If you're really paranoid, you can even disable things like the IR remote receiver that still exists on some macs and definitely on Macbooks. This would keep pranksters with Apple TV remotes from “Front Rowing” your installation. To disable, go to Security->General->Advanced (in >10.8) and “Disable remote control IR receiver”. + - **Network:** If you don't need remote access or don't need Internet access for the installation, it's not a bad idea to disable the Wifi so the "please select a wireless network" window doesn't pop up when you least expect it. You can also turn off the option to ask you to join a new network if the proper one isn't found. + - **Bluetooth** If running without a mouse or keyboard plugged in, sometimes you can get the annoying "Bluetooth keyboard/mouse setup" pop up over your application. You can temporality disable these by going to the advanced settings within the Bluetooth Preferences. See below for it's location in 10.6. + - **Security:** I would make sure that "Disable Automatic Login" is unchecked so you don't hit any surprises on reboots. If you're really paranoid, you can even disable things like the IR remote receiver that still exists on some macs and definitely on Macbooks. This would keep pranksters with Apple TV remotes from "Front Rowing" your installation. To disable, go to Security->General->Advanced (in >10.8) and "Disable remote control IR receiver". - **Notification Center:** You can either [disable Notification Center completely](http://www.tekrevue.com/tip/how-to-completely-disable-notification-center-in-mac-os-x/), or set your "Do Not Disturb" to basically on be on forever by setting it with overlapping times like the screenshot below ![BluetoothSettings](images/Bluetooth_settings.png) @@ -72,7 +72,7 @@ defaults write com.apple.finder CreateDesktop -bool false **Step 2: Boot into your software** ------------------------------- -Things get unplugged, power goes out, not everyone has budget or space for a battery backup etc etc. Above, I covered how to have everything reboot automatically after power failures or freezes, but you'll also need your app to be ready to go from boot and not leave the desktop open to prying eyes. There are many ways to have your application load automatically - the simplest is using OSX's built in tools: In the System Preferences “Accounts” panel, select “Login Items” and drag your application into there to have it open automatically on launch. +Things get unplugged, power goes out, not everyone has budget or space for a battery backup etc etc. Above, I covered how to have everything reboot automatically after power failures or freezes, but you'll also need your app to be ready to go from boot and not leave the desktop open to prying eyes. There are many ways to have your application load automatically - the simplest is using OSX's built in tools: In the System Preferences "Accounts" panel, select "Login Items" and drag your application into there to have it open automatically on launch. ![Login Items](images/Login_items.png) @@ -100,14 +100,14 @@ In Lingon, hit the + to create a new launchd plist. Just make it a standard laun ![LingonSetup](images/LingonSetup.png) -One additional/optional thing you can add to this is to put an additional key in the plist for a “Successful Exit”. By adding this, your app won't re-open when it has detected that it closed normally (ie You just hit escape intentionally, it didn't crash). Can be useful if you're trying to check something and OS X won't stop re-opening the app on you. To easily add this to the key, click the advanced tab and click the checkbox for "Successful exit" - or just add it manually as it in the above screenshot. +One additional/optional thing you can add to this is to put an additional key in the plist for a "Successful Exit". By adding this, your app won't re-open when it has detected that it closed normally (ie You just hit escape intentionally, it didn't crash). Can be useful if you're trying to check something and OS X won't stop re-opening the app on you. To easily add this to the key, click the advanced tab and click the checkbox for "Successful exit" - or just add it manually as it in the above screenshot. **Shell script+Cron Job method** (I got the following super helpful tip from [Kyle McDonald](http://kylemcdonald.net/)) ) -This method is sort of deprecated in relation to the launchd method - you can run shell scripts with Lingon and launchd in the same manner as what we've got here. Shell scripting is your best friend. With the help of the script below and an application called CronniX (or use Lingon) , you will be able to use a cronjob to check the system's list of currently running processes. If your app does not appear on the list, then the script will open it again, otherwise it won't do anything. Either download the script or type the following into a text editor, replacing Twitter.app with your app's name and filepath. Don't forget the “.app” extension in the if statement!: +This method is sort of deprecated in relation to the launchd method - you can run shell scripts with Lingon and launchd in the same manner as what we've got here. Shell scripting is your best friend. With the help of the script below and an application called CronniX (or use Lingon) , you will be able to use a cronjob to check the system's list of currently running processes. If your app does not appear on the list, then the script will open it again, otherwise it won't do anything. Either download the script or type the following into a text editor, replacing Twitter.app with your app's name and filepath. Don't forget the ".app" extension in the if statement!: \#!/bin/sh if [ $(ps ax | grep -v grep | grep "Twitter.app" | wc -l) -eq 0 ] then @@ -116,9 +116,9 @@ This method is sort of deprecated in relation to the launchd method - you can ru else echo "Twitter running" fi -Save that file as something like “KeepOpen.sh” and keep it next to your application or somewhere convenient. +Save that file as something like "KeepOpen.sh" and keep it next to your application or somewhere convenient. -After creating that file, you'll need to make it executable. To do this, open the Terminal and in a new window type “chmod +x ” and then enter the path to the shell script you just created (you can either drag the shell script into the terminal window or manually type it). It would look something like this: +After creating that file, you'll need to make it executable. To do this, open the Terminal and in a new window type "chmod +x " and then enter the path to the shell script you just created (you can either drag the shell script into the terminal window or manually type it). It would look something like this: 4Evr-MacBook-Pro:~ Forever4Evr$ chmod +x /Users/Forever4Evr/Desktop/KeepOpen.sh @@ -131,7 +131,7 @@ After downloading CronniX, open it up and create a new cronjob. In the window th ![Cronnix_link](images/Cronnix-settings.png) -Now just hit “New” and then make sure to hit “Save” to save it into the system's crontab. Now if you just wait a minute then it should open your app every minute on the minute. Maybe save this one for the very end if you have more to do :) +Now just hit "New" and then make sure to hit "Save" to save it into the system's crontab. Now if you just wait a minute then it should open your app every minute on the minute. Maybe save this one for the very end if you have more to do :) This is a great tool if there is an unintended crash because the app will never be down longer than a minute. @@ -147,7 +147,7 @@ This is a great tool if there is an unintended crash because the app will never sleep 10 done -Just type this into a plaintext document and save it as something like ”KeepMyAppAlivePlz.command” and then use chmod as above to make the file executable and then drop this in your login items as above. This one will just continuously try and open your app every 10ms, but if it is already open, the OS knows to not try opening it a second, third, fourth time. +Just type this into a plaintext document and save it as something like "KeepMyAppAlivePlz.command" and then use chmod as above to make the file executable and then drop this in your login items as above. This one will just continuously try and open your app every 10ms, but if it is already open, the OS knows to not try opening it a second, third, fourth time. Make sure to check the Console.app for any errors that may have come through when no one caught them, whenever you check the installation in person or remotely. This is not a fix-all for buggy programming, just a helper to keep things running smooth. The more things you can do to leave yourself notes about why the crash happened, the faster you can address the core issue. @@ -158,7 +158,7 @@ Applescript is also a very solid choice for doing some more OS specific work in This one is a little more preventative, or maybe superstitious so hopefully someone can point out a concrete reason why this is a good idea. Depending on your app and the amount of stuff it reaches into, there could be some memory leaks or other OS bugs that you haven't accounted for. Rebooting every day or week is a good idea to keep everything tidy, system wise. -The simplest option by far would be to go to System Preferences->Energy Saver and then click “Schedule…” and enter in some values if you need to turn the computer off to rest for a longer period of time to save it some stress when it might not be used at night time or something. Heat can do funny things sometimes, so if you have a chance to get your computer to rest and the time to test it, definitely give this a shot…saves some energy too which is nice. +The simplest option by far would be to go to System Preferences->Energy Saver and then click "Schedule…" and enter in some values if you need to turn the computer off to rest for a longer period of time to save it some stress when it might not be used at night time or something. Heat can do funny things sometimes, so if you have a chance to get your computer to rest and the time to test it, definitely give this a shot…saves some energy too which is nice. ![Auto-reboot](images/Auto_reboot.png) @@ -221,7 +221,7 @@ All that is left is to write this output to a text file, which you can do with a This line basically says - tell me the open processes (px aux) - only give me the lines that have "Tweetdeck" in them (grep Tweetdeck) - and then append them to a text file located at this location ( >> path_to_text_file) -Now we just need to make this an executable shell script and set it up as a launch daemon or cron job – see above at Step 3 to learn how to run the shell script at a regular interval using Lingon and launchd. If the app isn't running, it will only return the “grep YourAppName” process which is a good thing to log because if your app isn't open you won't know how long it's been out (nothing will be logged), but having the grep process logged will at least tell you it was checking for it. Grep will also more accurately tell you what time it checked – the other app will only give you a start time and up time. +Now we just need to make this an executable shell script and set it up as a launch daemon or cron job – see above at Step 3 to learn how to run the shell script at a regular interval using Lingon and launchd. If the app isn't running, it will only return the "grep YourAppName" process which is a good thing to log because if your app isn't open you won't know how long it's been out (nothing will be logged), but having the grep process logged will at least tell you it was checking for it. Grep will also more accurately tell you what time it checked – the other app will only give you a start time and up time. Let's also take this one step further and say, hypothetically, that the Triplehead2Go display adapter you have is fairly wonky and you don't always get the displays or projectors to connect after reboot – or maybe a projector is shutting itself off and disrupting things. Well we can log the currently available resolutions too! Try entering the line below in your own terminal: @@ -233,7 +233,7 @@ Let's say you want to make sure you're running a resolution of 3840×720 at all system_profiler SPDisplaysDataType | grep Resolution -This will return “Resolution: 3840×720″ which you can combine with the above lines to write it all to a text file. So here would be your shell script file if you wanted to record the currently running processes and the current resolutions: +This will return "Resolution: 3840×720″ which you can combine with the above lines to write it all to a text file. So here would be your shell script file if you wanted to record the currently running processes and the current resolutions: \#!/bin/bash ps aux | grep 'YourAppName' >> /Users/you/filepath/Install6ProcessLog.txt @@ -259,7 +259,7 @@ If you were using a gmail account you would do: The line in the passwd file mentioned in the article would be: smtp.gmail.com:587 installationSupport@gmail.com:yourpassword -Now send a test email to yourself by running: echo “Hello” | mail -s “test” “InstallationSupport@gmail.com” +Now send a test email to yourself by running: echo "Hello" | mail -s "test" "InstallationSupport@gmail.com" Second step is to combine this new found ability to send emails from the Terminal with a process to check if your application is still running…something like the below would work with some tweaking for what you're looking to do: @@ -286,7 +286,7 @@ Memory leak murderer See [this article](http://blairneal.com/blog/memory-leak-murderer/) about combining the above process with something that kills and restarts an app if it crosses a memory usage threshold -Bonus – if using MadMapper – see [this link](http://blairneal.com/blog/applescript-to-automatically-fullscreen-madmapper-for-installations/) for an AppleScript that will open MadMapper and have it enter fullscreen – and enter “OK” on a pesky dialog box. +Bonus – if using MadMapper – see [this link](http://blairneal.com/blog/applescript-to-automatically-fullscreen-madmapper-for-installations/) for an AppleScript that will open MadMapper and have it enter fullscreen – and enter "OK" on a pesky dialog box. Alternate resources: -------------------- diff --git a/chapters/intro_to_graphics/Cut Material.md b/chapters/intro_to_graphics/Cut Material.md index 93283cc7..92069768 100644 --- a/chapters/intro_to_graphics/Cut Material.md +++ b/chapters/intro_to_graphics/Cut Material.md @@ -79,7 +79,7 @@ Assign the initial drawing mode to the rectangle brush in `setup()` using: `draw else if (drawingMode == triangleMode) { } } -Scroll down to find [`keyPressed(int key)`](http://openframeworks.cc/documentation/application/ofBaseApp.html#!show_keyPressed "keyPressed Documentation Page"). Similar to `mousePressed(...)`, this function is called any time a key is pressed, and it receives an `int` called `key` to identify which key is currently being pressed. That `int` is the [ASCII](http://en.wikipedia.org/wiki/ASCII "ASCII Wiki Page") code for the key that was pressed. ASCII is an agreed upon system for assigning numbers to characters. We will use `key` to change `drawingMode`: “r” for rectangle mode, “c” for circle mode, etc. In C++, we can compare an integer like `key` with a character directly using `==` or `!=`. Add these lines to `keyPressed(...)`: +Scroll down to find [`keyPressed(int key)`](http://openframeworks.cc/documentation/application/ofBaseApp.html#!show_keyPressed "keyPressed Documentation Page"). Similar to `mousePressed(...)`, this function is called any time a key is pressed, and it receives an `int` called `key` to identify which key is currently being pressed. That `int` is the [ASCII](http://en.wikipedia.org/wiki/ASCII "ASCII Wiki Page") code for the key that was pressed. ASCII is an agreed upon system for assigning numbers to characters. We will use `key` to change `drawingMode`: "r" for rectangle mode, "c" for circle mode, etc. In C++, we can compare an integer like `key` with a character directly using `==` or `!=`. Add these lines to `keyPressed(...)`: if (key == 'r') drawingMode = rectangleMode; // It is important to use `r` and not "r" here else if (key == 'c') drawingMode = circleMode; // See C++ Basics chapter on strings vs char for more info