Ways to Stutter input for a Graphical program?

Started by
5 comments, last by kinglink 19 years, 1 month ago
I am trying to start to make a gui for my system. now first thing to meantion is I'm going with DirectX, and that includes direct Input as my API of choice for input. I have tried to take input in according to Frame rate, which worked great on my system and made it look good, but when I sent it to two friends computers I was told it was wonky. I am willing to continue to use that for now but I wanted to see if there was a "simpler" way. So I tried to use "elapse time" and it looked ok (though I was stuttering only for .001 of a second) until I realized. that if I change to a different window and then go back to the "game" window (the GUI) all of a suddent .001 becomes very very fast. The only thing I do when it loses focus or gains focus is set an "alive" state that tells the render to actually render. There's no apparent reason for this. I can post my timing functions but it's not really that interesting, I have a float for Elapse time, and "ticks" of the QPC calls. but other then that, The only other current option I have is "Frames" and none of them seem 'standard" (especially when you consider the speed up of the GUI. Can anyone suggest a good way to do this? P.S. Stutter to me means where if you hold down it doesn't go to all three menu choices over and over, and it becomes almost luck on which one you get, I could do "just move down only one on a key press" but I'd like to make the GUI fluid.
Advertisement
What you're doing basically is:
if(TimeToRender){  GetInput();  UpdateObjects();  Render();}


That makes your input lag on your friends machines. Do this:
GetInput();UpdateObjects();if(TimeToRender){  Render();}


