Click here to Skip to main content
15,867,704 members
Articles / Game Development

Day 99 of 100 Days of VR: Endless Flyer – Creating A Database For Power-Up Upgrades

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
6 Feb 2019CPOL9 min read 2.1K  
How to create a database for power-up upgrades

Introduction

In this post, we’re going to put the finishing touches to our item shop!

In the previous post, we created a new scene for our Item Store and added the basic UI for the scene.

With the UI in place, we’re going to create the appropriate scripts today to:

  1. define a data model of what our power-up looks like and their costs
  2. save and load the player’s power-up level
  3. purchase our power-ups

Today’s going to be pretty script heavy, so let’s get to it.

Step 1: Creating Data Models for the Power-Ups

Step 1.1: Define What We Are Creating

We want to be able to buy upgrades for our power-ups, however, to do that, we need to represent something in the code that we can use.

Our goal is to be able to create a database of the sort to be able to define our power-up at each level.

We’re not going to do anything fancy to store this information like storing it in a database or a text file. Instead, we’re just going to store it in a class that we can access. We’ll see what I mean later.

What sort of representation do we need to use for our data? Here’s a couple that fits all our power-ups.

  1. Level – what is the level of this upgrade
  2. Effect – how effective is our power-up at the specific level, specifically, for magnet we’re going to increase our range, for multiplier the multiplier we use, and for invincible the speed we travel at
  3. Cost – how many coins does it cost to buy the upgrade

Those three criteria will be used to define what our power-ups will look like.

Step 1.2: Creating the Script

Now that we have defined the 3 criteria that we are looking for, let’s translate this into code.

  1. Create a new script called PowerUpsDatabase, just like our DataManager, this will be a static class that we can reference whenever we want to get information.

Here’s what it looks like:

C#
public class PowerUpModel
{
    public int Level;
    public float Effect;
    public int Cost;

    public PowerUpModel(int level, float effect, int cost)
    {
        this.Level = level;
        this.Effect = effect;
        this.Cost = cost;
    }
}

public static class PowerUpsDatabase {
    public static PowerUpModel[] MagnetPowerUps = {
        new PowerUpModel(0, 15, 50),
        new PowerUpModel(1, 20, 100),
        new PowerUpModel(2, 25, 200),
        new PowerUpModel(3, 30, 400),
        new PowerUpModel(4, 35, -1)
    };

    public static PowerUpModel[] MultiplierPowerUps =
    {
        new PowerUpModel(0, 2, 50),
        new PowerUpModel(1, 3, 100),
        new PowerUpModel(2, 4, 200),
        new PowerUpModel(3, 5, 400),
        new PowerUpModel(4, 6, -1)
    };

    public static PowerUpModel[] InvinciblePowerUps =
    {
        new PowerUpModel(0, 2, 50),
        new PowerUpModel(1, 2.25f, 100),
        new PowerUpModel(2, 2.5f, 200),
        new PowerUpModel(3, 2.75f, 400),
        new PowerUpModel(4, 3, -1)
    };
}

Looking at the Code

There are two classes in this script:

The first one is PowerUpModel in which we are using to store the important values that we will use for each of our power-up upgrades: the level, the effect, and the cost to purchase. I added a constructor that we can use to pass in the level, effect, and cost variables when we create an instance of this class. All we do in the constructor is use the values we passed in and store it inside our class.

Next, we have PowerUpsDatabase which is a static class that any script can access that we create 3 arrays of PowerUpModel, we create 3 arrays, one for each of our upgrades. For each of our arrays, I created the initial PowerUpModels that we will use for our item store.

Now you might be wondering what the effect value will be used for. We won’t use them in today’s post, but essentially:

  1. Magnet – the effect will be used to determine the radius of our Magnet Collider. As we improve our magnet, our collection radius will get bigger and bigger
  2. Multiplier – the effect will be used to determine the multiplier value that we will multiply our score and coin with
  3. Invincible – the effect of the invincible will be used to determine the speed that the player will fly. At level 0, we will go 2x faster up to 3x faster at level 4.

