|
Are these two (handling keyboard/mouse input and handling the graphics display) typically done in separate threads or in a single thread? I've been considering doing them in separate threads so the input is always responsive, however, that may not be the best idea, given how often I will have to synchronize between the two.
Advantages of using only a single thread:
-input polling is combined with the graphics loop, so there is less overhead as the loop takes longer to execute (advantage for single core processors but a disadvantage for multi-core processors)
-no synchronization required
Disadvantages of using only a single thread:
-input may be required for a variety of components, such as handling combat and other character states and reliance on a combined (input + graphics) cycle can slow down the processing of these other components
-will not scale as well with multiple cores
Any suggestions? This is my first time venturing into game engine development (from scratch, because it's more fun and you learn more that way).
|
|
|
|
|
This is purely off the top of my head, but it seems you can rely on window messaging for most things. Windows generates messages for mouse movement etc, which you set up handlers for. You can set up a timer to cause windows to send timer messages at certain intervals as well, which is useful for updating the game state. Each character could have a thread, but that's not strictly necessary. They could just be in a list and every 1/100 of a second you update the next one (when you receive a WM_TIMER msg from windows). Threads are mandatory for background computation that would otherwise freeze the system.
|
|
|
|
|
I was thinking of using a key array (of bools) and catching WM_KEYDOWN / WM_KEYUP to change the states of the keys from the input thread, then sending the states to the graphics thread. The input thread would have the WndProc function, whereas the graphics thread would simply check the local key array (in a while loop) to determine what happens.
Basically, it would look sort of like this:
WndProc (which runs in the input thread) catches WM_KEYDOWN where the key is VK_ESCAPE. The input thread sets key[VK_ESCAPE] = true. The graphics thread has a while loop that checks for VK_ESCAPE, and if true, it will return the thread (quit), if it sees another command such as the movement keys, then it will draw the next frame.
|
|
|
|
|
Having a while loop in the graphics thread seems pointless. You can imagine walking out to your mailbox opening it, closing it, walking back inside, and doing the same thing over and over again continuously until the mailman arrives. You accomplish nothing by putting this in a seperate thread. When you get the WM_KEYDOWN message just call the appropriate code to update the games state - it doesn't have to be in a seperate thread. If you can't update the games state fast enough to avoid slowing down user input, it means you can't update the game state fast enough to begin with (if that's clear). If its a single processor, seperate threads don't magically give you more speed. If its a seperate grapics processor, that's another matter I guess.
A seperate thread would be for a situation where a computation literally took several seconds to complete or something. Presumably you can animate your game fast enough to keep up with user input.
---------------------
Let me be clearer:
IF you hit some key, presmuably all you will do is change the value of some variable in a character object for example, which will be processed the next time a WM_TIMER message is received. Its better for the graphics to do nothing until it receives a timer message. Really, the timer is to slow things down. You'll set it at a certain level and everyone will be running around too fast.
-- modified at 14:59 Monday 18th June, 2007
|
|
|
|
|
If you can't update the games state fast enough to avoid slowing down user input,
it means you can't update the game state fast enough to begin with
Hmm... you do have a point.
Thanks.
|
|
|
|
|
Let me just add something:
Depending on your situation, its possible you could have a seperate thread for graphics. But you definitely wouldn't just sit there in a while loop. You would have shared access (via critical sections, mutexes or whatever) to data, which the input process would update and the graphics thread would check at set intervals. If the graphics thread has so much to do that is must run continuously without interruption, then it should have its own thread, it will check for updated data periodically, but shouldn't just be in a loop doing *nothing* but checking for data updates.
|
|
|
|
|
Then my question is, how do you explain the current crop of games today? They don't update the frame buffer synchronously. They won't be trying to send you 60 frames per second all the time. On heavier scenes, the frames may drop down to the 20s, and on lighter scenes, they may jump up to 150. What else, besides a while loop displaying graphics would do this?
|
|
|
|
|
Cyrilix wrote: Then my question is, how do you explain the current crop of games today? They don't update the frame buffer synchronously. They won't be trying to send you 60 frames per second all the time. On heavier scenes, the frames may drop down to the 20s, and on lighter scenes, they may jump up to 150. What else, besides a while loop displaying graphics would do this?
To make sure I understood correctly, I thought you were saying your graphics thread would literally have nothing to do until it recieved some sort of input, so it would do nothing but check an inbox, continuously, billions of times a second, until it recieved a message. This is pointless processing, even if you put in a seperate thread. If you're running a seperate *process* as opposed to thread, sometimes that sort of wait loop is necessary, but then you call Sleep() with each iteration to avoid wasting the CPU. A windows application behind the scenes has a message loop, but when it calls GetMessage, windows doesn't return until there is actually a message, so the calling process isn't wasting time continuosly checking.
AS far as modern games, I didn't think you were developing for PlayStation X or some specific game processor, but they can ascertain the game state (e.g. how many frames to display at a given time), without the sort of loop you're talking about.
Just to reiterate, I think the way to go for game state updates is a windows timer (don't know what the precise synax in MFC is).
|
|
|
|
|
Oh no, what I meant was... the graphics thread would be in a while loop constantly filling the frame buffer and putting it to the screen. On every iteration of filling this frame buffer, it would have to draw a bunch of shapes, and a set of variables that track your movement (say, x, y, z, and rotate), would determine how to redraw the scene. It would have to check these variables on every iteration. Basically, I'd have to know the translations and rotations that affect my camera every time I redraw.
The code would be very similar to what is on Nehe's OpenGL tutorial: Link to source
Here is the code that I'm pointing to, specifically:
while(!done)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if (msg.message==WM_QUIT)
{
done=TRUE;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else
{
if (active)
{
if (keys[VK_ESCAPE])
{
done=TRUE;
}
else
{
DrawGLScene();
SwapBuffers(hDC);
}
}
if (keys[VK_F1])
{
keys[VK_F1]=FALSE;
KillGLWindow();
fullscreen=!fullscreen;
if (!CreateGLWindow("NeHe's OpenGL Framework",640,480,16,fullscreen))
{
return 0;
}
}
}
}
MODIFIED:
I guess my question is -- you would consider this bad design?
-- modified at 16:07 Monday 18th June, 2007
|
|
|
|
|
The code sample you provided is in a loop with a PeekMessage. If any messages for the application are pending it processes those before going back to frame updates.
Here was your proposed design:
Cyrilix wrote: I was thinking of using a key array (of bools) and catching WM_KEYDOWN / WM_KEYUP to change the states of the keys from the input thread, then sending the states to the graphics thread. The input thread would have the WndProc function, whereas the graphics thread would simply check the local key array (in a while loop) to determine what happens.
Basically, it would look sort of like this:
WndProc (which runs in the input thread) catches WM_KEYDOWN where the key is VK_ESCAPE. The input thread sets key[VK_ESCAPE] = true. The graphics thread has a while loop that checks for VK_ESCAPE, and if true, it will return the thread (quit), if it sees another command such as the movement keys, then it will draw the next frame.
You weren't relinquishing control in anyway to process application messages. However, I'm not entirely clear on your design, because your last statement seems to say that movement in the game is only triggered by user input, whereas I thought there would be game animation regardless of user input.
But as to whether the code sample you provided is bad design, I will say I've never had much use for PeekMessage. In the code sample, you could just take the PeekMessage portion out, and put the remaining code in its own thread, where the OS itself would interrupt it as necessary. The GetMessage loop in the main thread would continue to handle application messages. Maybe you can tell me if I'm missing something
l
|
|
|
|
|
There will have to be game animation regardless of user input. When I say "if it sees another command such as the movement keys, then it will draw the next frame", I mean that if it sees that you're holding down the movement key to move in direction x, it will increment an x counter (based on how long you've been holding down the key). The bit of code above that I posted will check this counter every time a frame is drawn (DrawGLScene()) and translate the camera x units from the (0, 0, 0) position (or rather, translate the objects -x, since it's the objects that are moving, and not you). The main point is, it uses a while loop to constantly spit out frames to the screen. I thought you were advocating against using the while loop and producing frames only when you receive a signal, but it seems like you're not against doing so.
We may have misunderstood each other.
|
|
|
|
|
I have a feeling I may not be completely clear to you.
In the code sample, he has something he feels he has to do continuously. In that instance just create a seperate thread, and do it continously, and let the OS interrupt - No need to call PeekMessage. However, this code doesn't create a seperate thread but is in the main thread, that's why PeekMessage is being used. (You OTOH were saying you wanted to create a seperate thread for graphics updates.) However, in your case, you seemed to say you had nothing to do in the Graphics thread until some user input was received, so you would have a loop to just check for it continuously. That's a complete waste.
|
|
|
|
|
The graphics thread always has something to do. It has to draw the frames, whether or not user input is entered. If no user input or no AI interaction (that results in a change of what you can see on the screen) is there, then it should just draw the same frame, and then keep on drawing frames forever after that.
First, I'd like to ask whether or not you're disputing my statement above, because everything I mentioned in the last few posts is in question to whether or not you dispute drawing frames continuously.
|
|
|
|
|
Cyrilix wrote: The graphics thread always has something to do. It has to draw the frames, whether or not user input is entered. If no user input or no AI interaction (that results in a change of what you can see on the screen) is there, then it should just draw the same frame, and then keep on drawing frames forever after that.
First, I'd like to ask whether or not you're disputing my statement above, because everything I mentioned in the last few posts is in question to whether or not you dispute drawing frames continuously.
I'm not sure if I dispute it. How do you control at what rate the frames are being updated? If on a given frame, nothing has changed, do you go ahead and redraw it anway? It seems you would only update at set time intervals (1/10 of a second or 1/100, whatever), in which case you could put the update code in the main thread and have it triggered by WM_TIMER messages. Or, if running continuously in a seperate thread, Sleeping for a set time interval on each iteration. Maybe the AI engine could be running continuously in a seperate thread, and when it was time for an update, you could query it, and it could give the best data it had at the moment.
------
I guess I need to read more carefully - you did say a frame is updated whether its changed or not. I would say it should be on a timer.
You did say you were a beginner. I have written a several thousand line long windows app that is fairly entertaining game that is a little more sophisticated than pac-man.
|
|
|
|
|
I see what you mean, although I'm unsure of the implementation, but I will look into what you've suggested a bit more before making my decision.
Thanks.
|
|
|
|
|
Most games today are single threaded, believe it or not. They work everything on a frame by frame basis so for each frame they render all the graphics, do some user input and sometimes use up the rest of the time until they have to do the next frame by doing some AI or some house keeping operations.
I have tried implementating a properly multithreaded game engine with rendering on one thread, game mechanics on another and yet another for sound. It's HARD to get the kind of performance pro games expect doing it that way. When quad core is standard it will come and my AG engine will rock
Nothing is exactly what it seems but everything with seems can be unpicked.
|
|
|
|
|
Hi Matthew,
After all this long discussion, I'm still trying to figure out, regardless of whether I use multiple threads or a single thread, whether or not using a while loop to continuously draw my scene as in the OpenGL example, is the right thing to do.
My fundamental design for single thread is very simple: Do the DrawScene loop and take the input before drawing the frame each time. If there is no input or no AI interaction, then it will just draw the same scene as it did last time.
My fundamental design for multiple threads is just as simple: Do the input loop in the input thread, do the DrawScene loop in the graphics thread, and have the DrawScene take the input before drawing the frame every time. If there is no input or no AI interaction, then it will just draw the same scene as it did last time.
|
|
|
|
|
|
Hi all...
Is it possible to mix more than one bitmap in VMR9 using MixerBitmap in one time? I've tried to create two IVMRMixerBitmap instances, two SetInitialAlphaBitmap functions (as in BmpMix9 example), but only the last one is displayed.
Thank you...
-Houari
|
|
|
|
|
IVMRMixerBitmap::SetAlphaBitmap() sets a new bitmap, replacing the previous one.
You can, however, combine your bitmaps into one bitmap
Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
|
|
|
|
|
ah yes... that was in my mind too... ^^
but I need the position of my bitmaps in the video to be independently changed anytime I want.
is there any way to do this? I was also failed by using CDC in the same picture control with the vmr video (the CDC drawing is overlapped by the video...) -_-
thanks
-Houari
|
|
|
|
|
houari_id wrote: but I need the position of my bitmaps in the video to be independently changed anytime I want.
You'd need to redraw the offscreen bitmap each time the bitmaps change position.
If you're experienced with DirectDraw (I personally am not) you can also use the
VMR Renderless Playback Mode (Custom Allocator-Presenters)[^].
The alternative I chose was to make my own renderer filter so I had complete control over all the
drawing. That certanly isn't a necessary solution however.
houari_id wrote: I was also failed by using CDC in the same picture control with the vmr video (the CDC drawing is overlapped by the video...)
Yeah, that won't work well.. That's why mixing is necessary
Mark
"Posting a VB.NET question in the C++ forum will end in tears." Chris Maunder
|
|
|
|
|
Hi,
How could i code this fast in C++ by using classes:
I want to output the work days between two dates (start and end date input by user).
I thought through it but dont know how to code it.
My thoughts:
1) calculate (count up) the absolute days between the two dates (with using time.h and week modulo to find out the free Sundays)
2) make a class with holidays
3) calculate the holidays with the Gauss easter algorithm (found it on wikipedia and some other site, see bottom of post)
4) substract the holidays from the absolute days
5) "cout" the absolute days and the count up of holidays and the final work days
Carl Friedrich Gauß (1777 - 1854):
a = YYYY mod 19
b = YYYY mod 4
c = YYYY mod 7
d = (19a + M) mod 30
e = (2b + 4c + 6d + N) mod 7
YYYY: the year with 4 digits
M and N:
for 1583 - 1599 -> M=22, N=2
1600 - 1699 -> 22, 2
1700 - 1799 -> 23, 3
1800 - 1899 -> 23, 4
1900 - 1999 -> 24, 5
2000 - 2099 -> 24, 5
2100 - 2199 -> 24, 6
2200 - 2299 -> 25, 0
2300 - 2399 -> 26, 1
2400 - 2499 -> 25, 1
taking the above easter sunday should be: (22 + d + e).March or (d + e - 9).April
and there are 2 annomalies:
1) if the result of the above falls on the 26th of April -> easter sunday will be held on the 19th of April instead
2) If a > 10 and d = 28 and the result the 25. April, -> easter sunday be corrected to the 18. April.
but how to code this?
HELP
thx a lot
berni2k
|
|
|
|
|
berni2k wrote: but how to code this?
Indeed. That sound like a very interesting class assignment. Good luck.
|
|
|
|
|
thx, I am on the way and will post the code if i can manage to do it
|
|
|
|
|