I am currently working on writing a simple game in order to learn how to use SFML in C++. So far things have been going smoothly and I have a basic understanding of most things to do with SFML. The problem I have run into is finding an efficient way to and time based events.
The game I'm working on is a very simple space invaders esque game that has waves of enemies come in at predefined times during the level. As of now I have an event class that holds and controls what is supposed to happen with each called event in order to allow me to reuse simple events multiple times. As of now I trigger these events by looping utilizing an SFML cloock and with each iteration of the game loop running through a vector of all of the events for the current level and comparing the elapsed time on the clock with the specified time for the event to be called. The problem is that I have to check an entire vector of events every game loop iteration and if the event list get long enough I am worried it will begin to have an impact on the performance of the game.
I had an idea to give each event a simple numerical Id for its position in the timeline and simply store which event is supposed to run next that way I would only have to check the time of one event per loop iteration, and while this will work fairly well I think, I was curious if a more efficient method that didn't require a check every loop iteration was possible? I looked a bit into event driven programming but could not find much specifically related to time based events.
Thus I was wondering if anyone has had any experience with timelines or time based event triggering and would have any tips or resources that I could look at to figure out a more efficient idea? Any help would be great, thanks!
The method you suggest is just one comparison each time through the game loop. It doesn't get any faster than that.
To allow multiple events to fire at the same instant, use a multimap, where keys are event times, and values are the events themselves. The multimap will then be sorted by time.
Each time through the game loop, do something like this (pseudocode):
now = getCurrentTime()
while not events.isEmpty() and events.firstElement().key() < now:
e = events.firstElement().value
e.execute()
events.removeFirst()
Sort your vector based on the events' times and then just store how far you've gotten through the vector so far. Each loop then you'll advance that position until the next event shouldn't occur yet, and fire off the events you just iterated over.
std::vector<Event> time_line;
size_t time_line_position;
void fire_new_events(Time t) {
size_t new_time_line_position = time_line_position;
while(new_time_line_position < time_line.size()
&& time_line[new_time_line_position].time <= t)
++new_time_line_position;
fire_events(time_line.begin() + time_line_position,
time_line.begin() + new_time_line_position);
time_line_position = new_time_line_position;
}
Related
In my little project, I've decided to create a game that updates a counter of the user's experience points every second, as well as printing a menu and allowing the user to navigate said menu simultaneously. The code to update the user's experience is as follows, and it works perfectly fine standalone.
double timerX = GetTickCount();
double timerY = GetTickCount();
while(true)
{
double timerZ = GetTickCount() - timerX;
double timerA = GetTickCount() - timerY;
if(timerZ >= 1000) {
userExperience = userExperience + 1;
timerX = GetTickCount();
}
if(timerA >= 1100) {
system("CLS");
refreshExperience();
timerY = GetTickCount();
}
The function 'refreshExperience()' simply prints the 'userExperience' variable onto the screen using 'cout'.
At the same time as this, my program should be able to display the main menu GUI and ask for input from the user. However, I do not want the asking of input to halt the program, especially the money updater, as it is paramount that that is updated constantly. I have attempted to use multithreading by creating a thread for the 'refreshExperience' function, and also creating a thread for asking for input, but the problem still remained - the money would only update if the user was continually inputting (pressing keys). If he was not, the money would stay the same.
Any help would be very much appreciated.
Getting input from the user with no discernible break in program execution is only possible in GUI programming. When working in the console, every request for user input will block for the obvious reason that the program has to wait to actually have the necessary data before proceeding.
This is also why you should initialize variables before declaring them; if you don't, stack-allocated variables will contain random (to you) data and the program will not function as intended. Conceptually, this is the same problem the console has, except it doesn't have the luxury of free will and can't simply choose to skip the wait.
Conceptually, programs that have a user interface work by operating with a loop. Every event that occurs, from a mouse movement to a button click, triggers an event in the Window procedure. In the Win32 API, it's just a switch statement that checks for each possible event against what actually happened. When there's a match, the system triggers that event handler.
It should be noted that it only seems like there is no lag, because usually graphical window procedures are fast enough to seem to respond instantaneously. In reality, any action on the window triggers a calculation by the computer to determine what part of the window was blocked and must be redrawn, as it is now called "invalid."
Lastly, I would highly recommend a different method for the scoreboard update. I know it's just a contrived example for you to experiment with, but that means it's just as good if not better for trying out some design patterns, namely the observer pattern. Rather than the program checking for input every possible clock cycle it can is just a waste. When you have a situation like this, it's common to use callback functions, which in C are just function pointers that you pass along. That way you don't have to check to find out when the event is triggered, you can just have the event invoke the function that you passed in as a parameter. This is how Node.js works, by the way, and how it seems to do so much at once despite being single-threaded.
If you've heard anything about Reactive programming lately -it's been getting talked about just about everywhere in the C# community these past few months- this is what it's talking about, and the reason I bring it up is because this is one of the more common, though trivial, examples of a textbook reactive programming scenario.
So I'm pretty new with programming from scratch, have mainly used unity for a few years up untill now so my general programming knowledge is pretty good. Started studying game development at a university after summer though where we began programming from scratch and as a task we have to make a simple game in a 2D engine we made together in class.
So the game I decided to make was a copy of bomberman and I've gotten as far as where I'm now making the bombs functional.
The problem I'm having is that I don't know how to propperly add in a timer that counts down the time to where the bomb exlpode so the player can avoid it.
I've tried SDL_Delay and _sleep which both just pause the entire program so that doesn't work and I've searched around for more options but not really understood how things work. If I could get some expamples and links to pages that explains how to properly make something like this work (something easy and small hopfully :P) then that would be highly appreciated!
Note that we are using SDL in the engine.
Thanks!
Typically, a game uses a loop, in which you read user input (you are probably using SDL_PollEvent for that), advance the game state for a short time period and draw the screen. This loop is typically called the game loop, render loop or main loop.
A simple, accurate and typical way to delay an event (such as a timed explosion), is to store the future time into a queue. Then, each time the game state advances, check the first and therefore the oldest timestamp in the queue and if the current time is higher than the stored one, then we know that the the thing should now happen and you can call the function that executes the event without delay. Then remove the timestamp from the queue and check the next one until only future events remain or the queue is empty.
If the event delay can vary, then you'll need to use a priority queue to always get the event that should fire next.
skypjack points out in the comments that this is a problematic approach if you need to implement pausing the game. That can be solved by not measuring wall clock, but instead use a separate simulation time that drifts from the wall clock when the game is paused. They also propose a simpler solution:
store a timeToEvent (to be elapsed) and decrement it, so that you detach the game time from the real one. Once it's <= 0, it's its time.
That approach is simpler, but has more overhead for checking the expiration of deadlines.
If you've ever used XNA game studio 4 you are familiar with the update method. By default the code within is processed at 60 times per second. I have been struggling to recreate such an effect in c++.
I would like to create a method where it will only process the code x amount of times per second. Every way I've tried it processes all at once, as loops do. I've tried for loops, while, goto, and everything processes all at once.
If anyone could please tell me how and if I can achieve such a thing in c++ it would be much appreciated.
With your current level of knowledge this is as specific as I can get:
You can't do what you want with loops, fors, ifs and gotos, because we are no longer in the MS-DOS era.
You also can't have code running at precisely 60 frames per second.
On Windows a system application runs within something called an "event loop".
Typically, from within the event loop, most GUI frameworks call the "onIdle" event, which happens when an application is doing nothing.
You call update from within the onIdle event.
Your onIdle() function will look like this:
void onIdle(){
currentFrameTime = getCurrentFrameTime();
if ((currentFrameTime - lastFrameTime) < minUpdateDelay){
sleepForSmallAmountOfTime();//using Sleep or anything.
//Delay should be much smaller than minUPdateDelay.
//Doing this will reduce CPU load.
return;
}
update(currentFrameTime - lastFrameTime);
lastFrameTime = currentFrameTime;
}
You will need to write your own update function, your update function should take amount of time passed since last frame, and you need to write a getFrameTime() function using either GetTickCount, QueryPerformanceCounter, or some similar function.
Alternatively you could use system timers, but that is a bad idea compared to onIdle() event - if your app runs too slowly.
In short, there's a long road ahead of you.
You need to learn some (preferably cross-platform) GUI framework, learn how to create a window, the concept of an event loop (can't do anything without it today), and then write your own "update()" and get a basic idea of multithreading programming and system events.
Good luck.
As you are familiar with XNA then i assume you also are familiar with "input" and "draw". What you could do is assign independant threads to these 3 functions and have a timer to see if its time to run a thread.
Eg the input would probably trigger draw, and both draw and input would trigger the update method.
-Another way to handle this is my messages events. If youre using Windows then look into Windows messages loop. This will make your input, update and draw event easier by executing on events triggered by the OS.
At the moment I am writing a turn based game for the iOS platform. The client is written in Objective-C with CocoaTouch, and the server is written in C++ for the Ubuntu Server OS. The server is connected to a MySQL database, in which it stores user & game data.
Right now I wish to implement a time-per-turn restriction, and this has to be done on the server side. When a user takes a turn, the next user will have a maximum of 24 hours to answer, otherwise I want the game to skip this user's turn and move on to the next player. I have some ideas about how to do this, but I am not sure if they are any good. What I've been thinking of is storing the date&time of the last turn taken as an entity related to the Game table on my SQL database. Then I'm thinking of launching a thread on the server which runs until termination, and looks up current time minus every game's last turn, say every minute or so. If it's been more than 24hrs since the last turn was taken, this thread allows the next player in the queue to take their turn, and skips the lazy player.
Does it sound over-complicated? Is there another, more simple way to do this? I know it's been done in many games before, I just don't know how. Thanks in advance!
I don't think you need any threads or background processes at all in this case.
What I see here is a simple algorithm:
When a user logs in to the game/match - check up the last turn ending time in the database,
If the elapsed time from the last turn ending time is greater than 24h, get the current time, substract the time from the database (obviously you need to convert both times into hours) and divide it by 24,
If the division yelds an odd number, it's the turn of the other player (player A)
If the division yelds an even number, it's the turn of the player B.
Set the database time to databaseTime+division*24
This algorithm can skip multiple turns. When player A finishes his move, and 48h passed, it's players B turn.
You probably just want a background process that has a schedule of "next actions" to take, a sort of priority queue you can work through as the events should be triggered.
A single process can handle a lot of independent games if you design the server properly. The architecture would pick up an event, load any associated data, dispatch accordingly, and then go back to waiting for new events.
C++ does have frameworks for this, but you could prototype it in NodeJS or Python's Twisted really quickly.
Please look at the reactor pattern (boost.asio, ACE). These frameworks are asynchronous, use an event-driven model and require no threads. Below is pseudo code on how you can solve it:
reactor.addTCPListener(acceptSock(), Handler::AcceptSock) // calls AcceptSock when accepting a new TCP connection
rector.addTCPListener(clientSock, Handler::ClientData) // calls ClientData when user is sending the server game stats (its move, status etc)
.
.
.
later on somewhere
.
.
.
for(set<Game>::Iterator it = games.begin(); it != games.end(); ++it) {
(it*)->checkTurn() // this call can be responsible for checking the timestamps from the ClientData function
}
Summary:
With the reactor pattern you will be able to have a non-blocking server that can do cleanup tasks when it is not handling IO. That cleanup can be comparing timestamps to switch/pass turns.
So I'm stuck with a little c++ program. I use "codeblocks" in a w7 environment.
I made a function which shows a ASCII map and a marker. A second function updates the markers position on that map.
I would like to know how I could make my main structure so that the marker gets updated and the map showed, and this repeated at a certain time rate. Which functions can I use to make this happen. What strategy should I follow?
every x times/second DO { showmap(); updatePosition();}
I am a c++ beginner and I hope you can help!
A loop with usleep
unsigned XtimesPerSecond = 5; // for example
unsigned long long microseconds = 1000000 / XtimesPerSecond;
do
{
showmap();
updatePosition();
usleep(microseconds);
} while(true);
Depending on what else your program needs to be doing, you may need to employ event driven programming. If updating that marker is the only thing it will be doing, a simple while loop with a sleep will suffice, as demonstrated in other answers.
In order to do event driven programming you generally need an event loop - which is a function that you call in main, which waits for events and dispatches them. Most event loops will provide timer events - where, basically, you ask the event loop to call function X after a given time interval elapses.
You most likely don't want to write your own event loop. There are many choices for an event loop, depending on many things like programming language and required portability.
Some examples of event loops:
the Qt event loop,
the GLib event loop,
the Windows event loop, and many more...
Seems that you want to implement an infinite loop like games engine does.
Try to do this:
while (true)
{
showmap();
updatePosition();
sleep(1);
}