🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

It shouldnt work but it does...

Started by
9 comments, last by Xartrix 17 years, 2 months ago
First of all, hi :). Im currently reading through all those tutorials and they are really great, but there is something that is bugging me that I only recently noticed. There is a code in WinMain that increases the speed of an object when you press certain key, in this example it is: if (key[VK_DOWN]) xspeed+=0.01f; xspeed is a global variable, which is also used in DrawScene(), just before the end: xrotate+=xspeed; The issue here is that 1) when xspeed was declared (and after that as well) it wasn't assigned any value, but my guess is that if it has no value the compiler equals it zero...(this is not much of a issue just want to be sure) 2) so, I understand that you raise xspeed just under certain conditions (if key down is pressed), whereas xrotate should raise everytime the function DrawScene() is called (which is called almost everytime from WinMain) practically resulting in object spinning faster each time (you just increase or decrease speed by which is xrotate increased almost everytime) But the thing is that it spins at constant rate and I have no idea why... (if you dont understand what I am saying here please ask for clarification ;)) And I have one more small (c++ related) question (too much? :)) Another line: if (key['L'] && !lkey){ lkey=true; //code } if (!key['L']) lkey=false; so basicly here we have booleans (array named key and lkey) which aren't assigned any value before this code (they are located in WinMain as well btw) When I think about it, maybe you could assign value to the key array in window procedure... case WM_KEYUP: key[wparam]=false; ...but Im not sure when WM_KEYUP is executed, when you release the key or everytime the key is not pressed (is released), but again I think it's the first option... but back to the problem, I would like to ask how does the compiler know which 'if' to run when the variable's value wasn't specified before... One more thing (:P); I have been replacing BOOL with bool, TRUE with true and FALSE with false when writing my code, cause I don't like caps much (maybe this could be a problem) and I don't use Visual C++ (I've tried replacing BOOL,TRUE and FALSE with their lower-case but nothing extra happened), I use DevC++ Well, I hope I didn't bore you to death by this reading and I hope someone would help me :). Thank a lot! XX
Advertisement
Not looking at the code but my guesses would be:

You're just missing the initialization of xspeed. It's perhaps initialized somewhere other than the variable declaration.

Either xrotate is not global or its value is recalculated each tick before += xspeed.

-me
The object that is rotating starts at "zero" rotation every frame. In the first frame you might want it to rotate 1 degree. The second frame 2 degrees. The nth frame, n degrees... you would do this by incrementing xrotation by 1.0 each and every frame. This provides a smooth rotation of 1 degree per frame.

If you add xspeed to xrotation instead of incrementing by 1.0, you are simply rotating by xspeed degrees per frame instead of 1.0 degree per frame. So, in your example, increasing xspeed merely increases the rate of rotation one time, resulting in a faster but smoothly spinning cube.

Remember, the rotation you are setting is not a "rate", it is an absolute angle, with respect to the original unrotated orientation.

Quote: But the thing is that it spins at constant rate and I have no idea why...
Because it IS spinning at a constant rate. xspeed is that rate. if you increase xspeed, it will spin faster.
Quote: Original post by Xartrix
First of all, hi :). Im currently reading through all those tutorials and they are really great, but there is something that is bugging me that I only recently noticed.

There is a code in WinMain that increases the speed of an object when you press certain key, in this example it is:

if (key[VK_DOWN]) xspeed+=0.01f;

xspeed is a global variable, which is also used in DrawScene(), just before the end:

xrotate+=xspeed;

The issue here is that
1) when xspeed was declared (and after that as well) it wasn't assigned any value, but my guess is that if it has no value the compiler equals it zero...(this is not much of a issue just want to be sure)

2) so, I understand that you raise xspeed just under certain conditions (if key down is pressed), whereas xrotate should raise everytime the function DrawScene() is called (which is called almost everytime from WinMain) practically resulting in object spinning faster each time (you just increase or decrease speed by which is xrotate increased almost everytime)

But the thing is that it spins at constant rate and I have no idea why...
(if you dont understand what I am saying here please ask for clarification ;))


Hi! [smile]

1) No this is incorrect. The variable's value could be anything if it has not been initialized.

2) You didn't post the entire code, but I'm pretty sure that xrotate is not the rotation velocity, but the current angle. Which means that the rotation will constantly change, but not it's rate unless a key is being pressed.

Quote: Original post by Xartrix
And I have one more small (c++ related) question (too much? :))
Another line:

