Focus of Object Oriented design

Started by
4 comments, last by way2lazy2care 13 years, 1 month ago
I have two questions regarding OO design in games. I feel that I make it overly complex to myself, so it would be great if someone can give some recommendations.

1. For school I had to make a simple 2D game with monsters, humans, etcetera. Suppose a monster is an abstract class and you have two concrete derived classes ([font="Courier New"]MonsterA[/font] and [font="Courier New"]MonsterB[/font]). At some point I need to retrieve a list of all objects of type [font="Courier New"]monsterA[/font], because some other function in my game needs them. However I put all objects in a generic list so that I can update each one easily using polymorphism.
What is the best way to retrieve these objects? Creating more lists for each separate object sounds cumbersome, because then I lose the advantage of polymorphism. Using [font="Courier New"][color="#000080"]dynamic_cast[/font] sounds slow to me (or is this common in games?). And adding a member variable can work, but I think it's ugly.

2. This question is about restricting or allowing certain operations on the object itself. For example, the teacher said that you can model a bullet in a separate class and when it hits an object, you call the method [font="Courier New"]collidesWith(Bullet*)[/font], so that each object can deal with a bullet collision separately.
However, now it's possible for an object to just ignore the bullet so that the monster can never die (because he decides for himself). When other people make derivations of this class, I guess they should not be able to ignore the game rules.
I was more thinking toward another class that deals separately with collisions and updating the health. This won't work when health is stored as private in the object though and when new monsters are added I have to change this class as well. This makes it too coupled with other classes and results in a lot more classes/complexity.
So, do I need to restrict objects to update themselves or should I design it in a way that objects are responsible for themselves (assuming that each object updates it's state in a realistic matter, so not cheating with ignoring collisions with bullets, etc.).
Advertisement

Suppose a monster is an abstract class and you have two concrete derived classes (MonsterA and MonsterB).
[/quote]

I wouldn't, because that leads you directly into the problem you describe. Don't encode information into types (in languages like C++). The type of monster should just be a field of the monster class (if you even make that distinction between monster and player, since that too will lead to this sort of problem).

2. Either way is fine. To some degree, this second problem is something that cannot be solved well in many languages. In general though, forcing programmers to obey game rules is a social problem, not a technological one.

I have two questions regarding OO design in games. I feel that I make it overly complex to myself, so it would be great if someone can give some recommendations.

1. For school I had to make a simple 2D game with monsters, humans, etcetera. Suppose a monster is an abstract class and you have two concrete derived classes ([font="Courier New"]MonsterA[/font] and [font="Courier New"]MonsterB[/font]). At some point I need to retrieve a list of all objects of type [font="Courier New"]monsterA[/font], because some other function in my game needs them. However I put all objects in a generic list so that I can update each one easily using polymorphism.
What is the best way to retrieve these objects? Creating more lists for each separate object sounds cumbersome, because then I lose the advantage of polymorphism. Using [font="Courier New"][color="#000080"]dynamic_cast[/font] sounds slow to me (or is this common in games?). And adding a member variable can work, but I think it's ugly.

2. This question is about restricting or allowing certain operations on the object itself. For example, the teacher said that you can model a bullet in a separate class and when it hits an object, you call the method [font="Courier New"]collidesWith(Bullet*)[/font], so that each object can deal with a bullet collision separately.
However, now it's possible for an object to just ignore the bullet so that the monster can never die (because he decides for himself). When other people make derivations of this class, I guess they should not be able to ignore the game rules.
I was more thinking toward another class that deals separately with collisions and updating the health. This won't work when health is stored as private in the object though and when new monsters are added I have to change this class as well. This makes it too coupled with other classes and results in a lot more classes/complexity.
So, do I need to restrict objects to update themselves or should I design it in a way that objects are responsible for themselves (assuming that each object updates it's state in a realistic matter, so not cheating with ignoring collisions with bullets, etc.).

1. http://en.wikipedia.org/wiki/Decltype This is what you want, but it doesn't exist in C++ yet. Here's some current solutions: http://stackoverflow.com/questions/1540086/how-to-typeof-in-c
2. You are not responsible for the stupid things other people do with your code. When other people derive a new class, they are not following or ignoring game rules, they are creating game rules. If that SE wants his monster to react differently to bullets, then let him deal with it.

You could handle collision in the base class with some collision mesh, and change the collision mesh in child classes, but your worry that people will "ignore the game rules" is exactly the point of inheriting in the first place. If I wanted the monster to act just like Monster A I'd use Monster A.
Thanks for the suggestions. The workaround by adding a member function that returns a unique identifier per class seems reasonable.


[color="#1C2837"]The type of monster should just be a field of the monster class (if you even make that distinction between monster and player, since that too will lead to this sort of problem).[/quote]
@Telastyn: I don't really get your suggestion. I understand your point about not encapsulating information into types, but how can you flatten monsters, players, etc. in one class? I see that by using aggregation you can add a lot of flexibility to one class (e.g. drawing differently for players and monster). However a monster should be able to do different things than humans. Humans can shoot for example, but monsters can't. This seems cluttering to me and an even bigger social problem of not calling member functions that monsters really have in their public interface.
Thanks for the suggestions. Adding a member variable that returns a unique identifier per class seems to be reasonable.
Let me start by saying that I am not fan of OOP. In particular, practitioners of OOP (EDIT: perhaps only inexperienced practitioners?) seem to find opportunities to create class hierarchies everywhere, and this often makes things unnecessarily complicated. Although using polymorphism for different types of monsters sounds right at first, the fact that you need to get a list of monsters of type A makes me suspicious. In my experience polymorphism only works well when the only part of the code that needs to be concerned with different derived types is the factory function that creates them.

Let me start by saying that I am not fan of OOP. In particular, practitioners of OOP (EDIT: perhaps only inexperienced practitioners?) seem to find opportunities to create class hierarchies everywhere, and this often makes things unnecessarily complicated. Although using polymorphism for different types of monsters sounds right at first, the fact that you need to get a list of monsters of type A makes me suspicious. In my experience polymorphism only works well when the only part of the code that needs to be concerned with different derived types is the factory function that creates them.


To elaborate on this, objects with the same base class that are being stored together as type base class should only be referenced as types of the base class. Using virtual functions to have different function definitions for each of your subtypes is fine, but you should, in theory, be treating all monsters as monsters, not some monsters as monster A and some as monster B. They should be interfaced with the same if they are stored as the same type, but act differently through that interface.

This topic is closed to new replies.

Advertisement