Design question: Managing multiple methods

Started by
5 comments, last by Norman Barrows 9 years, 5 months ago

In my game, I have a bunch of methods which handles interactions between the player and objects within the world. The list of these methods is only going to grow as I move forward with the game. My question to you is this:

What is the best way to handle methods between the player and world? Currently I have them in my Player class and main game class and even at this point it looks sloppy and unorganized.

Player class contains interactions with inventory, and interactions between tree objects in the world. I don't know why I put the tree methods there but it seemed like the right place at the time.

Main game class contains all collision detection methods, and methods for creating a fire. I think the collision detection methods should stay in this class, but there is no reason for the CreateFire methods to be in there.

Would I be better off creating a new class that holds all of these methods that handle interactions between the player and the world? I know in XNA you can create a Game Component type class which may work.


public class InteractionHandler
{
   //some variables here
   public InteractionHandler{}
   //empty constructor
   public void UpdateHandler(//some parameters here)
   
   //all methods that handle interactions
}

This is the idea I have in my head. I've never created a game of this size before so I don't really have an idea about how to organize this.

Advertisement

There's a gazillion ways to do this, and a mere bajillion are actually "right". Sarcasm aside, I think we need more information on what you're actually doing right now. Short of that, the best I can say is "don't over-engineer things until you actually know what you need".

I'm trying to get into the habit of organizing my code before it becomes too cluttered and I can't find a method when I need it.

Player class:

-Load, update, and draw

-Remove and add items to inventory

-Pick up, Craft, and equip items

-Get items from a tree and bush(should be in seperate class?)

Main class:

-Load, update, and draw

-check collision between map and player

-check collision between solid objects and player

-sets player variables nextToTree, nextToFire, nextToBush(separate class?)

-3 methods for setting tinder in fire pit, lighting the fire, and adding logs to the fire(separate class?)

This is kinda the breakdown of what I have going on right now. I feel like some of these methods don't really fit in those 2 classes and I'm wondering how to organize this

I'm trying to get into the habit of organizing my code before it becomes too cluttered and I can't find a method when I need it.

Player class:

-Load, update, and draw

-Remove and add items to inventory

-Pick up, Craft, and equip items

-Get items from a tree and bush(should be in seperate class?)

Main class:

-Load, update, and draw

-check collision between map and player

-check collision between solid objects and player

-sets player variables nextToTree, nextToFire, nextToBush(separate class?)

-3 methods for setting tinder in fire pit, lighting the fire, and adding logs to the fire(separate class?)

This is kinda the breakdown of what I have going on right now. I feel like some of these methods don't really fit in those 2 classes and I'm wondering how to organize this

Ok, I see what you're getting at now.

Yeah, you definitely don't want a separate method/variable for each type of object.

Consider that each object is just that --an object. Depending on what language you're coding this in, there may already be a use for that word, but be creative ("GameObject" or whatever).

In general, the player usually doesn't store that type of information directly. At best, the player class knows what it can do, given the inputs it can make. It's up to some external entity to resolve that. For instance, if the player presses a button presses the "set tinder in firepit" button, the game has to:

1. resolve what the button does. If it does multiple things (like a "use" button), that entails asking what's nearest to the player and in activation range.

2. actually resolve the effect. This is probably done on the side of the objects.

I wouldn't use a "handler" for this. The general rule is that "classes are nouns", and at your level of experience, I would treat that as ironclad. "Handlers" are kinda-sorta nouns but not really. They're more like conjunctions in disguise.

As an outline of how I'd probably do it at first shot (I can almost guarantee this isn't completely valid C#, but that's not the point, and you shouldn't copy this verbatim anyway):


/*Not shown here -- "action" is an abstract concept to handle overloads of commands.  if "q" does different things in context, an action is a way to map that to the object being acted upon and resolve that context.*/

interface IGameObject
{
    void onUse(Entity entity, Action action);
    //other stuff...
}

public class Tree : IGameObject
{
    public static int treeWoodQty = 5;

    public void onUse(Entity entity, Action action)
    {
        if(action == CutDownTree)
        {
            cutDown();
            player.give(Wood, treeWoodQty); //"Wood" would probably be a class of its own, implementing an interface "item".
        }
        //stuff
    }

