Jump to content
  • Advertisement
Sign in to follow this  
Heelp

Code design problems again :(

This topic is 599 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

What's up, guys.

 

I wanted to ask you something.

 

Imagine a game like Dota 2, or League of Legends, they have like 100+ heroes, right? I was wondering how is every hero instantiated.

 

1st option: Character shadowFiend = Character( 5, 7, 55, 22, 150, 1300, 20, 35 ).( put 40 arguments in the constructor ).

 

2nd option: Make a new class for every hero, but then if you have 100 heroes, you need 100 classes. What I meant is, how to deal with Characters that are very different, and when I don't want to pass 30 arguments to the constructor?

 

3rd option: Character shadowFiend = Character( something );

shadowFiend.setSpeed( 5 );

shadowFiend.setStrength(7);

shadowFiend.setAgility( 12 );

 

and on and on...

 

What is the way normal people prefer?

 

2nd question:

I have a class Character and every character I create needs animations and shaders and a bunch of other stuff.

 

But the problem is that Blender can't export multiple animations on the same model, that's why I need a new model for every animation, and I store them at my ResourceManager class/object ( it doesn't manage anything, just stores ).

 

And I don't know how to deal with the animations because they are simply too much.

 

Should I create a new variable with a different name for every single animation,( I do this now, really bad )

or should I add them all in a vector.

 

But then if I add 20 animations in a vector, how am I going to remember which one is run, knockdown, attack, die, swim, whatever? Isn't this error-prone?

 

3rd question: I store all game content in one class called ResourceManager. And I need to pass that content somehow to my characters when I instantiate them. Is it ok to make a few vectors of pointers in the resourceManager class, so I can pass just the vectors. For example all the animations for Hero1, are in a vector<Anim*> Hero1Anims. So basically, I group the addresses of all common animations in one vector in order to pass them somewhere? Is this the best way?

 

4th question: My class character works with the same shaders for ALLL characters. Is there a way where I can access the resourceManager, get the needed shaders and just instantiate them in the header file of the Character class, instead of passing the same shaders every time to the Character's constructor. Should I make my resource manager global, can you suggest the easiest way you can think of?

 

 Any help is appreciated, if you don't understand anything, just ask, I'll try to clarify.

 

Thanks for taking the time to read all that messed up stuff. ^_^

Edited by codeBoggs

Share this post


Link to post
Share on other sites
Advertisement
Your constructor can take a single argument that is an object that maps strings to values. This mapping is specified in configuration files, and the constructor will then extract the values it needs ("character_type", "hit_points", "primary_weapon"...) to set up the character.

Share this post


Link to post
Share on other sites

What's the difference between:

1st: Using a global ResourceManager and accessing stuff from everywhere.

2nd: Passing resources as arguments to constructors every single time until i die, and resources are still accessed from everywhere. So it seems the same to me, but people say passing resources to objects' constructors is better than declaring the ResourceManager global. Do you know why?

Share this post


Link to post
Share on other sites
On option 2, if done properly, resources are not accessed from everywhere; they are accessed only from places that have explicitly been given references to them.

Having worked in environments of both types, I can tell you that the difference is enormous. For instance, if I want to use some class in my project for some different executable, option 1 makes it essentially impossible, because everything depends on everything else. Under option 2, the class interface will tell you all the things that it needs access to, so I know to provide those in my new program.

Share this post


Link to post
Share on other sites
they have like 100+ heroes, right? I was wondering how is every hero instantiated

 

In a game nothing of this kind is instantiated as single class, you have always certain types of components on a character like its mesh including animations that are mostyl bone data and transformation data processed in a shader these days, coresponding material and texture classes, a character class containing some information, character controller bound to local input or network messages and a lot more depending on the game.

 

If you are in a set environment like Unity 3D or Unreal Engine then this is stored as asset anywhere in your project where the copnfiguration has been made already and be loaded dynamicaly when needed and in a more custom environment these data is stored in any format the studio decided to use, maybe xml but may also be byte code.

 

We for example have serialized our ingame maps as a bunch of bytes where the game didnt know anything about what maps existed, what type they are and so on until they got loaded from a data package running scripts and doing all these stuff of 'initializing' the map class, where deserialisation works in general like

buffer -> readBytes <- asset
map <- create
map_Property <- buffer_getNBytes
map_Property <- buffer_getNBytes
map_Property <- buffer_getNBytes
map_Property <- buffer_getNBytes
map_setFinal

where our properties were like what object is placed identified by its id and mapped to the local object database where with what transforms and a custom data block for additional properties, heightmap, terrain, terrain types (it was a game where this matters) ...

Edited by Shaarigan

Share this post


Link to post
Share on other sites
Large games are built in terms of systems. A hero is not a single item, not a single class. Instead the data behind a hero is made up of many small objects each working together as systems. Many items can be shown on screen rendering together, so a hero may have references to meshes and animations. They may have items so each item works with an item system, or inventory systems, or weapons and armor systems, often being composed of objects that work with many systems at once.

While many beginning programmers like to make each object responsible for all actions, like giving an object something that renders and calling a render function on every object, that isn't how bigger games are composed. A rendering system handles all the rendering, and while an object may have some type of link to an object that renders, it is not the game object's responsibility to handle any rendering, except perhaps turning the model on and off. Each class should have a single responsibility, and game objects are usually container classes for other building blocks.

In some ways that gets back to your fourth question. You've built something that would apply to all the objects. That is a good starting point for thinking in terms of systems. You find the functionality that is common for all the parts, isolate the functionality into small individual responsibilities, and turn those into classes that implement a single responsibility. Then the object can be reused everywhere, with game objects being composed of many sub-components each with their own responsibility and behavior.

As a beginner you won't be building large systems, or even working with large systems unless you are using an existing engine like Unity or Unreal. Since both are free it might be worthwhile for you to download and try those engines out to learn somewhat about how systems interact.

Share this post


Link to post
Share on other sites

Different ways of constructing complex objects are the focus of the first third of the classic book Design Patterns. Your example 3 is what's known as the 'Builder' pattern. Another popular approach is to load in the data and pass that to a 'Factory Method' which sets up the object based on the data.

 

I don't know how to deal with the animations because they are simply too much

 

Use an enum of animation types (run, knockdown, attack) and those should be the keys in your data structure that map to the animations.

 

So basically, I group the addresses of all common animations in one vector in order to pass them somewhere? Is this the best way?

 

Does it matter if it's the 'best' way? It's probably best to focus on the problems you know you have, rather than worries about problems you might have.

Share this post


Link to post
Share on other sites

Thanks for clearing this up for me, guys. :)

 

Having worked in environments of both types, I can tell you that the difference is enormous.

Ok, I'll pass arguments like crazy. I hope it saves me some headaches in the long run. I really want to use a global, but I won't. :lol:

 

That is a good starting point for thinking in terms of systems. You find the functionality that is common for all the parts, isolate the functionality into small individual responsibilities, and turn those into classes that implement a single responsibility

Now that I think of it, My Character class has a lot of responsibilities. Need to cut some off. Thanks ^_^

 

Use an enum of animation types (run, knockdown, attack) and those should be the keys in your data structure that map to the animations.

Just tried it, works like a charm. But can I use vectors + enum class, instead of map + enum class?

Seems ok, right?

 

EDIT: yo, guys. Another question came up.

 

All my drawable objects have class GameObject as a base class and that class calls the render() function.

 

I have different types of objects, animated enemies, nonanimated floors and walls, but I want to draw them using one 'for' loop only.

 

Sounds easy, just declare the vector like this: vector<GameObject> worldObjects and then push back whatever object you want, like Character, Ghost, Wall, Player, whatever.

 

And it works, everything can be drawed in one loop only. I just loop through the worldObjects vector and call render() on each one of them.

 

But now I have both characters and static objects (wall, floor) in one vector. How can I call updateLogic() for Characters only? (because my walls and floors don't have any logic to them, they don't move ).

Edited by codeBoggs

Share this post


Link to post
Share on other sites

vector<GameObject> worldObjects and then push back whatever object you want, like Character, Ghost, Wall, Player, whatever
This doesn't actually work, the vector has no room for the additional data of a derived class.  vector<GameObject*> would work.

 

But now I have both characters and static objects (wall, floor) in one vector. How can I call updateLogic() for Characters only?
You don't, or rather you can code it with a dynamic_cast test, but you should not.

 

- Make an update vector for update (same problem as above, you can't have a vector with a base class, and store objects of derived classes in it, so you need to store the derived objects elsewhere anyway), separately from rendering, or

- make different vectors for different things (I don't see why 4 for-loops for drawing is so bad that you have to go out of your way to keep it 1 for-loop, and then have huge costs in update loop, and possibly elsewhere), or

- give the walls and floors an empty 'update' method.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!