Jump to content

  • Log In with Google      Sign In   
  • Create Account


Looking for some "best practices" advice


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
16 replies to this topic

#1 Ulfhedhin   Members   -  Reputation: 136

Like
0Likes
Like

Posted 10 September 2011 - 08:21 PM

I'm slowly getting my head wrapped around programming and I was wondering if there are any "best practices" out there that I should be following. I know the idea is to be "object oriented" but I am a little fuzzy as to how to apply/organize that. If a game has weapons, are each of those weapons in separate classes (or inherited classes from a "master weapon blueprint"?) Are the behaviors of these weapons governed by methods/functions? Are games organized in such a way that objects are "seen" (IE have access) throughout the game code via references or pointers more easily?

I realize these topics may be incredibly huge but I figure that since I really don't know where to start, I figure I'll start somewhere and just keep going :).

Any input, suggested reading, links, etc. would be greatly appreciated.

Ulfhedhin


Sponsor:

#2 bluehailex   Members   -  Reputation: 143

Like
1Likes
Like

Posted 10 September 2011 - 08:35 PM

What language are you talking about? There is no requirement to have an object oriented design, but it can make things more logical. If you are making weapons, you might want to derive a basic weapon class from an item class, and then derive the item class from an entity class. From your base weapon class, you could derive ranged and melee classes. That would be using a hierarchical entity system, but you could also use a component entity system where you essentially add components to an entity to make it what you want. You can make objects accessible to other parts of the game through references and pointers, but that doesn't mean make everything entirely global.

#3 Telastyn   Crossbones+   -  Reputation: 3726

Like
2Likes
Like

Posted 10 September 2011 - 08:48 PM

I'm slowly getting my head wrapped around programming and I was wondering if there are any "best practices" out there that I should be following.


There are, but what they are depend on what you're doing, what your doing it with, who you're doing it with, etc. Even then it often depends who you ask.

As a beginner, you're going to do bad things; don't worry too much about it. Write code, when you make bad code, learn from it.

I know the idea is to be "object oriented" but I am a little fuzzy as to how to apply/organize that. If a game has weapons, are each of those weapons in separate classes (or inherited classes from a "master weapon blueprint"?)


Not generally.

Are the behaviors of these weapons governed by methods/functions?


Usually. Sometimes the behavior is stored as data that drives some interpreter function.

Are games organized in such a way that objects are "seen" (IE have access) throughout the game code via references or pointers more easily?


Sometimes; not generally. One of the generally recognized best practices is to give things the least amount of access needed to make them work. The more things that touch a class means that many more things you have to look at when an instance of that class has somehow gotten into a odd/wrong state.

Sadly, the scope of 'best practices' is super huge. If you have more pointed questions as you write code (hint!) we can probably help you better.

#4 Ulfhedhin   Members   -  Reputation: 136

Like
1Likes
Like

Posted 10 September 2011 - 09:34 PM

Yikes! I guess I should have mentioned C++ LOL.

Yea, I know everything doesn't need to be global. But I'm noticing as I am creating a simple text-based RPG (as an exercise), I am needing to "see" various classes within my code and am having a tough time doing it sometimes. Perhaps it is poor organization on my part (hence me asking for "best practices" advice :) ) or just lack of experience (or both). But I am stumbling through it and I do a LOT of searching for solutions and more often than not I find what I need. I just have this nagging suspicion that it could be done better. That much is probably a given though LOL. It is just that feeling that I am on the cusp of understanding something vital but I haven't gotten that "lightbulb" moment yet.

An example would be my weapons in my RPG. At first I started out as having them listed in a struct with variables as their stats which were set to default values. These values would be determined when I created the character. I wasn't satisfied with that. So I gave each weapon its own struct with its own stats already initialized when the code was compiled. I wasn't satisfied with that either. So I had the bright idea of storing these items in a multidimensional string array (weapon name, weapon range numbers, etc) and I could cast the numbers to integers when I needed to. That turned out to be a huge headache. So then I thought that perhaps each weapon could be initialized on the fly via its own method that would set the variables as needed. I'm currently working on that one. So for right now, I am having weapons in one class with a separate method for each different one (the game is very small so there are only 5 weapons). So far it seems to work but I am trying to figure out a way for the game to call these methods when necessary from within the player's inventory and the "store" in the game. And I'm trying to wrestle with creating a vector array that'll serve as the player's inventory.

It's slow going and I know I'm making headway...even if what I'm doing comes to nothing. I know as well as anyone that you learn a lot when you mess up. Yet I also know that I learn very well when I either approach things from different angles or get different explanations on them. My brain wires all that together and I get that "lightbulb moment" :).

