User Input problems

Post your questions, suggestions and experiences regarding game design, integration of external libraries here. For irrEdit, irrXML and irrKlang, see the
ambiera forums
Post Reply
Mirror
Posts: 218
Joined: Sat Dec 01, 2007 4:09 pm

User Input problems

Post by Mirror »

Hello people. I have the following problem. Initially i was using the simple method for keyboard input ( without a bool array ) which just checked if a button was pressed and my program worked well. For smoothing ( the camera and the player's movement ) reasons i used the second form of the event receiver, which uses a bool array and resides inside the main game loop and using a dt for smoothing. Indeed the camera and the movement is smoothed and i'm also able to use keys simultaneously. There is one problem though : some variables which are changed by code inside one key event ( for example "W", affect the same variables inside another key event ( for example "S" ). So in some cases - since i'm using global variables - before some updates take place while the W key is pressed, they change also for the S key and things get screwed up.

One other issue i'm having is this : since my debugging info printed on the screen, i made a void function which is called inside the loop. for example:

Code: Select all

void DisplayDebugInfo() {

		stringw str = L"FPS: ";str += driver->getFPS();
		str += " XRt=";str += (f32)prot.X;
		str += " YRt=";str += (f32)prot.Y;
		str += " ZRt=";str += (f32)prot.Z;
.........
		debugtext1->setText(str.c_str());

}
But this caused me to define debugtext1 variable as global ( i didn't want to make it local for overhead reasons. afaik a local variable is re-defined each time the function is called and thus some overhead, correct me if i'm wrong. So because i'm trying to turn into separate functions code which is big and not easily managed in order to make simple the main() function, i'm getting more and more global variables. Is there any solution to this ?

I know that these are not irrlicht problems but general programming issue so that's why i posted here and not in the begginers' forum.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

Sure there's a bit of extra work to create a local variable each time round the loop (you're still doing that anyway with your stringw there) but i'm sure it's not enough to create any performance issues. That would only happen if you were creating hundreds of large variables probably.

And look at it this way. It's debug data, which means it won't be present in your final version of the app so you don't need to worry about its tiny affect on your performance for now. You can also make sure it never gets compiled into your final version of the app but putting a debug #ifdef around it and any calls to it.

so like this:

Code: Select all


// in main.h or globals.h or whatever is your primary header that gets included everywhere or most places necessary
#define DEBUG // this creates a 'pre-compilation compiler variable'.. i'm sure it's got a proper name but i don't know it off the top of my head. Basically it gets created during compilation but it isn't actually compiled into your code

...

// now for your debug function:

#ifdef DEBUG // this checks to see if DEBUG has been defined (i.e. you want your debug stuff to be compiled
void DisplayDebugInfo() {} // if so then it compiles the function
#endif // closes off the if statement

// if DEBUG isn't defined then the function doesn't get compiled so will create a compiler error if you try and use it, because it doesn't exist so when you wnat to use your debug function in your render loop...

int main() {

  ...

  while (device->run()) {
    
    ...

    #ifdef DEBUG // check if the debug stuff should be compiled
    DisplayDebugInfo(); // if so you can call the function
    #endif

    // render code here
  }
}

Image Image Image
Mirror
Posts: 218
Joined: Sat Dec 01, 2007 4:09 pm

Post by Mirror »

thank you JP that was really helpful and a good practice for game design.

What about the 1st problem, that of changes between different keys happening in the same time on variables taking place simultaneously and thus producing unwanted behaviour ? any ideas here ?
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

Show us the bit of code which deals with updating your bool keys (if any different from the wiki) and the bit where you use your bool keys to move your node around.
Image Image Image
Mirror
Posts: 218
Joined: Sat Dec 01, 2007 4:09 pm

Post by Mirror »

Code: Select all

void HandleUserInput() {
	if (device->isWindowActive()) { 
		if (KeybInput.isKeyPressed(KEY_KEY_W)) { 
			ppos += dis*pmovspeed*dt;

			ppos.normalize();
			ppos*=R;
			axis=dis.crossProduct(ppos);
			dis=ArbitraryRotate(dis, -0.5*pmovspeed*dt, axis);
			playernode->setPosition(ppos);
			cpos = (ppos - dis*10)*2;
			cam->setPosition(cpos);
			cam->setTarget(ppos);
			cam->setUpVector(cpos);
			ReturnPolarCoordinates(); 
			printf("chi=%f phi=%f thi=%f Dis.Z=%f\n",chi, phi, thi, dis.Z);

			cis=bis;
			cis.rotateYZBy(thi, cen);
			cis.rotateXZBy(phi, cen);
			dot=cis.dotProduct(dis)/0.7615634f;
			if (dot>0.9999) dot=1;
			if (dot<-0.9999) dot=-1;
			ang=acos(dot) / con;
			ang*=sign;
			chi=ang;
			
			pnode->setRotation(core::vector3df(0,180+ang,0));
			T1=pnode->getRelativeTransformation();
				prot=T1.getRotationDegrees();
				printf("W:T1: protX=%f, protY=%f, protZ=%f chi=%f\n",prot.X, prot.Y, prot.Z, chi);
			pnode->setRotation(core::vector3df(thi,-phi,0));
			T2=pnode->getRelativeTransformation();
				prot=T2.getRotationDegrees();
				printf("W:T2: protX=%f, protY=%f, protZ=%f chi=%f\n\n",prot.X, prot.Y, prot.Z, chi);
			T3.setbyproduct(T2,T1);
			prot=T3.getRotationDegrees();
			playernode->setRotation(prot);
		}

Code: Select all

		if (KeybInput.isKeyPressed(KEY_KEY_D)) {
			chi += protspeed * dt;
			dis=ArbitraryRotate(dis, protspeed * dt, ppos);
			cpos = (ppos - dis*10)*2;
			cam->setPosition(cpos);
			cam->setTarget(ppos);
			cam->setUpVector(cpos);
			ReturnPolarCoordinates();
			printf("chi=%f phi=%f thi=%f Dis.Z=%f\n",chi, phi, thi, dis.Z);

			if ( (fmod(chi,360) <= 0) && ( (fmod(chi,360)) >= -180) ) sign=-1;
			if ( (fmod(chi,360) <= -180) && ( (fmod(chi,360)) >= -360) ) sign=1;
			if ( (fmod(chi,360) >= 0) && ( (fmod(chi,360)) <= 180) ) sign=1;
			if ( (fmod(chi,360) >= 180) && ( (fmod(chi,360)) <= 360) ) sign=-1;

			pnode->setRotation(core::vector3df(0,180+chi,0));
			T1=pnode->getRelativeTransformation();
				prot=T1.getRotationDegrees();
				printf("D:T1: protX=%f, protY=%f, protZ=%f chi=%f\n",prot.X, prot.Y, prot.Z, chi);
			pnode->setRotation(core::vector3df(thi,-phi,0));
			T2=pnode->getRelativeTransformation();
				prot=T2.getRotationDegrees();
				printf("D:T2: protX=%f, protY=%f, protZ=%f chi=%f\n\n",prot.X, prot.Y, prot.Z, chi);
			T3.setbyproduct(T2,T1);
			prot=T3.getRotationDegrees();
			playernode->setRotation(prot);
		}
so the issue is : because the keys can be used simultaneously, a variable changing in the the "D" key loop, can be used in the "W" key loop without everything having finished in the "D" loop.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

You can't have any concurrent code running.. so the D and W loops can't execute simultaneously... events are queued up and you store the results of the key events in the bool array and then you check the bool array to see if the W key is pressed, then once you've finished that check (and any necessary code if the key is pressed) you then go on to check if the D key is pressed...

But do you mean that you're only really getting the result of one key being pressed? I'm not sure i fully understand what your problem is....
Image Image Image
Mirror
Posts: 218
Joined: Sat Dec 01, 2007 4:09 pm

Post by Mirror »

ok i will try to explain better this time. initially i wasn't using a bool array. i was using the simple method of user input as in the example tutorial. that way, everything worked perfectly ( player moved and rotated correctly ). But also he could only move ( W key ) or rotate ( A/D keys ). So if i was pressing the W key and then the D key, the W key stopped functioning and instead the D started. Also the movement was not smoothed. So i saw in the forum this second way of getting user input, with a bool array, and and i used it in the main game loop. Indeed everything got smoothed, and now when keys are pressed simultaneously the player can both rotate and move.

BUT, after a bit and while having both W and D for example pressed, he starts acting weird, moving where he shouldn't and rotating not correctly. I suppose that this is because all the variables here are global and if for example the variable "sign" changes in the D loop it gets passed to the W key loop before the D key loop code is finished.
JP
Posts: 4526
Joined: Tue Sep 13, 2005 2:56 pm
Location: UK
Contact:

Post by JP »

Make sign local then... or have multiple global versions of it like sign_for_w_key, sign_for_d_key etc.
Image Image Image
Post Reply