views:

133

answers:

7

I am making a game, and I have finally finished the gameplay aspect of it, but now it's time for me to create a menu and a high scores screen. I'm not entirely sure how to do it, the game will be in a different state (MENU_STATE, GAMEPLAY_STATE, SCORESCREEN_STATE) and in each state I want to draw different things to the screen, is it okay for me to do something like this then?

draw function()
{
    if MENU_STATE
        draw menu
    if GAMEPLAY_STATE
        draw game
    if SCORESCREEN_STATE
        draw scores
}

I've been following a strictly no logic in the draw function and it's been good so far, but I really can't figure out a different way to do this.

A: 

It is absolutely not ok to put game logic in a draw function.

However, if it makes your life easier in this specific case, it's ok anyway.

You can always change it later if it becomes a mess.

A: 

How would I go about changing it if it did become a mess? I really can't figure out any way to do it without having the logic in there.

Joe
Welcome to Stack Overflow :). If you're responding to an answer, it's better to use a comment -- that way it's clearer what you're responding to. This isn't a forum, and answers won't stay in the same order.
Andrew Aylett
New answers should not be posted as replies to previous answers. Try editing your original question instead, to add your reply, and then porgarmingduod should edit his answer to include a response to your addendum.
Ricket
Sorry, I can't figure out how to add comments up there.
Joe
+3  A: 

You are calling some drawing functions in that routine but that doesn't mean
you have to name it draw.

Perhaps this is more appropriate in your case:

// pseudocode
on_game_state function(state)
{
    select (state):
      MENU_STATE:
        draw menu
      GAMEPLAY_STATE:
        draw game
      SCORESCREEN_STATE:
        draw scores
}
Nick D
This is still logic in a drawing function, isn't it?
Andrew Aylett
+1 for pointing out that this isn't necessarily a draw function, or that it doesn't have to be. Note also that if there's actual drawing later in the function, that can be punted to a different function (that's actually a draw function) too, if you want to be strict about keeping game logic outside of any drawing function.
Platinum Azure
@Andrew Aylett: Not necessarily. If this is all that's in the function, then all it's doing is calling other functions for actual drawing, not doing any drawing itself. (EDIT: I guess I'm just assuming that "draw menu" and the like are separate function calls)
Platinum Azure
@Andrew Aylett, I assume @Joe is making his first steps into game programming. Simple games usually have a game loop which call functions for rendering, updating objects state, etc. The bigger part of the game *logic* should be implemented in a routine that will update object state IMO.
Nick D
@Andrew, "this is still logic in a drawing function, isn't it?": that function should be part of the main game loop, don't you agree?
Nick D
+4  A: 

You could use separate classes for the three states, implementing a common interface, and rather than setting a constant for state, set an instance of one of the classes:

interface IState {
    void draw();
}

class Menu implements IState {
    void draw() {
        // Draw menu
    }
}

class Game implements IState {
    void draw() {
        // Draw game
    }
}

void draw() {
    state.draw();
}

This still isn't ideal (you don't really want drawing code in your state, you want something a bit more separate), but the abstraction is a common one and could be relevant (and it's hard to advise further without knowing more of your architecture).

Andrew Aylett
+1 this is precisely the reason virtual functions (or, in C, function pointers) exist.
BlueRaja - Danny Pflughoeft
@BlueRaja and precisely why using virtual functions to do this in games is usually a bad idea i.e I have 100,000 objects to update and draw - calling a virtual function 100,000 times which is basically a table lookup is gonna ruin my performance pretty quickly
zebrabox
+1  A: 

Using a statemachine would make this simpler. Each state will have its own set of update and draw functions that are called when it is on top of the state stack. Instead of having one draw function with internal state switches you would have Game_Draw(), Menu_Draw(), HighScoreScreen_Draw() etc. Similarly your update functions could be separated out.

static void StateMachine_DrawTopState()
{
   switch(stateMachine_topState)
   {
       case STATE_GAMEPLAY:
       {
           Gameplay_Draw();
       }
       break;
       case STATE_MENU:
       {
           Menu_Draw();
       }
       break;
   }
}
Colin
A: 

Yes it's fine, game programmers are allowed to bend the rules for performance gains. The view and the model of a game world are quite often one and the same thing to avoid latency created by decoupling the view and the model.

There's no reason why you can't make the menu and highscores objects part of your game world, it's been done before in quite a few games.

PeanutPower
+1  A: 

Similar to Andrew Aylett's answer and assuming an object-oriented language, perhaps you could do something like:

Interface IState {
    void init();
    void update();
    void draw();
}

class GameplayScene implements IState {
    void init() {
        // initialize gameplay
    }
    void update() {
        // update game logic
    }
    void draw() {
        // draw game
    }
}

class MenuScene implements IState {
    void init() {
        // initialize menu
    }
    void update() {
        // update menu logic
    }
    void draw() {
        // draw menu
    }
}

class ScoresScene etc...

class TitleScene etc...

// Somewhere else, probably in the Game class
void Main() {
    // Init game
    Scene currentScene = new TitleScene;
    while (Scene != null) {
        Scene.init();
        Scene.update();
        Scene.draw();
    }
    // Exit game
}

You would also need to think about how to handle transition between scenes. You could have each scene class have a member variable called something like nextScene and the main function queries it at the start of the loop to switch to the proper scene.

If you don't have the luxury of using an object-oriented programming language (like C++, Java, C#, Python, etc.), both Colin's and Nick D's answers might help, although I'd try to have the switch statement in one place (say one big game_update function) to allow adding new states by making a change in one place. Alternatively, you could build on the Colin's state machine design to make something more generic and that doesn't explicitly require a hard-coded switch statement. (although to be honest I can't think of a good way to do it at the moment)

Firas Assaad