javaenumsroguelike

Is enumeration the right tool for generating creatures in a roguelike game?


I'm developing a roguelike game as a programming/database excercise and a hobby(and because I want to have my own "Dwarf Fortress" project to lord over as I please). I got stuck quite early while trying to write a robust enough system to generate various creatures in the game. I started simple; lets say I want the game to spit out a wolf somewhere(FXML, so Controller):

public class Controller {
    Creature pooch = new Creature(Species.WOLF);
}

Now, I'd like to be able to spawn these ordinary animals by only specifying their species, so that's what enumerations are for, no? I want to specify that wolves only eat meat, their possible body sizes(they're not clones after all, and where else to specify the sizes?), and the body type they have:

public enum Species {
    // Canines
    WOLF(Diet.CARNIVORE, 1050, 1325, 1600, CANINE.BodyPattern);

    // Canine constructor
    Species(Diet diet, double bodySizeMultiplierMin, double bodySizeMultiplierAvg, double bodySizeMultiplierMax,
            BodyPattern bodyPattern) {
        this.diet = diet;
        this.bodySizeMultiplierMin = bodySizeMultiplierMin;
        this.bodySizeMultiplierAvg = bodySizeMultiplierAvg;
        this.bodySizeMultiplierMax = bodySizeMultiplierMax;

    }

I want to reuse the same pattern for dogs, jackals, etc., so I only pass the body type, to be defined in another enum.

enum BodyPattern {

    CANINE(furryUpperBody, furryLowerBody, canineHead, canineMaw, canineLegs, furryTail);

    LinkedList<BodyPart> bodyPartsList;

    BodyPattern(BodyPart... args) {
        for (BodyPart  part : args) {
            bodyPartsList.add(part);
        }
    }
}

This is where I'm getting really lost(I didn't actually define any of those body parts, as I wasn't sure how to proceed). This is what I have for BodyPart so far:

public class BodyPart {

    public String name;

    private TissueLayer[] tissueLayersUp;
    private TissueLayer[] tissueLayersDown;
    private TissueLayer[] tissueLayersFront;
    private TissueLayer[] tissueLayersBack;
    private TissueLayer[] tissueLayersLeft;
    private TissueLayer[] tissueLayersRight;

    public BodyPart(String name, BodyPart[] appendages, int height, int width, int length, TissueLayer[] tissueLayersUp,
                    TissueLayer[] tissueLayersDown, TissueLayer[] tissueLayersFront, TissueLayer[] tissueLayersBack,
                    TissueLayer[] tissueLayersLeft, TissueLayer[] tissueLayersRight) {
        this.name = name;
        this.appendages = appendages;
        this.height = height;
        this.width = width;
        this.length = length;
        this.tissueLayersUp = tissueLayersUp;
        this.tissueLayersDown = tissueLayersDown;
        this.tissueLayersFront = tissueLayersFront;
        this.tissueLayersBack = tissueLayersBack;
        this.tissueLayersLeft = tissueLayersLeft;
        this.tissueLayersRight = tissueLayersRight;
    }
}

Tissue layers are the stuff that makes up the body parts, and are specified for each direction separately so that for example an attack against the front of the head damages the face, while an attack from the back goes against the neck/upper spine first. I want their thickness to be defined in relative terms only, to be multiplied upon generation by the size of the creature to generate the actual size, but as I said, I'm getting a bit lost, So where do I go from here? Should I reassign BodyPart as enum? Should I make another enum entirely? Am I completely off the track and should I use some different tool?


Solution

  • Now, I'd like to be able to spawn these ordinary animals by only specifying their species, so that's what enumerations are for, no?

    I'm afraid not, no.

    The best use case for enums is the enumeration of a set of objects which are constants and the identities of all of which are known at compile time. An example of data for which enums are ideal is playing cards or the planets of the solar system. Playing card suits and numbers are fixed, constant, and known in advance. Similarly, the planets in the solar system do not (frequently) change.

    Since you want to be able to dynamically create objects at need, you'll want to use ordinary classes with constructors to create new objects (such as animals) when your program needs them. It would be difficult to imagine a game that knows in advance all the animals it needs (with all their properties).