Now if I'm understanding your question, your input this way is too fast causing your menus to scroll through too many options with one keypress. Try another timer:
GetInput(){  /* Keyboard input code */  // Only operate if it's time to move down  if(UITimer >= UI_INPUT_RATE)  {    /* Input processing */  }}


As long as your UI_INPUT_RATE isn't as long as your rendering timer you shouldn't have lag problems but it should sufficiently "stutter" like you want.
- A momentary maniac with casual delusions.
That's what I've tried..

I guess I'll post some code.


Here is my "if I read" "check if I can read" and my timer function. it's currently in "time" mode.
#define INPUTPERFRAMERATE		.01void Display::didread(){	m_lastreadFrame=m_fElapsedTime;}bool Display::canread(){	if(stutter)		if(m_lastreadFrame+INPUTPERFRAMERATE>m_fElapsedTime&&m_lastreadFrame<m_fElapsedTime)			//makes it so it's not to fast, but also overflows don't hurt it.			return false;	return true;}void Display::ProcessTimer(){	m_dwTotalFrames ++;		if(m_bUseQPC)	{		QueryPerformanceCounter(&m_llTime);		m_fTimeForFrame = (float)(m_llTime.QuadPart - m_llLastTime) / (float)m_llTicksPerSec;		m_llLastTime = m_llTime.QuadPart;        m_iAbsoluteTime = (int)(m_llTime.QuadPart - m_llStartTime)/(int)m_llTicksPerSec;	}	else	{		m_ulTime = timeGetTime();		m_fElapsedTime = (float)(m_ulTime - m_ulStartTime)/1000.0f;		m_fTimeForFrame = (float)(m_llTime.QuadPart - m_llLastTime);		m_ulLastTime = m_ulTime;        m_iAbsoluteTime = (m_ulTime - m_ulStartTime)/1000;	}	m_fElapsedTime += m_fTimeForFrame;	    static float seconds = 0;    static DWORD dwNumFrames = 0;    dwNumFrames++;    seconds += m_fTimeForFrame;    if( seconds >= 1.0f )    {        m_fFPS = float( dwNumFrames / seconds );        seconds = 0;         dwNumFrames = 0;        m_fAvgFPS = (float)m_dwTotalFrames/(float)m_fElapsedTime;    }	}


Here is my game loop. this is in a different class then either input and display stuff becasue It's the thread class.

void Graphics::MyGameLoop(){    //How the handling works.	/*	Test Input, 	Render	check messages every x frames.  Currently 5	*/	frame=0;    MSG msg;    ZeroMemory(&msg, sizeof(MSG));    while(msg.message != WM_QUIT && m_bAlive != FALSE) //While alive and not quit	{        if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) 			//Check windows message.  This is the CURRENT input handler.  We will be moving to DirectInput soon		{			TranslateMessage(&msg);            DispatchMessage(&msg); //Sends it to Winproc		} 		else 		{            if(frame<FRAMESFORMESSAGE)  //if not at x messages			{				if(m_bActive)//if window is active	            {					entry->read(m_bPaused);					if(!m_bPaused)//and if app is not paused					{						if(!disp->Render())//Render							break;						frame++;//you just made another frame					}					else						disp->PauseTimer();				}				else					disp->PauseTimer();			}			else //if it's x frames			{					frame=0;//start counting again.				checkmessage();//Check messages			}		}    }	SAFE_DELETE(entry);	SAFE_DELETE(disp);	this->e->end();  //If the graphics is done, game is done.}


And Here's the read function. I use pause so I can pause the game and exit when I'm paused.
void Input::read(bool pause){	bool temp=disp->canread();	readkeyboard(pause||!temp);	if(!pause&&temp )		readmouse();	readjoystick(pause);}


And here is definitions of all my timing attributes
	float m_lastreadFrame;//for stutter	bool stutter;	//Frame System counters.	bool m_bUseQPC;    DWORD m_dwTotalFrames;    float m_fTimeForFrame;	//QPC version	LARGE_INTEGER	m_llTime;	LONGLONG		m_llLastTime;  //This is last ticks messure.	LONGLONG		m_llStartTime;     	LONGLONG		m_llTicksPerSec;    	//timegetTime version	ULONG m_ulTime;	ULONG m_ulLastTime;	ULONG m_ulStartTime;    float m_fElapsedTime;    int m_iAbsoluteTime;		// this is ABS(time passed)  Integer style.    float m_fFPS;    float m_fAvgFPS;	



So from this, shouldn't this be done right? My render speed is "As fast as possible" currently, it's on a multi thread system where this thread is the ONLY one that has access to the graphics and currently no other thread does anything more then while(1); likely the rendering speed will remain at that speed until the final game is ready. (though I'm using the presentation rate of DEFAULT_ONE, not DEFAULT_IMMEDIATE.)

The biggest problem for me as of this second is why does this code (though in Debug configuration) change speeds when I click away from my program, and then back to it. The speed change makes me wonder much more then "proper input speed".
Although perhaps not a solution in your particular case, there is an easier solution.

Have an array for "last frame" and "this frame" (storing input). If the key was pressed last frame, and is still being pressed this frame, ignore it. This way, every press moves through the menu option. This may or may not be feasible depending on the number of options your menu has.
The problem is I want to have it so it scrolls down "slower" but i want to have them be able to hold the button down so it scrolls. I just have a problem now with the change in speed which is making it hard to choose the right speed. When I activate the window again it doesn't do anything new but now all of a sudden something changes and now it's reading ultra fast.
Quote:Original post by GroZZleR
Although perhaps not a solution in your particular case, there is an easier solution.

Have an array for "last frame" and "this frame" (storing input). If the key was pressed last frame, and is still being pressed this frame, ignore it. This way, every press moves through the menu option. This may or may not be feasible depending on the number of options your menu has.


To expand on this to deal with the requirements: For each key, store a value 'key has been down for this many frames'. On each frame, you update these values (either increment or reset to zero). Then, if the key has been down for a 'magic number' of frames (say for example, a multiple of 10), then send an appropriate 'handle this key' event to the UI logic.
I think the question still remains why does the program speed up though, I full understand the various ways for a program to work, but the bigger problem is the code "stalls" a bit, while I could write an entire FPS counter (which is on the to do list but I need to implement a Font system and have been looking at the input first) I wanted to see if anyone knows why an alt-tab might speed up render rates.

Especially because knowing the FPS actually jumps won't actually help me tell what causes it to jump.

This topic is closed to new replies.

Advertisement