Skip to main content
GameDev.net gamedev.net
🔒 Locked

Is this overkill? Potentially error-prone?

Started by Plethora Apr 14, 2013 at 3:37 PM 4 replies 1.3k views
Original Post
Plethora
Plethora

My game is a strategy RPG. The Player at any given time has a team full of characters with as few as 3-4 and expanding to several dozen later in the game (though only some subset of these characters are necessarily "active"). In code, this translates to a Player object which owns up to several dozen instances of the Character class.

The character class has all sorts of functionality and data related to many aspects of the game. I was thinking about the fact that only a limited subset of the functionality available in the Character class is needed during a battle. My first implementation involved passing off control of the player's characters to a class called "Battle_Controller" which contains the map, a container of enemies, and so on and so forth. I started to think this wasn't a particularly good implementation.

My new thought is to create something like a "Battle_Character" class. The idea would be that its a smaller version of the Character class. The needed data would be obtained from the 'real' character at the start of a battle and the relevent methods from Character could be moved to Battle_Character. At the end of a battle the needed data could be sent back to the Player class and reintegrated with Character.

I like this implementation in one way as it seems like it aids encapsulation quite a bit as I'm no longer shuffling a whole lot of un-needed data and funtionality into and out of the Battle_Controller. On the other hand, it seems like I'm potentially creating a some very dependency laden code when it comes to obtaining and reintegrating data between the initial Character and the new Battle_Character.

I'm curious what people think, or if anyone has a third implementation option, I'd love to hear it. :)

I'm working on a game!  It's called "Spellbook Tactics".  I'd love it if you checked it out, offered some feedback, etc.  I am very excited about my progress thus far and confident about future progress as well!   http://infinityelephant.wordpress.com
Azaral
Azaral

The character class has all sorts of functionality and data related to many aspects of the game.



This should not be. The data and functionality should be only related to the character, nothing more. I might be reading the 'functionality and data related...' part to literally though. What I gather from this is you have functionality in the character class that operates on things that are not the character. If so, then you need to break this into another function that takes the character and the thing it is acting on into a completely different function.

Your character could be made up of different portions that are broken into classes, such as BattlePortion to follow your example. The battle portion of the character would contain everything you want to copy for battle. You would then have a function in your main character class to get this battle portion for doing battles. Pass it by reference. Then, you won't need to worry about copying it back in or pulling just the battle bits out because you've already made the distinctions just through the way you've set up your code.

It isn't overkill and will actually save you time and effort later in fixing errors. A lot of classes I write for things are VERY small. I break objects in to objects into objects. The smaller the better really (to a point, if you have classes containing just one data member better to not break it down that far lol).

It also solves this problem you mention here:

On the other hand, it seems like I'm potentially creating a some very dependency laden code when it comes to obtaining and reintegrating data between the initial Character and the new Battle_Character.

Plethora
Plethora


This should not be. The data and functionality should be only related to the character, nothing more. I might be reading the 'functionality and data related...' part to literally though. What I gather from this is you have functionality in the character class that operates on things that are not the character. If so, then you need to break this into another function that takes the character and the thing it is acting on into a completely different function.

Should have been more specific, This isn't what I meant. I just meant that a character can do a whole lot of things, the current character class contains methods that do things like attack, buying and selling items, moving from one place to another on the world map, moving from one tile to another on the battle map, talking to an npc, etc. My meaning was that my characters have a lot of functionality that, while certainly should be owned by the Character class, is often dependent on very distinct parts of the game. But the class is BIG, and that's ultimately the problem I'm trying to solve.

