Author Archives: Carlos Yanez

Create a Balloon Racing Game in Unity Using the Microphone

Final product image
What You'll Be Creating

Introduction

In this tutorial, you'll learn how to create a 2D game using C# and Unity. We'll be taking advantage of Unity's microphone support to enhance the gameplay of the game. The objective of the game is simple, reaching the other side of the level by avoiding the obstacles along the way. The player can move the main character by blowing on the device's microphone, moving it upwards.

You'll learn the following aspects of Unity game development in this tutorial:

  • setting up a 2D project in Unity
  • importing sprites
  • microphone controls
  • working with physics collisions

1. Create a New Unity Project

Open Unity and select New Project from the File menu to open the new project dialog. Tell Unity where you want to save the project and set the Set up defaults for: menu to 2D.

 

2. Build Settings

In the next step, you're presented with Unity's user interface. Set the project up for your preferred platform by choosing Build Settings from the File menu and selecting the target platform.

3. Unity User Interface

Before we get started, make sure the 2D button in the Scene panel is highlighted. You can also modify the current resolution in the Game panel.

You should also see Unity's workspace panels, which we'll use in this tutorial. Take a moment to explore Unity's user interface, such as the Scene, Game, Hierarchy, Project, Assets, and Inspector. We'll be using them a lot in this tutorial.

4. Game Interface

Our game's user interface is going to be straightforward. The next screenshot gives you an idea of the assets we'll be using and how the game's final user interface will end up looking. You can find the assets we'll be using in the source files on GitHub.


5. Programming Language

You can use one of three programming languages when using Unity, C#, UnityScript, a variation of JavaScript, and Boo. Each of these programming languages has its pros and cons and it's up to you to decide which one you prefer. My personal preference goes to the C# programming language and that's the language I'll be using in this tutorial.

If you decide to use another programming language, then make sure to take a look at Unity's Script Reference for examples.

6. Assets & Sound Effects

Before we start coding, we need to add the assets to the Unity project. You can do this one of several ways:

  • select Import New Asset from the Assets menu
  • add the items to the assets folder in your project
  • drag and drop the assets in the project window

After completing this step, you should see the assets in your project's Assets folder in the Project panel.

We'll use a number of sounds to create a great audial experience. The sound effects used in this tutorial were obtained from freesound.org.

7. Background

Start by dragging and dropping the background into the Hierarchy panel. It should automatically appear in the Scene panel.


8. Camera Size

Because the Scene panel is set to display a 2D view, you'll notice that selecting the Main Camera in the Hierarchy shows a preview of what the camera is going to display. You can also see this in the Game view. To make the entire scene visible, set the Size value of the Main Camera to 4 in the Inspector panel as shown below.

9. Sprite Sheet

We'll use a sprite sheet for our game's user interface elements. Unity has a sprite editor that makes using sprites a breeze. The artwork used in this tutorial was obtained from openclipart.org.

Import the artwork, select it from the Assets panel, and change the Sprite Mode option to Multiple in the Inspector panel.

Click the button labeled Sprite Editor and set the Type option to Automatic.

10. Cow Rigidbody 2D

With the sprite sheet sliced and ready to use, click the arrow that appears when the sprite sheet is selected and choose the sprite of the cow, the main character of our game. Drag it to the scene to add it.

To detect collisions, at least one of the colliding objects needs to have a Rigidbody 2D component attached to it. To add one to the cow, click the Add Component button in the Inspector panel. From the list of components, select RigidBody 2D in the Physics 2D section.

Check the Fixed Angle box to prevent the cow from rotating if a collision occurs. We won't be using the default physics gravity in this game, instead we'll simulate our own. Change the Gravity Scale from 1 to 0 to ensure the default gravity doesn't impact the object.

11. Adding Colliders

The floor is used to keep our main character from falling once we've added physics to the game. Create a new game object by selecting Create Empty from the GameObject menu.

To make the floor detect when the character is touching it, we need to add a Box Collider 2D component. A collider is a physics shape that defines the area that triggers a collision.

Select the floor game object in the Hierarchy, open the Inspector panel, and click Add Component. From the list of components, select Box Collider 2D in the Physics 2D section.

Change the Size property to X: 4.8 and Y: 0.05 to create a small rectangle where the cow will be positioned. Finally, add a Box Collider 2D to the cow game object by repeating these steps.

12. Cow Audio Source

An Audio Source component is used to play an audio clip when the player collects the star. This component will read the audio clip set in its options and play it when called from a script or at the start if the Play on Awake checkbox is selected.

To play a sound when the player collects a star, we first need to attach an Audio Source component to it. Select the star from the Hierarchy or Scene view, click the Add Component button in the Inspector panel, and select Audio Source in the Audio section.

As we only want the sound to play when the player touches the star, we need to uncheck the Play on Awake option. Click the little dot on the right, below the gear icon, to select the sound we want to play.

13. Adding Balloons

The balloons represent the lives or health of our main character. When a hand collides with the cow, it will pop one of the balloons to indicate that it was hit and the number of lives has decreased.

Drag the balloon sprite from the Assets to the Hierarchy panel and then back to the Assets. This will create a prefab of the balloon. You'll notice the text becomes blue indicating it's now a prefab. By creating a prefab, we can reuse the balloon without using additional resources.

Select the new prefab and press Command+D to duplicate it. Use the Rotation tool to slightly rotate the balloons as shown in the above screenshot.

We group the cow and balloons to make moving them a bit easier. To do this, drag a balloon from the Hierarchy panel and place it on top of the cow game object in the Hierarchy panel. The cow game object is highlighted to indicate that dropping the balloon onto it will add it as a child of the cow game object. The result is that moving the cow game object also moves the position of the balloons.

14. Adding Obstacles

The hands are the enemies or obstacles that need to be avoided if the player wants to finish the level by collecting the star. The hands move from side to side, leaving a narrow gap in the middle for the cow to pass through.

Because the hands are game objects that we'll use multiple times, we first convert it to a prefab as we did with the balloons. Follow the above steps to create the prefab and use the editor tools to position the hands as shown in the above screenshot.

We also need to add a collider to each hand to detect collisions. To add the collider, click the Add Component button in the Inspector panel and select Box Collider 2D in the Physics 2D section. You'll notice that a green box appears around the hand when you select it to indicate the hand has a collider tied to it.

We also play a sound when a hand collides with the cow, popping a balloon. To accomplish this, we first need to add the sound. Select the hand from the Hierarchy or Scene view, click the Add Component button in the Inspector panel, and select Audio Source from the Audio section.

The details of the audio component will show up in the Inspector Panel. Click the dot below the gear icon to select the correct sound.

15. Adding the Star

The goal of the game is to collect the star at the end of each level. The player can move the cow upwards by blowing on the device's microphone.

Drag the star from the Assets panel and add it to the Scene. In the Inspector's Transform section, change the values as shown in the screenshot below to position the star.

This will place the star at the top of the level. To detect when the cow collects the star, we need to add a collider to it like we've done a few times already. Add a Box Collider 2D to the star.

16. Adding Alerts

Alerts are also game objects. They are messages informing the player when the level has been completed or the game is over.

Drag the alerts from the Assets panel to the Hierarchy and then back to the Assets panel to convert them to a prefab. Later in this tutorial, we'll add a script to the alerts and show how they are used. Don't forget to delete them from the Scene once you've converted them to a prefab.

17. Adding Scripts

Unity includes a code editor, a version of Mono Develop. While it's a good editor, you can use whatever editor you like. Visual Studio, for example, is a popular choice if you're using Windows.

You can create a new file by launching your code editor, saving the file in the Assets folder of your project, and then adding it to a GameObject, just like you do with a component. Alternatively, you can create a new script in the Inspector by selecting New Script and then double-clicking it to open it.

18. Detecting Microphone Input

To move our main character, we'll need access to the device's microphone. By default, Unity provides basic support for capturing audio, but it doesn't include a property or method to detect the microphone's activity level, which is what we need to move the cow.

Fortunately, we can use a third party script that will give us access to a loudness property. The loudness property will allow us, along with transform.position, to move the cow.

Create an empty GameObject and name it MicrophoneInput. Use the Add Component button to attach the aforementioned script and an Audio Source component to the new game object.

By doing this, we enable the script and the application will start capturing the microphone's input. By adjusting the Sensitivity property in the Inspector, we control how much the cow is moved by the input of the microphone. The higher the value, the faster the cow will move. I've found that 50 is a good value to start with.

19. Moving the Hands

The following script defines the Hand class and controls the movement of the hands. The hands continuously move from left to right and vice versa. Let's see how this works.

Step 1: Properties

The first property we use in the script is moveSpeed, a float that defines the number of units a hand moves during every frame. It sets the x value of the transform.position property, moving the hand horizontally.

The second property, currentPos, is also a float and stores the current position of the hand before it moves. This will help us calculate the number of units the hand can move.

using UnityEngine;
using System.Collections;

public class Hand : MonoBehaviour
{
    private float moveSpeed = 0.02f;
    private float currentPos;
    public bool left = false;

Lastly, the left property of type boolean defines if the hand is moving to the left. This makes it easy to change the direction of a hand by setting the left variable to either true or false.

Step 2: Start Method

The Start method is a method defined in the MonoBehaviour class that is called during initialization, before any other method is called—with the exception of Awake, which we won't cover in this tutorial.

In the Start method, we can configure the object before any other code is run. In this case, we set the currentPos property to the hand's current position, before it has moved.

void Start()
{
    currentPos = transform.position.x;
}

Step 3: Change Position

In the Update method, we check if the hand is left or right, and move it in the correct direction during every frame. To do this, we write an if statement inside the Update method and decrease or increase the x position using the moveSpeed variable to modify the position property.

void Update()
{
    /* Move Hand */

    /* Move to the right if hand is on the left side */

    if (!left)
    {
        transform.position -= new Vector3(moveSpeed, 0, 0);
    } else
    {
        transform.position += new Vector3(moveSpeed, 0, 0);
    }

    /* Change moveSpeed to move in the other direction, creating a movement loop */

    if (transform.position.x <= currentPos - 0.7f)
    {
            moveSpeed *= -1;
    }
    if (transform.position.x >= currentPos + 0.7f)
    {
        moveSpeed *= -1;
    }
}
}

When the hand moves 0.7 units, we multiply the moveSpeed property by -1 to make the hand move in the opposite direction. The result is that the hands move from one side to the other in a continuous loop, making it harder for the cow to pass through the hands and reaching the star.

20. Cow Script

Create a new script and attach it to the cow game object. This script will handle the player's actions and a few other functions related to the game's mechanics, such as displaying the alerts. Let's take a look at the properties used in this script.

using UnityEngine;
using System.Collections;

public class Cow : MonoBehaviour
{
    private Vector3 gravity = new Vector3(0, 0.02f, 0);
    public GameObject micVolume;
    private float moveSpeed;
    private byte balloons = 3;
    public GameObject alertWin;
    public GameObject alertLose;
}
  • gravity: used to simulate a vertical force, it pulls the cow downwards
  • micVolume: reference to the MicrophoneInput game object
  • moveSpeed: gets the loudness value from the MicrophoneInput class
  • balloons: holds number of balloons, this value represents the player's lives
  • alertWin: reference to the alertWin game object
  • alertLose: reference to the alertLose game object

