Skip to content

Interface design and programming process

The aim of this project is not to develop a game but to show how it could interact with a device. So, this is a prototype of the idea of the game. The most important part of this process is the sync and loading of the steps in the device with the game.

As I stated during the Interface app & programming week, I used a free template from a Space Shooter game that I downloaded from Unity Assets Store. In this section of the documentation, I will explain all the changes that I made to this template and which other resources I used.

Check Interface app & programming week for information about Bluetooth and how I integrated it with the game.

Unity 3D game development

Before starting, I created this diagram to understand how things should work. Currently, not everything is working like this. Some parts are simulated, like for example the ‘counting steps’ screen. Steps are synced on the game screen because I added this screen later and didn’t have enough time to integrate it properly.

game diagram

Replacing the sprites

The simplest of all is to change the sprites. It is not a requirement but I wanted the whole project to have graphic coherence.

template evolution

Basically what I did was take the sprites that were in the project, import them into illustrator and draw my own sprites of the same size and then export them as .png and replace them.

template evolution

How to create the new screens for the game?

To create a new screen we need to create an empty object. Inside this object, we’ll be able to add other elements like backgrounds or UI components. I decided to create objects instead of Scenes because I was going to use the same camera and it’s easier to change from one screen to the next one.

template evolution

How to create buttons and other UI components?

To create the buttons use a library called Lean GUI that is very easy to use. They have several example components but I only needed a couple of buttons. They are very easy to modify and everything can be done from the Unity interface without modifying anything in the scripts.

In order to add a UI element it is necessary to create a canvas. The canvas contains all the UI elements of the screen. In this case, using an example, it already comes with a canvas.

template evolution

For the progress bar, I did the same but instead of using Lean GUI I downloaded another library called Beautiful Progress Bar Free - CYKO, also available for free in the Unity store.

How to move from one screen to the next one?

To move from one screen to the next one we need to use a script. In this case I created the followin script called TransitionController:

//required libraries
using System.Collections; 
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;

#region Serializable classes
[System.Serializable]

#endregion

public class TransitionController : MonoBehaviour {

    [SerializeField] // allows to assign objects in the unity UI 
    GameObject walk, game, welcome, steps; // reference to all game screens

    [SerializeField]
    LevelController levelController; // component that manages the game state

    public async void GoWalk() { // function that is called when the ship is destroyed 
        await Task.Delay(3000); 
        levelController.StopGame();
        game.SetActive(false); // inactive game screen
        walk.SetActive(true);  // set active walk screen
    }

    public void StartGame()  // function that is called when collecting step finishes
    {
        steps.SetActive(false); // inactive counting steps screen
        game.SetActive(true); // set active game screen
    }

}
This is how the UI looks when using ‘SerializeField’

OnClick

When Jump to start button is pressed it sets the collecting steps screen to active and sets the Welcome screen to inactive. Then, when the collectin steps screen finished collecting all the steps showing that on the progress bar it will set the collecting steps screen to inactive and the game screen to activate. To do this a new script needed to be added. This one is called StepController:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class StepController : MonoBehaviour
{
    private float var; // value that is being charged on the progress bar
    private float steps = 10f; // amount of steps that the progress bar will sum up (this is simulated for now)

    // this will let us control the slider using the UI  
    [SerializeField]
    private Slider stepsBar; 

    [SerializeField]
    private TransitionController transitionController; 

    // Update is called once per frame
    void Update()
    {
        var = Mathf.Lerp(var, steps, 1 * Time.deltaTime); // lerp is a function form Unity math package. Interpolates A and B by T, which means that it will try to grow from the origin value (var) to the maximum value (steps) this what simulates that the progress bar fill animation 

        stepsBar.value = var;

        // Advanced when charge is above 90%
        if (var / steps > 0.9) {
            transitionController.StartGame(); // calls the function start game from TransitionController script
        }
    }
}

LevelController scrip is the one that manage the game

LevelController script

When the ship is destroy ‘StopGame’ is called and it will stop the game and go to ‘go to walk’ screen

