java – RPG item, character, and display

Question description

I am currently developing an RPG to gain programming experience. An RPG consists of many individual components such as the combat system, quest system and the item system. I decided to develop an item system first, before I develop the other parts.

I have made some philosophical thoughts on the question of how items can be mapped in object oriented code so that the code is easily understandable and suitable for further development. I would like to present my current status here and ask you whether my item concept is suitable for further development, or whether I have made design mistakes that lead to poor results in further development.

First of all, I took care of consumable items like food and potions.

Short description of my Item concept and the code

All items, whether they are items of equipment or can be consumed, have general values such as a name, a price, and can be assigned to a category. Therefore there is a corresponding base class.

Item.java

public class Item {
    protected String name;
    protected String category;
    protected int price;
    
    public Item(String name, String category, int price) {
        this.name = name;
        this.category = category;
        this.price = price;
    }
    
    public Item(String name, String category) {
        this(name, category, 0);
    }
    
    public String getName() {
        return name;
    }
    
    public String getCategory() {
        return category;
    }
    
    public int getPrice() {
        return price;
    }
}

Consumable Items are special: They can be consumed und then unfold an effect on the being that consumes an Item. I decided to create an interface that says that.

Consumable.java

public interface Consumable {
    public void unfoldEffect(Character character);
}

There are two ressources a player has: He has health and energy. The amount of health points decides how much blows he can take before he dies. The amount of energy decides how strong his attacks will be. And so there are items that fill up health and energy. Both are represented in different classes that are based on the Item-class and the Consumable-Interface.

HealthItem.java

// can be food (bread, water) or healing potions or stuff like that
public class HealthItem extends Item implements Consumable {
    private int healthPoints;
    
    public HealthItem(String name, String category, int price, int healthPoints) {
        super(name, category, price);
        this.healthPoints = healthPoints;
    }
    
    public int getHealthPoints() {
        return healthPoints;
    }
    
    public void unfoldEffect(Character character) {
        character.regenerateHealthPoints(healthPoints);
    }
}

And the enery-item-class:

EnergyItem.java

public class EnergyItem extends Item implements Consumable {
    private int energyPoints;
    
    public EnergyItem(String name, String category, int price, int energyPoints) {
        super(name, category, price);
        this.energyPoints = energyPoints;
    }
    
    public int getEnergyPoints() {
        return energyPoints;
    }
    
    public void unfoldEffect(Character character) {
        character.regenerateEnergyPoints(energyPoints);
    }   
}

And of course there has to be a class that represents characters that can act in the game. These class is the base class for human players and NPCs.

Character.java

public class Character {
    // could be an orc, animal, human and what the imagination has to offer
    private String species;
    // not every char must have a name. E. g. pigs usually dont have names
    private String name;
    private int healthPoints;
    private int healthPointsMax;
    private int energyPoints;
    private int energyPointsMax;
    
    public Character(String species, String name, int healthPoints, int healthPointsMax ,int energyPoints, int energyPointsMax) {
        this.species = species;
        this.name = name;
        this.healthPoints = healthPoints;
        this.healthPointsMax = healthPointsMax;
        this.energyPoints = energyPoints;
        this.energyPointsMax = energyPointsMax;
    }
    
    public Character(String species, String name, int healthPoints, int energyPoints) {
        this(species, name, healthPoints, healthPoints, energyPoints, energyPoints);
    }
    
    public Character(String species, int healthPoints, int energyPoints) {
        this(species, null, healthPoints, energyPoints);
    }
    
    public String getName() {
        return name;
    }
    
    public int getHealthPoints() {
        return healthPoints;
    }
    
    public int getHealthPointsMax() {
        return healthPointsMax;
    }
    
    public int getEnergyPoints() {
        return energyPoints;
    }
    
    public int getEnergyPointsMax() {
        return energyPointsMax;
    }
    
    public void regenerateHealthPoints(int healthPoints) {
        if (this.healthPoints + healthPoints > this.healthPointsMax) {
            this.healthPoints = healthPointsMax;
        } else {
            this.healthPoints += healthPoints;
        }
    }
    
    public void regenerateEnergyPoints(int energyPoints) {
        if (this.energyPoints + energyPoints > energyPointsMax) {
            this.energyPoints = energyPointsMax;
        } else {
            this.energyPoints += energyPoints;
        }
    }
}

The game output will be printed to the console. So there also should be a class that handles some recurring output tasks.

Display.java

public class Display {
    public static void health(Character character) {
        System.out.println("health points: " + character.getHealthPoints() + " / " + character.getHealthPointsMax());
    }
    
    public static void energy(Character character) {
        System.out.println("energy points: " + character.getEnergyPoints() + " / " + character.getEnergyPointsMax());
    }
    
    public static void healthAndEnergy(Character character) {
        health(character);
        energy(character);
    }
    
    public static void basicDetails(Item item) {
        System.out.println("name: " + item.getName());
        System.out.println("category: " + item.getCategory());
        System.out.println("price: " + item.getPrice());
    }
    
    public static void details(HealthItem item) {
        basicDetails(item);
        System.out.println("health bonus: " + item.getHealthPoints());
    }
    
    public static void details(EnergyItem item) {
        basicDetails(item);
        System.out.println("energy bonus: " + item.getEnergyPoints());
    }
}

And here is a test class that tests my program.

ItemTestMain.java

public class ItemTestMain {
    public static void main(String() args) {
        // Create Items
        HealthItem bred = new HealthItem("bred", "food", 0, 20);
        EnergyItem manaPotion =  new EnergyItem("mana potion", "potion", 0, 50);
        
        // create character
        Character klaus = new Character("Man", "Klaus Dieter", 5, 100, 20, 50);
        Display.healthAndEnergy(klaus);
        
        // Let the character consume items
        System.out.println("The Character consumes: ");
        Display.details(bred);
        bred.unfoldEffect(klaus);
        Display.healthAndEnergy(klaus);
        
        System.out.println("The Character consumes: ");
        Display.details(manaPotion);
        manaPotion.unfoldEffect(klaus);
        Display.healthAndEnergy(klaus);
    }
}