if (key['L'] && !lkey){
lkey=true;
//code
}
if (!key['L']) lkey=false;

so basicly here we have booleans (array named key and lkey) which aren't assigned any value before this code (they are located in WinMain as well btw)

When I think about it, maybe you could assign value to the key array in window procedure...

case WM_KEYUP:
key[wparam]=false;

...but Im not sure when WM_KEYUP is executed, when you release the key or everytime the key is not pressed (is released), but again I think it's the first option...

WM_KEYUP and WM_KEYDOWN are events, whenever one of these events occur (key is pressed, or key is released) the event is fired and the code can catch it, and this specific code will then set a boolean corresponding to that key to true or false.


Quote: Original post by Xartrix
but back to the problem, I would like to ask how does the compiler know which 'if' to run when the variable's value wasn't specified before...

The compiler doesn't run any code, the compiler compiles your high-level code, in this case C++ to machine code. The "if" is evaluated each time that piece of code is run at run-time, the variable always has a value, it might change each time, but it always has some value (worst case scenario it has some value which is meaningless in the context and your application crashes).



Quote: Original post by Xartrix
One more thing (:P); I have been replacing BOOL with bool, TRUE with true and FALSE with false when writing my code, cause I don't like caps much (maybe this could be a problem) and I don't use Visual C++ (I've tried replacing BOOL,TRUE and FALSE with their lower-case but nothing extra happened), I use DevC++

That is not the problem.
Best regards, Omid
First of all excuse some of my rather incorrect statements I made above, I picked the first acceptable (at least for me :)) word that came to my mind and obviously it wasnt the right one..

@smitty: Ya I know that, but what I had in mind is little lower in this post
If you look to my scrap of code you'll see that in DrawScene() (which is being called from WinMain) there is some rotation before drawing the box (done by xrotate and yrotate which are absolute angles :)).

After you draw a box and increase angles by xspeed and yspeed (which are unknown at startup so I assume no ratation is made) lets say you press downkey or upkey for few seconds and xspeed increases (decreases), it is now 5.0f. Now lets say you won't press downkey or upkey until the end of this progem.

When WinMain calls DrawScene() xrotate and yrotate are increased by xspeed, in our case 5.0f. So logically the next time DrawScene is called (say its cycle number 1) the angles will be biggher. So in cycle number two, xrotate will be increased by another xspeed (by another 5.0f) making the angle bigger. In cycle number 3 its another 5.0f,...,in cycle n its anotehr 5.0f (I sound like I was talking to someone who cant read - Im sorry ;)). So if the angle is bigger everytime the DrawScene is called shouldn't it spin faster everytime you see it on screen?
*Enlightment* Now I understand it, to keep the box spinning the constant speed the angle needs to be increased by 'constnant' amount - our xspeed...oh silly me not to resolve this earlier...
Anyway thanks... - now only the bool problem remains :)

@Omid: 1) I thought that was the only sensible solution cause if I initialize the value or not it gives the same output...but maybe the compiler fills the code (again just a speculation)

2) yes, its the angle, my mistake (Apparently I shouldn't change the initial name cause it's kinda confusing for people that don't know what it means; I took that for granted :))
Xartrix said:

but back to the problem, I would like to ask how does the compiler know which 'if' to run when the variable's value wasn't specified before…

I don't know what I was thinking about when writing this sentence, it sounds crazy now..

Ill TRY to explain in the code below

#includes...ordinary variable initialization...(hwnd,hinstance,...)bool key[256],lkey,xspeed,xrotate,yspeed,yrotate;other functions...int DrawScene(){//preparing Scene (Clear buffers, translate,...)glRotatef(xrotate,1.0f,0.0f,0.0f);glRotatef(yrotate,0.0f,1.0f,0.0f);//drawing quads (a box)xrotate+=xspeed;yrotate+=yspeed;return true; /*another strange thing, the author (NeHe) returned true in int-type func, looks like it isn't a fault but he could change return type to bool*/}//Anotehr functions - kill and create windowLRESULT CALLBACK WndProc(params which are too long to type){ //window procedure   switch(msg){   // few cases    case WM_KEYDOWN: // when one presses the key   key[wparam]=true;   return 0; // original line, I would probably put break there   case WM_KEYUP:   key[wparam]=false; //when one releases the key   return 0; // same as the previous return      case WM_CLOSE: //before program ends   //code   return 0;*/This is trange here I had break here as well as in otehr cases but I found out that it causes a problem (at least on my PC), because when I substitute other return 0s with breaks in this code it will work except this; this one must be return 0 and I don't know why (offtopic)*/      } //switch ends   return DefWindowProcedure(hwnd,msg,wparam,lparam);}And finally:int WINAPI WinMain(long params I wont type){bool done=false; //additional varwhile(!done){   if(PeekMessage(its params){   code handling messages, calling wndproc by Translate & DispatchMsg(indirectly I think)   }   else{   //one more if here (whether the (Window || (OpenGL scene))<- one of these two Im not sure which one, but most likely OGL - is active)   DrawScene(); //calling the func above   SwapBuffers(hdc); //double buffering   if(key['L'] && !lkey){   lkey=true; //key l is pressed, so this code cannot be called again until it is released   //code to do when l is pressed but not held   }   if(!key['L']) //when L is released lkey is set to false meaning the code above can execute again when L is pressed   lkey=false;   //now the xspeed code is comming   if(key[VK_DOWN]) xspeed+=0.01f;   // when one holds key down speed is increased by 0.01   if(key[VK_UP]) xspeed-=0.01f //no comment here   // another code here   } //end of else   } //end of while} //end of WinMain 


Few notes:in this compressed code I have shown the position of those mentioned bools and the way they contribute to the code, but you may want to compile it yourself so Im adding complete unmodified code (its Lesson 8! (plus a start to lesson 9)). You may see for yourself that whether you initialize bools (to false!!) or not the code works.

http://www.gjar-po.sk/~medvec5d/cpp/main.cpp - My Code
http://nehe.gamedev.net/data/lessons/vc/lesson08.zip - The Original NeHe's Code For Visual C++ (should be the same or almost the same for DevC++)

XX
Quote: Original post by Omid Ghavami
1) No this is incorrect. The variable's value could be anything if it has not been initialized.


Actually, a lot of compilers null undeclared variables secretly during compiling, it does this to prevent a lot of bad problems.
But your right, it should be initialized at first possible moment.
Quote: Original post by lc_overlord
Actually, a lot of compilers null undeclared variables secretly during compiling, it does this to prevent a lot of bad problems.


I don't know of any that do this in a Release configuration; most do initialize memory in a Debug configuration because it's easier to trap overflow errors that way. Zeroing memory takes a long time and adversely effects runtime performance.

-me

Quote: Original post by lc_overlord
Quote: Original post by Omid Ghavami
1) No this is incorrect. The variable's value could be anything if it has not been initialized.


Actually, a lot of compilers null undeclared variables secretly during compiling, it does this to prevent a lot of bad problems.
But your right, it should be initialized at first possible moment.


Quote: Original post by Palidine
I don't know of any that do this in a Release configuration; most do initialize memory in a Debug configuration because it's easier to trap overflow errors that way. Zeroing memory takes a long time and adversely effects runtime performance.


I was curious so I did a few tests (in Release mode build), it seems the vc8 compiler initializes global variables, but not local ones. Though such testing is hardly proof of any general behavior [smile] Anyone who knows the details behind this? Logically it could make sense, since zeroing global values wouldn't affect runtime performance.

Quote:
/*another strange thing, the author (NeHe) returned true in int-type func, looks like it isn't a fault but he could change return type to bool*/

Did he return TRUE or true? Since TRUE is #define TRUE 1


Quote:
//one more if here (whether the (Window || (OpenGL scene))<- one of these two Im not sure which one, but most likely OGL - is active)

I checked the NeHe source, I believe it is:
if ((active && !DrawGLScene()) || keys[VK_ESCAPE]){    done = TRUE;......


active is used to determine whether the window is minimized or not.
Which means, IF (Not minimized AND DrawGLScene returned false) OR (Espace was pressed) THEN (quit application)
Best regards, Omid
Is xspeed declared static? Static variables (both local and global) are by default initialized to zero. That's in the C++ standard, it's guaranteed behavior.
Quote: Original post by pinacolada
Is xspeed declared static? Static variables (both local and global) are by default initialized to zero. That's in the C++ standard, it's guaranteed behavior.


No it's not static, the declarations are:
GLfloat	xrot;				// X RotationGLfloat	yrot;				// Y RotationGLfloat xspeed;				// X Rotation SpeedGLfloat yspeed;				// Y Rotation Speed


And no initializations in the code as far as I can find. The author of the NeHe tutorial code apparently was aware of this, I however did not expect such behavior.
Best regards, Omid

This topic is closed to new replies.

Advertisement