Thanks for the replies!

Ulfhedhin


#5 yewbie   GDNet+   -  Reputation: 665

Like
1Likes
Like

Posted 10 September 2011 - 11:18 PM

This is not something based out of a book but something based on my personal experience:

Make sure you know what your making before you make it, I don't know how many times I have ran into a problem because my idea is not fully fleshed out.
Also be aware of feature creep (its a bitch =) )

Make sure you program in such a way that you understand whats going, if you program 10000 lines of code and you dont know whats going on but it works you need to learn some more =)

#6 laztrezort   Members   -  Reputation: 955

Like
1Likes
Like

Posted 10 September 2011 - 11:53 PM

Yea, I know everything doesn't need to be global. But I'm noticing as I am creating a simple text-based RPG (as an exercise), I am needing to "see" various classes within my code and am having a tough time doing it sometimes.


This seems to be a common "hump" to get over when learning OOP. It seems so much easier to just have a global collection of objects that can be accessed when we want them - but we are told that globals are "evil". Also, we are told that encapsulation is good, but it's sometimes difficult to decide which class members to hide, and which to expose. Another early difficulty is over-designing classes - it often seems nice to add all of this functionality that we think may need for a class, but then we are told about KISS and YAGNI.

Experience, especially in the form of having the above mentioned things bite you in the ass, is probably the best way to learn.

So I gave each weapon its own struct with its own stats already initialized when the code was compiled. I wasn't satisfied with that either.


Why weren't you satisfied with this? All weapons are going to share a set of stats, so make a Weapon object (class or struct, whatever is appropriate for the language). If a particular weapon type never changes its state (stats) during the game, then you will not need a separate instance for each weapon - just keep a master list of weapon types and their stats, and index into it as needed. If weapons can change state during the game (their stats can change, such as current ammo, upgrades, wear and tear), then each weapon will have its own instance. In this case, the master list of weapon types is like a collection of blueprints, and is used to initialize a weapon instance.

Maybe if you focus on one particular aspect, and post some code, you will get some more specific suggestions.

#7 Drathis   Members   -  Reputation: 141

Like
1Likes
Like

Posted 11 September 2011 - 12:51 AM

To simplify things, try to think OOP as something you do to reduce complexity and duplication. With complexity you can start simply by reducing the number of if and switch clauses. Many times the you reduce code duplication at the same time. Using weapons as example, you might have something like this:

// the code might look like Java, sorry <img src='http://public.gamedev.net/public/style_emoticons/<#EMO_DIR#>/tongue.gif' class='bbc_emoticon' alt=':P' />

void shootPlayersGun(){
    if(reloadSeconds == 0 && (gun == PISTOL || gun == SHOTGUN || gun == SMG)){
        if(gun == PISTOL){
            reloadSeconds = 0.5;
            createBullet();
            bullets--;
        } else if(gun == SMG)
            reloadSeconds = 0.1
            createBullet();
            bullets--;
        } else if(gun == SHOTGUN)
            reloadSeconds = 1;
            createBullet();
            createBullet();
            createBullet();
            shells--;
        }
    } else if(heatPercent < 100 && (gun == BEAMWEAPON || gun == FLAMETHROWER)){
        heatPercent++;
        if(gun == BEAMWEAPON){
            createBeam();
        } else if (gun == FLAMETHROWER){
            createFlame();
            fuel--;
        }
    }
    
}

Now if you have a 10 weapons you are going to have really long if and it would become more and more complicated. If you define a weapon interface you can reduce this to:
player.weapon.fire()
Now you can put all your weapon code in different weapon classes that implement the weapon interface and you don't have to wonder what code is associated with you beam weapons and so on. You don't have as many if's so your code is less complicated. To create a new weapon you just create a new weapon class and put your code there. At this point you can also start using inheritance, composition and other OOP stuff to start reducing code duplication too. You might not have less lines of code but this less duplication means smaller chances of bugs and when you fix a bug in one place it gets fixed everywhere.

In C++ I guess you could use completely abstract classes to define an interface.

#8 mhagain   Crossbones+   -  Reputation: 7604

Like
1Likes
Like

Posted 11 September 2011 - 02:29 AM

I'd suggest that you're coming at this the wrong way round. You're thinking with an OOP hat firmly on, and trying to force your intended end result to meet the requirements of OOP. That's not going to work out well at all; instead think more about your intended goals and select design paradigms that serve those goals best. So instead of asking "what classes do I need to create in order to do blah?" you need to ask "I want to do blah, what's the best way of doing it?" Because otherwise you've selected a solution before you've really analysed what the problem actually is, and have a high risk of over-engineering.

