-2

I am learning how to make a game for a school. In this game, I have three different types of ships: destroyer, carrier, and a speed boat. I will declare an entityType enum:

enum EntityType {DESTROYER, CARRIER, SPEEDBOAT};

I have to have an Entity class that looks like:

class Enitity 
{
private:
    float acceleration, turnRate, maxSpeed, minSpeed;
    std::string entityType;
public:
    Entity(EntityType type);
    ~Entity();
    //Rest of class
};

For each ship type, they have different values. I have different values for each type of ship and I am trying to figure the best way to initialize each type of ship. I have thought of three ways of doing this. I am also trying to make it so that I can build on this in the future as I get more ship types.


Option 1: Create a file that holds a EntityData struct and creates data for each ship type like:

struct EntityData
{
    float acceleration, turnRate, maxSpeed, minSpeed;
    std::string entityType;
};

EntityData DestroyerData;
DestroyerData.acceleration = 5;
DestroyerData.turnRate = 2; 
DestroyerData.maxSpeed = 35;
DestroyerData.minSpeed = 0;
DestroyerData.entityType = "Destroyer";

EntityData CarrierData;
CarrierData.acceleration =2;
.....

Then within the Entity class's constructor have a switch statement that if the entityType is DESTROYER set the class's data to the struct's data.

Entity::Entity(EntityType type)
{
    EntityData data;
    switch (type)
    {
    case EntityType::DESTROYER:
        data = DestroyerData;
        break;
    case EntityType::CARRIER:
        break;
    default:
        break;
    }

    acceleration = data.acceleration;
    maxSpeed = data.maxSpeed;
    //Rest of variables
}

Option 2: Use inheritance and make the Entity class the base class and have each ship type have it's own class. In it's class just have those values initialized in the constructor.

class Destroyer : public Entity 
{
public:
    Entity(EntityType type);
    ~Entity();
    //Rest of class
};

Destroyer::Destroyer()
    : acceleration(5),
      maxSpeed(35), 
      //Rest of variables
{
}

Option 3: Have all the information set within the Entity class based off of the Entity Type by using a switch statement in Entity's constructor and not use the data structs or inherited classes?

Entity::Entity(EntityType type)
{
    switch (type)
    {
    case EntityType::DESTROYER:
        maxSpeed = 42;
        //TODO: Set the rest of the variables for the DESTROYER
        break;
    case EntityType::CARRIER:
        //TODO: Set the rest of the variables for the CARRIER
        maxSpeed = 55;
        break;
    default:
        break;
    }
}

Which method is best and why?



If down voting - Please explain why you are down voting so I can improve my question.

Community
  • 1
  • 1
kingcobra1986
  • 971
  • 2
  • 14
  • 38
  • How would you expect that to affect performance in particular? – πάντα ῥεῖ Mar 07 '17 at 20:27
  • Perhaps a generic "Ship" class that is constructed and initialized by a factory function which sets the default values according to type (from a table or map of the pre-defined "ship types", not using a `switch` statement or similar)? – Some programmer dude Mar 07 '17 at 20:27
  • 1
    If all ships have the same set of parameters and only the values differ, both inheritance and defining an own struct for each type are overkill. Just use different objects of the same class. – Frank Puffer Mar 07 '17 at 20:30
  • @FrankPuffer so it would be best to have a switch statement in the constructor and based on the EntityType, the values are properly initialize? Also is it overkill because of how many files or does it affect performance in any way? – kingcobra1986 Mar 07 '17 at 20:32
  • 1
    @kingcobra1986 What about reading deeper into the [Prototype Pattern](https://sourcemaking.com/design_patterns/prototype/cpp/1)? – πάντα ῥεῖ Mar 07 '17 at 20:35
  • @kingcobra1986 _"**If down voting** - Please explain why you are down voting so I can improve my question."_ Well, provide a [MCVE] that clarifies your concerns. – πάντα ῥεῖ Mar 07 '17 at 20:37
  • @kingcobra1986: Switch statement in the constructor is probably no good idea. Better use a factory method or something similar. – Frank Puffer Mar 07 '17 at 20:39
  • Sorry to break this to you, but structs can also be sub-classes. – juanchopanza Mar 07 '17 at 21:03
  • @πάνταῥεῖ I added code to help you understand what i mean – kingcobra1986 Mar 07 '17 at 21:08
  • @kingcobra1986 What's `EntityType`? – πάντα ῥεῖ Mar 07 '17 at 21:11
  • Regarding your "Option 2", if all `Entity` children have the same data members, why not have them in the *parent*? Then make the parent `Entity` class have a protected constructor that takes values for the data as arguments, and e.g. `Destroyer` could invoke the parent constructor with the correct values. I.e. the `Destroyer` class would only have a single function: The constructor, and no data members. And make the child classes *structures* instead so you don't have to type the `public:`. :) – Some programmer dude Mar 07 '17 at 21:11
  • @πάνταῥεῖ it's a enum – kingcobra1986 Mar 07 '17 at 21:13
  • @Someprogrammerdude I meant to not copy the variables. I was just typing it up real quick for this post, I haven't written the actual code yet. – kingcobra1986 Mar 07 '17 at 21:15
  • To those with the downvotes, I have changed my original question to provide code and give a clearer example. Please let me know if it is still too confusing, because I would like this question reopened without having to copy/paste it in a new question. Thanks – kingcobra1986 Mar 07 '17 at 23:45

1 Answers1

1

The best way to utilize C++ OOP would be with inheritance. This would allow you to utilize a std::vector<*genericShip>fleet, and store all three types inside. Additionally, if, for example, a destroyer could fire a cannon, a carrier could launch an airplane, but a speed boat could not, this approach would allow you to implement functions for each. Another advantage is that if you need to individually tweak values for specific ships, that would be allowed in this approach, and lastly, you can add new ships with ease.

パスカル
  • 479
  • 4
  • 13