Would it make sense, then, to turn Character into a base class of sorts, which would have certain information that should be available across all game parts (for example, basic stats should always be available because there will be a status window and/or screen that can be accessed whether you're in battle or not)? I could then derive a Battle_Char class, a Town_Char class, etc. The sub classes would contain only methods used in those specific contexts and could be created upon creation of a town or battle?

I'm working on a game!  It's called "Spellbook Tactics".  I'd love it if you checked it out, offered some feedback, etc.  I am very excited about my progress thus far and confident about future progress as well!   http://infinityelephant.wordpress.com
Trienco
Trienco


This should not be. The data and functionality should be only related to the character, nothing more. I might be reading the 'functionality and data related...' part to literally though. What I gather from this is you have functionality in the character class that operates on things that are not the character. If so, then you need to break this into another function that takes the character and the thing it is acting on into a completely different function.

Should have been more specific, This isn't what I meant. I just meant that a character can do a whole lot of things, the current character class contains methods that do things like attack, buying and selling items, moving from one place to another on the world map, moving from one tile to another on the battle map, talking to an npc, etc. My meaning was that my characters have a lot of functionality that, while certainly should be owned by the Character class, is often dependent on very distinct parts of the game. But the class is BIG, and that's ultimately the problem I'm trying to solve.

Those are actually very good examples of things that should probably not be in the character class. Generally you want to minimize your dependency on other classes and modules, doing everything at such a specific level is achieving the opposite. Why does your character need more than functions to add/remove gold and add/remove items? The whole process of buying or selling definitely does not need to be in the character class.

Moving around the world? If you just talk about changing position, then the position should be set from the outside. What if you want other objects to move around that aren't characters? Will you copy/paste the whole code? And if it includes path finding, that is again a generic and reusable thing that doesn't belong in a character class.

A conversation is also a thing of its own and while it might need references to two characters, I don't see why it should all be handled in a character class. Not everything that involves a character should be dumped in there. Especially in C++ one should seriously reconsider the urge to put every function into a class in the first place. Global functions that manipulate objects through their interface are not only "acceptable", but the best way to be modular and extendable, as you can add a whole ton of functionality without touching existing code (buyItem(Character& character, Shop& shop)).

Everytime you ask yourself "should this be part of class X or class Y, because it involves both of them" you should consider that the answer might be "neither".

f@dzhttp://festini.device-zero.de
Plethora
Plethora


Especially in C++ one should seriously reconsider the urge to put every function into a class in the first place.

While I recognize that this is case dependent in nearly all cases and that there are clearly good examples of when to do each thing, I have to say that I'm surprised to hear that. I used to use a lot more global functions than I do these days. I've never been one to avoid seeking help, and over the years I've been urged to include more and more things within classes than the other way around. I mean, I do maintain a file I call Simples... I have a variety of general use functions and a few structs that are useful in general cases, but I try to resist putting anything in there that has any real complexity to it. Is that the sort of thing with which I should do more, not less?

I'm working on a game!  It's called "Spellbook Tactics".  I'd love it if you checked it out, offered some feedback, etc.  I am very excited about my progress thus far and confident about future progress as well!   http://infinityelephant.wordpress.com
Azaral
Azaral


Especially in C++ one should seriously reconsider the urge to put every function into a class in the first place.

While I recognize that this is case dependent in nearly all cases and that there are clearly good examples of when to do each thing, I have to say that I'm surprised to hear that. I used to use a lot more global functions than I do these days. I've never been one to avoid seeking help, and over the years I've been urged to include more and more things within classes than the other way around. I mean, I do maintain a file I call Simples... I have a variety of general use functions and a few structs that are useful in general cases, but I try to resist putting anything in there that has any real complexity to it. Is that the sort of thing with which I should do more, not less?

You want your classes to be as small and well defined as possible. This makes the data easier to manager and when there is a bug it makes it easier to find. For example, if you have your buying and selling being done between two classes, this will make it harder to find a bug and make it more likely to cause one accidentally. If you have a function that says


BuyItem(Character& buyer, Store& seller, Item purchasedItem)

and it controls the actual taking the item from the store, adding the item to the character, and removing the gold from the character and adding it to the store (if applicable), it makes it much easier to find a bug if when you purchase something the amount of gold taken or the item given is wrong. It is ALL in ONE place, and that place is very small.

This would be run inside of a function such as


BrowseStore(Character& shopper, Store& storeToLookAt)


The adage "An engineer's job isn't done when he can add no more, but when he can take no more away" (or something like that) applies. If you make your functions and classes as defined as possible (to an extent there are exceptions) you will have a much easier time going through your code, avoiding making accidental bugs, and when you do come across a bug, an easier time fixing it.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.