    void cutDown() {} //not implemented here.
}

The inventory probably should exist separately from the player class.

Likewise, crafting and equipping probably shouldn't be in the player class.

Collision shouldn't be directly handled by the main class, but probably by a class that the main class owns.

Are you separating the idea of the player (what the user has collected, accomplished, etc...) from the idea of the player's avatar (the visible representation) walking around?

The visually animated appearance of the player in-game shouldn't own or know about things like inventory and crafting.


"don't over-engineer things until you actually know what you need".

THIS! THIS! THIS!

a MILLION times THIS!

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

hard to say what the best OO way to organize it would be.

in Caveman 3.0, you have player data structures.

load and save operate on the entire game. in OO there would be player.load and player.save routines, plus load and save methods for every other data structure in the game.

render and update again are game wide, with player.render and player.update being the OO versions.

Its best to keep inventory lists as generic as possible, so they can be used for both entities and containers. Caveman 3.0 basically treats inventory lists as objects, and a player "has a" inventory list (composition, right? i don't usually do OO). OO equivalent.methods include inventory.add, inventory.remove, inventory.return_quality_of_best(item_type), etc.

picking up an item is part of input handling and calls inventory object methods.

selecting current weapon is the only manual equipping, done via the all-in-one in-game menu. best armor etc is automatically equipped.

crafting and actions in general (pick berries, gather wood, etc) are handled using "action handlers". the game has over 100 types of generic action handlers. Action handlers are as generic as possible, so for example there's one action handler for cooking all 31 types of food in the game, one for all 45 types of skill research, and one for all 65 types of weapons training. In OO terms, like it or not, most of these seem to be player methods: player.eat, player, drink, player bathe, player.gather(WOOD), player.research(STONEWORKING), etc. what can you say? you have an object (the player) who can do a LOT of stuff! <g>.


Main class:
-Load, update, and draw
-check collision between map and player
-check collision between solid objects and player

sounds ok.


-sets player variables nextToTree, nextToFire, nextToBush(separate class?)

i only do this on the fly as needed. player hits select key. see whats in front of them (IE are they next to tree, rock, water, etc.). then show a popup menu of actions possible with that object.

this is the part of OO i don't like. is player_gather_wood a player (or inventory) method, or is it a tree method?

well, the fact is, its neither. what you have is a tree.take_wood method that monitors time required, does success checks, and reduces resources.

and you have an inventory.add(WOOD) method. and then at a higher level you have controlling code that calls these methods to do the actual work. the controlling code knows about both trees and inventory lists. therefore it technically doesn't really belong with trees _OR_ inventory lists, but instead in some higher level controlling object. Usually its at this point that i decide that OO is not all its cracked up to be and i get back to building games (using non-OO code) rather than wasting time worrying about whether some method that operates on two different types of objects belongs in the first or second object type.


-3 methods for setting tinder in fire pit, lighting the fire, and adding logs to the fire(separate class?)

now this just SCREAMS to be made into an object! fire.set_tinder_method_1, fire.set_tinder_method_2, fire.set_tinder_method_3 fire.light, fire.add_logs. don't forget fire.check, fire.playwith, fire.putout, and fire.grab_burning_stick (equips the player with a lit torch tool/weapon).

in procedural code:

when they hit select, if near_fire() show_fire_actions_menu(). switch result: do some fire method.

in OO style:

when they hit select: if (fire.player_nearby()) fire.do_action(fire.selected_action())

fire.selected_action displays a menu of interactions possible with the fire at that time, and returns the action selected

fire.do_action(some_action) calls a fire method, based on the selected action.

i'd say the thing to do is start with your basic methods for all object types, stuff like inventory.add, tree.getwood, etc.
then where you put the controlling code is up to you. in caveman 3.0, i guess you'd say the controlling code is in update(). if the player is doing an action (gather wood, etc), update calls the action handler for gather wood. the handler monitors time passing, does success checks, and reduces resources, it also does the call to add2invetory() when they make a success check.
not sure where i'd put item.equip. maybe it should be player.equip(ITEM_TYPE). yes, better. more generic. that's where it should be: equip(ITEM) is one of the things a player can do.
try making a list:
noun.verb
tree.getwood
player.equip
fire.add_logs
etc.
that should help define all the objects, and which methods belong with with objects.
once you've made your list (on paper) you'll have a complete list of all classes and methods in the game, all nicely thought out and organized and ready to be typed in.
figuring out the best organization may be non-trivial and might require some thought. note that i used the example of player.gather(resource_type). this should probably be something more like resource.remove and inventory.add, which are both called from higher level controlling code.
what we really need is not OO syntax, but MOO syntax (multiple object oriented) which would include built-in constructs for "where the controlling code should go"! <g>.
reading over my post, it seems you'd have a generic gather method, which would call resource.reduce and inventory.add. and that gather method would probably be a player method. IE gather itself would not be a part of a resource object. just the resource.reduce_resources part.
a recurring design pattern in games (and software in general): 2 (or more) data type objects (inventory and tree) and controlling code that interacts with both, but technically belongs in neither. OO's been around a long time, but i've never heard of anyone coming up with a way this situation should be handled. there's probably a design pattern for it somewhere that i'm unaware of.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

This topic is closed to new replies.

Advertisement