It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#9 HNikolas   Members   -  Reputation: 192

Like
2Likes
Like

Posted 11 September 2011 - 02:30 AM

I did not entirely read the thread but based on your posts, it looks like you have few design issues at hand. You should read a good OOP design book or a tutorial to get the hang of it. Most of your problems could easily be avoided with a good understanding of OOP design. It is very broad topic so I will not even try to cover it in this reply.

Other keywords to search for would be software design, software engineering, design patterns and so on, but be aware that these are even broader and more advanced topics(and require good OOP base).
Ruby on Rails, ASP.NET MVC, jQuery and everything else web.. now also trying my hand on games.

#10 pulpfist   Members   -  Reputation: 528

Like
1Likes
Like

Posted 11 September 2011 - 04:59 AM

Always remember to Keep It Simple (KISS)
Also, don't force things into some OO structure, or you can easily end up with convoluted code that is hard to extend.

One example:
A player could be a class, and a weapon could be a class, but making the weapon part of the player class is not so obvious to me.
I mean, how is the player going to leave the weapon behind, or hand it to another player if it is a part of him?
In this simple scenario, I would probably create three classes instead: Player, Inventory, Weapon.
The inventory could be part of the player, and the inventory could have one or more slots for items, like weapons.

That's just an example though. It may be more than you need, in which case you should make things simpler.

Basically, always make sure that the member function (operation) you add to a class actually belongs to that class.
Sometimes it does, other times it makes more sense to introduce a new class.

Also, to avoid globals you are going to have to pass objects around as parameters to other objects and their member functions.

Another good practice is to take full advantage of the C++ standard template library.
For a small RPG game you should make yourself familiar with the string and the vector class as a minimum.

#11 Ulfhedhin   Members   -  Reputation: 136

Like
0Likes
Like

Posted 11 September 2011 - 04:40 PM


So I gave each weapon its own struct with its own stats already initialized when the code was compiled. I wasn't satisfied with that either.


Why weren't you satisfied with this? All weapons are going to share a set of stats, so make a Weapon object (class or struct, whatever is appropriate for the language). If a particular weapon type never changes its state (stats) during the game, then you will not need a separate instance for each weapon - just keep a master list of weapon types and their stats, and index into it as needed. If weapons can change state during the game (their stats can change, such as current ammo, upgrades, wear and tear), then each weapon will have its own instance. In this case, the master list of weapon types is like a collection of blueprints, and is used to initialize a weapon instance.


I was unable to figure out how to use structs in a way that would allow for multiple versions of them. For example, I did not know how to work it to where a player could have multiples of a particular weapon in their inventory that was stored in an array. I initially had the struct system working beautifully so long as the player (and enemies) were locked into having only one weapon. But when the idea of having the potential for multiple instances of a particular weapon came up, that is when I started stumbling.

Here is a bit of code for how I set up the weapon struct:

struct Weapon
{
     string mName;
     Range mRange;
}

The range links to a Range.h file that has "mLow" and "mHigh" variables that determine the weapon's damage. Like I said, this code worked fine when you selected your class and were given the default weapon and the values for that weapon were set. But like I said, I was unsure how to implement this when I needed multiple instances of them in a player's inventory. This could easily be a case of me not being able to see the forest because of the trees and I am missing an obvious solution right in front of me. And perhaps I am trying to be too much of a slave to OOP (as suggested by one poster). This is great stuff and I appreciate all the replies! :)

Ulfhedhin


#12 Bregma   Crossbones+   -  Reputation: 4849

Like
1Likes
Like

Posted 11 September 2011 - 04:56 PM

Here is a bit of code for how I set up the weapon struct:

struct Weapon
{
     string mName;
     Range mRange;
}

The range links to a Range.h file that has "mLow" and "mHigh" variables that determine the weapon's damage. Like I said, this code worked fine when you selected your class and were given the default weapon and the values for that weapon were set. But like I said, I was unsure how to implement this when I needed multiple instances of them in a player's inventory. This could easily be a case of me not being able to see the forest because of the trees and I am missing an obvious solution right in front of me. And perhaps I am trying to be too much of a slave to OOP (as suggested by one poster). This is great stuff and I appreciate all the replies!

No, I would say that's excellent OO design. Your Range class, for example, should have some functions that operate on it (constructor, copy operators, min(), max(), what have you). that's good encapsulation. Your weapon: it's good encapsulation.

It seem what you might need to do is to realize the difference between classes (or structs) and objects (instances of structs).

