I'm doing dialog based, MFC game.
During the game there is a battle phase , and I want to display each text on the screen with a small delay,
I tried using sleep and also tried CTime, but both display only the last text at each battle...
here is an example of the code...
void CDNDPprojectDlg::OnBnClickedAction()
{
CString Damaged;
damage=me->Attack(enemy,WeID);
SDialog.Format(_T("You done %d damage, using %s,\r\n %s has %d HP left"), damage,Damaged,monName,enemy->getHP());
Output.SetWindowTextW(SDialog);
if(enemy->getHP() <1)
{
Won();
return;
}
NextAttack();
if(me->getHP() <1)
{
Died();
return;
}
}
at the beginning of all 3 functions there is Sleep(700). it does a delay but display only the last
Output.SetWindowTextW(SDialog);
that I put...I guess its something of threading, please help me.
thanks
There is a hard way, an easy way and a shameful way.
The hard way is to do multi threading - check AfxBeginThread, you pass a pointer to your CDNDPprojectDlg, and do the job there after each of your sleep. It's hard because at one point you will need to synchronise your main thread and your new thread when they access common resource... a lot to learn there but before that a lot of pain
The other way is to either use a timer SetTimer and override OnTimer
The third way is to use something like the DoEvents in Visual Basic (ha the shame!). Just call it after you have done something and your screen will refresh. I will deny any knowledge of having passed that code to you.
BOOL DoEvents()
{
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
return FALSE;
}
if (!AfxGetApp()->PreTranslateMessage(&msg))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
return TRUE;
}
Good luck!
Related
I'm currently working on writing a reparenting window manager using C++ and the XCB library. I unmanage windows when I recieve an UnmapNotify event; in this case the code is very simple:
if (unmap_ignore > 0) {
unmap_ignore--;
return;
}
client *cl = nullptr;
size_t idx = 0;
for (client &c : clients) {
if (c.window == ev->window) {
cl = &c;
break;
}
idx++;
}
if (!cl)
return;
xcb_unmap_window(conn, cl->frame);
clients.erase(clients.begin() + idx);
However, this does not work for some clients that don't bother unmapping the window (usually happens when you force kill the process). Then instead a DestroyNotify is sent. However the ev->window field there (typeof ev = xcb_destroy_notify_event_t) is some value that isn't what I want... here are some example logs (also note each line is a new DestroyNotify event, I get it twice for some reason and each time the #window field is different but not correct):
Found a client window: 4194307 but this was destroyed: 4194305
Found a client window: 4194307 but this was destroyed: 4194313
I remember before I tried to write a window manager in Xlib and had this exact same issue. I must be missing something obvious though, but if I look at the code of other reparenting window managers like Awesome or Herbsluftwm they just use the window field and have no problems. What am I doing wrong?
(my full code is here: http://ix.io/3yDj)
One thing I suspect is that it is just giving me two children windows of the destroyed parent instead of sending the actual parent. no idea why, but it is the most logical thing I can come up with. I just want to be able to handle this so I can unmap the frame for things that don't send UnmapNotify events.
I also first thought that it may report DestroyNotify on the parent window instead of the client reparented one, so I tried checking the frame but to no avail:
Found a client window: 2097152 but this was destroyed: 4194305
Found a client window: 2097152 but this was destroyed: 4194313
I've been truly stumped on this so any help is appreciated, thanks!
Awesome for example does the exact same thing as I tried with ev->window:
static void
event_handle_destroynotify(xcb_destroy_notify_event_t *ev)
{
client_t *c;
if((c = client_getbywin(ev->window)))
client_unmanage(c, CLIENT_UNMANAGE_DESTROYED);
else
for(int i = 0; i < globalconf.embedded.len; i++)
if(globalconf.embedded.tab[i].win == ev->window)
{
xembed_window_array_take(&globalconf.embedded, i);
luaA_systray_invalidate();
}
}
I'm new to SFML, been trying to have a multi-threading game system (all of the game logic on the main thread, and the rendering in a dedicated thread using sf::Thread; mainly for practicing with threads) as explained in this page ("Drawing with threads" section):
Unfortunately my program has a long processing time during it's update() and makes the rendering process completely out of control, showing some frames painted and some others completely empty. If it isn't obvious my rendering thread is trying to paint something that isn't even calculated, leaving this epileptic effect.
What I'm looking for is to allow the thread to render only when the main logic has been calculated. Here's what I got so far:
void renderThread()
{
while (window->isOpen())
{
//some other gl stuff
//window clear
//window draw
//window display
}
}
void update()
{
while (window->isOpen() && isRunning)
{
while (window->pollEvent(event))
{
if (event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
{
isRunning = false;
}
else if (m_event.type == sf::Event::Resized)
{
glViewport(0, 0, m_event.size.width, m_event.size.height);
}
}
// really resource intensive process here
time = m_clock.getElapsedTime();
clock.restart().asSeconds();
}
}
Thanks in advance.
I guess the errors happen because you manipulate elements that are getting rendered at the same time in parallel. You need to look into mutexes.
Mutexes lock the element you want to manipulate (or draw in the the other thread) for as long as the manipulation takes and frees it afterwards.
While the element is locked it can not be accessed by another thread.
Example in pseudo-code:
updateThread(){
renderMutex.lock();
globalEntity.manipulate();
renderMutex.unlock();
}
renderThread(){
renderMutex.lock();
window.draw(globalEntity);
renderMutex.unlock();
}
I didn't find sufficient answer for this, any suggestion is welcome..
I have a simple MFC single-document app, upon opening file a lengthy computation takes place in separate thread:
BOOL CrhMonkeyDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
CMainFrame* pMainFrame = (CMainFrame*)AfxGetMainWnd();
// Start working thread to process the file
m_rhFile.StartParseFile(lpszPathName);
//periodically check progress and update
int progress, lines;
while ((progress = m_rhFile.GetProgress()) < 1000) {
lines = m_rhFile.GetNumLines();
CString strProgress;
strProgress.Format(_T("%d lines, %d percent complete"), lines, progress);
pMainFrame->SetStatusBarText(strProgress);
Sleep(1000);
}
UpdateAllViews(NULL);
}
The thread is started like this:
UINT ParseFileThread(LPVOID Param)
{
RhFile* rhFile = (RhFile*)Param;
rhFile->ParseFile();
return TRUE;
}
int RhFile::StartParseFile(LPCTSTR lpszPathName)
{
m_file.open(lpszPathName);
AfxBeginThread(ParseFileThread, this);
return 0;
}
Initially it does work updating the status bar periodically, but after 10-15 seconds the updates stop and "Not Responding" appears in app title.
I have tried to start the thread at lower priority, and also added periodic SwitchToThread() (always returning 0), and Sleep(50) inside ParseFile(), but it doesn't help.
I guess I am doing something wrong, but can't figure out what
Thanks for reading this!
I have developed an OpenGL ES 2.0 win32 application, that works fine in a single thread. But I also understand that UI thread and a rendering thread should be separate.
Currently my game loop looks something like that:
done = 0;
while(!done)
{
msg = GetMessage(..); // getting messages from OS
if(msg == QUIT) // the window has been closed
{
done = 1;
}
DispatchMessage(msg,..); //Calling KeyDown, KeyUp events to handle user input;
DrawCall(...); //Render a frame
Update(..); // Update
}
Please view it as a pseudo code, cause i don't want to bother you with details at this point.
So my next step was to turn done into an std::atomic_int and create a function
RenderThreadMain()
{
while(!done.load())
{
Draw(...);
}
}
and create a std::unique_ptr<std::thread> m_renderThread variable. As you can guess nothing has worked for me so far, so i made my code as stupid and simple as possible in order to make sure i don't break anything with the order i call methods in. So right now my game loop works like this.
done.store(0);
bool created = false;
while(!done)
{
msg = GetMessage(..); // getting messages from OS
if(msg == QUIT) // the window has been closed
{
done.store(1);
}
DispatchMessage(msg,..); //Calling KeyDown, KeyUp events to handle user input;
// to make sure, that my problem is not related to the fact, that i'm rendering too early.
if(!created)
{
m_renderThread = std::make_unique<std::thread>(RenderThreadMain, ...);
created = true;
}
Update(..); // Update
}
But this doesn't work. On every draw call, when i try to somehow access or use my buffers \ textures anything else, i get the GL_INVALID_OPERATION error code.
So my guess would be, that the problem is in me calling glGenBuffers(mk_bufferNumber, m_bufferIds); in the main thread during initialization and then calling glBindBuffer(GL_ARRAY_BUFFER, m_bufferIds[0]); in a render thread during the draw call. (the same applies to every openGL object i have)
But I don't now if i'm right or wrong.
I'm really having trouble closing my console application with FreeGLUT.
I would like to know what the best way is to take every possible closing, because I don't want any memory leaks (I'm pretty afraid of those).
So I already tried the following, which is giving me an exception like this:
First-chance exception at 0x754e6a6f in myProject.exe: 0x40010005: Control-C.
int main(int argc, char **argv)
{
if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, true) )
{
// more code here as well ....
glutCloseFunc(close); // set the window closing function of opengl
glutMainLoop();
close(); // close function if coming here somehow
}
else
{
return 1;
}
return 0;
}
void close()
{
// keyboardManager is a pointer to a class
// which I want to delete, so no memory will leak.
if(keyboardManager) // do I need this check?
delete keyboardManager;
}
bool CtrlHandler(DWORD fdwCtrlType)
{
switch(fdwCtrlType)
{
// Handle the CTRL-C signal.
case CTRL_C_EVENT:
// and the close button
case CTRL_CLOSE_EVENT:
close();
return true;
// Pass other signals to the next handler.
case CTRL_BREAK_EVENT:
return false;
// delete the pointer anyway
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
default:
close();
return false;
}
}
So what goes right is:
Closing the window of glut
Closing the console application with the x
Closing my window of glut with my keyboardmanager if(keyboardManager->isKeyDown[27]) glutExit();
What goes wrong is:
Closing the console application with CTRL+C, it gives the exception from above.
This is in Visual Studio 2008 C++.
UPDATE
I found that the exception is thrown, because I'm in debug. So that won't be a problem. But the question is still open: What is the most elegant way to actually close glut?
atexit() seems to work as well, so maybe I can use this?
I use this function:
void glutLeaveMainLoop ( void );
There is more information on their sourceforge page but I never used that functionality:
The glutLeaveMainLoop function causes freeglut to stop the event loop. If the GLUT_ACTION_ON_WINDOW_CLOSE option has been set to GLUT_ACTION_CONTINUE_EXECUTION, control will return to the function which called glutMainLoop; otherwise the application will exit.
http://freeglut.sourceforge.net/docs/api.php#EventProcessing
It is safe to use delete on a null pointer, no need to check.
Thanks to Maarten's post, this works to me:
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,GLUT_ACTION_CONTINUE_EXECUTION);
whenever you want to leave the mainloop without termiante the application use:
glutLeaveMainLoop();
don't forget to include "freeglut.h"
I use glutDestroyWindow(int handle);
or
According to ID: RigidBody at OpenGL forum
void destroy_window()
{
window_valid = -1;
}
void display_func()
{
if(window_valid == -1)
return;
// draw things
}
Try this method:
glutDestroyWindow(glutGetWindow());