HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavaModerate

Implement "Upgrades" Feature for Game

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
implementgameforupgradesfeature

Problem

I am building a simple adventure game that has "upgrades" feature.

In this game, user controls one player, that can be upgraded to increase things such as:

  • Amount of gold earned



  • Maximum health



  • Attack power



  • (more of this would be added later, for example: defense upgrade, experience, etc.)



An "upgrade" has a max level cap, effects on each level of upgrade, and the cost for each upgrade.

Here's my current approach.

This is my Upgrades class, containing all possible upgrades:

public class Upgrades {

    public static final int GOLD_LEVEL_CAP = 10;
    public static final float GOLD_EFFECT_PER_LEVEL = 0.01f;
    public static final int[] GOLD_UPGRADE_COSTS = {
        100, 200, 300, 400, 500,
        600, 700, 800, 900, 1000
    };

    public static final int HEALTH_LEVEL_CAP = 10;
    public static final int HEALTH_EFFECTS_PER_LEVEL = 100;
    public static final int[] HEALTH_UPGRADE_COSTS = {
        100, 200, 300, 400, 500,
        600, 700, 800, 900, 1000
    };

    public static final int POWER_LEVEL_CAP = 5;
    public static final float POWER_EFFECT_PER_LEVEL = 0.05f;
    public static final int[] POWER_UPGRADE_COSTS = {
        1000, 2000, 3000, 4000, 5000
    };

}


And this is the class that stores the current upgrades: (owned by Player class)

public class UpgradeProgress {

    private int goldUpgradeLevel = 0;
    private int healthUpgradeLevel = 0;
    private int powerUpgradeLevel = 0;

    public void upgradeGold() {
        if (goldUpgradeLevel < Upgrades.GOLD_LEVEL_CAP) {
            goldUpgradeLevel++;
        }
    }

    // Getter
    public int getGoldUpgradeLevel() {
        return goldUpgradeLevel;
    }

    // and so on..
    // same for Health and Power
}


However, if I want to add a new upgrade, for example, I wanted to add a "Defense Upgrade". I should modify both Upgrades and UpgradeProgress classes.

Is this efficient and acceptable?

Or is there any better approach?

Solution

I don't know any Java, but I think I can give you some ideas that may help you refine this code and make it easier to extend. Take a look at my question about skill upgrades on this site, because I got some very good feedback on this and I think it is relevant to your situation.

Hard coding all of those values into the Upgrades class limits you in many ways. It is nice that everything is in in one place for the sake of easily editing it all at once, but as you note it is forcing you to change data in multiple places if you want to extend the class at all, or even if you want to add new kinds of Upgrades to the game.

What I suggest (which is also the suggestion made to me in the question I linked above) is to make a base Upgrade class (though possibly with a different name), and then make one for each of the Upgrades that you want in your game. Give it all the values that you are assigning in the Upgrades class, and give it the logic that you have in the UpgradeProgress class. This way, all of your Upgrades will have the same underlying properties and functionality, and you can create a limitless number of them without having to change anything. Just instantiate them with the values you want.

You may need a different base class for DefenseUpgrade or any other Upgrade that has different logic inside. It may or may not be a good idea to have it inherit from the original class, it just depends on how many of the properties and methods are the same. In general though, I would recommend composition over inheritance whenever possible.

This code may be wrong because I don't know Java but here is the basic idea I am suggesting (syntax improved by @Larethian):

public abstract class Upgrade {

    private int LEVEL_CAP;
    private float EFFECT_PER_LEVEL;
    private int[] UPGRADE_COSTS;

    private int currentUpgradeLevel = 0;

    protected Upgrade(int levelCap, float effectPerLevel, int[] upgradeCosts){
        LEVEL_CAP = levelCap;
        EFFECT_PER_LEVEL = effectPerLevel;
        UPGRADE_COSTS = upgradeCosts;
    }

    public void increaseUpgradeLevel() {
        if (currentUpgradeLevel < LEVEL_CAP) {
            currentUpgradeLevel++;
        }
    }

    // Getter
    public int getUpgradeLevel() {
        return currentUpgradeLevel;
    }

    public int getTotalEffect() {
        return effectPerLevel*currentUpgradeLevel;
    }

    //could have getters or setters for any properties necessary
}


The Player would either have a few of these upgrades and would call the necessary logic to increase their levels when appropriate, or the Player could have another class such as UpgradeCollection that could contain all of the Upgrades inside it.

Code Snippets

public abstract class Upgrade {

    private int LEVEL_CAP;
    private float EFFECT_PER_LEVEL;
    private int[] UPGRADE_COSTS;

    private int currentUpgradeLevel = 0;

    protected Upgrade(int levelCap, float effectPerLevel, int[] upgradeCosts){
        LEVEL_CAP = levelCap;
        EFFECT_PER_LEVEL = effectPerLevel;
        UPGRADE_COSTS = upgradeCosts;
    }

    public void increaseUpgradeLevel() {
        if (currentUpgradeLevel < LEVEL_CAP) {
            currentUpgradeLevel++;
        }
    }

    // Getter
    public int getUpgradeLevel() {
        return currentUpgradeLevel;
    }

    public int getTotalEffect() {
        return effectPerLevel*currentUpgradeLevel;
    }

    //could have getters or setters for any properties necessary
}

Context

StackExchange Code Review Q#58532, answer score: 17

Revisions (0)

No revisions yet.