When the game starts there are 3 different routines running:

  • Planets moving
  • Enemies waves
  • Bonus

  public void StopGame() {
        foreach (Coroutine c in routines)
        {
            if (c != null ){
                StopCoroutine(c); // all game routines are stoped 
            }
        }

        // look for all the things that already are in the screen and errase them
        foreach (var p in GameObject.FindGameObjectsWithTag("Planet"))
        {
            if (p != null)
            {
                Destroy(p);
            }
        }

        foreach (var p in GameObject.FindGameObjectsWithTag("Projectile"))
        {
            if (p != null)
            {
                Destroy(p);
            }
        }

        foreach (var p in GameObject.FindGameObjectsWithTag("Bonus"))
        {
            if (p != null)
            {
                Destroy(p);
            }
        }

        foreach (var e in GameObject.FindGameObjectsWithTag("Enemy"))
        {
            if (e != null)
            {
                Destroy(e);
            }
        }
    }
Then the script will call ‘LevelController’ to change the screen.

How to load the steps into the game?

There is a script called ‘PlayerBluetoothConnect’ which uses the library that I’ve used during the Interface app & programming week.

PlayerBluetoothConnect

Part of the script that sends a Y to the device to errase the steps and go back to 0

//  HM10_Status.text = "Received Serial: " + Encoding.UTF8.GetString (bytes);
                    string data = Encoding.UTF8.GetString (bytes); //getting the bluetooth data and turning it into text to be able to process it (data = y : x)
                    Debug.Log(data + " bluetooth " + Player.instance + "pepe");
                    string[] values = data.Split(':'); //values to recieve and tranform into an array (split the x and the y into separate values --> values = ["10.0","20.0"])
                    AngleY = float.Parse (values[0]); // variable Y: transform the text for Y into a number
                    AngleX = float.Parse (values[1]); //Variable X: transform the text for X into a number
                    Steps = int.Parse (values[2]); //Variable Steps: transform the text for X into a number
                    if(Steps > 0 && Player.instance != null && !Player.instance.gameObject.activeInHierarchy)//if the player is not active and steps are more than 0 
                    {
                        LevelController.UpdateSteps(Steps);//Updates the steps from the device
                        SendString ("Y");
                    }
                    });

How add the music?

Adding music is simple. You just have to add the files inside the assets in a folder, then create an Audio Source on the screen where we want to put that music and drag the music file to the input field called AudioClip.

Music

Device interface

I did this diagram at the same time as the one for the software. The goal was to use him as a guide during the process. Some things don’t work yet but this illustrates how the prototype should work in an ideal world.

hardware diagram

Counting the steps using the accelerometer

During the Interface app & programming week I documented how to show the faces on the OLED and how to switch from the sad face to the happy face when the device moved.

On this part of the code I just added a delay because the face was changing too fast.

//If the user walks then change the face
  if (steps - prevSteps > 0) {
    oled.bitmap(0, 0, 128 , 8, happyface_bitmap); //happy face
    lastHappyTime = millis(); //asign the amount of time since the board was on and the face was happy
    //decide how much to wait to change the face back to sad
  } else if ( millis() - lastHappyTime > 5000) {
    oled.bitmap(0, 0, 128 , 8, sadface_bitmap); //sad face

  }

Additionally I added this to send the steps to the game and then restet the value to 0:

prevSteps = steps; //update step count

  //read the value from the bluetooth
  char readCommand = bluetooth.read();
  resetSteps(readCommand);
  calibrate(readCommand);

}


void resetSteps(char c) {
  if (c == 'Y') {
    steps = 0;
  }
}
After syncing the software sends a ‘Y’ to the device which makes the number of steps go back to 0.

steps to 0

I also added this part to send a ‘C’ to the device for calibration. I didn’t implement this yet on the game code.

void calibrate(char c) {
  if (c == 'C') {
    mpu.calcOffsets(true, true); // gyro and accelero

  }
}

Connecting the device with the game and using the gyroscope to play

I documented this on Interface app & programming week but as I was having some issues with the values that I was getting from the gyroscope so decided to chage the library from which was a little bit old to . With this change the values become more stable.

Find the final files here:


Last update: June 8, 2021