None of the code here has any specific functionalities, they’re more like references that we can refer to later to figure out what effects we should use for the player.

Step 2: Save the Player’s Power-Up Level

Step 1.1: Store the Player’s Power-Up

After we have created the different upgrade levels for each of our three power-ups, we now need to know what level the player is at. This is the purpose of the Level field inside PowerUpModel.

Like how we store the player’s coin and score, we can store our power-up upgrade level in the exact same way.

Let’s make the changes to DataManager. Here’s what it looks like:

C#
using UnityEngine;

public class DataManager 
{
    private static string _coinKey = "Coin";
    private static string _scoreKey = "Score";
    private static string _magnetLevelKey = "Magnet";
    private static string _multiplierLevelKey = "Multiplier";
    private static string _invincibleLevelKey = "Invincible";

    public static int LoadCoin()
    {
        return PlayerPrefs.GetInt(_coinKey, 0);
    }

    private static void SaveCoin(int coin)
    {
        PlayerPrefs.SetInt(_coinKey, coin);
    }

    public static int LoadScore()
    {
        return PlayerPrefs.GetInt(_scoreKey, 0);
    }

    private static void SaveScore(int score)
    {
        PlayerPrefs.SetInt(_scoreKey, score);
    }

    public static void AddCoin(int coin)
    {
        int totalCoin = LoadCoin() + coin;
        SaveCoin(totalCoin);
    }

    public static void BuyUpgrade(int coin)
    {
        int currentCoin = LoadCoin();
        if (currentCoin >= coin)
        {
            SaveCoin(currentCoin - coin);
        }
    }

    public static void AddNewScore(int score)
    {
        if (LoadScore() < score)
        {
            SaveScore(score);
        }
    }

    public static int LoadMagnetLevel()
    {
        return PlayerPrefs.GetInt(_magnetLevelKey, 0);
    }

    public static int LoadMultiplierLevel()
    {
        return PlayerPrefs.GetInt(_multiplierLevelKey, 0);
    }

    public static int LoadInvincibleLevel()
    {
        return PlayerPrefs.GetInt(_invincibleLevelKey, 0);
    }

    public static void IncreaseMagnetLevel()
    {
        IncreaseLevel(_magnetLevelKey, PowerUpsDatabase.MagnetPowerUps.Length - 1);
    }

    public static void IncreaseMultiplierLevel()
    {
        IncreaseLevel(_multiplierLevelKey, PowerUpsDatabase.MultiplierPowerUps.Length - 1);
    }

    public static void IncreaseInvincibleLevel()
    {
        IncreaseLevel(_invincibleLevelKey, PowerUpsDatabase.InvinciblePowerUps.Length - 1);
    }

    private static void IncreaseLevel(string upgradeKey, int upgradeMaxLevel)
    {
        int currentLevel = PlayerPrefs.GetInt(upgradeKey, 0);
        if (currentLevel < upgradeMaxLevel)
        {
            PlayerPrefs.SetInt(upgradeKey, currentLevel + 1);
        }
    }
}

Looking at the Fields

The fields are straightforward, our data manager is going to keep track of our upgrade level for our three power-ups: magnet, multiplier, and invincible. The fields are the keys to access our database entry.

Walking Through the Code

  1. LoadMagnetLevel, LoadMultiplierLevel, LoadInvincibleLevel() are all public static functions that return to us the current level of the upgrades for the user.
  2. IncreaseMagnetLevel, increaseMultiplierLevel, IncreaseInvincibleLevel() are all public static functions that call IncreaseLevel with the specific power-up we’re going to increase and the max level from our PowerUpDatabase, for which we just use the length – 1. Yes, we could have just put in 4 since our power-ups are always size 5, however, if we ever decide to make changes, we’ll have to refactor our code. This makes our code future proof.
  3. Finally, we have IncreaseLevel() which is a private general function that will increase our power-up upgrade level that is called by the three functions mentioned above. The code is written this way to prevent us from carelessly increasing our level. For further checks, we make sure that the current level of the upgrade is lower than the max level. If it is, we change our key to be 1 higher than its current value
  4. We also added BuyUpgrade() we’ll be using this shortly, but we take in the cost of the upgrade, make sure that we can afford the upgrade and if we can, we save our new coin total to our PlayerPrefs.

Step 3: Add the Power-Up UI Script

Step 3.1: Create the Script

We have a model in code that we can use for our power-ups, we have a way for us to keep track of our current levels, now it’s time for us to create the script that we will use when interacting with our UI.

Create a new ItemStoreCanvasController script on our Item Store Canvas game object.

This script will define public functions that we will bind to Pointer Click events for clicking our button. Alongside that, we’ll also be writing some logic to display the text in our UI.

Here’s what the ItemStoreCanvasController looks like:

C#
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class ItemStoreCanvasController : MonoBehaviour {
    public Text CoinText;
    public Button MagnetButton;
    public Button MultiplierButton;
    public Button InvincibleButton;

    private Text _magnetBuyText;
    private Text _multiplierBuyText;
    private Text _invincibleBuyText;

    void Start ()
    {
        _magnetBuyText = MagnetButton.GetComponentInChildren<Text>();
        _multiplierBuyText = MultiplierButton.GetComponentInChildren<Text>();
        _invincibleBuyText = InvincibleButton.GetComponentInChildren<Text>();
        UpdateUI();
    }

    private void UpdateUI()
    {
        CoinText.text = "Coin: " + DataManager.LoadCoin();
        UpdateUpgradeButton(DataManager.LoadMagnetLevel(), 
        MagnetButton, _magnetBuyText, PowerUpsDatabase.MagnetPowerUps);
        UpdateUpgradeButton(DataManager.LoadMultiplierLevel(), 
        MultiplierButton, _multiplierBuyText, PowerUpsDatabase.MultiplierPowerUps);
        UpdateUpgradeButton(DataManager.LoadInvincibleLevel(), 
        InvincibleButton, _invincibleBuyText, PowerUpsDatabase.InvinciblePowerUps);
    }

    private void UpdateUpgradeButton(int upgradeLevel, Button button, 
                                     Text text, PowerUpModel[] powerUpModels)
    {
        // if our upgrade level is at the max level already, 
        // we set the text to say it's maxed and disable the button
        if (upgradeLevel >= powerUpModels.Length - 1)
        {
            button.interactable = false;
            text.text = "Maxed";
            return;
        }

        // Show the cost as our purchase button, however if we can't afford it, disable the button
        int coin = DataManager.LoadCoin();
        int cost = powerUpModels[upgradeLevel].Cost;
        text.text = cost.ToString();
        if (coin < cost) { button.interactable = false; } } 
        public void BuyMagnet() { print("buy magnet"); 
        int coin = DataManager.LoadCoin(); int level = DataManager.LoadMagnetLevel(); 
        int cost = PowerUpsDatabase.MagnetPowerUps[level].Cost; if (coin >= cost)
        {
            DataManager.BuyUpgrade(cost);
            DataManager.IncreaseMagnetLevel();
            // When we make a purchase, we have to update our UI to reflect our new state
            UpdateUI();
        }
    }

    public void BuyMultiplier()
    {
        int coin = DataManager.LoadCoin();
        int level = DataManager.LoadMultiplierLevel();
        int cost = PowerUpsDatabase.MultiplierPowerUps[level].Cost;
        
        if (coin >= cost)
        {
            DataManager.BuyUpgrade(cost);
            DataManager.IncreaseMultiplierLevel();
            // When we make a purchase, we have to update our UI to reflect our new state
            UpdateUI();
        }
    }

    public void BuyInvincible()
    {
        int coin = DataManager.LoadCoin();
        int level = DataManager.LoadInvincibleLevel();
        int cost = PowerUpsDatabase.InvinciblePowerUps[level].Cost;

        if (coin >= cost)
        {
            DataManager.BuyUpgrade(cost);
            DataManager.IncreaseInvincibleLevel();
            // When we make a purchase, we have to update our UI to reflect our new state
            UpdateUI();
        }
    }

    public void StartGame()
    {
        SceneManager.LoadScene(0);
    }
}

It’s been a while since we’ve seen a new long script! Let’s dig into it.

