From 3302fb7327889b61e0f55182f20cabd639eaafad Mon Sep 17 00:00:00 2001 From: Todd Thille Date: Wed, 11 Feb 2015 16:22:39 +0200 Subject: [PATCH] game_design chapter edit suggestions Clean up minor typos and reformatting, rewording for increased clarity. --- chapters/game_design/chapter.md | 130 ++++++++++++++++---------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/chapters/game_design/chapter.md b/chapters/game_design/chapter.md index c0eb2145..3420a66e 100644 --- a/chapters/game_design/chapter.md +++ b/chapters/game_design/chapter.md @@ -2,9 +2,9 @@ *by [Phoenix Perry](http://www.phoenixperry.com) and [Jane Friedhoff](janefriedhoff.com)* -Game developers are, in greater and greater numbers, turning to openFrameworks' creative coding toolkit to develop their games. Unlike platforms like Unity, GameMaker, and Construct2, oF was not specifically developed for game makers. However, oF's ability to port to mobile, manipulate video, utilize camera input, support generative graphics, and hook in with devices like Arduino and Kinect (among other features) makes it a very attractive option for developers who want to be able to rapidly produce compelling, unique games. +Game developers are, in greater and greater numbers, turning to openFrameworks’ creative coding toolkit to develop their games. Unlike platforms such as Unity, GameMaker, and Construct2, OF was not specifically developed for game makers. However, OF’s ability to port to mobile, manipulate video, utilize camera input, support generative graphics, and hook in with devices like Arduino and Kinect (among other features) makes it a very attractive option for developers who want to be able to rapidly produce compelling, unique games. -###Popular games in open frameworks +###Popular games made with openFrameworks ![Spell Tower by Zach Gage](images/RushModeSm.png "Spell Tower by Zach Gage") @@ -14,23 +14,23 @@ Game developers are, in greater and greater numbers, turning to openFrameworks' ![Scream Em Up by Jane Friedhoff](images/screamup.png "Scream Em Up by Jane Friedhoff") -In this chapter, we'll learn about game development in openFrameworks. We'll cover what goes into making a game, as well as how to code a simple space shooter. Finally, we'll put an experimental oF twist on our game by implementing OSC functionality, which will allow you to alter the difficulty of the game live—while a player is playing it. +In this chapter, we’ll learn about game development in openFrameworks. We’ll cover what goes into making a game, as well as how to code a simple space shooter. Finally, we’ll put an experimental OF twist on our game by implementing OSC functionality, which will allow you to alter the difficulty of the game live—while a player is playing it. -Ready? Let's go! +Ready? Let’s go! ## How do game developers actually make games? -There are as many ways to make games as there are game developers. However, many developers follow an iterative process: that is, adding a single component, testing it, adding an additional component, testing it again, and so on. Regardless of the platform, this method allows game developers to quickly figure out what parts of the initial idea are worth keeping and rapidly test additions they think might be interesting--without having to risk wasting time on building out a complete game that, in retrospect, isn't compelling. +There are as many ways to make games as there are game developers. However, many developers follow an iterative process: that is, adding a single component, testing it, adding an additional component, testing it again, and so on. Regardless of the platform, this method allows game developers to quickly figure out what parts of the initial idea are worth keeping and rapidly test additions they think might be interesting--without having to risk wasting time on building out a complete game that, in retrospect, isn’t compelling. -This iterative process can be done digitally or physically. Paper prototyping is the process of testing mechanics and interactions with paper models and analogs. Although these paper prototypes don't necessarily look like the final game, they can be mocked up quickly and thrown away cheaply, allowing developers to experiment with core mechanics more rapidly than they could with code. For example, a puzzle game's board and pieces can likely be mocked up with paper and dice more quickly than it can be implemented in even a basic mobile app. When a developer makes a digital prototype, or one made with code, they will similarly typically start by refining game mechanics, keeping assets rough until they get closer to the end. Finally, developers enter the long process of tuning their game, tweaking various parameters about the game until it feels just right. +This iterative process can be done digitally or physically. Paper prototyping is the process of testing mechanics and interactions with paper models and analogs. Although these paper prototypes don’t necessarily look like the final game, they can be mocked up quickly and thrown away cheaply, allowing developers to experiment with core mechanics more rapidly than they could with code. For example, a puzzle game’s board and pieces can likely be mocked up with paper and dice more quickly than it can be implemented in even a basic mobile app. When a developer makes a digital prototype, or one made with code, they will similarly typically start by refining game mechanics, keeping assets rough until they get closer to the end. Finally, developers enter the long process of tuning their game, tweaking various parameters about the game until it feels just right. -We're going to use openFrameworks to play with the final step of this process. In the game we're making, we're not going to settle on one set of parameters that stay static from game to game. We're going to use openFrameworks' OSC library to allow us to communicate wirelessly from another device (e.g. a smartphone or table) so we can tune those parameters live, giving our players experiences tailored just for them. +We’re going to use openFrameworks to play with the final step of this process. In the game we’re making, we’re not going to settle on one set of parameters that stay static from game to game. We’re going to use openFrameworks’ OSC library to allow us to communicate wirelessly from another device (e.g. a smartphone or tablet) so we can tune those parameters live, giving our players experiences tailored just for them. ## So what is OSC, anyway? -OSC, or Open Sound Control, came about as an advancement to MIDI, so let's talk about MIDI first. MIDI is a data protocol that sends and receives information between devices, typically electronic musical instruments. MIDI is what allowed things like keyboards and drum machines to fire in sync. If you've heard pop music, you've heard MIDI in action. +OSC, or Open Sound Control, came about as an advancement to MIDI, so let’s talk about MIDI first. MIDI is a data protocol that sends and receives information between devices, typically electronic musical instruments. MIDI is what allowed things like keyboards and drum machines to fire in sync. If you’ve heard pop music, you’ve heard MIDI in action. MIDI has data channels, on which you can send or receive single messages, or events. Programmers could associate these MIDI events with actions that their electronic instruments could take. For example, you could set up your keyboard to send data on channel 1, and receive data on MIDI channel 2. More specifically, you could program a specific key (say, the 'a' key) to send out a MIDI event on channel 1. If your drum machine is set up to receive on channel 1, it will receive that message and perform the appropriate action (e.g. playing). A pretty cool system, but one that was limited by its pre-defined and discrete message types. @@ -43,13 +43,13 @@ OSC messages consist of the following: * Arguments. The actual value that is being transmitted (e.g. `6`, `"Hello world"`, etc.). There are plenty of inexpensive apps for smartphones and tablets that provide customizable GUIs (complete with buttons, sliders, etc.) for sending different kinds of MIDI messages. Download one (we like TouchOSC) so we have something to send our messages with. -With this in mind, let's start making our game! +With this in mind, let’s start making our game! ## Our basic game--& making it not-so-basic -OpenFrameworks handles OSC as an included addon, so our first step will be to run the project generator and create a project with the OSC addon. (If you haven't had a chance to read about addons, now would be a good time to jump over to [here] and do just that!) Launch the project generator, then, in the main menu, click the word "Addons." A popup will appear. Select ofxOsc and then click back. Now, next to the word Addons, you should see ofxOsc. Press "generate". When it completes the project creation process, close the generator and open up the project in either Visual Studio or Xcode. The project will be set up in your myApps folder. Open it now. +OpenFrameworks handles OSC as an included addon, so our first step will be to run the project generator and create a project with the OSC addon. (If you haven’t had a chance to read about addons, now would be a good time to jump over to [here] and do just that!) Launch the project generator, then, in the main menu, click the word "Addons." A popup will appear. Select ofxOsc and then click back. Now, next to the word Addons, you should see ofxOsc. Press "generate". When it completes the project creation process, close the generator and open up the project in either Visual Studio or Xcode. The project will be set up in your myApps folder. Open it now. -Here's what our game will have: +Here’s what our game will have: * A player, who has an on-screen position, a movement speed, and an image to represent it * Some enemies, who have an on-screen position, a movement speed (with the horizontal value based on a sine wave), an image to represent them, and an interval to keep track of when they can shoot next @@ -61,7 +61,7 @@ Here's what our game will have: 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 horizontal movement of our enemies--whether they move in a more exaggerated sine wave, or whether they move in more of a straight line * The frequency with which our enemies shoot * The frequency with which our level controller spawn enemies * Whether a life bonus is on screen or not @@ -72,7 +72,7 @@ Let’s start with our testApp. There are a few things we definitely know we’l ###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 `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; @@ -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). @@ -303,7 +303,7 @@ 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) -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`. +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`. 
 For now, our `update_bullets()` function will call the `update()` function in each bullet, and will also get rid of bullets that have flown offscreen in either direction. @@ -384,7 +384,7 @@ Remember, the first parameter in the bullet’s setup is whether it comes from t ###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 @@ -437,7 +437,7 @@ 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`: @@ -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 //-------------------------------------------------------------- @@ -541,9 +541,9 @@ void testApp::update_bullets() { } ``` -###Our game's brain +###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 @@ -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: @@ -733,10 +733,10 @@ void testApp::draw(){ } ``` -###Let's get visual +###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: @@ -751,7 +751,7 @@ void testApp::setup(){ } ``` -Draw them in the appropriate game states using `start_screen.draw(0, 0);` and `end_screen.draw(0, 0);`. +Draw them in the appropriate game states using `start_screen.draw(0, 0)` and `end_screen.draw(0, 0)`. Add in the last two functions: @@ -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. +###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 TouchOSC 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.* +*TouchOSC 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 inline with 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 Wi-Fi 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 matter 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 iOS and Android devices on both Windows and Mac, this tool will become indispensable 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 both your computer and your mobile device. If you are on a Mac, just open up your System Preferences. Go to the Network setting and click on your Wi-Fi 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 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,9 +847,9 @@ 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 LAN 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 IP address 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`. +At this point, go ahead and launch TouchOSC on your device and the TouchOSC 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 running, 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`. We are going to make this interface now and deploy it to our phone. We will make this interface to control these parameters in our game: @@ -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 `Rotary H`. Next make two `Label H` 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. @@ -877,12 +877,12 @@ The last thing to set up will be the bottom label to display what our interval v ![](images/updatedValsinterval.png) -This is the pattern we are going to use for all of our knobs and labels. Essentially, the pattern is +This is the pattern we are going to use for all of our knobs and labels. Essentially, the pattern is: * Create 3 interface elements for each parameter * A label for the name of the parameter you will be controlling * An interface element like a knob to change it with - * An output label to display the current in game variable setting + * An output label to display the current in-game variable setting Do this now for the other two knobs. The settings are below for each one. @@ -914,7 +914,7 @@ Do this now for the other two knobs. The settings are below for each one. **Set 4** -We are going to add one more but this one will be a Push Button verses a RotaryH. Right click to create it just like the knob. Make that now and 2 labels. Here are the settings: +We are going to add one more but this one will be a `Push Button` versus a `Rotary H`. Right click to create it just like the knob. Make that now and 2 labels. Here are the settings: * Label H * Color: Pink @@ -925,11 +925,11 @@ We are going to add one more but this one will be a Push Button verses a RotaryH * From: 0 To: 1 * Label H * Color: Pink - * OSC: /updatedVals/triggerBouns + * OSC: /updatedVals/triggerBonus -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 TouchOSC. 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` +This is when we need the network address of your computer we retrieved earlier. Under Connections `OSC:`, set it to the IP address 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: @@ -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" @@ -954,29 +954,29 @@ Finally, TouchOSC is set up. Let’s link it to our game and run our very first LiveTesting::LiveTesting(){ sender.setup("192.168.0.11", 8000); - //this is the ip address of your ipad/android and the port it should be + //this is the IP address of your iOS/Android device and the port it should be //set to receive on receiver.setup(8001); - /*this is the port you're game will receive data on. + /*this is the port your game will receive data on. For us this is the important one! Set your mobile device to send on this port.*/ m.setAddress("/game"); - /*This is OSC's URL like naming convention. You can use a root url address like + /*This is OSC’s URL like naming convention. You can use a root URL address like structure and then everything under that address will be accessible by that message. - It's very similar to a folder path on your hard drive. You can think of the + It’s very similar to a folder path on your hard drive. You can think of the game folder as your root directory and all the bits that are /game/someOtherName are inside of it.*/ } ``` -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 outgoing 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 mobile device 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 device 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. +Each time we make a change on our device, it will send over the updates to our code via TouchOSC. 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. ```cpp while (receiver.hasWaitingMessages()) { @@ -986,7 +986,7 @@ Each time we make a change on our device, it will send over the updates to our c ``` -Every incoming message will come with its own unique address tag and new arguments. You can get access to a message's address via the getAddress function. For example,`if(m.getAddress() == "/game/max_enemy_amplitude")`, will test to see if the message address is /game/max_enemy_amplitude. If it is, set the variable equal to that value in your game's codebase and they are linked together. Every swipe of the knob will translate to direct changes in your game. We do this for every single value we want to set. +Every incoming message will come with its own unique address tag and new arguments. You can get access to a message’s address via the getAddress function. For example,`if(m.getAddress() == "/game/max_enemy_amplitude")`, will test to see if the message address is /game/max_enemy_amplitude. If it is, set the variable equal to that value in your game’s codebase and they are linked together. Every swipe of the knob will translate to direct changes in your game. We do this for every single value we want to set. ```cpp if(m.getAddress() == "/game/max_enemy_amplitude") @@ -1004,11 +1004,11 @@ Every incoming message will come with its own unique address tag and new argumen ``` -At the same time, we are also going to send those exact same values back out to our device so we can see the numbers that the settings in our game are currently at. This is handy for two reasons. One, you get visual feedback of the current variables values' on your device. Two, if you happen to land on settings that feel right in your game, you can take a screen cap on your device. After stopping the game, go back and change the variables to match in your code and the next time you run your program, it will start with those parameters. +At the same time, we are also going to send those exact same values back out to our device so we can see the numbers that the settings in our game are currently at. This is handy for two reasons. One, you get visual feedback of the current variables values’ on your device. Two, if you happen to land on settings that feel right in your game, you can take a screen capture on your device. After stopping the game, go back and change the variables to match in your code and the next time you run your program, it will start with those parameters. To pack up all of the values in our current running game and send them back to the device every frame we will create a variable of type `ofxOscMessage` called `sendBack`. When we have a string match for the address in the `ofxOscMessage m`, we just copy the arguments over to `sendBack` via the right function (in this case usually `addFloatArg`) and set the address pattern using the `setAddress` function. Finally, we use the built in `sendMessage` function to send the message out over OSC. -Here's the complete code to add to your LiveTesting.cpp file +Here’s the complete code to add to your LiveTesting.cpp file ```cpp void LiveTesting::update() @@ -1017,7 +1017,7 @@ void LiveTesting::update() while (receiver.hasWaitingMessages()) { //get the message, which will hold all of our arguments inside of it. - //It's a collection of data! + //It’s a collection of data! ofxOscMessage m; //pass a reference to that message to the receiver @@ -1028,13 +1028,13 @@ void LiveTesting::update() //this will be the message we send back from our game //to our device letting it know what value we received //from it and displaying that back to us so we know what our - //current game setting are at + //current game settings are at ofxOscMessage sendBack; - //remember or address tags are unique. + //remember our address tags are unique. //we set up the /game tag as our root address and each / denotes a sub tag - //if theses strings are a match, we know the message that came in is our + //if these strings are a match, we know the message that came in is our //amplitude if(m.getAddress() == "/game/max_enemy_amplitude") @@ -1063,7 +1063,7 @@ void LiveTesting::update() { //this is exactly the same as above. //We just simply are testing to see if the address - //tag is this value and if so doing the exact + //tag is this value and if so doing the exact same //process of setting our ingame value to match the value of the //incoming argument and sending back our interval_time to our device. @@ -1087,7 +1087,7 @@ void LiveTesting::update() } else if (m.getAddress() == "/game/triggerBonus") { - //and finally we rap it up this is last test. + //and finally we wrap it up in this last test. triggerBonus = m.getArgAsInt32(0); cout << triggerBonus << endl; //send visual feedback @@ -1103,9 +1103,9 @@ void LiveTesting::update() You have reached the end of the tutorial. Now do a real testing session. Run the game and have a friend play it while you change the knobs. Once you have settings you like, quit the game and add those values into the code to make them permanent updates. For a bonus challenge, find a few settings you like, and create a difficulty ramp for game using those values of time. - -###Resouces -We've reached the end of the chapter but not the end of the journey. A few great resources for independent games scene are listed here: +**[ TNT The directions for the bonus challenge seem unclear. ]** +###Resources +We’ve reached the end of the chapter but not the end of the journey. A few great resources for independent games scene are listed here: [Come Out And Play](http://www.comeoutandplay.org/) [Kill Screen](http://killscreendaily.com/) [Indiecade](http://www.indiecade.com) @@ -1119,7 +1119,7 @@ We've reached the end of the chapter but not the end of the journey. A few great [Different Games](http://www.differentgames.org/) ###About us -This chapter was written by two members of the [Code Liberation Foundation](http://www.codeliberation.org), [Phoenix Perry](http://www.phoenixperry.com) and [Jane Friedhoff](janefriedhoff.com). This organization teaches women to program games for free. Featuring game art by Loren Bednar. We build community, create a safe spaces for women who want to learn to program in a non-male dominated setting and generally rock. +This chapter was written by two members of the [Code Liberation Foundation](http://www.codeliberation.org), [Phoenix Perry](http://www.phoenixperry.com) and [Jane Friedhoff](janefriedhoff.com). This organization teaches women to program games for free. Featuring game art by Loren Bednar. We build community, create safe spaces for women who want to learn to program in a non-male dominated setting and generally rock. ![](images/clfTwitter.png)