2
\$\begingroup\$

I have about 60 skills within my game, which are loaded from a JSON file. Each skill is a subclass of a skill object and has attributes like range, cost, target type, etc. Currently each skill has an integer index to identify the skill. Warrior skills begin at 100, wizard at 200, rogue at 300, etc.

Now I'm at a point where I'm implementing the mechanics of what these skills actually do, I have created an enumerated type with 60 integers corresponding to the indices from within a JSON file. And what I have right now is a switch statement with 60 cases:

enum SkillsEnum
{
    sPowerAttack = 100,
//59 more enums with skill names
}

-(void)doSkillActionWithTarget:(CharacterModel*)target
{
    DLog(@"Skill activated");

    switch (self.skillIndex) {
        case sPowerAttack:
        {
            //apply skill effect here
            break;
        }
     //59 more skills
     }
}

I'm working in Objective-C, an object oriented language and am interested if there's a better or more flexible to refer to skills within the game engine?

In other words, would there be any benefit from creating more specialized separate class hierarchies for skills, or passing them around as Maps/Dictionaries?

\$\endgroup\$
2
\$\begingroup\$

General advice is to start with the switch statement.

At some point you may notice that you're writing a lot of very similar code in different 'case' blocks within the switch statement. If and when you notice that, that's the time to refactor the code so that those similar cases can be coalesced into a single block.

Until then, go with the switch statement. It will get you back to coding your game more quickly than trying to do something clever at this point.

\$\endgroup\$
2
\$\begingroup\$

One alternative that avoids lengthy switch statements all over the program would be to define inside your Skill interface additional components that define its behavior. These components would be implementing an interface as well.

For example, all skills might contain an attack behavior, which could look like:

IAttackBehavior attackBehavior;

Creating an actual instance to put inside the attackBehavior can be done via a factory method, for example:

attackBehavior = attackBehaviorFactory::createAttack( /* relevant parameters here */ );

The parameters can be supplied by a JSON file as well. You would probably see some switch statements inside this factory method, but they would be contained to one place.

Once your attackBehavior is implemented, you could call it with:

mySkill.attack(target); // calls mySkill::attackBehavior(target) 

I'm not sure if this answers your question perfectly, so let me know if you have any questions.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.