For example, if you want a player to have zero or more weapons, the player should have a std::vector<Weapon>. You can even initialize it at compile time if you have an up-to-date compiler that implements the current C++ standard (most of them on consumer dev platforms do). If you want to get fancy (and I recommend you do this later, but not too much later) you could use a std::vector<std::shared_ptr<Weapon>>.
Stephen M. Webb
Professional Free Software Developer

#13 Ulfhedhin   Members   -  Reputation: 136

Like
0Likes
Like

Posted 11 September 2011 - 07:15 PM

I think I see where you're going with this. But what I don't understand is how it is implemented into that vector array. Let's say that a player has 3 weapons in his inventory (not counting the one he's using). How would that be expressed from within an array? I did have a point where I wondered if this could work but since I didn't know how to (or even if it could be) implemented, I had to skip over it. Would it be a case of something like this (I just thought of it LOL)?

Weapon weapon; // create weapon object
vector<weapon> inventoryWeapons; // create vector array for inventory that holds weapons

inventoryWeapons[0] = // not sure what goes here...how can this hold the weapon name and the range?

Would this array hold separate structs somehow? If I understand it right, an array can hold objects but I'm not sure about structs. For example, in the code I have using the struct, a weapon is initialized this way:

weapon.mName = "Sword";
weapon.mRange.mLow = 4;
weapon.MRange.mHigh = 8;

Like I said, I'm not sure how this would go into an array. Especially if there are a handful of other weapons such as daggers and axes. Do each of these different weapons need to be initialized within their own struct or can their values be set up elsewhere? I tried this way as well but again, I didn't know how to use them in arrays. That really seems to be my hangup right there.

Ulfhedhin


#14 Bregma   Crossbones+   -  Reputation: 4849

Like
1Likes
Like

Posted 11 September 2011 - 07:52 PM

Let's just say you had a Range class (or struct) that looked something like this.
struct Range
{
  Range(int low, in high) : mLow(low), mHigh(high) {}
  int mLow;
  int mHigh;
};
Let's also suppose your Weapon struct looked like this.
struct Weapon
{
  Weapon(const std::string& name, int min, int max) : mName(name), mRange(min, max) { }
  std::string mName;
  Range       mRange;
};
Finally, I'll assume you have a Player class that looks like this, eliding stuff like cup size and drinking prowess. I don't know what kind of RPG you like, I'll keep mine a secret too.
struct Player
{
  std::string                       mName;
  std::vector<Weapon> mWeapons;
};
Somewhere in you code, you're going to do something like this.
  Player player;

  // Create some weapons
  Weapon intruder("dagger", 1, 4);
  Weapon venusButterfly("butterfly", 1, 8);

  // Equip the player.
  player.mWeapons.push_back(intruder);
  player.mWeapons.push_back(venusButterfly);
The code marked Create some weapons creates two weapon objects -- instances of the Weapon struct. The Equip the player lines then add copies of those objects to the players mWeapons member variable. Viola, your player will have his hands busy.

Note that it's copies of the original objects that are added to the vector, and that the vector's push_back member function is used to insert the weapons, not its overloaded operator[] (like an array).

I think the key is that the intruder is an object of type Weapon. Weapon is a struct (or class, same diff).

You might want to start by read up on an introduction to the standard library, starting with std::vector. It's an excellent way to learn about OO design and encapsulation. It's also a very useful tool.

Once your player has his weapon in hand, er, so to speak, you will want to learn how to iterate over the vector (hint: begin() and end()).
Stephen M. Webb
Professional Free Software Developer

#15 pulpfist   Members   -  Reputation: 528

Like
0Likes
Like

Posted 12 September 2011 - 02:24 AM

Bregma's example is pretty much what I had in mind.

I don't want to add more to it at this point other than the fact that its necessary to get used to C++ vectors

There is a decent introduction here to get you started

#16 Slavik81   Members   -  Reputation: 360

Like
1Likes
Like

Posted 12 September 2011 - 02:57 AM

Effective C++ by Scott Meyers has good advice about language-specific coding details.

#17 Delphawi   Members   -  Reputation: 235

Like
0Likes
Like

Posted 12 September 2011 - 07:32 AM

Like I said, I'm not sure how this would go into an array. Especially if there are a handful of other weapons such as daggers and axes. Do each of these different weapons need to be initialized within their own struct or can their values be set up elsewhere? I tried this way as well but again, I didn't know how to use them in arrays. That really seems to be my hangup right there.

You can make the inventory as a class , and give it some stats (Item count , Weight , and an Array of numbers)
You can use this array of numbers to store the weapons ? Yes , if every weapon has its number (pistol 0 , smg 1 , rpg 5 , ...) you can fill the array with the appropriate numbers of the weapons currently with the player .
So when the player presses 1 to use his SMG , you can just check the array .




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS