Jump to content

  • Log In with Google      Sign In   
  • Create Account


Midori Ryuu

Member Since 12 Aug 2012
Offline Last Active Sep 30 2012 10:03 PM

#4985637 I like the product of programming but not the process -- help?

Posted by Midori Ryuu on 30 September 2012 - 10:05 PM

Either use libraries and frameworks to abstract that work for you, or you can always try going into modding games! There are even games like Starcraft 2 for example that come with a GUI for making mods.


#4971406 Composition heavy OOP vs pure entity component systems?

Posted by Midori Ryuu on 20 August 2012 - 04:43 AM


How is this different from adding the vehicle's components inside the tank through inheritance and then adding a cannon component? They really seem the same to me. Will it cause the same problem as the one in your second example?

In practice, in effect, there's no apparent difference... but you need to distinguish between OOP and OOD.
Lots of people use inheritance when writing OOP code out of convenience -- "I want all this stuff in my new class, so I'll inherit it" -- n.b. this same goal can be achieved via composition or inheritance.
However, when designing in OOD, the concepts implemented in OOP languages have very specific meanings and using these concepts implies that you're promising to follow certain rules -- e.g. making a class implies you'll follow the SRP, and inheriting a class implies you follow the LSP.

All these inflexible, monolithic, inheritance-based designs of the past have be born out of teams who understood OOP, but not OOD. That's fine -- the majority of code written in OOP languages probably isn't following OO rules at all, and at the same time, OO designs can be implemented in non-OOP languages, such as C... but it's important to note the destiction between the OO theory of design, and the OOP features in certain languages. They're meant to go together, but don't have to.

Back to the choice of inheritance vs composition here though --
1) The main difference in this case is that with composition, Tank only gains access to Vehicle's public interface, whereas with inheritance, Tank gains access to it's protected interface. This is probably bad as it increases the potential to extra unnecessary coupling.
2) If using inheritance, it would also be valid for Tank to inherit from Cannon, and then compose in a Vehicle... so how do you choose which one is right? If it's an arbitrary choice between the two, then it seem that inheritance is unnecessary, and should probably be avoided. If the answer is to inherit from both, then what happens when you want a tank with 2 cannons, or if you make a transforming super-tank made up of 2 vehicles?

Common wisdom is that you should default to composition for code re-use, and only use inheritance where necessary.


The problem is I am trying to keep the layout of my code intuitive (to me at least). As in, a tank "Is a" vehicle but "has a" cannon. So that is why I opted to go with limited inheritance in some places, despite composition being a better solution, since the damage that it might cause will be rather small in comparison to large inheritance chains.

I do agree with you that it's better to compose here, but I kind of feel that as long as I don't allow the inheritance to expand more than 2-3 levels deep it's an acceptable tradeoff to the advantages given by composition. Then again, it is the (bad) OOP thinking that's immersed in my head thinking that, and the examples you keep giving are really helping to dispel that kind of thinking (Transforming super-tank made up of two vehicles! Posted Image)

It will be a pain, and probably cost me more development, but I will try to do things the correct way this time, since I know that once I do things the right way, it will be much easier doing it the right way the second time, and third time and so on.


If so, then the will the character class have a polymorphic reference to the BaseController which can be either an instance of PlayerController or AIController?

I had it the other way around, where Character is unaware of the controller classes at all, and the controllers have a polymorphic reference to the character.

