PDA

View Full Version : Game Engine



kernco
26th February 2010, 02:14
Hi everyone,

I'm writing a game engine and I wanted to get some input about my design. First of all, here's a quick outline of how I want the engine to behave. This isn't a graphics engine (I'll be using QGraphicsView/Scene for that), it's just the engine that will be updating the properties of the objects that are in the game. The game engine will run in a separate thread so that if there are too many objects for the system to handle, the application's interface will remain responsive and only the updating of the game world will lag. The game engine should allow a maximum frames per second (in this case, a frame isn't updating the graphics on the screen, but calling the update function for every object in the game), and if the system can't maintain that fps, time in the game world shouldn't slow down, only the updating of objects in the game world. For example, if an object is moving 5 pixels per second, but isn't updated for 3 seconds, then it should move 15 pixels when it's updated.

All the objects in the game will inherit from a class I'll be calling MyObject in the code I show here. The MyObject class has a virtual function called tick() which the engine will call to update the object. Subclasses will implement this function to do things like update the object's position, speed, etc. I've gone through a few different ways to implement this engine, and run into problems with each of them. Here is my current iteration:


class GameEngine : public QThread
{
Q_OBJECT

public:
explicit Ticker(QObject *parent = 0);

void add(MyObject* object) {
done_->enqueue(object);
}

void doFrame() {
qSwap(queue_, done_);
while (!queue_->empty()) {
MyObject *object = queue_->dequeue();
object->tick();
add(object);
}
}

private:
QQueue<MyObject*> *queue_;
QQueue<MyObject*> *done_;
};

class MyObject : public QObject
{
Q_OBJECT

public:
explicit MyObject(QObject *parent) : QObject(parent) {
timer_.start();
}

protected slots:
virtual void tick() = 0;

protected:
//Implementations of tick() can use this to know the time between calls.
int elapsed() {
int time = timer_.elapsed();
timer_.restart();
return time;
}

private:
QTimer timer_;
};

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0) : MainWindow(parent) {
engine = new GameEngine;
engine->start();
startTimer(20);
}

protected:
void timerEvent(QTimerEvent *event) {
engine->doFrame();
}

private:
GameEngine *engine;
};

It's pretty simple, but gets most of the job done. My main question is what will happen if the system can't process the tick() function for every object in the 20 msecs before the next frame. Since the objects keep track of how long it's been since the last time they updated, I don't see a problem there. What happens with the event queue from the timer, though? If a timer event is being posted every 20 msecs, but it takes say 30 msecs to process each frame, will the event queue just keep growing and growing?

Another thing I'm not sure about is having a separate timer for each object to track the time between updates. Is there a better way to do this? Maybe pass an int to the tick function that indicates the current time, and each object just stores an int which is the time of its last update?

Any other comments about this? Other issues you think I might run in to? Better ways of going about this problem? Thanks!