The everthing else class

Started by
5 comments, last by Durfy 16 years, 9 months ago
I'm having some difficulties with applying OOD to games. I'm talking about simple games (the current "game" I'm designing is Conway's Game of Life). What seems to happen is that I'm able to design the "physical" components of a game just fine. But then, when I have to actually make it work, everything becomes blurry. What I tend to end up with is class that is an uberclass that basically does everything to make the game work. As I understand it, this is bad design. It really goes against the single responsibility principle. So could anyone give me some pointers on how to tackle this problem (in general) or does anyone have some links or books that might help me out? Also, if the description of problem is too vague, please say so. I'll give a more concrete example.
Advertisement
I think I understand what you are saying, but without anything more concrete it is difficult to give advice on what to do. Perhaps you could post the code that you feel is the uberclass?
Mike Popoloski | Journal | SlimDX
Well, you're always going to have some piece of code that bootstraps everything, but if that piece of code becomes pretty big, you should rethink your design.

Maybe if you posted some code, I could give you more specific advice.

Well, to a degree there's almost always going to be a top level class that 'makes the game work'. But that should be its sole responsibility, to make different bits aware of each other and kick them off. The general advice of practice more, abstract more probably applies. Design is something that takes experience to get better at.
Take your uber class. Take a tiny part of it - for example, two or three data member that share a similar goal. Put these into another class (let's call it A). Modify your uber class to use an instance of this class. Compile, run, verify that everything goes fine. Examine A. It contains only data, but you feel there is a underlying responsibility that is linked to these data. Goes bask to your uber class. Extract the methods that correspond to this responsibility. Move them in A. Compile, run, verify that everything is OK. Go back to your uber class, spot some other data members that outline another responsibility. Move them in class B. Compile, run, verify that everything is OK. Goes bask to your uber class. Extract the methods that correspond to this responsibility. Move them in B. Compile, run, verify that everything is OK. Repeat, rinse.

This iterative process (I stressed on it by using a lot of repetition) is called refactoring. The goal is to enhance an existing design into something that is better. Martin Fowler wrote a complete book about this (including how to safely perform the different refactoring steps).

At the end of the process, what you should have is a set of smaller classes that have one responsibility and a glue class whose goal is to make the ease communication between the smaller classes. Now, the final design is probably not perfect, but it should be better than your original design. Given the fact that this gave you another organization to think about, you can try to spot design problems in it, and you can then try to enhance it again (either by refactoring it again or by doing it again from scratch).

HTH,
Right, I'll take my current project as an example.

Conway's Game of Life

Layout: The lay-out is really simple. We have a field on the left and a little menu on the right.

Required functionality: The user should have control over the simulation and over the field. Besides that we need some additional basic application functionality.
Simulation Control:
- Start simulation
- Stop simulation
- Reset simulation
- Set speed of simulation
Field control:
- Setting the state of the cells with a mouse
- Clear the cellfield
- Load a cellmap from a textfile
- Save the current cellfield as a cellmap in a textfile
Basic Application Functionality:
- A help-button
- A quit-button

Now, I went on with designing the game, starting with the cellfield. I'll present my class designs in a basic manner: "-" is a data member and "*" is a member function.

class CellField
- cells (will probably be a vector of bools, but like I said, I'll keep it simple)
* SetCellState;
* GetCellState

baseclass Simulation
* Start
* Pause
* Reset
* SetSpeed

baseclass CellFieldManip
* ChangeCellstate
* ClearCellField
* LoadCellMap
* SaveCellField

class CellFieldManager inherits from Simulation and CellFieldManip
- CellField
* GetCellField

[This is probably flawed, because handling input and updating the screen would use only a part of this class.]

Now things get a little more difficult:
class menu
I'm working on a decent menu class atm

class CatchInput
unsure of interface and inner workings (I'm currently doing research on SDL)

ehh help? This is where I get stuck, more or less.


Heh in reality there will be one main class that should it fail would effect more than one component. But as game sound has to relate to movement / physics this is necessary. Usually I like to wrap my classes up having my main class just be something like Game with one method process()
hehe prolly bad design but i like it
-durfy

This topic is closed to new replies.

Advertisement