0
\$\begingroup\$

There is a very good game loop in the link which is tailored for windows forms. I need it in c++/cli so I converted the code as below. Here is my main loop.

using namespace System;
using namespace System::Windows::Forms;

HWND g_theAppHandle = nullptr;

bool IsApplicationIdle()
{
  MSG msg;
  return PeekMessage(&msg, g_theAppHandle, 0, 0, 0) == 0;
}

void OnIdle(System::Object ^sender, System::EventArgs ^e)
{
  while (IsApplicationIdle())
  {
    if (PunkEd::ABTCLI::g_initSuccess)
    {
      PunkEd::ABTCLI::Frame(0.0f);
    }
  }
}

[STAThread]
int CALLBACK WinMain(
  _In_ HINSTANCE hInstance,
  _In_ HINSTANCE hPrevInstance,
  _In_ LPSTR     lpCmdLine,
  _In_ int       nCmdShow
  )
{
  _CrtMemState memstate;
  _CrtMemCheckpoint(&memstate);

  PunkEd::PunkEdMain^ theApp = gcnew PunkEd::PunkEdMain;
  g_theAppHandle = (HWND)theApp->Handle.ToPointer();

  Application::Idle += gcnew System::EventHandler(&OnIdle);
  Application::Run(theApp);

  _CrtMemDumpAllObjectsSince(&memstate);
  return 0;
}

This loop triggers PunkEd::ABTCLI::Frame(0.0f); every time the application is idle. And Frame(float deltaTime); function triggers everyting related to game. Like render and physics. However my rendering window is a panel. And I override its mouse move callback as below.

private: System::Void panel1_MouseMove(System::Object^  sender, System::Windows::Forms::MouseEventArgs^  e) {
  Debug::WriteLine(e->Location);

  glm::vec3 cp = glm::vec3(e->Location.X, e->Location.Y, 0);
  glm::mat4 view = g_camera->GetViewMatrix();
  glm::mat4 project = g_camera->m_projection;
  glm::unProject(cp, view, project, glm::vec4(0.0f, 0.0f, (float)panel1->Width, (float)panel1->Height));

  cp.x -= panel1->Width / 2.0f;
  cp.y -= panel1->Height / 2.0f;

  g_cursor->m_node->m_translation = cp.xzy;
}

This function updates my curser's position in the game. However my render function is get called after I stop moving the mouse. How can I overcome this stuation such that my curser position gets update and renders immediatly after I moved mouse.

\$\endgroup\$
  • \$\begingroup\$ If you're doing this in C++/CLI it seems like you could very possibly just use the more natural Win32 version of the loop. Also, I don't understand your question entirely; you mean that with your mouse-move hook in your panel, the render function only gets called after you're done moving the mouse, not during? And you want it to be called while you move the mouse as well? \$\endgroup\$ – Josh Sep 6 '16 at 20:14
  • \$\begingroup\$ I couldn't think of using win32 version. I'll try it immediately. For the second part. Yes the stuation is as you said so. \$\endgroup\$ – Cihan Sep 6 '16 at 20:17
1
\$\begingroup\$

For the technique presented in the answer you linked to work well, you need to keep the event queue as empty as possible, because the emptying of the queue is what drives your update and render callbacks.

The scenario you are seeing likely occurs because mouse movements are Windows events (WM_MOUSEMOVE), and by hooking them in the panel and doing a bunch of work during one, you keep the event queue full longer than usual (this is partly because WM_MOUSEMOVE is a bit special, and if the mouse is moving you'll basically get one event every time GetMessage is called on your behalf).

While the event queue is "full" of these events, you won't receive OnIdle callbacks and your game won't "remain idle" for the purposes of OnApplicationIdle. Since you only render when the game is idle, you thus defer rendering noticeably while moving the mouse.

When you don't do anything for mouse-move events, they process out quick enough that you don't notice (that Debug::WriteLine is going to be particularly slow).

One possible solution then is to avoid hooking mouse move events or doing expensive stuff in them, and instead directly querying the state of the mouse every update tick (which should also happen inside your "is idle" loop).

\$\endgroup\$
  • \$\begingroup\$ Thank you ! I deleted Debug::WriteLine and its all working smoothly. \$\endgroup\$ – Cihan Sep 6 '16 at 20:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.