views:

55

answers:

3

I'm working on a simple game design, and I wanted to break up my game objects into more reusable components. But I'm getting stuck on how exactly to implement the design I have in mind. Here's an example:

I have a Logger object, whose job is simply to store a list of messages and render them to screen. You know, logging. Originally the Logger just held the list, and the game loop rendered it's contents. Then I moved the rendering logic into the Logger.Draw() method, and now I want to move it further into a LoggerRenderer object.

In effect, I want to have the game loop call RenderAll, which will then call Logger.Render, which will in turn call the LoggerRenderer.Render and finally output the text. So the Logger needs to contain a Renderer object, but the Renderer needs access to the Logger's state (the message queue) in order to render.

How do I resolve that? Should I be passing in the message queue and other state information explicitly to the Render method? Or should the game loop be calling the Renderer directly and it links back to the logger, but the RenderAll method never actually sees the logger object itself?

This feels kind of like Command pattern, but I'm botching it up terribly.

+1  A: 

Or should the game loop be calling the Renderer directly and it links back to the logger, but the RenderAll method never actually sees the logger object itself?

This one.

Cory Petosky
So then does the Logger object also lack "_renderer = new Renderer()"? The only connection is from Renderer -> Rendered_Object and not back the other way?
CodexArcanum
Correct. Otherwise what was the point of splitting your renderer code off into its own class in the first place?
Cory Petosky
A: 

Here's how I would do it

class Logger {
    List<Message> messages;
    Message[] getMostRecent(int numMostRecent) { ... }
}

class MyGame {
    void draw() {
        // all my ui stuff
        Message[] messagesToRender = myLogger.getMostRecent(numRowsInLogWindow);
        String formattedMessages = magicalFormattingIfNecessary(messagesToRender);
        logWindow.setText(formattedMessages);
    }
}

Splitting objects off is good, but for something simple like a message log, you'll be better off keeping it simple and straightforward. I've overseen the development of dozens of games, and most of the problems were from over-complicating the design of it.

If you want to make a MessageFormatter object, you can do that, but only if you have multiple formats you need to accommodate.

Note: Yes my pseudo-code is really in Java. Adapt as necessary =)

glowcoder
A: 

Any time you have one object needing to access the internals of another object, you should consider that the code smell of Feature Envy. Don't do that.

If you really do need to have a LogRenderer, have it just render one message at a time and let your Log call it as necessary.

E.g. the Log says "for each message, renderer->RenderMessage(message)".

This assumes that the Log owns the LogRenderer. If you've got some other architecture then you may need to shuffle some things a bit, but endeavor to keep Feature Envy to a minimum.

dash-tom-bang