You should design your code in layers, where each layer only uses classes in layer below it, or the same layer. You should also generally avoid designs where two classes both know about each other, i.e. dependencies should almost always be 1-way, not cyclic.
For example, C is in the top layer and knows about the public interfaces of A and B. A+B are in the layer below, and each have some complex private details that are wrapped up in a simpler public interface. Also, A and B don't know about each other at all - they're decoupled, which is good; they rely on the next layer of code to glue them together in some useful way. See also the Law of Demeter on principles about loose coupling - you generally want each class to have knowledge of as few other classes as possible, and use sensible layering to glue different bits together into a useful whole.
In this case, the controller is in the top layer ©, and AI and characters are in the bottom layer (A & B). C makes use of A&B's public interfaces, inside it's private details, and then wraps this behaviour up in a new public interface (which might be used by another layer above this).
+-----------+
		|  public   |
		| interface |
		|-----------|
		|Component C|
		|-----------|
		|  private  |
		|  details  |
		+-----------+
		  |	   |
		  |	   |
		 \|/	 \|/
+-----------+   +-----------+
|  public   |   |  public   |  
| interface |   | interface |  
|-----------|   |-----------|  
|Component A|   |Component B|  
|-----------|   |-----------|  
|  private  |   |  private  |  
|  details  |   |  details  |  
+-----------+   +-----------+


Ah yes, that makes a lot more sense, since the player might be in control of many characters, and it also enables the AI to reason in term of groups (cooperation, etc..) instead of just simple characters. That and once the lower layers are taken care of, I assume programming the game and scripting will be a breeze!

On another forum where I asked this question it was also pointed how I the setup I made would have caused, for example, the coupling of the characters and rendering to be coupled, which will come in the way in case of a server-client architecture is done for multiplayer.

By following your way the rendering will be decoupled from the characters and allows for client side rendering only.

Thank you for the time you're taking to answer my questions and all the free tips you're giving us!



Just a small question though, (I know it's example and implementation specific and doesn't have much to do with the thread but) why is the AI in the layer below the controller? Is it because it will ask C to provide the public interface of B?
You say that I should talk to the below layers, and the dependency should be 1 way, but won't this be better achieved if the A.I is above the controller for it to be able to control the characters, tanks,etc.. through the Controller which provides a public interface wrapping the lower layer?

Thank you again for your patience to my noobiness!


#4971370 Composition heavy OOP vs pure entity component systems?

Posted by Midori Ryuu on 20 August 2012 - 01:47 AM


I would have a small tree for vehicles. The root vehicle class would have a rendering component, a collision component, position component etc..

Then a tank, a subclass of vehicle would inherit those components from it, and be given it's own "cannon" component.

This is still an abuse of the OO concept of inheritance. You could compose your tank out of a vehicle and a cannon -- e.g.
struct Tank {
  Vehicle vehicle;
  Cannon cannon;
};


How is this different from adding the vehicle's components inside the tank through inheritance and then adding a cannon component? They really seem the same to me. Will it cause the same problem as the one in your second example?

The same goes for the Characters. A character would have it's own components, then the Player Class would inherit it, and be given an Input controller, while other enemy classes would inherit from the Character class and be given an AI controller.

As an example of how inheritance is causing unnecessary restrictions here -- what if you want the ability for the player to take over an AI character, and let the AI take control of their previous character? Decoupled composition allows for this:
struct BaseController
{
  Character* controlled;
}
struct PlayerController : BaseController
{
  InputDevice inputs;
  void ReadInputsAndControlCharacter();
};
struct AiController : BaseController
{
  CharacterAi brains;
  void UpdateBrainsAndControlCharacter();
};
void SwapControl( BaseController& a, BaseController& b ) { std::swap( a.controlled, b.controlled ); }
N.B. in the above, CharacterAi, InputDevice and Character are completely decoupled - they don't know about each other at all. The player and AI controller classes form a 'bridge' between these decoupled components -- reading intentions from inputs or AI and passing them on to the character interface (and reading character state ans passing it to the 'brain').


I was actually thinking about similar problems when I posted. I thought of doing some sort of duck-typing in a scripting language to solve this, but I didn't have an actual idea how to. The way you implemented the controllers is much more elegant. I assume this removes the need for a player and an enemy class and the distinction will be made at runtime when the components are assigned?

If so, then the will the character class have a polymorphic reference to the BaseController which can be either an instance of PlayerController or AIController?