Note that public variables need to be set up in the Unity's editor. They are all references to prefabs. Setting the value of a variable in the editor is easy. Save the script and make sure there are no errors. Then switch back to Unity and select the game object to which the script is attached. You should see the variables listed below the script component as shown below.

Drag and drop the required or preferred asset to the variable, or click the little dot below the gear icon to select it.

Make sure that the asset and the variable are of the same type or you won't be able to drop it or see it when you click on the dot icon.

21. Moving the Cow

Step 1: Moving

To move the cow upwards, we'll use the FixedUpdate method. Why not the regular Update method? This method is a predefined MonoBehaviour method that runs every fixed frame rate instead of every frame. This means that it will be smooth even if the current frame rate is a little low. Add the following code block to the script:

void FixedUpdate()
{
    /* Move Cow upwards based on Mic volume */

    moveSpeed = micVolume.GetComponent<MicrophoneInput>().loudness * 0.01f;
    transform.position = new Vector3(0, transform.position.y + moveSpeed, 0);
    
    /* Simulate our own gravity (this one doesn't get stronger when high) */

    transform.position -= gravity;
}

We calculate the speed by getting the current loudness of the microphone. This loudness is obtained from the MicrophoneInput class and then multiplied by 0.01. We do this to prevent the cow from moving too fast.

The cow character is moved by increasing the y value of the transform.position property, using the speed we stored in stored in moveSpeed.

Step 2: Simulating Gravity

In addition to moving the cow, we also apply a downward force to it, the gravity. We achieve this by decreasing the position of the cow using the gravity vector we created earlier. Doing this will constantly reduce the y position of the cow without making it fall faster, which happens if we were to use the default gravity behavior.

22. Hands Collision

Step 1: Detecting Collisions

In the next step, we detect if any of the hands collide with the cow. The OnTriggerEnter2D method runs when two objects collide without physics interaction. In this case, we check if the cow collides with an object named "Hand", which can be any of the hands on the scene, and play the audio attached to the cow game object if the collision occurs. You'll notice we also inspect the cow's alpha property. Why we do this is explained in the next step.

void OnTriggerEnter2D(Collider2D other)
{
    /* Hands Collision */

    if (other.name == "Hand" && transform.GetComponent<SpriteRenderer>().color.a == 1)
    {
        other.audio.Play();

Step 2: Preventing Multiple Collisions

Collisions are tested multiple times every frame, meaning that three collisions will occur in a very short time popping all the balloons. Since we don't want this to happen, we need a way to prevent this.

A useful way to do this is to change the alpha of the hit object. This will also give the user visual feedback indicating that it has been hit. The next lines will take care of that.

/* Prevent from multiple collision */

Color alpha = new Color(1, 1, 1, 0.5f);
transform.GetComponent<SpriteRenderer>().color = alpha;
Invoke("EnableCollision", 1);

We first create a new Color object and assign it the color of the game object and set the alpha value to 0.5 to make it semi-transparent. We then access the game object SpriteRenderer, which lets us modify its color.

The last line in this block of code waits a second and then calls a the EnableCollision function. This  function resets the color values of the cow making it able to detect a collision again. We'll implement this function later in this tutorial.

23. Removing Balloons

When the cow is hit by a hand, one balloon needs to be removed. We call the Destroy method on a balloon game object. We use the Find function, because we don't have a reference to each of the balloons.

This function searches the game's assets and returns the game object that we're looking for, in this case a balloon.

/* Remove Balloon */

Destroy(GameObject.Find("Balloon"));
balloons--;

But wait, aren't there three balloons in the scene? That is correct. However, the Find function returns the first match it can find. In other words, it returns the first balloon game object it finds.

We also decrement the balloons counter to help us know when the cow has lost all its lives.

24. Game Over

The game is over when all the balloons have been popped. To test this, we check if balloons is equal to 0 and display an alert if true. We also set the gravity's y property to 0 and pause the game by setting timeScale to 0.

The timeScale property controls how time passes in the game environment. It can be used to make the game faster or slower based on its value. The default time scale is 1.0, increasing its value accelerates the frame rate associated functions and decreasing it slows them down. Setting it to 0 pauses the game, preventing any new collisions.

/* Game Over */

    if(balloons == 0)
    {
        GameObject alert = Instantiate(alertLose, new Vector3(0, 0, 0), transform.rotation) as GameObject;
        gravity.y = 0;
        Time.timeScale = 0;
    }
}

25. Level Complete

When the player gets to the other side of the level we need to remove the star and display an alert indicating that the level has been completed.

The if statement checks if the collision is in fact with the star game object and plays the audio attached to the cow if the name is correct. We then remove the star from the scene before creating the alert. We also set the gravity's y property to 0 as we did in the previous step.

/* Star Collision */

    if (other.name == "Star")
    {
        audio.Play();
        Destroy(other.gameObject);
        GameObject alert = Instantiate(alertWin, new Vector3(0, 0, 0), transform.rotation) as GameObject;
        gravity.y = 0;
    }
}

26. Enabling Collisions

The EnableCollision method resets the alpha value of the cow game object after it has been hit by a hand. Doing this will enable the cow game object to detect another hit. Note that the Color object has an alpha of 1.

void EnableCollision()
{
    Color alpha = new Color(1, 1, 1, 1);
    transform.GetComponent<SpriteRenderer>().color = alpha;
}

27. Restarting the Game

The Reload method uses the Application class to reload the current level. Create a new script named Restart , add the following code block to it, and attach it to both of the alert prefabs we created earlier.

using UnityEngine;
using System.Collections;

public class Restart : MonoBehaviour
{
    void Update()
    {
        if (Input.GetButton("Fire1"))
        {
            Reload();
        }
    }

    void Reload()
    {
        Application.LoadLevel(Application.loadedLevel);
    }
}

We first test if the user taps on the screen using the Input class and call the Reload method if true. The implementation of the Reload method is short and simple. All we do is load the current level, reseting every object and variable to its initial state.

28. Testing

It's time to test the game. Press Command-P to play the game in Unity. If everything works as expected, you are ready for the final steps.

29. Player Settings

When you're happy with your game, it's time to select Build Settings from the File menu and click the Player Settings button. This should bring up the Player Settings in the Inspector panel where you can set the parameters for your application.

These settings are application-specific and include the creator or company, application resolution, display mode, etc. These settings depend on the devices you're targeting and the stores or markets you will be publishing your game on.

30. Build and Play

Once your project is properly configured, it's time to revisit the Build Settings and click the Build button. That's all it takes to build your game for testing and/or distribution.

Conclusion

In this tutorial, we've learned how to implement microphone controls, physics interaction, sprite sheets, and other aspects of game development using Unity. I encourage you to experiment with the result and customize the game to make it your own. I hope you liked this tutorial and found it helpful.

Develop a Monkey Ball Inspired Game with Unity

Final product image
What You'll Be Creating

Introduction

In this tutorial, you'll learn how to create a mobile 3D game using C# and Unity. The objective of the game is to use the accelerometer to move the ball and reach the portal.

You will learn about the following aspects of Unity game development in this tutorial:

  • 3D Primitives
  • accelerometer controls
  • camera movement
  • physics
  • GUI Textures

1. Create a New Unity Project

Open Unity and select New Project from the File menu to open the new project dialog. Tell Unity where you want to save the project and set the Set up defaults for: menu to 3D.


2. Build Settings

In the next step, you're presented with Unity's user interface. Set the project up for mobile development by choosing Build Settings from the File menu and selecting your platform of choice.


3. Devices

The first thing we need to do after selecting the target platform is choosing the size of the artwork we'll be using in the game. This will help us select a proper size for the 3D textures and 2D GUI without making the artwork blurry or use textures that are too large for the target device. For example, the artwork needs to have a higher resolution if you're targeting an iPad with a retina display than a Lumia 520.

iOS

  • iPad without Retina: 1024px x 768px
  • iPad with Retina: 2048px x 1536px
  • 3.5" iPhone/iPod Touch without Retina: 320px x 480px
  • 3.5" iPhone/iPod with Retina: 960px x 640px
  • 4" iPhone/iPod Touch: 1136px x 640px

Android

Because Android is an open platform, there's a wide range of devices, screen resolutions, and pixel densities. A few of the more common ones are listed below.

  • Asus Nexus 7 Tablet: 800px x 1280px, 216 ppi
  • Motorola Droid X: 854px x 480px, 228 ppi
  • Samsung Galaxy SIII: 720px x 1280px, 306 ppi

Windows Phone & BlackBerry

  • Blackberry Z10: 720px x 1280px, 355 ppi
  • Nokia Lumia 520: 400px x 800px, 233 ppi
  • Nokia Lumia 1520: 1080px x 1920px, 367 ppi

Note that the code we'll write in this tutorial can be used to target any of the platforms.


4. Export Graphics

Depending on the devices you're targeting, you may need to convert the artwork to the recommended size and pixel density. You can do this in your favorite image editor. I've used the Adjust Size... function under the Tools menu in OS X's Preview application.


5. Unity User Interface

You can modify the resolution that's being displayed in the Game panel.


6. Game Interface

The interface of our game will be straightforward. The above screenshot gives you an idea of the artwork we'll be using and how the final game interface will end up looking. You can find the artwork and additional resources in the tutorial's source files on GitHub.


7. Programming Language

You can use one of three programming languages when using Unity, C#, UnityScript, a variation of JavaScript, and Boo. Each programming language has its pros and cons, and it's up to you to decide which one you prefer. My personal preference goes to the C# programming language so that's the language I'll be using in this tutorial.

If you decide to use another programming language, then make sure to take a look at Unity's Script Reference for examples.


8. Sound Effects

I'll use a number of sounds to improve the audial experience of the game. The sound effects used in this tutorial were obtained from playonloop.com and Freesound.


9. 3D Models

To create our game we first need to get our 3D models. I recommend 3docean for high quality models, textures, and more, but if you're testing or learning then a few free models are good as well. The models in this tutorial were downloaded from SketchUp 3D Warehouse where you can find a good variety of models of all kinds.

Now, as Unity doesn't recognize the SketchUp file format we need to convert it to something Unity can import. We first need to download the free version of SketchUp, which is called SketchUp Make

Open your 3D model in SketchUp Make, select Export > 3D Model from the File menu, and choose Collada (*.dae).

Choose a name and location, and click the save button. This will create a file and a folder for the 3D model. The file holds the data for the 3D object while the folder contains the model's textures. You can then import the model into Unity as explained in the next step.


10. Import Assets

Before we start coding, we need to add our assets to the Unity project. You can do this one of several ways:

  • select Import New Asset from the Assets menu
  • add the items to the assets folder in your project
  • drag and drop the assets in the project window

After completing this step, you should see the assets in your project's Assets folder in the Project panel.


11. Create Scene

We're ready to create the scene of our game by dragging objects to the Hierarchy or Scene panel. We'll also use Unity native 3D primitive objects to create the level as shown in the next steps.

12. Setup Camera

Let's first position our Main Camera a little bit higher to achieve the view we want. Select it from the Hierarchy panel and adjust the Transform values in the Inspector to match the  ones shown below.

Don't worry if you don't see any changes. We haven't created anything for the camera to see yet. Next, use the Inspector to set the Background color to RGB: 0, 139, 252.

