Class Interaction

Started by
7 comments, last by starruler 15 years, 9 months ago
Say I had three classes: Battle, Monster, Skill. The monster class has attributes like Attack power and Defense as well as things like HP and XP plus a list of skills that it has. The skill class has a damage amount and then some representation of side-effects that it can impose. Side-effects are something like temporarily reducing the defense of the enemy, or raising your own attack, or a healing spell, etc etc. Damage that a certain Skill deals is based on a simple formula ATK + Damage - DEF. This game is loosely based off of Pokemon. So a battle would be something very similar to one in that series. It's turn based and on your turn you select one of your attacks. So my question is the best way to have these three classes interact?
Advertisement
You don't say what would be included in the "Battle" class, but I'd wager that Battle itself wouldn't be so much of a class as a single looping function that took in two monster classes as arguments. Purely from an abstract standpoint, I'd have a set of "states" (possibly booleans) that can be set in the Monster class, so that if a skill causes, lets say, poison, then in that particular skill's function you would set the target monster's isPoisoned state to true when used.

Are you still planning code, or is any of this written yet? Also, what language are you writing this in?

Hazard Pay :: FPS/RTS in SharpDX (gathering dust, retained for... historical purposes)
DeviantArt :: Because right-brain needs love too (also pretty neglected these days)

You're right about the battle class. I envision it as a sort of the game loop for the battle. I included it because maybe some of the temporary changes could go there. I'm using C++ and there isn't too much code to write until I've figured this out. I have outlined the Skill and Monster classes with what I stated in my first post however. The problem with states is say I had two skills. Scare and SuperScare that both lowered the attack of the enemy. These are essentially the same skill with SuperScare lowering the attack even more. States wouldn't be a great choice for this and instead a variable containing the amount the attack has been lowered would be a better choice.

This is one of the ways I have thought about implementing the interaction. I could have the Monster class contain a second variable for each of its attributes that is the current change. And the beginning or end of a battle these are reset. The main problem I have is where to have these variables be set. Is it the skill that changes them? The other Monster? I could try something like Skill::doIt(Attacker, Defender). But that's lots of accessors being called and lots of functions that have to be written (even if they're very small).
As for temporary effects:

// something like this?template <class T>class Attribute{public:	// Constructor	Attribute (T value = T()) m_Initial (value), m_Effective (value) { }	// Sets the initial value (retains the effective offset)	void SetInitial (T value) {		T delta = m_Initial - m_Effective;		m_Initial = value;		m_Effective = delta + m_Initial;	}	// Gets the initial value	T GetInitial (void) {		return m_Initial;	}	// Adds an effect to the current value	void AddEffect (T effect) {		m_Effective += effect;	}	// Removes an effect on the current value	void RemoveEffect (T effect) {		m_Effective -= effect;	}	// Gets the effective value (assuming all effects are monitored)	T Get (void) {		return m_Effective;	}private:	T m_Effective;	T m_Initial;};int main (){	Attribute<int> defense (100);	// when you strike a monster with a spell it reduces its defense for 2 seconds	defense .AddEffect (-40);		// ... wait 2 seconds in your loop then remove the effect	defense .RemoveEffect (-40);}


This is a fast way of doing attribute effects though its probably not that robust.
I never would've thought about moving an attribute into it's own class to have all the functions there. That's a pretty good idea.

However, that only solves the problem of writing lots of functions, unless I make the attributes public I'd still have the same issues of how to get Skills to modify members of the Monster.
Quote:Original post by starruler
I never would've thought about moving an attribute into it's own class to have all the functions there. That's a pretty good idea.

However, that only solves the problem of writing lots of functions, unless I make the attributes public I'd still have the same issues of how to get Skills to modify members of the Monster.


One idea?
class Character{protected:	std::map <std::string, Attribute <int>> m_Skills;	std::map <std::string, Weapon*> m_Weapons;public:	// Constructor	Character (void) {		m_Skills["health"].SetInitial (100);		m_Skills["attack"].SetInitial (50);		m_Skills["defense"].SetInitial (50);		m_Skills["magic"].SetInitial (50);	}	// Get an attribute	Attribute <int>& GetSkill (const char* skillname)	{		return m_Skills[skillname];	}};// monster derivationclass Monster : public Character{public:	Monster () {		m_Weapons["axe"] = new AxeWeapon();		m_Skills["attack"].SetInitial (75);		m_Skills["defense"].SetInitial (45);		m_Skills["axe"].SetInitial (10);	}};int main (){	Character* monster = new Monster();	monster->GetSkill ("health").AddEffect (-20);	delete monster;}
While that class would provide the ability to modify all the attributes, like attack power, or defense rating. But my skills are like certain kinds of attacks that the monster can use, say, scratch or tackle.

A user selects the attack by some means and then the attack is imposed on the enemy creature, or in some cases our own creature as well. This would occur if the skill increased the attack power of its user. I'm wondering about how to achieve this in a manner that is "good". Not something that smells of a hack. A lot of the ideas I've come up with that smell that way.
Quote:Original post by starruler
Say I had three classes: Battle, Monster, Skill. [...]

So my question is the best way to have these three classes interact?


Battle should contain the algorithm. That algorithm can call methods on the Monsters and Skills to gather data, calculate the results, and then apply them to the Monsters.

Quote:...how to get Skills to modify members of the Monster


The Battle class queries the Skill for the relevant values, then applies them to the Monster in question. Each skill can return a list of side-effects to apply to the user and a list to apply to the victim.

Having a generic representation for these side-effects is probably crucial if this code is to be short and simple. If you draw up a list of all your attributes, give them unique names or IDs, then applying a side-effect is typically as easy as "applySideEffect(attributeId, amount, duration)". Call that once on the Monster in question for every side-effect returned from the Skill.
So something sort of like what thre3Dee drew up. I like his idea of having the temporary value encapsulated, it makes the Monster class much cleaner.

Do you think that having the attributes in a map is a good idea? Or using an enum for the AttributeType.


Here's what I'm seeing:
The user somehow tells the battle which skill they would like to use. The battle calls a function UseSkill(name) that takes care of maybe lowering MP on the attacking monster. The battle queries the two monsters for relevant attack and defense values and calculates the damage it deals to the defender. It then calls getSideEffects on the skill which returns a list of some generic representation of a sideEffect ( Maybe it has which monster to affect, which attribute, and the amount ). I like how that sounds.

This topic is closed to new replies.

Advertisement