Game Design With Update and Draw Functions

Started by
3 comments, last by tool_2046 10 years, 8 months ago

Objects in my game have both update and draw functions as expected, the update function sometimes need a delta time variable and the draw function sometimes needs a window object.

I have seen lots of engines pass in the delta time variable through every update function and pass in the window object through every draw function like so:


//C++
void State::update(float deltaTime)
{
     sprite.pos += vel * deltaTime;
}

void State::draw(Window window)
{
     window.draw(sprite);
}

The problem with passing these objects through every single update and draw method is that sometimes the're not used. For example, a main menu does not need a delta time variable but does need a window object, but you can't just omit the parameter if you don't need it because the main menu inherits from the game state object which contains the parameters.

So would it be better in design to never pass these objects into functions but instead make them static like so?


//C++
void State::update()
{
     sprite.pos += vel * GameManager::deltaTime;
}

void State::draw()
{
     GameManager::window.draw(sprite);
}

I'm asking because this is a very fundamental concept to game engines and the latter example just seems to make more since but it seems like the former example is favored.

Which is better code design? Thanks.

Advertisement

I would suggest go ahead have them and passing them in, but I would pass the Window by reference to avoid unwarranted copied.

What you can do then is have all objects that require an update and a draw be stored globally in common lists, and can all be looped through and called the same way:

class GameObject
{
public:
  GameObject() {}
  virtual void Update(Window& window) {}
  virtual void Draw(double deltaTime) {}
};
 
class SomeEnemy : public GameObject
{
  ...
};
 
class SomeBackgroundItem : public GameObject
{
  ...
};
 
// in Code somewhere:
std::vector<GameObject> GameObjects;
 
void MyGame::Initialize()
{
  // add all enemies to GameObjects
  SomeEnemy thisEnemy;
  GameObjects.push_back(thisEnemy)
  SomeBackgroundItem  backgroundItem;
  GameObjects.push_back(backgroundItem);
  ...
}
 
void MyGame::MainLoop()
{
  double deltaTime = GetDeltaTime();
  for (uint32_t i = 0; i < GameObjects.size(); ++i) {
    GameObjects[i].Update(deltaTime);
  }
  for (uint32_t i = 0; i < GameObjects.size(); ++i) {
    GameObjects[i].Draw(MainWindow);
  }
}

My Gamedev Journal: 2D Game Making, the Easy Way

---(Old Blog, still has good info): 2dGameMaking
-----
"No one ever posts on that message board; it's too crowded." - Yoga Berra (sorta)

I'm not saying which is better(as honestly, it is more of a preference kind of thing anyway), but Unity does it through static classes, where for example there is a Time class, and to access the deltaTime, you use Time.deltaTime. Note that I'm using the "Time" which is the actual name of the class, not an instance of the class.



A static delta is another dependency. The update function that takes a float can compile with any code that has floats - any C++. The other example means that your game object now needs to be aware of the GameManager namespace or class. It also no longer starts out with the delta time in a register. It has to load it from memory.

If it's getting ignored almost all the time, though, it might make more sense to use those registers to pass in other, more important things.

Anything passed in as a parameter is very flexible to play around with for debugging or game feature purposes. However, too many unused parameters can lead to bad style as some programmers might just pass 0 or NULL in when they realize some parameter isn't used, and then things break when you do use them. It's also just unwieldy to have too many parameters.

In the end, it's not really a big deal which way you go, but I prefer using parameters until I start to feel bad about too many parameters everywhere.

Objects in my game have both update and draw functions as expected...

OK, I know this isn't what you are asking about, but I'm going to say it anyway. Don't have a "draw" or "update" method per object. Instead have collections of "drawables" and "updaters" in your game objects. That way you can easily combine behavior and create more complex components without having to subclass a billion different objects. Also, if your object doesn't need to draw itself or update itself, this works well.

This topic is closed to new replies.

Advertisement