13. Background

Our platform level will be floating above a background, which will be a representation of a sea. It will be created using Unity primitives, a simple Plane with a texture applied to it.

While Unity can work with 3D objects of any type created by other programs, it is sometimes easier and/or more convenient to use primitives for prototypes.

To create the sea, for example, select Create Other > Plane from the GameObject menu and adjust the Transform values in the Inspector to match the ones shown below.

You should a square in the Scene panel. We'll use it to detect when the player falls from the platform, ending the game.

It's worth mentioning that these primitive objects already have a Mesh Collider attached to them, which means that they will automatically detect collisions or trigger events when they come in contact with a RigidBody.

14. Texture Material

To apply a texture to the sea plane, we need to create a Material. A Material is used to define how a GameObject looks and it is essential to add a texture to a GameObject.

Select Create > Material from the Assets menu to create one, find it in the Assets panel, and use the Inspector to select the texture you want to use as your sea. These are the settings I've used:

You'll notice a message in the material section stating that it's recommended to use Mobile/Diffuse as a shader, because the default white color doesn't do anything. Changing it to Mobile/Diffuse will also help with performance.


15. Adding Light

You may have noticed that the sea is a bit darker than it should be. To fix this, we need to add a Light to our scene. Select Create Other from the GameObject menu and select Directional Light. This will create an object that produces a beam of light. Change its Transform values as shown in the following screenshot to make it illuminate the sea.

This looks much better.

16. Creating Platforms

The platforms are parts of our level and are used by the player to move the ball to the portal on the other side of the sea.

Create a Plane as you did for the sea and adjust the Transform values in the Inspector as shown below. This will create and put the first platform in place.

We can now use Unity's Move and Rotation tools to create the other platforms. They're all of the same size so we can use them vertically or horizontally by duplicating them using Command+D on OS X and Control+D on Windows.


17. Platform Texture

Create a new Material like we did in Step 14 and apply the texture to it. Mine looks like this:

Adjust the x and y tiling until you're happy with the result.


18. Border Cylinders

We need to create a border to prevent our player from falling off too easily. To do this, we'll use a new type of primitive, a Cylinder.

Select Create Other > Cylinder from the GameObject menu and adjust the Transform values in the Inspector as shown below.

This will add a small border to the edge of the first platform. Create a new Material and change its color in the Inspector to RGB: 255, 69, 0.

The result should look like this:

Use Command+D (Control+D on Windows) to duplicate the border and the Scale tool to change its size. Position the duplicates at the platforms' edges using Unity's tools.


19. Portal

The portal is the goal line of the game. The player will use the accelerometer to control the ball and take it to this point while picking up items and avoiding falling off the platform. The portal is a 3D model, which we imported in Step 10.

Drag and drop it on the Scene or Hierarchy panel and change its Transform values to the following:

This will position it at the end of the platforms.


20. Portal Collider

Because imported 3D models don't have a collider by default, we need to attach one. Since we only need to test if the ball hits the blue area of the portal, we'll attach the collider to it.

Take a look at the portal model in the Hierarchy view and you'll notice a small triangle to the left of its name. Click the triangle to expand the portal's group and select the first item. I've added the -Collider suffix for clarification.

Click the Add Component button in the Inspector and choose Physics > Mesh Collider. This will add a collider using the shape of the model's selected area.


21. Portal Audio Source

To provide feedback to the player, we'll play a sound effect when the ball touches the portal's collider. Because we'll be triggering the event using the previously created collider, we need to add the audio source to that same object.

Select it from the Hierarchy panel, click the Add Component button in the Inspector panel, and select Audio Source from the Audio section.

Uncheck Play on Awake and click the little dot on the right, below the gear icon, to select the sound you want to play.

22. Adding Islands

The islands are nothing more than decorative elements to make the level less empty. I've used an imported 3D model and a Cylinder to make them. I won't go into detail creating the islands since they're not essential to the game. With what you've learned so far, you should be able to create them yourself.


23. Adding Bananas

As in Monkey Ball, the player will be able to collect bananas during the game. Start by dragging the model from the Assets panel to the Scene. Don't worry about its location just yet, because we'll convert it to a Prefab later since we'll be reusing it multiple times.

24. Banana Mesh Collider

As I mentioned earlier, imported models don't have a collider by default, so we need to attach one to the banana. Click the Add Component button in the Inspector and choose Physics > Mesh Collider. This will add a collider using the model's shape. Make sure to check the Trigger checkbox, because we want to detect collisions, but we don't want the ball to react with the banana.


24. Adding the Player

It's time to create our game character, which will be a simple Sphere primitive. Select Create Other > Sphere from the GameObject menu to create the primitive and modify the Transform values in the Inspector as shown below.

This will create the sphere and position it at the start of our level.

To make the sphere semi-transparent, we need to change its Shader options. Open the Inspector and change the shader to Transparent/Diffuse.


25. Player RigidBody

To detect a collision with the player, we need to attach a RigidBody to it. To add one, select Add Component from the Inspector panel, followed by Physics > RigidBody. You can leave the settings at their defaults.


26. GUI Textures

To display the game's user interface, we'll use Unity's GUI Textures. Unity's documentation provides a clear explanation of GUI Textures:

GUI Textures are displayed as flat images in 2D. They are made especially for user interface elements, buttons, or decorations. Their positioning and scaling is performed along the x and y axes only, and they are measured in Screen Coordinates, rather than World Coordinates.

By default, images imported to the Assets folder are converted to Textures that can be applied to 3D objects. We need to change this to GUI Texture for the images we want to use in the game's user interface.

Select the images you want to convert in the Assets panel and open the Inspector, click on the Texture Type drop-down menu and select GUI.

You can now drag and drop the images to the Scene. The images will always appear in front of every object on the stage and will be treated as 2D elements.

27. GUI Text

Inside each GUI element, we'll display a number indicating the number of bananas the player has collected and the time the player has left.

Select Create Other > GUI Text from the GameObject menu to create a text object, place it at the center of the GUI element, and change the text in the Hierarchy panel to 0. Do the same for the time on the right. I've set the default time to 30 seconds.

You can use a custom font for the text by adding the font to the Assets folder and then changing the Font property of the text in the Inspector.

28. Adding Scripts

It's time to write some code. With the user interface in place, we can start writing the necessary code to add functionality to our game. We do this by means of scripts. Scripts are attached to different game objects. Follow the next steps to learn how to add interaction to the level we've just created.


29. Move Scene

We'll start by making use of the device's accelerometer. Moving the player using the accelerometer is fairly simple in Unity. There's nothing to set up and it's easy to understand.

Select the stage, click the Add Component button in the Inspector panel, and choose New Script. Name the script MoveScene and don't forget to change the language to C#. Open the newly created file and add the following code snippet.

using UnityEngine;
using System.Collections;

public class MoveScene : MonoBehaviour
{
    void Update()
    {
        transform.rotation *= Quaternion.Euler(Input.acceleration.y/6, -Input.acceleration.x/3, 0);
    }
}

We use the Update method to request data from the accelerometer in every frame using the Input.acceleration property, which measures the device's movement in a three-dimensional space. This allows us to get the x, y, and z values, and use them to control the player's position.

We then apply the obtained values to the transform.rotation property of the level by invoking Quaternion.Euler, which returns the rotation values. Note that we divide the accelerometer's values to avoid that the player moves too fast, making the gameplay difficult.

We only modify the level's x and y values, because we only need it to tilt and not to move closer to or farther from the camera.

30. Camera Follow

The following script is attached to the Main Camera. It calculates the space between the camera and the player and maintains it while the ball moves.

using UnityEngine;
using System.Collections;

public class FollowPlayer : MonoBehaviour
{
    public GameObject player;
    private Vector3 playerOffset;

    // Use this for initialization
    void Start()
    {
        playerOffset = transform.position - player.transform.position;
    }
    
    // Update is called once per frame
    void Update()
    {
        transform.LookAt(player.transform);
        transform.position = player.transform.position + playerOffset;
    }
}

The script uses two variables that are worth explaining:

  • player: This is a reference to the player in the Scene. You can set this in the Inspector.
  • playerOffset: This is the distance between the camera and the player. Because we maintain the same distance between camera and player, the camera follows the player as it moves. The offset is calculated in the Start method.

We direct the camera to the player and set its position to the player's position plus the value of playerOffset. Because we do this in the Update method, the camera position is calculated and updated in every frame. The result is that the camera follows the player. This is a simple yet effective strategy to create a camera that follows the player.

31. Picking Bananas

The following script is attached to the banana and handles any interactions with it. We start by getting references to the corresponding sound and the text displaying the number of collected bananas, which we'll need to play the sound and increase the counter in the top left when the player collides with a banana. Once you've declared the variables in the script, you need to set these references in the Inspector.

using UnityEngine;
using System.Collections;

public class PickBanana : MonoBehaviour
{
    public AudioClip bananaSound;
    public GUIText bananaText;

    void OnTriggerEnter(Collider other)
    {
        AudioSource.PlayClipAtPoint(bananaSound, transform.position);
		int score = int.Parse (bananaText.text) + 1;
		bananaText.text = score.ToString();
        Destroy(gameObject);
    }
}

Next, we call a method that detects when the ball collides with a banana. When this happens, we play the sound and increase the counter.

To modify the counter, we create a variable using the value of the GUI Text and use the int.Parse method to convert the string to a number and increment the number by 1. We then set the value to the GUI Text, first converting the number to a string by invoking the toString method. Finally, we invoke Destroy to remove the banana game object.

32. Falling Off the Platform

The following class is used to detect when the player falls off the platform into the sea. Attach the script to the sea game object.

using UnityEngine;
using System.Collections;

public class Lose : MonoBehaviour
{
    void OnCollisionEnter()
    {
        audio.Play();
        Invoke("Reload", 1.59f);
    }

    void Reload()
    {
        Application.LoadLevel(Application.loadedLevel);
    }
}

This simple class uses the OnCollisionEnter method to detect when the ball collides with the sea, which means the player has fallen off the platform. When this happens, we play the sound attached to the sea and use the Invoke method to call the Reload method, which restarts the game by reloading the current scene.

The second parameter of the Invoke method defines the delay with which the Reload method is invoked. This is necessary as we first want the sound to finish before we start a new game.

33. Monitoring Time

The next class, Timer, is attached to the time GUI in the top right. It reduces the time and ends the game when the counter reaches 0.

using UnityEngine;
using System.Collections;

public class Timer : MonoBehaviour
{
    public GUIText timeText;

    void Start()
    {
        InvokeRepeating("ReduceTime", 1, 1);
    }

    void ReduceTime()
    {
        int currentTime = int.Parse(timeText.text) - 1;
        timeText.text = currentTime.ToString();

        if (currentTime == 0)
        {
            audio.Play();
            Invoke("Reload", 1.59f);//waits until sound is played to reload
            Destroy(timeText);
        }
    }

    void Reload()
    {
        Application.LoadLevel(Application.loadedLevel);
    }
}

We keep a reference to the text in the timeText variable to make modifying the user interface easy. In the Start method, we call the InvokeRepeating method, which repeatedly invokes the ReduceTime method repeatedly.

To update the text in the user interface, we create a variable to convert the text to a number, just like we did earlier, and subtract one second and update the user interface with the result.