Looking at the Fields

  • public Text CoinText – The Text UI that we use for our string
  • public Button MagnetButton – The Button UI for the Magnet Button
  • public Button MultiplierButton – The Button UI for the Multiplier Button
  • public Button InvincibleButton – The Button UI for the Invincible Button
  • private Text _magnetBuyText – The Text UI for the text component in the Magnet Button
  • private Text _multiplierBuyText – The Text UI for the text component in the Multiplier Button
  • private Text _invincibleBuyText – The Text UI for the text component in the Invincible Button

Walking Through the Code

There’s quite a bit of code we have this time around. To help make sense of this code, we have to understand that the Controller has two purposes:

  1. Show the correct values for our UI. This includes displaying the accurate coins and shop upgrade costs when we buy something. As an extra, I also made the button appear not interactable if we can’t buy the upgrade anymore.
  2. Separate public click functions that will get called when a user clicks on the buttons we have in our UI. This includes our 3 buy buttons and our start game button.

Now that we understand this, let’s walk through the code.

  1. In Start(), we set up our script by getting the Text components from our Button and then we call UpdateUI() to set up the values of our UI.
  2. In UpdateUI(), we set to display our coin value and then call UpdateUpgradeButton() with information specific to our upgrade so we can write re-usable code to display our Buttons correctly.
  3. In UpdateUpgradeButton(), we are given the Button and Text of the button we want to change along with other information like which PowerUpModel we’re using and its current level. We disable our button if we’re at the max level or if we can’t afford the upgrade. We display the cost of the upgrade on button text, otherwise, we say Max if we already have the highest upgrade.
  4. BuyMagnet, BuyMultiplier, and BuyInvincible are all very similar. These are all public functions that will get bound to their corresponding buttons. When we click on them, we will check to see if we can afford the upgrade and if we can, we’ll call our DataManager to decrease our coin count and increase our upgrade level. Once we do that, we update our UI to reflect our new state.
  5. StartGame() is the function we bind to our Game Start button. In this function, we simply start to go back to our main scene to play the game.

Setting Up the Script

Almost there! We have our script now, we just need to set it up.

  1. Drag our Coin Text to the Coin Text slot, Buy Magnet to the Magnet Button slot, Buy Multiplier to the Multiplier Button Slot, Buy Invincible to the Invincible Button slot in our Item Store Canvas Controller script.

Here’s what it looks like:

Image 1

And then, we need to bind each of our Buttons to call our public function from this script.

  1. In Buy Magnet, create a new component called Event Trigger
  2. Create a new Pointer Down Event
  3. Add a new event to it and drag the Item Store Canvas game object to the slot
  4. Next, select the function to be called when this event gets fired, look for Item Store Canvas Controller > BuyMagnet

Do this for the other buy button and the Game Start button.

Here’s an example of what one looks like:

Image 2

End of Day 99

Once we have finished all of this, play the game, earn some money (or cheat like I did and put DataManager.AddCoin(10000) in Start() of any script) and then buy some upgrades.

Here’s what our result looks like:

Image 3

Pretty neat, right? As you can see, I already maxed out 2 of my upgrades and will be working on the Invincible one next.

The only problem is that these upgrades don’t really do anything in the game. In our final post in the 100 days challenge, we’re going to implement the upgrade level system to our game. It’s going to be glorious! I’ll see you all next time!

Day 98 | 100 Days of VR | Day 100

Home

The post Day 99 of 100 Days of VR: Endless Flyer – Creating A Database For Power-Up Upgrades appeared first on Coding Chronicles.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Joshua is a passionate software developer working in the Seattle area. He also has experience with developing web and mobile applications, having spent years working with them.

Joshua now finds his spare coding time spent deep in the trenches of VR, working with the newest hardware and technologies. He posts about what he learns on his personal site, where he talks mostly about Unity Development, though he also talks about other programming topic that he finds interesting.

When not working with technology, Joshua also enjoys learning about real estate investment, doing physical activities like running, tennis, and kendo, and having a blast with his buddies playing video games.

Comments and Discussions

 
-- There are no messages in this forum --