[edit]Sorry for the C++ examples

It's perfectly fine as long as you excuse my inexperience with C++, as I may have understood the example you gave a bit wrong.. >_<


#4971354 Composition heavy OOP vs pure entity component systems?

Posted by Midori Ryuu on 20 August 2012 - 12:00 AM

I admit, I have made the sin of overusing, and even abusing inheritance. The first (text) game project that I made when I was taking my OOP course went as far as "Locked door" and "unlocked door" from "Door" and "Room with one door", "Room with two doors", and so on from "Room".

With the (graphical) game I worked on recently, I thought I had learned my lesson and put a limit on using inheritance. However I noticed the problems soon beginning to appear. My root class was beginning to bloat more and more, and my leaf classes were full of duplicate codes.

I thought I was still doing things wrong, and after looking it up online I discovered that I wasn't the only one with this problem. It's how I ended up discovering Entity systems after some thorough research (read: googlefu)

When I began reading on it, I was able to see how clearly it was able to solve the problems I was having with the traditional OOP hierarchy with components. These were in the first readings however. When I stumbled upon more… “radical” ES approaches, such as the one at T-machine.

I began disagreeing with the methods they were using. A pure component system seemed either overkill, or rather, unintuitive, which is probably the strength of OOP. The author goes so far as to say that ES system is the opposite of OOP, and while it may be usable along OOP, it really shouldn’t. I'm not saying it's wrong, but I just didn't feel like a solution I would like to implement.

It was then that I stumbled on Hodgman post, and it really made sense to me. I really didn’t see any conflict between OOP and composition; rather, the two seemed as one.

So to me, and to solve the problems I was having at the beginning of the post, without going against my intuitions, is to still use a hierarchy, however it won’t be a monolithic hierarchy like the ones I used before, but rather a polylithic one (I couldn’t find a word opposite to monolithic), which consists of several, smaller trees.

The following example shows what I mean (this is insipied by an example I found in Game Engine Architecture, Chapter 14).

I would have a small tree for vehicles. The root vehicle class would have a rendering component, a collision component, position component etc..

Then a tank, a subclass of vehicle would inherit those components from it, and be given it's own "cannon" component.

The same goes for the Characters. A character would have it's own components, then the Player Class would inherit it, and be given an Input controller, while other enemy classes would inherit from the Character class and be given an AI controller.



I don't really see any problems with this design. Despite not using a pure Entity Controller System, the problem with the bubbling up effect, and the large root class is solved by using a multi-tree hierarchy, and the problem of the heavy, code duplicating leafs is gone since the leafs don't have any code to begin with, just components. If a change needs to be done to the leaf level, then it's as simple as changing a single component, instead of copy pasting the code everwhere.

Of course, being as inexperienced as I am, I did not see any problems when I first started using the single hierarchy, inheritence heavy model, so if there are problems with the model that I'm currently thinking of implementing, I wouldn't be able to see it.

Your opinions?

P.S: I am using Java, so using multiple inheritance to implement this instead of using normal components is not possible.

P.P.S: Intercomponent communications will be done by linking dependent components to each other. This will lead to coupling, but I think it's an ok trade off.


#4969753 How to efficiently manage animations and/or textures (resources) in a game? (...

Posted by Midori Ryuu on 15 August 2012 - 12:20 AM

I can't speak much to the Java/Slick2D specifics, but the following two patterns/idioms are the answer to your first problem.

Flyweight Pattern

Copy on Write

Use the flyweight pattern to easily share resources between entities, and then use copy on write so that you can "add a frame to a particular entity's animation," without effecting the other entities.


Thank you for the link! I had implemented (or at least think I had implemented) the Flyweight Pattern in my design, as the images are shared by the animations.

However I did not know about the Copy on Write! That will probably help me fix the animation problem I'm having.


If anyone has any other solutions, I'm always looking for insight!

And thank you again nox! :)


PARTNERS