When the counter reaches 0, the appropriate sound is played and we destroy the counter text. We invoke the Reload method with a delay to restart the game when the sound has finished playing.

34. Level Complete

The last class, EndLevel, is used to detect when the player reaches the portal. When the player passes through the portal, we display a message on screen and destroy destroy the ball. We do this to prevent the ball from falling in the sea.

using UnityEngine;
using System.Collections;

public class EndLevel : MonoBehaviour
{
    public GameObject complete;
    public GameObject player;

    void OnTriggerEnter(Collider other)
    {
        audio.Play();
        Invoke("Restart", 2);
        GameObject alert = Instantiate(complete, new Vector3(0.5f, 0.5f, 0), transform.rotation) as GameObject;
        Destroy(player.rigidbody);
    }

    void Restart()
    {
        Application.LoadLevel(Application.loadedLevel);
    }
}

The Instantiate method is used to create an instance of the message that is displayed to the player. It lets us use the GUI element from the project's Assets instead of having it on the scene. Finally, we restart the game with a delay of two seconds.

35. Testing

It's time to test the game. Press Command+P to play the game in Unity. If everything works as expected, then you're ready for the final steps.


36. Player Settings

When you're happy with your game, it's time to select Build Settings from the File menu and click the Player Settings button. This should bring up the Player Settings in the Inspector panel where you can set the parameters for your application.

These settings are application specific data that includes the creator or company, app resolution and display mode, rendering mode (CPU, GPU), device OS compatibility, etc. Configure the settings according to the devices you're targeting and the store or market where you plan to publish the app.


37. Icons and Splash Images

Using the graphics you created earlier, you can now create a nice icon and a splash image for your game. Unity shows you the required sizes, which depend on the platform you're building for.

38. Build and Play


Once your project is properly configured, it's time to revisit the Build Settings and click the Build Button. That's all it takes to build your game for testing and/or distribution.

Conclusion

In this tutorial, we've learned how to use the accelerometer to control the movement of the player, GUI Textures, primitives, and other aspects of game development in Unity. I encourage you to experiment with the result and customize the game to make it your own. I hope you liked this tutorial and found it helpful.

Create a 2D Platform Game with Unity and the Dolby Audio API

Final product image
What You'll Be Creating

Introduction

In this tutorial, you'll learn how to create a mobile 2D game using C# and Unity. We'll be taking advantage of the Dolby Audio Plugin for Unity to enhance the game's audial experience. The objective of the game is simple, reaching the other side of the level while avoiding enemies and collecting coins.

In this tutorial, you will learn the following aspects of Unity game development:

  • setting up a 2D project in Unity
  • creating Prefabs
  • movement and action buttons
  • working with physics collisions
  • using a sprite sheet
  • integrating the Dolby Audio API

1. Create a New Unity Project

Open Unity and select New Project from the File menu to open the new project dialog. Tell Unity where you want to save the project and set the Set up defaults for: drop-down menu to 2D.

 

2. Build Settings

In the next step, you're presented with Unity's user interface. Set the project up for mobile development by choosing Build Settings from the File menu and select Android as the target platform.


3. Devices

Since we're about to create a 2D game, the first thing we need to do after selecting the target platform is choosing the size of the artwork that we'll use in the game. Because Android is an open platform, there's a wide range of devices, screen resolutions, and pixel densities available on today's market. A few of the more common ones are:

  • Samsung Galaxy SIII: 720px x 1280px, 306 ppi
  • Asus Nexus 7 Tablet: 800px x 1280px, 216 ppi
  • Motorola Droid X: 854px x 480px, 228 ppi

Even though we'll be focusing on the Android platform in this tutorial, you can use the same code to target any of the other platforms that Unity supports.


4. Export Graphics

Depending on the devices you're targeting, you may need to convert the artwork for the game to the recommended size and pixel density. You can do this in your favorite image editor. I've used the Adjust Size... function under the Tools menu in OS X's Preview application.


5. Unity User Interface

Before we get started, make sure to click the 2D button in the Scene panel. You can also modify the resolution that's being displayed in the Game panel.


6. Game Interface

The interface of our game will be straightforward. The above screenshot gives you an idea of the artwork we'll be using and how the final game interface will end up looking. You can find the artwork for this tutorial in the source files of this tutorial.


7. Programming Language

You can use one of three programming languages when using Unity, C#, UnityScript, a variation of JavaScript, and Boo. Each of these programming languages has its pros and cons and it's up to you to decide which one you prefer. My personal preference goes to the C# programming language so that's the language I'll be using in this tutorial.

If you decide to use another programming language, make sure to take a look at Unity's Script Reference for examples.


8. 2D Graphics

Unity has built a name for being a great platform for creating 3D games for various platforms, such as Microsoft's Xbox 360, Sony's PS3, Nintendo's Wii, the web, and various mobile platforms.

While it's always been possible to use Unity for 2D game development, it wasn't until the release of Unity 4.3 that it included native 2D support. We'll learn how to work with images as sprites instead of textures in the next steps.


9. Sound Effects

I'll use a number of sounds to create a great audial experience for the game. The sound effects used in this tutorial were obtained from as3sfxr and PlayOnLoop.


10. Import Assets

Before we start coding, we need to add our assets to the Unity project. You can do this one of several ways:

  • select Import New Asset from the Assets menu
  • add the items to the assets folder in your project
  • drag and drop the assets in the project window

After completing this step, you should see the assets in your project's Assets folder in the Project panel.

11. Create Scene

We're ready to create the scene of our game by dragging objects to the Hierarchy or Scene panel.


12. Background

Start by dragging and dropping the background into the Hierarchy panel. It should automatically appear in the Scene panel.

Because the Scene panel is set to display a 2D view, you'll notice that selecting the Main Camera in the Hierarchy shows a preview of what the camera is going to display. You can also see this in the Game view. To make the entire scene visible, change the Size value of the Main Camera to 1.58 in the Inspector panel.


13. Floor

The floor is used to keep our main character from falling once we've added physics to the game. Drag it from the Assets folder and position it in the scene as shown below.


14. Floor Collider

In order to make the floor detect when the character is touching it, we need to add a component, a Box Collider 2D to be precise.

Select the floor in the scene, open the Inspector panel, and click Add Component. From the list of components, select Box Collider 2D from the Physics 2D section.

15. Jump Button

We'll use buttons to control our main character in the game. Drag and position the jump button in the Scene and add a Circle Collider2D component as shown in the previous step.


16. Jump Sound

To play a sound when the character jumps, we first need to attach it to the jump button. Select it from the Hierarchy or Scene view, click the Add Component button in the Inspector panel, and select Audio Source in the Audio section.

Uncheck Play on Awake and click the little dot on the right, below the gear icon, to select the sound we want to play when the player taps the button. In the next step, we'll implement the logic for playing the sound when the player taps the button.


17. Jump Script

Let's create the script that will control our character. Select the jump button and click the Add Component button in the Inspector panel. Select New Script and name it Jump. Don't forget to change the language to C#.

Open the newly created file and add the following code snippet.

using UnityEngine;
using System.Collections;

public class Jump : MonoBehaviour
{
    public float jumpForce;
    private GameObject hero; //used to reference our character (hero) on the scene

    // Use this for initialization
    void Start()
    {
        hero = GameObject.Find("Hero"); //gets the hero game object
    }
    
    // Update is called once per frame
    void Update()
    {
		/* Check if the user is touching the button on the device */

        if (Application.platform == RuntimePlatform.Android)
        {
            if (Input.touchCount > 0)
            {
                if (Input.GetTouch(0).phase == TouchPhase.Began)
                { 
                    CheckTouch(Input.GetTouch(0).position, "began"); // function created below
                } else if (Input.GetTouch(0).phase == TouchPhase.Ended)
                {
                    CheckTouch(Input.GetTouch(0).position, "ended");
                }
            }
        }

		/* Check if the user is touching the button on the Editor, change OSXEditor value if you are on Windows */
        
        if (Application.platform == RuntimePlatform.OSXEditor)
        {
            if (Input.GetMouseButtonDown(0))
            {
                CheckTouch(Input.mousePosition, "began");
            }
            
            if (Input.GetMouseButtonUp(0))
            {
                CheckTouch(Input.mousePosition, "ended");
            }
        }
    }

    void CheckTouch(Vector3 pos, string phase)
    {
		/* Get the screen point where the user is touching */
        Vector3 wp = Camera.main.ScreenToWorldPoint(pos);
        Vector2 touchPos = new Vector2(wp.x, wp.y);
        Collider2D hit = Physics2D.OverlapPoint(touchPos);

		/* if button is touched... */
        
        if (hit.gameObject.name == "JumpButton" && hit && phase == "began")
        {
            hero.rigidbody2D.AddForce(new Vector2(0f, jumpForce)); //Add jump force to hero
            audio.Play(); // play audio attached to this game object (jump sound)
        }
    }
}

The code snippet may seem daunting, but it's actually pretty straightforward. We first get a reference to the hero object, an instance of the GameObject class, so we can use it later. We then detect if the user is touching the jump button and, if they are, add a force to the hero object. Last but not least, we play the jump sound when the jump button is tapped.

18. Movement Buttons

The steps to add and implement the movement buttons, left and right, are very similar. Start by placing the buttons in the scene and add a Circle Collider 2D to each button like we did with the jump button.



19. Movement Scripts

Create a new script, attach it to the left button, and name it MoveLeft. Replace  its contents with the following code snippet, which contains the MoveLeft method.

using UnityEngine;
using System.Collections;

public class MoveLeft : MonoBehaviour
{
    public Vector3 moveSpeed = new Vector3();
    private bool moving = false;
    private GameObject[] scene; //array of game objects that conform the scene
    private GameObject bg;
    
    // Use this for initialization
    void Start()
    {
        scene = GameObject.FindGameObjectsWithTag("Moveable"); //Game objects with Moveable tag
        bg = GameObject.Find("Background"); //Game Background
    }
    
    // Update is called once per frame
    void Update()
    {
       /* Detect touch */ 
		if (Application.platform == RuntimePlatform.Android)
        {
            if (Input.touchCount > 0)
            {
                if (Input.GetTouch(0).phase == TouchPhase.Began)
                { 
                    CheckTouch(Input.GetTouch(0).position, "began");
                } else if (Input.GetTouch(0).phase == TouchPhase.Ended)
                {
                    CheckTouch(Input.GetTouch(0).position, "ended");
                }
            }
        }
        
        if (Application.platform == RuntimePlatform.OSXEditor)
        {
            if (Input.GetMouseButtonDown(0))
            {
                CheckTouch(Input.mousePosition, "began");
            }
            
            if (Input.GetMouseButtonUp(0))
            {
                CheckTouch(Input.mousePosition, "ended");
            }
        }
        
        // Move if button is pressed
        if (moving && bg.transform.position.x < 4.82f)
        {
            for (int i = 0; i < scene.Length; i++)
            {
                if (scene [i] != null)
                {
                    scene [i].transform.position += moveSpeed;
                }
            }
        }
    }
    
    void CheckTouch(Vector3 pos, string phase)
    {
        Vector3 wp = Camera.main.ScreenToWorldPoint(pos);
        Vector2 touchPos = new Vector2(wp.x, wp.y);
        Collider2D hit = Physics2D.OverlapPoint(touchPos);
        
        if (hit.gameObject.name == "LeftButton" && hit && phase == "began")
        {
            moving = true;
        }
        
        if (hit.gameObject.name == "LeftButton" && hit && phase == "ended")
        {
            moving = false;
        }
    } 
}

In this script, we create an array of the elements tagged as Moveable—we'll tag them later in this tutorial—to make it easier to move them all at once. To move the elements, we first check if the button is being touched and change the position using moveSpeed in the Update function. It's as simple as that.

Create another script, attach it to the right button, and name it MoveRight. This script contains the MoveRight method and its implementation is similar to that of the MoveLeft method we saw a moment ago. We change the direction of the movement by replacing += moveSpeed with -= moveSpeed. This will move the scene in the opposite direction.

In the MoveRight script, we also check if the player has completed the level.

using UnityEngine;
using System.Collections;

public class MoveRight : MonoBehaviour
{
    public Vector3 moveSpeed = new Vector3();
    private bool moving = false;
    private GameObject[] scene;
    private GameObject bg;
    public AudioClip completeSound;
    private GameObject[] buttons;
    private GameObject completeText;
    private bool ended = false;
    public Font goodDog;
    
    // Use this for initialization
    void Start()
    {
        scene = GameObject.FindGameObjectsWithTag("Moveable");
        bg = GameObject.Find("Background");
        buttons = GameObject.FindGameObjectsWithTag("Buttons");
    }
    
    // Update is called once per frame
    void Update()
    {
        if (Application.platform == RuntimePlatform.Android)
        {
            if (Input.touchCount > 0)
            {
                if (Input.GetTouch(0).phase == TouchPhase.Began)
                {
                    CheckTouch(Input.GetTouch(0).position, "began");
                } else if (Input.GetTouch(0).phase == TouchPhase.Ended)
                {
                    CheckTouch(Input.GetTouch(0).position, "ended");
                }
            }
        }

        if (Application.platform == RuntimePlatform.OSXEditor)
        {
            if (Input.GetMouseButtonDown(0))
            {
                CheckTouch(Input.mousePosition, "began");
            }

            if (Input.GetMouseButtonUp(0))
            {
                CheckTouch(Input.mousePosition, "ended");
            }
        }
        
        // Move if button is pressed && stage is not over
        if (moving && bg.transform.position.x > -4.8f)
        {
            for (int i = 0; i < scene.Length; i++)
            {
                if (scene [i] != null)
                {
                    scene [i].transform.position -= moveSpeed;
                }
            }
        }

        // Stage Completed
        if (bg.transform.position.x <= -4.8f && ended == false)
        {
            Alert("complete");
        }
    }

    void CheckTouch(Vector3 pos, string phase)
    {
        Vector3 wp = Camera.main.ScreenToWorldPoint(pos);
        Vector2 touchPos = new Vector2(wp.x, wp.y);
        Collider2D hit = Physics2D.OverlapPoint(touchPos);
            
        if (hit.gameObject.name == "RightButton" && hit && phase == "began")
        {
            moving = true;
        }
                
        if (hit.gameObject.name == "RightButton" && hit && phase == "ended")
        {
            moving = false;
        }
    }

    public void Alert(string action)
    {
        ended = true;

        completeText = new GameObject();
        completeText.AddComponent("GUIText");
        completeText.guiText.font = goodDog;
        completeText.guiText.fontSize = 50;
        completeText.guiText.color = new Color(255, 0, 0);
        
        if (action == "complete")
        {
            AudioSource.PlayClipAtPoint(completeSound, transform.position);

            completeText.guiText.text = "Level Complete!";
            completeText.guiText.transform.position = new Vector3(0.24f, 0.88f, 0);

        } else
        {
            completeText.guiText.text = "Game Over";
            completeText.guiText.transform.position = new Vector3(0.36f, 0.88f, 0);
        }

        bg.GetComponent().Stop();
        
        for(int i = 0; i < buttons.Length; i++)
        {
            buttons[i].renderer.enabled = false;
            Invoke("restart", 2);
        }
    }

    void restart()
    {   
        Application.LoadLevel(Application.loadedLevel);
    }
}

The Alert  function creates and displays a message to the player and plays the sound attached to the background sprite. For this to work, add the corresponding sound to the background sprite as we saw earlier in this tutorial. We also hide the buttons and restart the game with a delay of two seconds.

20. Sprite Sheet

We'll use a sprite sheet for the rest of the game elements. Unity has a sprite editor that makes using sprites a breeze. The artwork used in this tutorial was obtained from OpenGameArt.org.

Import the artwork, select it from the Assets panel, and change the Sprite Mode option to Multiple in the Inspector panel.

Open the Sprite Editor by clicking the button below and select Slice > Automatic.


21. Hero

With the sprite sheet sliced and ready to use, click the arrow that appears when the sprite sheet is selected and choose the sprite for the hero, the main character of our game. Place it on the scene and add a Collider 2D component to it.


22. Hero RigidBody 2D

To detect a collision with our hero, at least one of the colliding objects needs to have a RigidBody 2D component attached to it. To add one to our hero, select Add Component in the Inspector panel, followed by Physics 2D > RigidBody 2D.

Check the Fixed Angle box to prevent the hero from rotating if a collision occurs.

23. Hero Sound

When our hero is hit by an enemy, we play another sound to give the player feedback. If you've ever played Super Mario Bros., then you probably know what effect we're after. To accomplish this, we first need to add the sound. Select it from the Hierarchy or Scene view, click the Add Component button in the Inspector panel, and select Audio Source in the Audio section.

The details of the audio component will show up in the Inspector Panel. Click the dot below the gear icon and select the hit sound.

24. Collecting Coins

As in many traditional 2D platformers, you can collect coins in our game. Because we'll use this object multiple times in the game, we'll convert it to a Prefab once we've added all the necessary components.

Drag the coin from the Assets folder and add a Collider2D as we saw in the previous steps.


25. Coin Sound

We play a sound whenever our hero collects a coin. Add an Audio Source component as we saw a moment ago and select the coin sound from the project's assets.



26. Coin Script & Prefab

Attach this simple script to the coin. It detects when the coin and the hero collide. The coin is destroyed and a sound is played to indicate that the coin has been collected by the hero.

using UnityEngine;
using System.Collections;

public class GrabCoin : MonoBehaviour
{   
    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.gameObject.name == "Hero")
        {
            audio.Play();
            Destroy(gameObject.collider2D);
            gameObject.renderer.enabled = false;
            Destroy(gameObject, 0.47f);// Destroy the object -after- the sound played
        }
    }
}

With all the components in place, drag the coin from the Hierarchy panel to the Assets panel to convert it to a Prefab. You'll notice the text becomes blue indicating it's now a Prefab.


27. Enemy

Let's not forget the enemies of the game. Drag the artwork for the enemy from the Assets folder and add two Collider 2D components as shown in the screenshot below.


The colliders are reduced in size to prevent the hero from colliding with both colliders at once. Change the settings of each Collider 2D component as below.

The first collider in the panel is the topmost collider that we've added to the enemy. It will detect if the hero jumps on top of the enemy and destroys it. The logic for this action is shown in the script below.

We mark the second collider as a trigger by checking the checkbox labeled Is Trigger. It detects when the enemy runs into the hero or vice versa. When that happens, the player loses the game.


The script attached to the enemy is shown below and implements the logic we just discussed. As you can see, the enemy is moved to the left in every frame and the script detects when the hero jumps on top of the enemy or when the hero runs into the enemy.

using UnityEngine;
using System.Collections;

public class Enemy : MonoBehaviour
{
    public Vector3 moveSpeed;
    public AudioClip hitSound;
    public GameObject alertBridge;

    // Use this for initialization
    void Start()
    {
    }
    
    // Update is called once per frame
    void Update()
    {
        transform.position -= moveSpeed; //Move the enemy to the left
    }

    void OnCollisionEnter2D(Collision2D other) //Hero jumps on enemy
    {
        if (other.gameObject.name == "Hero")
        {
            AudioSource.PlayClipAtPoint(hitSound, transform.position);
            Destroy(gameObject);
        }

    }

    void OnTriggerEnter2D(Collider2D other) //hero hits side of enemy
    {
        if (other.gameObject.name == "Hero")
        {
            other.gameObject.audio.Play(); //Play audio
            Destroy(other.gameObject.collider2D); //Remove collider to avoid audio replaying
            other.gameObject.renderer.enabled = false; //Make object invisible
            Destroy(other.gameObject, 0.626f); //Destroy object when audio is done playing, destroying it before will cause the audio to stop
            alertBridge.GetComponent().Alert("gameover");
        }
    }
}

28. Bricks

Bricks are used as platforms. The hero can jump on the bricks to avoid enemies and collect coins. Drag the brick artwork from the Assets panel and add a Collider 2D component to it. Don't forget to convert it to a Prefab, because it will be used quite a bit in the game.


29. The End

We'll use a sprite to show the finish line of the level. Drag it from the Assets panel to the Scene as shown in the screenshot below.

30. Dolby Audio Plugin


Let's enhance the audial experience of our game by using the Dolby Audio Plugin for Unity. However, let me first explain why you should be using the Dolby Audio Plugin and how it will improve your game.

Dolby Digital Plus is an advanced audio solution built into many mobile devices including tablets. Mobile applications can leverage the Dolby Digital Plus capabilities via API. Some of the benefits include Audio Optimization, Volume Maximization, and Volume Leveling. Dolby has made its API available for several platforms, including Android and Kindle Fire. In our game, we will take advantage of the Dolby Audio Plugin for Unity.

Note that the plugin for Unity is free to use and very easy to integrate. In other words, there's no reason not to include it in your next game.

Start by downloading Dolby's Unity plugin. You can download it from the Unity Asset Store or directly from Dolby's developer website. If you choose the latter option, then create a free account to download the plugin or log in if you already have a Dolby developer account. Extract the package and copy the version you need to Assets > Plugins > Android. That's how easy it is to install the plugin for Unity.

Create a new script and attach it to an object that is always present in the game like the background or the camera. Name the script Dolby and populate it with the following code snippet.

using UnityEngine;
using System.Collections;

using System.Runtime.InteropServices; //Allows us to use DLLImport

public class Dolby : MonoBehaviour
{
    private GameObject debugText;
    public Font arial; 

	/* Import plugin functions */

    [DllImport("DSPlugin")]
    public static extern  bool isAvailable();
    [DllImport("DSPlugin")]
    public static extern  int initialize();
    [DllImport("DSPlugin")]
    public static extern  int setProfile(int profileid);
    [DllImport("DSPlugin")]
    public static extern  int suspendSession();
    [DllImport("DSPlugin")]
    public static extern  int restartSession();
    [DllImport("DSPlugin")]
    public static extern void release();

    // Use this for initialization
    void Start()
    {
		/* Textfield created for feedback */        
		debugText = new GameObject();
        debugText.AddComponent("GUIText");
        debugText.guiText.font = arial;
        debugText.guiText.fontSize = 14;
        debugText.guiText.color = new Color(255, 0, 0);
        debugText.transform.position = new Vector3(0, 1, 0);
        
        /* Initialize Dolby if Available */

        if (isAvailable())
        {
            Invoke(Init, 0.1f); // Wait 100ms to make sure Dolby service is enabled
        }
        else
        {
            debugText.guiText.text = "Dolby Sound Not Available";
        }
    }
    
    void Init()
    {
        debugText.guiText.text = "Dolby Sound Available";
        setProfile(2); /* Set Profile to "Game" */
        initialize();
    }

    void OnApplicationPause()
    {
        suspendSession();// Dolby sound stops if app switched or paused
    }

    void OnApplicationFocus()
    {
        restartSession(); // Restart Dolby sound if app is active
    }

    void OnApplicationQuit()
    {
        release(); //Stops Dolby Sound completely
    }
}

I'm sure you agree that it's very easy to integrate the Dolby Audio API into your game. We first create a debugText object, which is of type GameObject, to receive feedback from the device. We then import the necessary functions defined by the Dolby Audio API and initialize the Dolby Audio API if the user's device supports it.

To ensure that the Dolby service is enabled, we briefly wait (0.1s) before calling the initialize() method. If we don't do this, there's a chance you receive a -1 error, which can happen when you try to set Dolby on when the service is getting established.

Dolby has also included functions to suspend and restart the sound when needed, which is useful when we switch to another application and we don't need the sound enhancement. This is important to conserve battery power and other device resources. We can also stop the sound enhancement completely by invoking release as we do in OnApplicationQuit.


31. Testing

It's time to test the game. Press Command-P to play the game in Unity. If everything works as expected, you are ready for the final steps.


32. Player Settings

When you're happy with your game, it's time to select Build Settings from the File menu and click the Player Settings button. This should bring up the Player Settings in the Inspector panel where you can set the parameters for your application.

These settings are application specific and include the creator or company, application resolution, display mode, etc. These settings depend on the devices you're targeting and the stores or markets you will be publishing your game on.


33. Icons and Splash Images

Using the graphics you created earlier, you can now create a nice icon and a splash image for your game. Unity shows you the required sizes, which depend on the platform you're building for.

34. Build and Play


Once your project is properly configured, it's time to revisit the Build Settings and click the Build button. That's all it takes to build your game for testing and/or distribution.

Conclusion

In this tutorial, we've learned about the new Dolby Audio Plugin for Unity, sprite sheets, controls, collision detection, and other aspects of game development using Unity. I encourage you to experiment with the result and customize the game to make it your own. I hope you liked this tutorial and found it helpful.

Working with Unity’s 2D Tools

In this tutorial, I'll show you how to take advantage of the new 2D Tools included in Unity to create a 2D Game.

1. Application Overview

In this tutorial, you'll learn how to create a Unity 2D project and create a mobile game using C# and Unity.

The objective of the game is to shoot a teleporting ray at the cows before they can reach the safety of the barn.

In this project you will learn the following aspects of Unity development:

  • setting up a 2D project in Unity
  • becoming familiar with the Unity interface
  • creating a Prefab
  • attaching scripts to game objects
  • working with physics collisions
  • using timers

2. Create a New Unity Project

Open Unity and select New Project from the File menu to open the new project dialog. Select a directory for your project and set Set up defaults for to 2D.


3. Build Settings

In the next step, you're presented with Unity's interface. Set the project up for mobile development by choosing Build Settings from the File menu and selecting your platform of choice.

Unity can build for iOS, Android, BlackBerry, and Windows Phone 8, which is great if you plan to create a mobile game for multiple platforms.


4. Devices

Since we're about to create a 2D game, the first thing we need to do after selecting the platform we're targeting, is choosing the size of the artwork that we'll use in the game.

iOS:

  • iPad without Retina: 1024px x 768px
  • iPad with Retina: 2048px x 1536px
  • 3.5" iPhone/iPod Touch without Retina: 320px x 480px
  • 3.5" iPhone/iPod with Retina: 960px x 640px
  • 4" iPhone/iPod Touch: 1136px x 640px

Because Android is an open platform, there are many different devices, screen resolutions, and pixel densities. A few of the more common ones are listed below.

  • Asus Nexus 7 Tablet: 800px x 1280px, 216 ppi
  • Motorola Droid X: 854px x 480px, 228 ppi
  • Samsung Galaxy SIII: 720px x 1280px, 306 ppi

And for Widows Phone and BlackBerry:

  • Blackberry Z10: 720px x 1280px, 355 ppi
  • Nokia Lumia 520: 400px x 800px, 233 ppi
  • Nokia Lumia 1520: 1080px x 1920px, 367 ppi

Even though we'll be focusing on the iOS platform in this tutorial, the code can be used to target any of the other platforms.


5. Export Graphics

Depending on the device you're targeting, you may need to convert the artwork to the recommended size and pixel density. You can do this in your favorite image editor. I've used the Adjust Size... function under the Tools menu in OS X's Preview application.


6. Unity Interface

Make sure to click the 2D button in the Scene panel. You can also modify the resolution that's being used to display the scene in the Game panel.


7. Game Interface

The user interface of our game will be simple. You can find the artwork for this tutorial in the source files of this tutorial.


8. Language

You can use one of three languages in Unity, C#, UnityScript, a language similar to JavaScript in terms of syntax, and Boo. Each language has its pros and cons, but it's up to you to decide which one you prefer. My preference goes to the C# syntax, so that's the language I'll be using in this tutorial.

If you decide to use another language, then make sure to take a look at Unity's Script Reference for examples.


9. 2D Graphics

Unity has built a name for being a great platform for creating 3D games for various platforms, such as Microsoft Xbox 360, Sony PS3, Nintendo Wii, the web, and various mobile platforms.

While it has always been possible to use Unity for 2D game development, it wasn't until the release of Unity 4.3 that it included native 2D support. We'll learn how to work with images as sprites instead of textures in the next steps.


10. Sound Effects

I'll use a number of sounds to improve the game experience. The sound effects used in this tutorial can be found at Freesound.org.


11. Import Assets

Before we start coding, we need to add our assets to the Unity project. Theres are several ways to do this:

  • select Import New Asset from the Assets menu
  • add the items to the assets folder in your project
  • drag and drop the assets in the project window

After completing this step, you should see the assets in your project's Assets folder in the Project panel.

12. Create Scene

We're ready to create the scene of our game by dragging objects to the Hierarchy or Scene panel.


13. Background

Start by dragging and dropping the background into the Hierarchy panel. It should then appear in the Scene panel.

Because the Scene panel is set to display a 2D view, you'll notice selecting the Main Camera in the Hierarchy shows a preview of what the camera is going to display. You can also see this in the game view. To make the entire scene visible, change the Size value of the Main Camera to 1.6 in the Inspector panel.


14. Ship

The ship is also a static element the player won't be able to interact with. Position it in the center of the scene.


15. Barn

Select the barn from the Assets panel and drag it to the scene. Position it as illustrated in the screenshot below.


16. Barn Collider

To make sure the barn is notified when a cow hits it—enters the barn—we need to add a component, a Box Collider 2D to be precise.

Select the barn in the scene, open the Inspector panel, and click Add Component. From the list of components, select Box Collider 2D from the Physics 2D section. Make sure to check the Is Trigger box.

We want the cow to react when it hits the door of the barn so we need to make the collider a bit smaller. Open the Inspector and change the Size and Center values of the collider to move the box closer to the door of the barn.


17. Barn Collision Script

It's time to write some code. We need to add a script so the application can respond to the collision when a cow enters the barn.

Select the barn and click the Add Component button in the Inspector panel. Select New Script and name it OnCollision. Remember to change the language to C#.

Open the newly created file and add the following code snippet.

using UnityEngine;
using System.Collections;

public class OnCollision : MonoBehaviour
{
    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.gameObject.name == "cow(Clone)")
        {
            /* Play the save cow sound */
            audio.Play();
            /* Destroy the cow */
            Destroy(other.gameObject);
        }
    }
}

The snippet checks for a collision between the object to which the script is linked, the barn, and an object named cow(Clone), which will be an instance of the cow Prefab that we'll create later. When a collision takes place, a sound is played and the cow object is destroyed.


18. Barn Sound

To play a sound when a cow hits the barn, we first need to attach the sound to the barn. Select it from the Hierarchy or Scene view, click the Add Component button in the Inspector panel, and select Audio Source from the Audio section.

Uncheck Play on Awake and click the little dot on the right, below the gear icon, to select the barn sound.

You can increase the size of the icons in Unity's user interface (gizmos) by clicking Gizmos in the Scene panel and adjusting the position of the slider.


19. Ray

Drag the ray graphic from the Assets panel to the scene and add a collider to it. This is necessary to detect a collision with the unlucky cow. Check the Is Trigger option in the Inspector panel.

20. Ray Script

Create a new script by repeating the steps I outlined a few moment ago. Name the script Bullet and replace its contents with the following code snippet:

using UnityEngine;
using System.Collections;

public class Bullet : MonoBehaviour
{
    public AudioClip cowSound;

    // Use this for initialization
    void Start()
    {
        renderer.enabled = false; /* Makes object invisible */
    }
    
    // Update is called once per frame
    void Update()
    {
        /* Get main Input */
        if (Input.GetButton("Fire1"))
        {
            renderer.enabled = true; /* Makes object visible */
            /* Play the ray sound */
            audio.Play();
        }
        
        if (renderer.enabled == true)
        {
            transform.position += Vector3.down * (Time.deltaTime * 2);
        }

        /* Check for out of bounds */

        if (this.transform.position.y < -1.5)
        {
            transform.position = new Vector2(0.08658695f, 0.1924166f); /* Return bullet to original position */
            renderer.enabled = false;
        }
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.gameObject.name == "cow(Clone)")
        {
            AudioSource.PlayClipAtPoint(cowSound, transform.position);
            /* Destroy the cow */
            Destroy(other.gameObject);
            transform.position = new Vector2(0.08658695f, 0.1924166f); /* Return bullet to original position */
            renderer.enabled = false;
        }
    }
}

That's a lot of code, but it isn't complicated. Let's see what is happening. First, we create an AudioClip instance named cowSound, which we'll use to store an audio file. This is just another technique to play a sound if you don't want to add two audio components to the object. We declare the variable as public so we can access it from the Inspector. Click the little dot on the right of cowSound and select the audio file.

We then make the ray invisible by disabling its renderer. We use the same object so we can save resources, which is an important optimization for less powerful devices.

We detect touches on the screen, which make the ray visible and play back the ray sound (see below). If the object is visible, it means that it should be going down to hit a cow.

