开发者

Is it okay to put game logic in a draw function?

开发者 https://www.devze.com 2022-12-20 12:54 出处:网络
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

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 st开发者_StackOverflowate 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.


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).


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
}


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;
   }
}


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)


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.


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消