Reputation: 678
I have in mind an idea for my first java project (OO focused). This project is some kind of a very basic roleplaying game (NO GUI, it's very basic), so I have some OOD questions.
A player (no player class is intended, at least for now) can choose a character class (you know, fighter, wizard etc... in the future he might be able to choose a few characters so he can have a party). After the character has been created he can fight against other foes (controlled by the program).
Each character has some methods like:
Attack (use a weapon, if he's a spell caster then casting spells also can use Attack).
Some character classes (like wizards) can Cast Spells. Most spells will are offensive or defensive, so they can use Attack or Defend method. let's say that castFireball can call Attack(20) for example. Some spells can do other things like castHeal which heals the character and changes the current hit points.
Buy (optional for future). same implementation for all characters of course.
Suggested implementation: I thought about creating an abstract class (with info like Level, Armor class, Abilities (like strength, dexterity, wisdom etc.). and some methods like attack and defend. Other specific classes will extend Character so it looks like:
Character (abstract)
Character Class (like fighter)
Level
Hit Points
Current Hit Points
Armor Class
.
.
.
Inventory (List)
Strength
Dexterity
Wisdom
Fighter Wizard Rouge Cleric (All extends Character)
Questions:
Keep in mind that it should be basic, but it should be planned for future changes and additions. It would look like:
How would you like to attack?
3
Which spell would you like to cast?
1
You hit the enemy with a fireball, and dealt 20 damage.
It's very vague, but you get the idea..
Thanks a lot !!
Upvotes: 2
Views: 850
Reputation: 37940
Generally, class B
should be a subclass of A
only if there is an is-a relationship between them - that is, if it would make sense to say that any instance of B
also is an instance of A
. By applying this, you can e.g. see that the character classes are the only viable candidates for subclasses of Character
: A Warrior
is a Character
, but it is not the case that a Weapon
is a Character
. Instead, there is a has-a relationship between the other classes and Character
: a Character
has a Weapon
. In that situation, you should use composition: the Character
class could have a field of the type Weapon
(or, more likely, a field of the type List<Weapon>
, so that you can have multiple weapons).
But even if you can make a class hierarchy, it's not certain that you should. If the differences between the character classes can wholly be implemented as differences in stats (which are presumably just fields in the class) or some simple ability differences, you might only need the Character
class. On the other hand, if the behavioral differences are huge and you'd end up with a bunch of if
statements to select the appropriate behavior for various character classes in different situations, it might be wise to introduce subclasses. However, as @plalx and @B. Dalton point out, it is often possible to use composition instead, extracting the behavioral differences to an abstract CharacterAbilities
class and its subclasses.
Upvotes: 1
Reputation: 12440
As for weapons, shields and spells, I would model them into two interfaces:
applyEffect()
method that modifies the abilities (possibly create a copy of base abilities, then run all passive items' applyEffect()
on those to get final abilities with items)performAction(Character self, Character target)
that would modify the tow combating characters in some way, e.g. HealSpell
implementation would increase character's hitpoints stat, Dagger
would perform an attack on the target.Upvotes: 0
Reputation: 1639
I would advise against making Character
an abstract base-class of (for instance) Fighter
. Being a fighter is only an attribute of the character. I simply tells you that he can wield a sword and wear plate-mail, for instance. In some games, it is assumed that a Warrior
character will always be a warrior. Then, when requirements change, so that a character can change class to, say, Mage, there is a whole data migration problem rather than simply a change of attributes. K
Keep your inheritance tree as shallow as you can. Use aggregation and composition instead of inheritance when you can.
Upvotes: 1
Reputation: 2437
Classes should have a single responsibility (or more specific a single reason to change)
1) Abstract class looks the way to go, as you can have common behaviour contained in the class, reducing duplication. An interface only defines the 'contract'
2) See opening statement, sounds like another responsibility.
3) See 2
4) Depends on content, classes may be better
5) Maybe a different abstract class inheriting fro character to determine spell properties. Avoid static methods. Also worth looking at a design pattern for spells. Could have an interface with a method 'castSpell' and each spell implements its own functionality.
Plenty of different options - Best to have a go and see what works. If you get stuck, post the code.
Upvotes: 0
Reputation: 19
Using an abstract class here works very well since all other character classes will be extended from this class and the class itself is never instantiated.
This is a matter of preference, if your abilities are more complex than integers you may consider making them a class, however if all you are doing is adding temporary buffs/debuffs I recommend having two integers for each ability: one for the current ability value and another for your base value without the buffs/debuffs.
Having inventory as a class is a good idea. Some people may be tempted to create an array of inventory items and manipulate it as the game requires. I think creating a separate class keeps everything nicely encapsulated, even if you are just manipulating an array.
Enumerations are useful in creating a weapon but I would also recommend a separate class for this as well. If you use enumerations for all items you may end up having to use a lot of math, specifically division and modular to get item types. Creating an item class and extending it to different item types allows all items to be contained in a common array using the parent class type while giving them different stats/abilities/uses.
Spells can follow similar to the way I described items above (in fact a spell could be an item if you wanted to hold them in your inventory). Make sure to have some enumerations to describe the spell and its function and then a method to interpret these when it is cast.
Upvotes: 0