There's also code to detect if the ray is outside the scene's bounds. If this is the case, we reposition it, ready to fire again (check the ray's x and y values in the Inspector).

The last part checks whether the ray hits a cow. If it does, it plays the cow sound and destroys the cow. The ray is then made invisible and repositioned at its original position, ready to fire again.


21. Ray Audio Source

To add the audio for the ray,  select it in the Hierarchy or Scene view and click Add Component in the Inspector panel. Select Audio Source from the Audio section. Uncheck Play on Awake and click the little dot on the right to select the sound file.


22. Add a Cow

Drag the graphic for the cow from the Assets panel and position it in the scene as shown below.


23. Rigid Body 2D

To detect a collision, at least one of the colliding objects needs to have a RigidBody2D component associated with it. As the cow can collide with both the barn and the ray, it's best to add the component to the cow.


24. Cow Collider

We also need to add a collider to the cow so we can detect collisions with the barn and the ray. Make sure to check the Is Trigger checkbox in the Inspector.


25. Move Cow Script

Add a script component to the cow and replace its contents with the following:

using UnityEngine;
using System.Collections;

public class MoveCow : MonoBehaviour
{
    public Vector3 moveSpeed;
    public float spawnTime = 2f;
    public float spawnDelay = 2f;

    // Use this for initialization
    void Start()
    {
        moveSpeed = Vector3.left * Time.deltaTime;
        InvokeRepeating("ChangeSpeed", spawnDelay, spawnTime);
    }

    void ChangeSpeed()
    {
        moveSpeed = new Vector3(Random.Range(-1, -2), 0, 0) * 0.05f;
    }
    
    // Update is called once per frame
    void Update()
    {
        transform.position += moveSpeed;
    }
}

The MoveCow class animates the cow across the screen using a variable named moveSpeed. The InvokeRepeating method changes the speed of the cow to make it sprint from the moment it reaches the center of the scene. This makes the game more challenging.


26. Create Cow Prefab

With the necessary components added to the cow, it's time to convert it to a Prefab. What is a Prefab? Let's consult the Unity Manual:

"A Prefab is a type of asset—a reusable GameObject stored in Project View. Prefabs can be inserted into any number of scenes, multiple times per scene. When you add a Prefab to a scene, you create an instance of it. All Prefab instances are linked to the original Prefab and are essentially clones of it. No matter how many instances exist in your project, when you make any changes to the Prefab you will see the change applied to all instances."

If you're coming from Flash and ActionScript, then this should sound familiar. To convert the cow to a prefab, drag the cow from the Hierarchy panel to the Assets panel. As a result, the name in the Hierarchy will turn blue.

Converting the cow to a prefab allows us to reuse it, which is convenient as it already contains the necessary components.


27. Spawner Script

The Spawner script is responsible for the cows to appear. Open MonoDevelop—or your favorite C# editor—and create a new script:

using UnityEngine;
using System.Collections;

public class Spawner : MonoBehaviour
{

    public float spawnTime = 2f;
    public float spawnDelay = 2f;
    public GameObject cow;

    // Use this for initialization
    void Start()
    {
        InvokeRepeating("Spawn", spawnDelay, spawnTime);
    }

    void Spawn()
    {
        /* Instantiate a cow */

        GameObject clone = Instantiate(cow, transform.position, transform.rotation) as GameObject;
    }
}

We call the InvokeRepeating method to spawn cows using the values set by spawnTime and spawnDelay. The GameObject cow is set to public and is created using the Inspector. Click the little dot on the right and select the cow Prefab.


28. Spawner Game Object

To instantiate the cow prefab, we'll use the graphic of the cow we've added to the scene a few minutes ago. Select it and remove its components. Then add the Spawner script.


29. Testing

It's time to test the game. Press Command + P to play the game in Unity. If everything works as expected, you are ready for the final steps.


30. Player Settings

When you're happy with your game, it's time to select Build Settings from the File menu and click the Player Settings button. This brings up the Player Settings in the Inspector panel where you can adjust the parameters for your application.


31. Application Icon

Using the graphics you created earlier, you can now create a nice icon for your game. Unity shows you the required sizes, which depend on the platform you're building for.


32. Splash Image

The splash or launch image is displayed when the application is launched.

33. Build

Once your project is properly configured, it's time to revisit the Build Settings and click the Build Button. That's all it takes to build your game for testing and/or distribution.

34. Xcode

If you're building for iOS, you need Xcode to build the final application binary. Open the Xcode project and choose Build from the Product menu.

Conclusion

In this tutorial, we've learned about the new 2D capabilities of Unity, collision detection, and other aspects of game development with Unity.

Experiment with the result and customize it to make the game your own. I hope you liked this tutorial and found it helpful.

Corona SDK: Create a Balance Ping-Pong Game

In this tutorial, I’ll be showing you how to create a balance game in Corona SDK. You’ll learn more about touch controls and collision detection without physics. The objective of the game is to keep the ball from touching the floor. Read on.


1. Application Overview

App Overview

Using ready-made graphics, we’ll create an entertaining game using Lua and the Corona SDK APIs. The player will be able to move a ping-pong paddle on the screen in order to hit a ball. You can modify the parameters in the code to customize the game.


2. Target Device

Target Device

The first thing we need to do is select the platform we want to run our application on so we’re able to choose the size of the images we’ll use.

The iOS platform has the following requirements:

  • iPad 1/2/Mini: 1024px x 768px, 132 ppi
  • iPad Retina: 2048px x 1536px, 264 ppi
  • iPhone/iPod Touch: 320px x 480px, 163 ppi
  • iPhone/iPod Retina: 960px x 640px, 326 ppi
  • iPhone 5/iPod Touch: 1136px x 640px, 326 ppi

Because Android is an open platform, there are many different devices and resolutions. A few of the more common screen characteristics are:

  • Asus Nexus 7 Tablet: 800px x 1280px, 216 ppi
  • Motorola Droid X: 854px x 480px, 228 ppi
  • Samsung Galaxy SIII: 720px x 1280px, 306 ppi

In this tutorial, we’ll be focusing on the iOS platform in terms of graphics. In particular, we’ll be developing for the iPhone and iPod touch. However, the code of this tutorial can also be used if you target the Android platform.


3. Interface

Interface

We’ll use a simple user interface involving multiple shapes, buttons, bitmaps, and more. The graphics that we’ll use for this tutorial can be found in the project included with this tutorial.


4. Export Graphics

Export Graphics

Depending on the device you’ve selected, you may need to convert the graphics to the recommended resolution (ppi), which you can do in your favorite image editor. I used the Adjust Size… option in the Tools menu in the Preview application on OS X. Remember to give the images a descriptive name and save them in your project folder.


5. Application Configuration

We’ll use a configuration file, config.lua, to make the application go full screen across devices. The configuration file shows the original screen size and the method used to scale the content in case the application is run on another resolution.

application =
{
    content =
    {
        width = 320,
        height = 480,
        scale = "letterbox"
    },
}

6. main.lua

Let’s write the actual application. Open your preferred Lua editor. Any plain text editor will work, but it is recommended to use a text editor that has syntax highlighting. Create a new file and save it as main.lua in your project folder.


7. Project Structure

We’ll structure our code as if it were a class. If you’re familiar with ActionScript or Java, you should find the project structure familiar.

Necesary Classes
Variables and Constants
Declare Functions
    contructor (Main function)
    class methods (other functions)
call Main function

8. Hide Status Bar

display.setStatusBar(display.HiddenStatusBar)

This code snippet hides the status bar. The status bar is the bar at the top of the device’s screen that shows the time, signal, and other indicators.


9. Background

Background

A simple background for the application’s user interface. The code snippet below draws the background to the screen.

-- Graphics
-- [Background]
local bg = display.newImage('bg.png')

10. Title View

Title View

This is the title view. It’s the first interactive screen to appear in our game. These variables store its components.

-- [Title View]
local title
local playBtn
local creditsBtn
local titleView

11. Credits View

Credits View

The credits view shows the credits and copyright of the application. This variable is used to store it.

-- [CreditsView]
local creditsView

12. Instructions Message

Instructions

A message with instructions will appear at the start of the game and it will disappear after the first tap.

-- Instructions
local ins

13. Paddle

Paddle

This is the graphic for the ping-pong paddle. It will be placed at the view’s center.

-- Paddle
local paddle
local paddleTop
local paddleBottom

14. Ball

Ball

And this is the graphic for the ping-pong ball used in the game.

-- Ball
local ball

15. Alert

Alert

The alert is displayed when the player misses the ball and the game is over. It displays a message and ends the game.

-- Alert
local alertView

16. Sounds

Sounds

We’ll use sound effects to spice up the game. The sounds used in this game can be found on freesound, a collaborative database of Creative Commons Licensed sounds.

-- Sounds
local pong = audio.loadSound('pong.mp3')

17. Variables

The following code snippet shows the variables that we’ll use. Read the comments to understand what each variable is used for.

-- Variables
local scoreTF -- score textfield
local scale = 1.1 -- initial ball scale
local variation = 0.05 -- controls the scale variation
local ballX = 0
local ballY = 0
local ballVar = 0.5 -- ball variation

18. Declare Functions

Declare all functions as local at the start.

-- Functions
local Main = {}
local startButtonListeners = {}
local showCredits = {}
local hideCredits = {}
local showGameView = {}
local gameListeners = {}
local startGame = {}
local hitTestObjects = {}
local update = {}
local movePaddle = {}
local alert = {}

19. Constructor

Next, we create the function that will initialize the game logic.

function Main()
  -- code...
end

20. Add Title View

We start by placing the title view in the stage and call a function that will add tap listeners to the buttons.

function Main()
  titleBg = display.newImage('titleBg.png', 26, 72)
  playBtn = display.newImage('playBtn.png', 125, 225)
  creditsBtn = display.newImage('creditsBtn.png', 115, 290)
  titleView = display.newGroup(titleBg, playBtn, creditsBtn)
  startButtonListeners('add')
end

21. Start Button Listeners

The following function adds the necessary listeners to the TitleView‘s buttons.

function startButtonListeners(action)
  if(action == 'add') then
    playBtn:addEventListener('tap', showGameView)
    creditsBtn:addEventListener('tap', showCredits)
  else
    playBtn:removeEventListener('tap', showGameView)
    creditsBtn:removeEventListener('tap', showCredits)
  end
end

22. Show Credits

The credits screen is shown when the user taps the about button. A tap listener is added to the credits view to dismiss it when the user taps it.

function showCredits:tap(e)
  playBtn.isVisible = false
  creditsBtn.isVisible = false
  creditsView = display.newImage('credits.png', 0, display.contentHeight)
  lastY = titleBg.y
  transition.to(titleBg, {time = 300, y = (display.contentHeight * 0.5) - (titleBg.height + 50)})
  transition.to(creditsView, {time = 300, y = (display.contentHeight * 0.5) + 35, onComplete = function() creditsView:addEventListener('tap', hideCredits) end})
end

23. Hide Credits

When the user taps credits view, it is animated out of the stage and removed.

function hideCredits:tap(e)
  transition.to(creditsView, {time = 300, y = display.contentHeight + 25, onComplete = function() creditsBtn.isVisible = true playBtn.isVisible = true creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end})
  transition.to(titleBg, {time = 300, y = lastY});
end

24. Show Game View

When the play button is tapped, the title view is animated off the screen and the game view is revealed. There are a number of moving parts so we’ll take a closer look at each of them.

function showGameView:tap(e)
  transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil bg:addEventListener('tap', startGame) end})

25. Instructions Message

The following code snippet adds the instruction message.

ins = display.newImage('ins.png', 112, 370)

26. Paddle Parts

Next, we add the paddle parts. It is split up into two parts for better collision detection.

-- Paddle
  paddleBottom = display.newImage('paddleBottom.png', 138.6, 262)
  paddleTop = display.newImage('paddleTop.png', 110, 166)
  paddle = display.newGroup(paddleBottom, paddleTop)

27. Ball

We add the ball and set its scale.

-- Ball
  ball = display.newImage('ball.png', 146, 201)
  ball:scale(scale, scale)

28. Score

We create a score text field at the top right of the stage.

