How to implement simple tick-based engine in c++? - c++

I'm writing a text game and I need a simple combat system, like in MUDs, you issue commands, and once in a while "tick" happens, when all those commands execute, player and monsters deal damage, all kinds of different stuff happens. How do I implement that concept?
I thought about making a variable that holds last tick time, and a function that just puts events on stack and when that time is (time +x) executes them all simutaniously. Is there any easier or cleaner variant to do that?
What would be possible syntax for that?
double lastTickTime;
double currentTime;
void eventsPile(int event, int target)
{
// how do i implement stack of events? And send them to execute() when time is up?
}
void execute(int event, int target)
{
if ((currentTime - lastTickTime) == 2)
{
eventsHandler(event, target);
}
else
{ // How do I put events on stack?
}
}

The problem with simple action stack is that the order of actions will probably be time based - whoever types fastest will strike a first hit. You should probably introduce priorities in the stack, so that for instance all global events trigger first, then creatures' action events, but those action events are ordered by some attribute like agility, or level. If a creature has higher agility then that it gets the first hit.

From what I've seen, most such engines are event, rather than time, based. with a new tick being triggered some interval after the last tick ended. (thus mostly avoiding the issue of ticks taking longer than the interval)
This also simplifies implementation; you simply have a game loop that triggers a tick event, then sleeps/yields for the required interval. Which is trivial.
It can further be simplified by modeling the world as a tree, where each element manages propagating events (such as ticks) to their children. so long as you avoid / manage 'loops', this works well (I've done it).
This effectively reduces the tick system to something like this (psudocode):
while (isRunning) {
world->tick();
sleep(interval);
}
In most cases, theres little need to get much fancier than adjusting for the length of the previous duration.
Any individual entities actions would be part of their own action queue, and handled during their own "tick" events.
Usually user commands would be split into "ingame" and "meta" commands, anything ingame would merely amend their character's action queue, to be processed in their next tick, as per normal for any other entity.
Simple round-based combat follows naturally from this foundation. realtime can be modeled with a finer division of ticks, with optional 'time-pooling'.

Use a timer executing every x ms (whereas x is your ticktime), execute any actions put on the stack in that method.

Related

Callbacks and the main game loop. Is it a good practice?

I'm writting a game using C++. I wonder how can I optimize my game loop. For example, we have some game with the main loop looks like this:
while ( gameContinue ) {
if ( SCENE == HELP_SCENE ) {
renderHelpScene();
} else if ( SCENE == SCORE_SCENE ) {
renderScoreScene();
} else if ( SCENE == MAIN_GAME_SCENE ) {
renderMainGameScene();
} // .... and many others scenes
}
I'm thinking on how to make this code faster and lighter. I think about using callbacks so we will not need many if-cases. Something like this:
typedef void (*callback_function)(void);
callback_function renderFunc;
void renderMainGameScene() {
renderFunc = renderScoreScene(); // set to another scene if we need this
}
void renderScoreScene() {
renderFunc = renderAnyAnotherSceneWeNeedNow();
}
renderFunc = renderMainGameScene();
while ( gameContinue ) {
renderFunc();
}
What do you think about it? How do you organize your main loops?
I've personally started using multi-threading. I have a thread for object updates, a thread for objects collision and a thread for drawing. Each thread loops with a while (GetMessage()) and threads send messages from one to another.
At each cycle (frame), my main loop sends a message to each thread to:
Calculate collision for modified objects
Update objects (movement, state etc.)
Draw the updated objects
That's how I do it (at least on my GDI/GDI+ games). Not sure if the best way, but so far it works like a charm :).
Helpful patterns for this kind of problem are the State Pattern and the Strategy Pattern.
As you can see they are both similar. The Strategy pattern is a bit simpler than the State, but in exchange the State Pattern is more powerful and probably better fitted for a game engine like this. You can also easily create a stack with this for example: game start -> menu -> game run -> menu.
If the parent state of the last menu is game run, the menu would look different (e.g. "Return game" instead of "Start game" in the first menu). The states can be popped and you have a easy navigation.
Using call-backs should be fine. Just be careful not to have any cyclic dependencies in your headers. Notably it's a bad idea to include the header for your controller loop anywhere other than the .cpp for the controller loop.
As for the runtime benefits, they are very small. The if-else method will not noticeably slow down your game. Alternatively, there is also the switch statement, which is preferable to a series of if-else statements in terms of code readability.

Fire events in one class subscribed from another

I have a class AwesomeMousePointer that has some function to start playing animations on the mouse:
class AwesomeMousePointer{
void startAnimat();
void stopAnimat();
};
I have another object to which I have given the responsibility of figuring out whether the mouse anims should start or not (this is based on the internal hit testing on the object, for eg: if the mouse is inside the object for a specific time)
class SomeShape(){
Event<MouseArgs> startAnim
Event<bool> interrutptAnim
bool hitTest(int x, int y);
//Inside some loop function, check if the mouse is inside the object
if(hitTest(mouseXPos, mouseYPos)){
//if the mouse if inside for x time
NotiftyEvent(startAnim, MouseArgs);
}
else{
//mouse left the object
NotifyEvent(interruptAnim, false);
}
Now, again inside my AwesomeMousePointer, I'll add listeners for the events i.e
AddListener(SomeShape::startAnim, &AwesomeMousePointer::startAnim);
AddListener(SomeShape::interruptAnim, &AweseommousePointer::interruptAnim);
The single event system by using NotifyEvent and AddListener are working correctly in short different example I tried. Now inside this application of mine, I have a lot of the objects of SomeShape and a single AwesomeMousePointer. My question is if the above logic for the anims will work or should I explicitly pass the SomeShape object explicitly to subscribe to their events, in which things would become a bit difficult.
For eg:
AddListener(shapeObject1.startAnim, &AwesomeMousePointer::startAnimat);
AddListener(shapeObject2.startAnim, &AwesomeMousePointer::startAnimat);
AddListener(shapeObject3.startAnim, &AwesomeMousePointer::startAnimat);
OR
AddListener(SomeShape::startAnim, &AwesomeMousePointer::startAnimat);
Will the second one from the above work out? If not, how will that be done without explicitly passing the object since that makes the unclear and ShapeObjects shouldn't be inside the MousePointer.
Will this work if I make the events inside SomeShape as static?
static Event<MouseArgs> startAnim
static Event<bool> interrutptAnim
You say that you don't want to have coupling between the senders and targets. In this case, usage of Poco events is not appropriate. According to http://pocoproject.org/slides/090-NotificationsEvents.pdf, you should use Notifications instead of Events, because your senders and targets do not need to know each other then.

How do I progressively load a widget in QT?

I have a custom widget which displays many items in rows:
void update(){ //this is a SLOT which is connected to a button click
QVBoxLayout *layout = this->layout();
if (layout == NULL){
layout = new QVBoxLayout;
this->setLayout(layout);
} else {
QLayout_clear(layout); //this is a function that I wrote that deletes all of the items from a layout
}
ArrayList *results = generateData(); //this generates the data that I load from
for (int i = 0; i < results->count; i++){
layout->addWidget(new subWidget(results->array[i]));
}
}
The problem is that there are about 900 items and a profile reveals that simply adding the child object to the layout takes 50% of the time (constructing takes the other 50%). Overall it takes about 3 seconds to load all of the items.
When I click on the button to load more data, the entire UI freezes for the 3 seconds and then all of the items appear together when everything is done. Is there a way to progressively load more items as they are being created?
The first trick is, as Pavel Zdenek said, to process only some of the results. You want to process as many together so that the overhead (of what we're going to do in the next step) is low, but you don't want to do anything that would make the system seem unresponsive. Based on extensive research, Jakob Nielsen says that "0.1 seconds is about the limit for having the user feel that the system is reacting instantaneously", so as a rough estimate you should cut your work into roughly 0.05 second chunks (leaving another 0.05 seconds for the system to actually react to the user's interactions).
The second trick is to use a QTimer with a timeout of 0. As the QTimer documentation says:
As a special case, a QTimer with a timeout of 0 will time out as soon
as all the events in the window system's event queue have been
processed. This can be used to do heavy work while providing a snappy
user interface.
So that means that a timer with a timeout of 0 will be executed next, unless there is something else in the event queue (for instance, a mouse click). Here's the code:
void update() {
i = 0; // warning, this is causes a bug, see below
updateChunk();
}
void updateChunk() {
const int CHUNK_THRESHOLD = /* the number of things you can do before the user notices that you're doing something */;
for (; i < results->count() && i < CHUNK_THRESHOLD; i++) {
// add widget
}
// If there's more work to do, put it in the event queue.
if (i < results->count()) {
// This isn't true recursion, because this method will return before
// it is called again.
QTimer::singleShot(0, this, SLOT(updateChunk()));
}
}
Finally, test this a little bit because there's a gotcha: now the user can interact with the system in the "middle" of your loop. For instance, the user can click the update button while you're still processing results (which in the above example means that you would reset the index to 0 and reprocess the first elements of the array). So a more robust solution would be to use a list instead of an array and pop each element off the front of the list as you process it. Then whatever adds results would just append to the list.
#Adri is generally right, the twist is that the "another thread" must be the UI thread again. The point is to allow UI thread's event loop to keep spinning. The fast and dirty way is to put QCoreApplication::processEvents() in your for() cycle. Dirty because, as the doc says, it should be called "ocassionally". It might have some overhead even if there are no UI events, and you are messing Qt's performance optimization as to when and how often spin the loop. Slightly less dirty would be to call it only ocassionally, after chunks of result.
Cleaner and proper way is to create a private slot, which pops one result element (or chunk, to speed up), adds to the layout and increments index. Then it will recall itself until end of results. The gotcha is to define connect() with forced connection type Qt::QueuedConnection, so it will get deferred after already queued UI events (if any).
And because you run in only one thread, you don't need any locking over results.
Adding example per OP's request:
While #TomPanning solution is correct, it kind of hides the real solution behind QTimer which you don't need - you don't need any timing, you just need a specific non-timer behavior upon specific parameter value. This solution does the same thing, minus the QTimer layer. On the other hand, #TomPanning has a very good point about the plain ArrayList not being very good data storage, when interaction can happen in between.
something.h
signals: void subWidgetAdded();
private slots: void addNextWidget();
ArrayList* m_results;
int m_indexPriv;
something.cpp
connect(this,SIGNAL(subWidgetAdded()),
this,SLOT(addNextWidget(),
Qt::QueuedConnection);
void addWidget() {
// additional chunking logic here as you need
layout->addWidget(new subWidget(results->array[m_indexPriv++]));
if( m_indexPriv < results->count() ) {
emit subWidgetAdded(); // NOT a recursion :-)
}
}
void update() {
// ...
m_results = generateData();
m_indexPriv = 0;
addNextWidget(); // slots are normal instance methods, call for the first time
}

Is it bad practice to have nested render loops?

I'm porting a game from Ruby to C++. There is a main render loop that updates and draw the content. Now let's say that during the game, you want to select an item another screen. The way it's done in the original code is to do Item item = getItemFromMenu(); getItemFromMenu is a function that will open the menu and do have its own update/render loop, which mean that during the whole time the player has this other screen open, you are in a nested render loop. I feel like this is a bad method but I'm not sure why. On the other hand it's very handy because I can open the menu with just 1 function call and so the code is localized.
Any idea if this is a bad design or not?
I hesitated to post it on gamedev, but since this is mostly a design issue I posted it here
edit : some pseudo-code to give you an idea:
The usual loop in the main part of the code:
while(open) {
UpdateGame();
DrawGame();
}
now inside UpdateGame() i would do something like:
if(keyPressed == "I") {
Item& item = getItemFromInventory();
}
And getItemFromInventory():
while(true) {
UpdateInventory();
if(item_selected) return item;
DrawInventory();
}
A good way to handle something like this would be to replace the DrawInventory() call with something like InvalidateInventory(), which will mark the current graphical state of the inventory as outdated and request it to be redrawn during the next frame rendering (which'll happen pretty soon after when the main loop gets to DrawGame()).
This way, you can keep running through the main loop, but the only parts of the screen that get looked at for redrawing are the ones that have been invalidated, and during normal gameplay you can invalidate your (2/3)D environment as a normal part of processing, but then inside the inventory you can always mark only inventory assets as needing to be redrawn, which minimises overhead.
The other part of your inner loop, UpdateInventory(), can be a part of UpdateGame() if you use a flag to indicate the current game state, something like:
UpdateGame()
{
switch(gameState)
{
case INVENTORY:
UpdateInventory();
break;
case MAIN:
default:
UpdateMain();
break;
}
}
If you really wanted, you could also apply this to drawing:
DrawGame()
{
switch(gameState)
{
case INVENTORY:
DrawInventory();
break;
case MAIN:
default:
DrawMain();
break;
}
}
But I think drawing should be encapsulated and you should tell it which part of the screen, rather than which separate area of the game, needs to be drawn.
What you've created with your nested render loop is functionally a state machine (as most game render loops tend to be). The problem with the nested loop is that many times you'll want to do the same sorts of things in your nested loop as your outer loop (process input, handle IO, update debug info etc).
I've found that it's better to have one render loop and use a finite state machine (FSM) to represent your actual states. Your states might look like:
Main menu state
Options menu state
Inventory state
World view state
You hook up transitions between states to move between them. The player clicking a button might trigger the transition which could play an animation or otherwise, then move to the new state. With a FSM your loop might look like:
while (!LeaveGame()) {
input = GetInput();
timeInfo = GetTimeInfo();
StateMachine.UpdateCurrentState(input, timeInfo);
StateMachine.Draw();
}
A full FSM can be a bit heavyweight for a small game so you can try a simplified state machine using a stack of game states. Every time the user does an action to transition to a new state you push the state on a stack. Likewise when they leave a state you pop it off. Only the top of the stack typically receives input and the other items on the stack may/may not draw (depending on your preference). This is a common approach and has some upsides and downsides depending on who you talk to.
The simplest option of all is to just throw a switch statement in to pick which render function to use (similar to darvids0n's answer). If you're writing an arcade clone or a small puzzle game that would do just fine.

Exception Handling in Qt Script with C++?

I have the following action which is executed when a certain
button is pressed in a Qt application:
#include <shape.h>
void computeOperations()
{
polynomial_t p1("x^2-x*y+1"),p2("x^2+2*y-1");
BoundingBox bx(-4.01, 4.01,-6.01,6.01,-6.01,6.01);
Topology3d g(bx);
AlgebraicCurve* cv= new AlgebraicCurve(p1,p2);
g.push_back(cv);
g.run();
//Other operations on g.
}
Topology3d(...), AlgebraicCurve(..), BoundingBox(...),
polynomial_t(...) are user defined types defined in the
corresponding header file .
Now for some values of p1 and p2, the method g.run() works perfectly.
Thus for some other values of p1 and p2, g.run() it is not
working anymore as the method gets blocked somehow and the
message "Application Not Responding" appears and I have to
kill the Application.
I would want to have the following behavior: whenever
g.run() is taking too long, gets blocked for some particular
values of p1, p2, I would want to display an warning box
using QMessageBox::Warning.
I try to do this with try{...} and catch{...}:
#include <shape.h>
class topologyException : public std::runtime_error
{
public:
topologyException::topologyException(): std::runtime_error( "topology fails" ) {}
};
void computeOperations()
{
try
{
polynomial_t p1("x^2-x*y+1"),p2("x^2+2*y-1");
BoundingBox bx(-4.01, 4.01,-6.01,6.01,-6.01,6.01);
Topology3d g(bx);
AlgebraicCurve* cv= new AlgebraicCurve(p1,p2);
g.push_back(cv);
g.run();
//other operations on g
throw topologyException();
}
catch(topologyException& topException)
{
QMessageBox errorBox;
errorBox.setIcon(QMessageBox::Warning);
errorBox.setText("The parameters are incorrect.");
errorBox.setInformativeText("Please insert another polynomial.");
errorBox.exec();
}
}
This code compiles, but when it runs it does not really
implement the required behavior.
For the polynomials for which g.run() gets blocked the error
message box code is never reached, plus for the polynomials
for which g.run() is working well, the error message box
code still is reached somehow and the box appears in the
application.
I am new to handling exceptions, so any help is more than
welcomed.
I think the program gets blocked somewhere inside g.run() so
it does not reach the exception, still I do not understand
what really happens.
Still I would want to throw this exception without going
into the code of g.run(), this function is implemented as
part of a bigger library, which I just use in my code.
Can I have this behavior in my program without putting any
try{...} catch{...} block statement in the g.run() function?
You cannot achieve what you want with the use of try-catch. if g.run() takes too much time or goes into an infinite loop, that doesn't mean an exception will be thrown.
What you can do is, you can move the operations that take a lot of time into another thread. Start that thread in your event handler and wait for it to finish in your main thread for a fixed amount of time. If it does not finish, kill that thread & show your messagebox.
For further reference, read QThread, Qt Thread Support
Thanks for the suggestions.
So I see how I should create the thread, something like:
class myopThread : public QThread
{
public:
void run();
};
Then I am rewriting the run() function and put all the operations that take a lot of time in it:
void myopThread::run()
{
polynomial_t p1("x^2-x*y+1"),p2("x^2+2*y-1");
BoundingBox bx(-4.01, 4.01,-6.01,6.01,-6.01,6.01);
Topology3d g(bx);
AlgebraicCurve* cv= new AlgebraicCurve(p1,p2);
g.push_back(cv);
g.run();
//other operations on g
exec();
}
Okay everything is clear so far, still I do not see how to "Start that thread in your event handler and wait for it to finish in your main thread for a fixed amount of time. If it does not finish, kill that thread & show your messagebox."
I mean start the thread in the event handler refers somehow at using the connect (..Signal, Slot..) still I do not see how exactly this is done. I have never used QThread before so it is more then new.
Thank you very much for your help,
madalina
The most elegant way to solve this that I know of is with a future value. If you haven't run across these before they can be quite handy in situations like this. Say you have a value that you'll need later on, but you can begin calculating concurrently. The code might look something like this:
SomeValue getValue() {
... calculate the value ...
}
void foo() {
Future<SomeValue> future_value(getValue);
... other code that takes a long time ...
SomeValue v = future_value.get();
}
Upon calling the .get() method of course, the value computed is returned, either by calling the function then and there or by retrieving the cache value calculated in another thread started when the Future<T> was created. One nice thing is that, at least for a few libraries, you can pass in a timeout parameter into the .get() method. This way if your value is taking too long to compute you can always unblock. Such elegant isn't usually achieved.
For a real life library, you might try looking into the library documented here. As I recall it wasn't accepted as the official boost futures library, but it certainly had promise. Good luck!