OUYA Game Development by Example Beginner's Guide (2014)
Chapter 5. Enhancing Your Game with Touch Dynamics
In the previous chapter, Chapter 4, Moving Your Player with Controller Input, you learned how to capture basic input from the player and enable them to navigate the game world with both the keyboard and the OUYA controller. Methods of processing input as well as everything else you've learned in this book so far are techniques that aren't just applicable to OUYA games; game logic such as player input and cameras are present in every game, and Unity projects can be deployed to many more platforms other than Android, such as iOS, Windows, OS X, and BlackBerry. However, certain features exist exclusively in the OUYA API that you can program to make full use of the console, as you'll discover in this chapter.
One of the OUYA's unique features is the touchpad on all OUYA controllers. By default, the touchpad functions as a basic mouse cursor that can be moved around the screen by dragging a finger across the touchpad surface. This is available automatically in any OUYA game even if you don't program it, but you can add scripts to your game that override this function and use the touch data to add special mechanics to your game.
In this chapter, we'll cover the following topics:
· Using the touchpad to interact with buttons
· Using cursor data to add touch input to games
· Incorporating touch data into your mechanics
Using the touchpad to interact with buttons
To get a good feel of how the OUYA touchpad works, we'll begin by utilizing its most simple functionality: clicking on the GUI buttons. We'll create and expand on a cannonball game prototype throughout the chapter, creating a clickable button to fire a cannonball and eventually overriding the touch functionality to calculate the power and angle based on a swipe gesture.
Creating the cannonball prototype
The goal of our cannonball game will be to hit a target on the other side of the screen by applying a variable force to the cannon prefab. Before we implement touch functionality, we have to create the cannon itself.
Time for action – creating a cannon prefab
Perform the following steps to create a cannon prefab:
1. Create a new Unity project titled TouchCannon.
You're probably used to setting up scenes at this point, so we'll start by quickly establishing the base elements we need.
2. Import your OUYA Core package into the Unity scene.
3. Set the project to Android from a standalone, and make sure your player settings match the settings we went over in Chapter 2, Installing Unity and the OUYA ODK. We need to actually deploy to the OUYA to test this prototype because it relies on the OUYA controller's touchpad.
4. Create a new plane positioned at 0, 0, 0 and increase its X scale to 10 because we want the cannon and target to be on opposite ends of a horizontal platform.
5. Create a directional light with default settings—you may recall that positions of directional lights is irrelevant, so you can put it wherever you like.
6. Finally, position the main camera at 0, 10, -25 so that the entire platform is in view from above.
After you've done all of this, your game screen should look similar to the following screenshot:
7. Now's a good time to save your scene. Create a Scenes folder in your Assets directory and save this scene as game.unity.
Next, we'll create the cannon prefab that we'll eventually code to receive the touch input. So far, we've only used primitive objects in our prototypes, but we want this prefab to be a discernible cannon, so we'll combine some basic shapes and link them all together to make a more complex model.
8. Start by creating a basic cube that will serve as the root object. As it's the center of the cannon, scale it up to twice its original size to make sure it isn't too small.
9. Next, create a basic cylinder and use the Move tool to position it within the cube, pointing out at an angle, as shown in the following screenshot:
10. Once you're happy with the position of the cylinder, find it in the Hierarchy window, hold left-click over it, and drag it onto the root cube in the hierarchy.
When you release the left-mouse button, the cylinder will become a child of the root cube, which means the cylinder position, movement, and rotation are locked to that cube. You've effectively combined the cylinder and the cube to be a single object, using the cube as a root.
Here's a chance to let your artistic side shine; you can link any number of primitive shapes to the root cube to make your cannon look exactly how you want, and as long as they're all added to the cube object in the hierarchy, they'll act as one.
11. Add some other objects to the cube to make the cannon look nice as the focus of your prototype.
When you turn your object into a prefab, all of your positioned objects will be saved, so you don't have to worry about adding meticulous details to your cannon more than once. After adding some basic shapes, your cannon will begin to take a clear form, as shown in the following screenshot:
Obviously, models in final games aren't made of primitive shapes; 3D modeling software allows game artists to manipulate faces, vertices, and edges of complex meshes to create realistic and stylized game objects. While programming and prototyping, you won't need fancy models, but before publishing a game on the OUYA marketplace, you may consider taking up modeling or partnering up with a 3D artist to really make your game pop.
If you want to get into 3D modeling but don't want to buy software just yet, check out Blender at blender.org. It's a free, open source modeling software that can export models that can be imported into Unity. The Blender community also offers several tutorials and resources for beginners.
The last step to finishing our cannon is to link it to a prefab.
12. Create a new folder called Prefabs in your Assets directory and right-click on it to access the Create menu.
13. Create a new prefab called Cannon and drag your cannon object from the hierarchy onto it to complete the prefab link.
The root object's name will turn blue in the hierarchy, and you'll now be able to create as many cannons as you want by dragging the Cannon prefab onto the scene. You can even delete the original object and create a fresh one from the prefab if you want.
14. Once you're finished, position your cannon at -20, 1, 0 so that it lies on the left-hand side of the platform in the game window.
What just happened?
You've added multiple scripts to prefabs in previous tutorials, and now you've added multiple physical objects as well. The more complex a prefab becomes, the more its value becomes apparent. Combining primitives in prefabs is a great way to get the game's tone across to anyone who sees it in an unfinished state, when you may be waiting on final 3D models or iterating visual styles. Whether you're demoing it for a friend or pitching it to a potential investor, a little bit of visual polish goes a long way, regardless of how good your code is.
Time for action – creating an interactive button
Now that you've created a cannon prefab, we can start writing scripts for it that use the OUYA controller's touchpad. The first functionality we'll add is an interactive button that makes the cannon fire a cannonball when it's tapped. Perform the following steps to add an interactive button:
1. Create a new script named CannonScript.cs in your Code folder and attach it to your Cannon prefab.
2. Open CannonScript.cs in your code editor.
3. Declare the following variables at the top of the CannonScript class definition, just before the Start function:
4. private int buttonWidth;
5. private int buttonHeight;
6. private string buttonText;
8. void Start()
11. Initialize each variable with values for our new button in the Start function. Give the button a width of 100, a height of 50, and a "Fire!" text label, as shown in the following code:
12.Private int buttonWidth;
13.private int buttonHeight;
14.private string buttonText;
18. buttonWidth = 100;
19. buttonHeight = 50;
20. buttonText = "Fire!";
The button we're going to create will be a part of our Graphical User Interface (GUI), so we'll add a function definition to extend Unity's built-in OnGUI function. The OnGUI function is run for every frame, much like the Update function, but it is run specifically when Unity is rendering 2D user interface elements.
21. Add OnGUI directly below your Update function, as shown in the following code:
30. Insert the following lines into the OnGUI function to display a button with your preset properties:
33. if(GUI.Button(new Rect(Screen.width / 2 – buttonWidth /2, 0, buttonWidth, buttonHeight), buttonText))
35. //code to run when button is pressed goes here
The GUI.Button function can create a default button with minimal parameters, requiring only a position, width, height, and text.
The first parameter of our button's rectangle, Screen.width / 2 – buttonWidth / 2, positions our button in the direct horizontal center of the screen. Screen.width / 2 produces a coordinate in the middle of the screen, and subtracting buttonWidth / 2 accounts for the offset of the button's upper-left anchor. The second parameter is the vertical position, which we left at 0, so it will appear to be at the very top of the screen.
If you're having trouble seeing your GUI element on your TV but not in the Unity editor, it may be hidden by the TV's overscan. You can fix this by setting the Y value slightly higher, depending on how much overscan your TV has; try a value of 0.1 or 0.2. We'll get into the details of compensating for overscan in a later chapter.
37. Verify that your button is drawn correctly by pressing the play button in the Unity editor.
Your button should be displayed in the top-center section of the screen, as shown in the following screenshot:
Now that the button is displayed properly, we can script code so that it can be run whenever it's pressed. We want the cannon to fire a new cannonball every time the code is called, so first, we'll need to create a cannonball prefab.
38. Create a new sphere from the Create menu in the Hierarchy window.
39. Create a new material called CannonballMat in your Project window, color it black with a specular shader, and drag it on to the sphere to apply it.
Your sphere with the shiny black material applied should now look enough like a cannonball, as shown in the following screenshot:
40. Create a new prefab called Cannonball in the Prefabs folder.
41. Link the sphere to your Cannonball prefab by clicking-and-dragging it from the Hierarchy window to the prefab in the Project window.
42. Delete the sphere you created as the base for the cannonball; we can create as many cannonballs as we want with our prefab, and there's no reason to have a cannonball hanging around in our scene.
The only thing our cannonball needs now is a rigidbody component so that it can behave like a physical object.
43. Left-click on the Cannonball prefab in the Project window to display it in the Inspector menu.
44. Click on the Add Component button, select the Physics menu, and click on Rigidbody to add a rigidbody component to the Cannonball prefab.
Our cannonball is complete, and we're ready to incorporate it into our script.
45. Declare a public GameObject variable called cannonballPrefab next to your other variables in the CannonScript class, as shown in the following code:
46.private int buttonWidth;
47.private int buttonHeight;
48.private string buttonText;
public GameObject cannonballPrefab;
49. Link the Cannonball prefab to the new variable by dragging the prefab onto the new public CannonballPrefab field in the cannon's Inspector window.
When the prefab has been properly linked, your CannonScript component should look like the following screenshot in the Inspector window:
The cannonballPrefab variable will allow our CannonScript code to create a new instance of the cannonball every time the button is pressed.
50. Create a new function called FireCannon in your CannonScript class:
54. Create a variable of type Vector3 for the new cannonball's position and initialize it with the cannon's position as shown in the following code:
57. Vector3 cannonballPos = gameObject.transform.position;
58. Offset the cannonball's position from the cannon's position by adjusting the x and y values as shown:
61. Vector3 cannonballPos = gameObject.transform.position;
62. cannonballPos.x += 2;
63. cannonballPos.y += 2;
64. Add a line that instantiates a new cannonball at our newly created location:
67. Vector3 cannonballPos = gameObject.transform.position;
68. cannonballPos.x += 2;
69. cannonballPos.y += 2;
71. Instantiate(cannonballPrefab, cannonballPos, Quaternion.identity);
The rotation argument for our call to Instantiate, which we set as Quaternion.identity, is basically the rotational equivalent of zero, or the object's default rotation. As we don't care how the object is rotated when it's instantiated (especially because the rotation doesn't affect the appearance or trajectory of spheres), using Quaternion.identity is fine for this instantiation.
72. Finally, add a call to your FireCannon function to your button statement in OnGUI as shown:
75. if(GUI.Button(new Rect(Screen.width / 2 – buttonWidth / 2, 0,
76. buttonWidth, buttonHeight), buttonText))
78. //code to run when button is pressed goes here
Our cannon is now capable of firing cannonballs whenever the Fire! button is pressed.
81. Click on Build & Run in the File menu to deploy your prototype to the OUYA console.
82. Test your new firing functionality by moving the touch cursor over the new button and tapping it.
You'll notice that as we haven't coded a physical force on the cannonballs yet, they just fall out of the cannon when they're instantiated:
The next step will be to add a force to these cannonballs at the moment of instantiation so that we can make them really fly.
What just happened?
You just created a button that can instantiate a new cannonball at our cannon's location with a click or a touch. Unity interprets OUYA's default touchpad cursor in the same way that it interprets a mouse on a computer, so no additional coding was needed to make the button compatible with both the PC and the OUYA cursor inputs.
The OUYA touchpad cursor can be moved by dragging a finger across the touchpad on the controller, and a "click" is performed simply by tapping a finger on the face of the touchpad. This basic functionality is all built into Unity, but we'll push the touchpad's capabilities even further later on in the chapter when we add swipe gestures. Before we do that, however, we need to give our cannonballs some force.
Time for action – adding an impulse force to a rigidbody component
Force can be applied to any GameObject variable that has a rigidbody component using Unity's AddForce function. In the case of our cannonballs, we want to add force to them as soon as they're instantiated; so in this section, we'll be editing our FireCannon function to include an additional force on any new cannonballs.
To change the properties of an instantiated prefab, we need a variable linked to it. Fortunately, Unity's Instantiate function returns the instantiated prefab, so we can store that in a new local variable in our FireCannon function. Perform the following steps to add an impulse:
1. Modify the call to Instantiate in your FireCannon function to store the return value in a new GameObject:
2. void FireCannon()
4. Vector3 cannonballPos = gameObject.transform.position;
5. cannonballPos.x += 2;
6. cannonballPos.y += 2;
8. GameObject newCannonball = (GameObject)Instantiate(cannonballPrefab, cannonballPos, Quaternion.identity);
Note that in addition to declaring a new GameObject variable, we also wrote GameObject in parentheses before the Instantiate function call. This is called typecasting, and essentially, it just tells the function what we're expecting to receive from it, even if that function doesn't explicitly return that type by default. A lot of function returns don't need to be typecasted, but Instantiate can return a lot of different general information that doesn't only apply to GameObject variables, so we explicitly typecasted the return asGameObject so that it can be manipulated like one. Now that we have a GameObject variable that points to our newly instantiated cannonball, we can manipulate its properties even after it's instantiated.
9. Add the following line to your FireCannon function to give the cannonball some initial force in the direction of the cannon's barrel:
12. Vector3 cannonballPos = gameObject.transform.position;
13. cannonballPos.x += 2;
14. cannonballPos.y += 2;
16. GameObject newCannonball = (GameObject)Instantiate(cannonballPrefab, cannonballPos, Quaternion.identity);
18. newCannonball.rigidbody.AddForce(12.5f, 12.5f, 0f, ForceMode.Impulse);
There are several different parameter sets that can be passed into AddForce depending on what you're trying to do, but for our purposes, we used the one that takes three positional values and a ForceMode class. The first three values refer to the x, y, and zcoordinate values, respectively, and ForceMode is a Unity class that lets you define how the force is applied. The four different ForceMode options are listed in the following table:
This is the most basic ForceMode option. It is typically used when applying a continuous force such as a push or pull. Mass is considered in this equation.
Similar to Force, this adds a constant acceleration to an object, but it does not take the mass of the object into account. This would be used to simulate physics equations that don't rely on mass, such as Earth's gravitational pull.
This adds an immediate force to an object over the course of one frame, taking the mass of the object into consideration. This is used in forces that represent an impact, such as an object being fired or an instantaneous motion.
This instantly adjusts the object's velocity without regarding mass. This can be used in the same cases as an impulse force where the mass of the object doesn't matter.
We used Impulse because a cannonball being fired from a cannon is most closely related to an instantaneous and powerful force that doesn't maintain itself after the initial impact.
19. Test your new code by starting the game and pressing the Fire! button again, either in the Unity editor or by deploying it to the OUYA.
You'll see that your cannonballs now fly horizontally across the scene whenever you click on the Fire! button, as shown in the following screenshot:
What just happened?
You've now integrated the basic touch functionality into your cannon's firing mechanic using the OUYA controller's touchpad or a mouse to call the FireCannon function. However, touch controls don't stop at buttons; clicking/tapping is only the most basic of several ways you can make your game more unique with non-standard controls.
Next, we'll explore another one of these techniques by writing code that collects the cursor's position over several frames and uses it to analyze gestures such as swiping.
Using cursor data to add touch input to games
Gesture touch controls have become increasingly popular with the presence of mobile touchscreen devices, and even though there aren't any gestures built in to the OUYA SDK, the idea behind them is simple enough that we can code a solution ourselves.
Essentially, every touch gesture has a start point, an end point, and a speed at which the player's finger moves between them. In this section, we'll create variables for this data and create a function that fires a cannonball with a speed and angle based on a touch gesture.
Time for action – reading mouse position in Unity
To begin, we'll create a GUI object that displays the x and y coordinates of our mouse as we move it. We'll be able to observe the range and current position of the mouse, which we can then use to write a gesture function. Perform the following steps to read mouse position:
1. Open the Create menu in the Hierarchy window and select GUI Text to create a new text object.
2. Your default GUI Text object will appear as shown in the following screenshot:
We don't want this text to obscure our game at all, so we'll reposition it to stay in the upper-left corner of the screen.
3. Click on the GUI Text object in the Hierarchy window to display it in the Inspector window.
4. Change the X and Y values of the GUI Text object's Transform component to 0 and 1, respectively.
5. Change the color of the text in the object by selecting a new color from the Color field in the GUIText component.
After performing the previous two steps, your GUI Text object should appear as shown in the following screenshot in the Inspector window:
Next, we need to script the actual text to display on the object.
6. Create a new script called MousePositionText.cs and open it in your code editor.
7. Add the following line to the script's Update function:
8. void Update()
10. gameObject.guiText.text = "X: " + Input.mousePosition.x + " Y: " + Input.mousePosition.y;
Wondering why we're using the addition operator (+) when coding the text to display? In the context of text, or strings, the addition operator can be used to link multiple pieces of text together from one end to another. Unity can convert many simple data types into a string value, so we can use the x and y coordinates of the mouse position as dynamic text and tie it all together using the addition operator.
11. Click on play in the Unity editor and move your mouse around the screen to see your mouse position text update.
The text will update every time the Update function is run (for every frame), and it will display your mouse position data as shown in the following screenshot:
If you aren't testing the game in fullscreen, keep in mind that the mouse position data will reflect the position of your mouse on the monitor, not just inside the Game view. However, this is something we'll never have to consider in code because games are always displayed in fullscreen on the OUYA.
What just happened?
You've now created a dynamic text object that displays the coordinates of your cursor on the screen. We haven't done anything with that data yet, but it's always a good idea to create text to visualize the data before or during your implementation. This is commonly referred to as debug text because it helps programmers conceptualize and debug their mechanics, but is not included in the game's final interface.
Next, we'll start saving the values displayed into variables so that we can use them in our velocity and angle calculations.
Time for action – creating a vector from cursor movement
Our cannonballs are propelled by an initial force that we create using the X and Y elements of the AddForce vector. Up until this point, the two values were set at a constant value of 12.5, creating the same velocity and angle each time.
In this section, we'll use the change in the X and Y values from our cursor to affect the dynamic X and Y values in our firing function so that the velocity and angle are affected by the way the cursor is moved. Perform the following steps to create the vector:
1. Declare two new float variables called mouseX and mouseY next to the other variables in your CannonScript.cs file as shown:
2. private int buttonWidth;
3. private int buttonHeight;
4. private string buttonText;
5. public GameObject cannonballPrefab;
7. private float mouseX;
private float mouseY;
8. Create a new function called CaptureTouch in CannonScript.cs using the following code:
9. void CaptureTouch()
As swipe gestures happen over multiple frames of our game, we need to be able to capture the touch data for every frame.
12. Add a call to CaptureTouch in the Update function as shown in the following code:
16. Add the following lines to CaptureTouch to store the cursor's x and y coordinates in your new variables:
19. mouseX = Input.mousePosition.x;
20. mouseY = Input.mousePosition.y;
As we need to capture cursor data for every frame, it would be inefficient to act on the data if it hasn't changed or isn't being used.
21. Add a statement that checks whether the mouse position has changed since the last frame and return from the function if it hasn't. Make sure that you keep the assignments to mouseX and mouseY at the very end of the function because we don't want to synchronize the values until we get the difference between them.
24. if(mouseX == Input.mousePosition.x && mouseY == Input.mousePosition.y)
27. mouseX = Input.mousePosition.x;
28. mouseY = Input.mousePosition.y;
Writing a single-line statement in the body of a function that returns if certain conditions are met (or not met) is called an early return. Using this is a great way to give your processor some slack if the conditions recognize that the rest of the function is useless. Note that there are no curly braces enveloping the previous statement; for single-line statements, you can simply write the line to be run directly after the if statement. However, if you wanted to expand the conditional functionality to run multiple lines, you would need to insert brackets like we've done in our other conditional statements.
If the statement does not trigger a return, we can assume that the mouse is currently in motion. The next step is to measure the distance that the cursor has traveled by subtracting the current distance from the previous distance.
29. Create the following temporary variables inside your CaptureTouch function and initialize them as shown:
32. if(mouseX == Input.mousePosition.x && mouseY == Input.mousePosition.y)
35. float deltaX = Input.mousePosition.x - mouseX;
36. float deltaY = Input.mousePosition.y - mouseY;
38. mouseX = Input.mousePosition.x;
39. mouseY = Input.mousePosition.y;
The term delta refers to a value of change, so we named our new variables deltaX and deltaY to reflect the change in their respective coordinates. You may remember using a value called Time.deltaTime in Chapter 4, Moving Your Player with Controller Input; this is another value of change, representing the amount of time that has passed since the last frame.
We've got the changed values that we'll use to fire our cannon, but currently we don't have a firing function that takes any parameters. Create a new FireCannon function below your current FireCannon function that takes two float values as shown:
void FireCannon(float xForce, float yForce)
Your code can contain multiple functions of the same name, but only if they have different parameters. This is called function overloading. You can use this to your advantage as a developer. By creating a function that can handle all different kinds of parameters, you enable that function to be called with one of many inputs without the need to typecast.
Define your new FireCannon function in the same way as your old one, but with the xForce and yForce variables taking the place of the 12.5 constant force value:
void FireCannon(float xForce, float yForce)
Vector3 cannonballPos = gameObject.transform.position;
cannonballPos.x += 2;
cannonballPos.y += 2;
GameObject newCannonball = (GameObject)Instantiate(cannonballPrefab, cannonballPos, Quaternion.identity);
newCannonball.rigidbody.AddForce(xForce, yForce, 0f, ForceMode.Impulse);
Now add a line to your CaptureTouch function that calls FireCannon with the cursor delta values:
float deltaX = Input.mousePosition.x - mouseX;
float deltaY = Input.mousePosition.y - mouseY;
mouseX = Input.mousePosition.x;
mouseY = Input.mousePosition.y;
Your code is almost ready to test, but we're missing one thing. Right now, FireCannon is called every time there's a change in mouse position, even if the change is part of the same swipe from a different frame. We don't want to instantiate multiple cannonballs on a single swipe, so we'll add a boolean value that ignores the CaptureTouch function if we're in the middle of a swipe.
40. Create a boolean variable called isSwiping next to your other variables and initialize it as false as shown in the following code:
42.private float mouseX;
43.private float mouseY;
private bool isSwiping = false;
45. Add another early return to your CaptureTouch function that exits if a swipe is being made:
48. if(mouseX == Input.mousePosition.x && mouseY == Input.mousePosition.y)
51.//exit the function if a swipe is being made
52. if(isSwiping == true)
54. We need to mark the isSwiping variable as true every time a cannonball is being fired, so add a line that sets isSwiping to true if the cursor is moved while isSwiping is false:
58. //exit the function if a swipe is being made
59. if(isSwiping == true)
61. mouseX = Input.mousePosition.x;
62. mouseY = Input.mousePosition.y;
66. isSwiping = true;
Note that we capture the cursor values even if a swipe is in progress because we still need to check their state in the next frame.
Finally, we need to set isSwiping to false if the mouse isn't moving, so add a line to your first early return that checks the change in the position. The following code is the full CaptureTouch function:
if(mouseX == Input.mousePosition.x && mouseY == Input.mousePosition.y)
isSwiping = false;
if(isSwiping == true)
mouseX = Input.mousePosition.x;
mouseY = Input.mousePosition.y;
isSwiping = true;
float deltaX = Input.mousePosition.x – mouseX;
float deltaY = Input.mousePosition.y – mouseY;
mouseX = Input.mousePosition.x;
mouseY = Input.mousePosition.y;
Your code is finally ready for testing and will instantiate and fire a cannonball every time the cursor is moved based on the direction of the movement.
68. Test your new mechanics by starting the game and moving the cursor.
You'll notice that the cannonballs don't have much force behind them anymore. That's because the cursor's delta values are captured for every frame, so the instantaneous change is much smaller than our original constant force value of 12.5. To remedy this, we'll multiply the delta values in the AddForce function.
69. Modify the AddForce call in your FireCannon function to multiply each of the delta values by 5 as shown:
70.void FireCannon(float xForce, float yForce)
73. newCannonball.rigidbody.AddForce(xForce * 5, yForce * 5,0f, ForceMode.Impulse);
Due to the precision of the OUYA's touchpad when using this method of touch capturing, sometimes two individual swipes are detected when only one was performed. To remedy this, we'll add a simple counter that prevents two cannonballs from being fired in a quick succession.
74. Declare the counter next to your other variables as follows:
private int fireCooldown = 0;
We'll let the cannon fire a cannonball as long as the cooldown is at zero, but we'll increase the value of fireCooldown as soon as we fire.
75. Add the following lines at the beginning and end of your FireCannon function to implement the previous logic:
76.void FireCannon(float xForce, float yForce)
78.if(fireCooldown > 0)
81.newCannonball.rigidbody.AddForce(xForce * 5, yForce * 5,0f, ForceMode.Impulse);
82.fireCooldown = 120;
We'll subtract 1 from fireCooldown for each frame until it gets back to 0. By setting it to 120 when the cannon fires, it will wait for 120 frames (about two seconds) before firing again.
83. Lastly, add the following lines to your Update function to decrease the cooldown value by 1 for each frame if it's above 0 and not ready to be fired yet:
88.if(fireCooldown > 0)
You can now test the game and see the cannonballs being fired in whatever direction the cursor is moving, even straight up:
Additionally, the faster you swipe, the farther the cannonball travels.
What just happened?
You've successfully overridden the OUYA cursor's default mouse functionality to create true touch gesture mechanics in your game. By measuring the change in the cursor position and keeping track of separate motions, you can enable your player to "touch" your game and engage them even more.
We're not completely done with our current implementation; we still need to hide the cursor that the OUYA displays by default whenever it receives a touch input.
As we base our touch data on the change in cursor position, the function will cease to work when the cursor hits a border of the screen and cannot further change its position. A future update to the OUYA SDK or Unity may enable you to reset the cursor position on the OUYA, but currently the cursor can only be manipulated on PC builds. When integrating touch into your game, try to do so in a way that won't leave your player stuck if the cursor hits a border.
Have a go hero – capturing touch input over multiple frames
In the previous section, you saw how cursor movement over one frame can affect the direction of force on a cannonball. However, as we only measured the change over one frame, the function is not very precise, and you need to move the cursor very quickly if you want a strong shot.
Use what you've learned about game scripting so far to measure cursor coordinates over multiple frames during a single touch sequence and create a function that averages out each frame's delta change to produce a more precise touch gesture. Here are a couple of tips to get you started:
· It's a smart idea to store the coordinate data collected from each frame in an array so they're all kept together.
· Hint: declare two arrays to store your X and Y coordinates over five frames, as shown in the following code:
· float deltaValuesX = new float ;
float deltaValuesY = new float ;
You can access individual values of the array by putting a bracketed index directly after the name. This is shown in the following example, which prints out the third value in the array:
Hint: to access each element of the array in succession, use a for loop that runs five times with a counter incrementing at each step, and use the counter variable to access the corresponding element. The basic structure is demonstrated in the following code in a for loop that prints the value of each element of the array:
for(int i = 0; i < 5; i++)
· Modify your CaptureTouch function so that it measures delta values even if a swipe is in progress, but make sure to stop it from measuring delta values as soon as the swipe is ended.
Incorporating touch data into your mechanics
Now that you're capturing touch data from the cursor, all that's left is to make the concept complete by turning it from a feature into a full mechanic tied to the game. In this section, we'll hide the default OUYA cursor from displaying while our user swipes to fire a cannonball to try and hit a target on the other end of the level.
Time for action – hiding the cursor on the screen
OUYA's cursor is slightly different than other components of our game in that it's displayed and managed by an unseen Java script that we didn't need to create. This code is a core part of the OUYA SDK, so we can't change it directly; instead, we need to use methods that have been included in the SDK that serve the purpose of safely modifying core functionality.
By default, the cursor appears whenever the cursor is moved, as shown in the following screenshot:
Perform the following steps to hide the cursor on the screen:
1. Create a new function called HideCursor in CursorScript.cs:
2. void HideCursor()
5. Add the following line to the HideCursor function to call the Java function that hides the cursor graphic:
6. void HideCursor()
9. Add a call to HideCursor in your Update function so that it's called for every frame:
13. Deploy your game to the OUYA console and swipe the touchpad to fire the cannon.
You'll notice that the cursor no longer appears on the screen when you move it with the touchpad.
What just happened?
The JavaShowCursor function that you called from the OuyaSDK class is only one of the many ways you can interact with the under-the-hood features of the development kit. The Unity engine can't access or control the OUYA cursor because it's handled by Java, but we can access the cursor indirectly with the ODK.
Now that our touch mechanic is fully implemented, all we need to do is create a target for the player to hit.
Time for action – creating a target for the cannon
To complete our prototype, we'll add a target for the player to attempt to hit with a cannonball and make it change color when they've successfully hit it. Perform the following steps to do so:
1. Create a new Cube from the Hierarchy window's Create menu.
2. Position the cube at 20, 5, 0 so that it's on the opposite end of the plane from the cannon and slightly higher than it.
Your cube should look as shown in the following screenshot:
We want our target cube to be a bit larger and easier to see, so we'll make a few more changes to it.
3. Increase the scale of the cube to 3, 3, 3.
4. Create a new Material, assign it a unique color, and apply it to your target by clicking-and-dragging it from the Project window to the cube in the Hierarchy window.
After making the previous changes, your target cube should look as shown in the following screenshot:
Now that our cube is a clear target, we can script it to react when a cannonball hits it. In full games, hitting a target would do something like increment a point value or load the next level, but for the purposes of our prototype, we'll just make the cube change its color to signify a successful collision.
5. Create a new script called TargetScript.cs and open it in your code editor.
6. Add a definition for Unity's built-in collision-checking function OnCollisionEnter as shown:
7. void OnCollisionEnter(Collision collidingObj)
10. Add the following line to the OnCollisionEnter function to make it turn red when a cannonball collides with it:
11.void OnCollisionEnter(Collision collidingObj)
13. gameObject.renderer.material.color = Color.red;
14. Attach TargetScript.cs to the target cube by dragging it from your Code folder in the Project window to the target cube in the Hierarchy window or the Scene view.
15. Run your game and fire a cannon at the target until you hit it to observe the new collision functionality.
Once a cannonball hits the target, it will immediately change color to denote a collision, as shown in the following screenshot:
What just happened?
Congratulations, your touch prototype is complete! You've successfully used the basic and advanced touch inputs to make your game more than just a simple button-and-joystick game. Try exploring the touch functionality to make it more robust and precise; the menu and button controls with the touchpad will do your game well, but defining a library of touch gestures in your code base goes above and beyond what is provided to you to work with in the OUYA SDK and will impress your players no end.
Feel free to keep exploring with the cannon prototype and see how far you can push the touch capabilities, but don't edit the core features of the project too much; we'll be returning to this prototype in Chapter 7, Expanding Your Gameplay with In-App Purchases, where we'll create different classes of cannonballs that all behave uniquely.
Pop quiz – touching the sky
Q1. How does the touchpad behave by default?
1. A graphical cursor with a menu-clicking ability
2. It doesn't, additional code is required to implement it
3. An invisible touch input reader
Q2. Which of the following restricts advanced touch coding with delta values for OUYA in Unity?
1. Java/C# compatibility
2. Screen borders
3. Always-present graphical cursor
Q3. How can you manipulate parts of the OUYA platform that Unity can't access?
1. Edit the SDK directly
2. You cannot
3. Use external code wrappers provided in the SDK
Now that you've acquired a taste for the capabilities of touch in OUYA games, you can start creating games that diverge from common controller-based games that don't feature touch such as Xbox 360 and PlayStation 3 games. You've also learned more about manipulating data in both the Unity engine and the OUYA SDK, which can help you create solutions for complex custom systems that don't have pre-written implementations.
In the next chapter, we'll move back to our marble prototype and program a system that will allow us to save data from the game, even after it stops running.