-- Score
  score = display.newImage('score.png', 260, 0)
  scoreTF = display.newText('0', 278, 21, 'Marker Felt', 30)
  scoreTF:setTextColor(238, 238, 238)
  gameListeners('add')
end

29. Game Listeners

The following function adds the necessary listeners for starting the game logic.

function gameListeners(action)
  if(action == 'add') then
    bg:addEventListener('touch', movePaddle)
  else
    bg:removeEventListener('touch', movePaddle)
    Runtime:removeEventListener('enterFrame', update)
  end
end

30. Start Function

The startGame function removes the instruction message and adds a listener to the main function of the game. In the function, a random y position is selected from the previously created table and subsequently adds physics to the newly created object. We add a collision listener to every enemy and also add them to the enemies table.

function startGame()
  display.remove(ins)
  bg:removeEventListener('tap', startGame)
  Runtime:addEventListener('enterFrame', update)
end

31. Hit Test Objects

For collision detection without using physics, we use a great function, which you can find on the Corona Labs Code Exchange website.

function hitTestObjects(obj1, obj2)
        local left = obj1.contentBounds.xMin <= obj2.contentBounds.xMin and obj1.contentBounds.xMax >= obj2.contentBounds.xMin
        local right = obj1.contentBounds.xMin >= obj2.contentBounds.xMin and obj1.contentBounds.xMin <= obj2.contentBounds.xMax
        local up = obj1.contentBounds.yMin <= obj2.contentBounds.yMin and obj1.contentBounds.yMax >= obj2.contentBounds.yMin
        local down = obj1.contentBounds.yMin >= obj2.contentBounds.yMin and obj1.contentBounds.yMin <= obj2.contentBounds.yMax
        return (left or right) and (up or down)
end

32. Scale Ball

The update function, shown below, runs every frame. In this function, we first scale the ball based on the values set by the variables.

function update()
  -- Scale Balls
  scale = scale - variation
  ball.xScale = scale
  ball.yScale = scale

33. Ball Raise

This part increases the ball size to simulate an increase in its height.

-- Raising
  if(math.floor(ball.xScale * 10) >= 15) then
    variation = 0.05
  end

34. Ball Missed

The same method is used to check if the ball has touched the floor, an essential aspect of the game.

-- Missed
  if(math.floor(ball.xScale * 10) < 3) then
    alert()
  end

35. Move Ball

In the following code snippet, we move the ball. Based on the value of the variables, it is moved up or down.

-- Move Ball
  ball.x = ball.x - ballX
  ball.y = ball.y - ballY

36. Ball Hit

A scale is set to be the same paddle height, which means that the ball has touched the paddle. We then increase the score and play a sound to provide feedback to the user.

-- Falling and Hit with paddle
  if(math.floor(ball.xScale * 10) == 3 and hitTestObjects(paddleTop, ball)) then
    variation = -0.05
    -- Increase Score
    scoreTF.text = tostring(tonumber(scoreTF.text) + 1)
    -- Play Sound
    audio.play(pong)

37. Change Ball Direction

The paddle is divided in four sections, top left, top right, bottom left, and bottom right. Each section moves the ball in a different direction.

-- Move Ball based on where it hits
    if(ball.x < paddle.x + 50) then       ballX = (math.random() * 0.5) + ballVar     end     if(ball.x  > paddle.x) then
      ballX = (math.random() * -0.5) - ballVar
    end
    if(ball.y < paddle.y + 75) then       ballY = (math.random() * 0.5) + ballVar     end     if(ball.y > paddle.y - 70) then
      ballY = (math.random() * -0.5) - ballVar
    end
    -- Increase moving distance
    ballVar = ballVar + 0.025 -- Every four hits increases 0.1
  end
end

38. Move Paddle

The movePaddle function handles the movement of the paddle using touch controls.

function movePaddle(e)
  if(e.phase == 'moved') then
    paddle.x = e.x
    paddle.y = e.y
  end
end

39. Alert

The alert function creates an alert view. The function animates the alert view onto the screen and ends the game.

function alert()
  gameListeners('rmv')
  alert = display.newImage('alert.png', (display.contentWidth * 0.5) - 105, (display.contentHeight * 0.5) - 55)
  transition.from(alert, {time = 300, xScale = 0.5, yScale = 0.5})
end

40. Call Main Function

In order to start the game, the Main function needs to be invoked. With the rest of the code in place, we do that here.

Main()

41. Loading Screen

Loading Screen

On the iOS platform, the file named Default.png is displayed while the application is launching. Add this image to your project’s source folder, it will be automatically added by the Corona compiler.


42. Icon

Icon

Using the graphics you created earlier, you can now create a nice icon. The dimensions of the icon size for a non-retina iPhone are 57px x 57px, while the retina version needs to be 114px x 114px. The artwork for iTunes is required to be 1024px x 1024px. I suggest creating the iTunes artwork first and then creating the smaller sized images by scaling the iTunes artwork down to the correct dimensions. There is no need to make the application icon glossy or add rounded corners as this is taken care of by the operating system for you.


43. Testing in Simulator

Testing

It’s time to test our application in the simulator. Open the Corona Simulator, browse to your project folder, and click Open. If everything works as expected, you’re ready for the final step.


44. Build Project

Build

In the Corona Simulator, go to File > Build and select the target device. Fill out the required fields and click Build. Wait a few seconds and your application is ready to test on a device and/or to be submitted for distribution.


Conclusion

In this tutorial, we’ve learned about touch listeners, and collision detection. Experiment with the final result and try to modify the game to create your own version of the game. I hope you liked this tutorial and found it helpful. Thank you for reading.

Corona SDK: Build a Frogger Inspired Game – Interface Creation

In this tutorial series, I’ll be showing you how to create a Frogger Inspired game with the Corona SDK. You’ll learn about moving objects across the screen and detect when they are colliding using the physics engine. The objective of the game is to move the Frog on the stage to its containers without being hit by an obstacle. Read on!

1. Application Overview

App Overview

Using pre made graphics we will code an entertaining game using Lua and the Corona SDK API’s.

The player will be able to use the on-screen pad to move the frog and get it to the other side, you can modify the parameters in the code to customize the game.

2. Target Device

Target Device

The first thing we have to do is select the platform we want to run our app within, this way we’ll be able to choose the size for the images we will use.

The iOS platform has these characteristics:

  • iPad 1/2/Mini: 1024x768px, 132 ppi
  • iPad Retina: 2048×1536, 264 ppi
  • iPhone/iPod Touch: 320x480px, 163 ppi
  • iPhone/iPod Retina: 960x640px, 326 ppi
  • iPhone 5/iPod Touch: 1136×640, 326 ppi

Because Android is an open platform, there are many different devices and resolutions. A few of the more common screen characteristics are:

  • Asus Nexus 7 Tablet: 800x1280px, 216 ppi
  • Motorola Droid X: 854x480px, 228 ppi
  • Samsung Galaxy SIII: 720x1280px, 306 ppi

In this tutorial, we’ll be focusing on the iOS platform with the graphic design, specifically developing for distribution to an iPhone/iPod touch, but the code presented here should apply to Android development with the Corona SDK as well.


3. Interface

Interface

A simple and friendly interface will be used. This involves multiple shapes, buttons, bitmaps and more.

The interface graphic resources necessary for this tutorial can be found in the attached download.

Frogger Sprite Pack.


4. Export Graphics

Export Graphics

Depending on the device you have selected, you may need to export the graphics in the recommended PPI. You can do this in your favorite image editor.

I used the Adjust Size… function in the Preview app on Mac OS X.

Remember to give the images a descriptive name and save them in your project folder.


5. App Configuration

An external file will be used to make the application go fullscreen across devices, the config.lua file. This file shows the original screen size and the method used to scale that content in case the app is run in a different screen resolution.

application =
{
    content =
    {
        width = 320,
        height = 480,
        scale = "letterbox"
    },
}

6. Main.lua

Let’s write the application!

Open your prefered Lua editor (any Text Editor will work, but you won’t have syntax highlighting) and prepare to write your awesome app. Remember to save the file as main.lua in your project folder.


7. Code Structure

We’ll structure our code as if it were a Class. If you know ActionScript or Java, you should find the structure familiar.

Necessary Classes
Variables and Constants
Declare Functions
    contructor (Main function)
    class methods (other functions)
call Main function

8. Hide Status Bar

display.setStatusBar(display.HiddenStatusBar)

This code hides the status bar. The status bar is the bar on top of the device screen that shows the time, signal, and other indicators.


9. Import Physics

We’ll use the Physics library to handle collisions. Use this code to import it:

-- Physics
local physics = require('physics')
physics.start()
physics.setGravity(0, 0)

10. Background

Background

A simple graphic is used as the background for the application interface, the next line of code stores it.

-- Graphics
-- [Background]
local bg = display.newImage('bg.png')

11. Title View

Title View

This is the Title View, it will be the first interactive screen to appear in our game, these variables store its components.

-- [Title View]
local title
local playBtn
local creditsBtn
local titleView

12. Credits View

Credits View

This view will show the credits and copyright of the game, this variable will be used to store it.

-- [CreditsView]
local creditsView

13. Game Background

Game Background

This image will replace our previous background. This will be the game background.

-- Game Background
local gameBg

14. Frog

Instructions

The frog you will be able to control.

-- Frog
local frog

15. Pad

Place Holders

This is the on-screen pad used to move the frog around the level.

-- [Pad]
local up
local left
local down
local right


16. Cars

Shapes

The obstacles the player needs to avoid to cross to the other side.


17. Alert

Alert

This is the alert that will be displayed when you win the game. It will complete the level and end the game.

  -- Alert
  local alertView


18. Sounds

Sounds

We’ll use Sound Effects to enhance the feeling of the game, the sounds used in this app were generated by AS3SFXR.

-- Sounds
local moveSnd = audio.loadSound('move.mp3')
local loseSnd = audio.loadSound('lose.mp3')
local goalSnd = audio.loadSound('goal.mp3')

19. Variables

This are the variables we’ll use. Read the comments in the code to learn more about them.

-- Variables
local lastY --Used to reposition the titleView after credits tween
local obstacles --Obstacles group
local counter = 0 --Counts the frogs that had crossed the street

20. Declare Functions

Declare all functions as local at the start.

-- Functions
local Main = {}
local startButtonListeners = {}
local showCredits = {}
local hideCredits = {}
local showGameView = {}
local gameListeners = {}
local addObstacle = {}
local movePlayer = {}
local update = {}
local onCollision = {}
local alert = {}

21. Constructor

Next we’ll create the function that will initialize all the game logic:

function Main()
	-- code...
end

22. Add Title View

Now we place the TitleView in the stage and call a function that will add the tap listeners to the buttons.

function Main()
	title = display.newImage('title.png', 64, 130)
	playBtn = display.newImage('playBtn.png', 134, 245)
	creditsBtn = display.newImage('creditsBtn.png', 114, 305)
	titleView = display.newGroup(bg, title, playBtn, creditsBtn)
	startButtonListeners('add')
end

Next Time…


In this part of the series you’ve learned the interface and the basic setup of the game. In the next and final part of the series, we’ll handle the level creation, collision detection, and the final steps to take prior to release like app testing, creating a start screen, adding an icon and, finally, building the app. Stay tuned for the final part!