# tips for testing conditions

• 04-07-2003
Silvercord
tips for testing conditions
Hi there, I am finally coming up to AI of sorts, in this case it is a spaceship that automatically rights itself based on different variables. I've made it a pretty smooth process, but it could be much better. I basically used a lot of if and if/else statements to perform the necessary actions based on the current X and Y rotation, the mouse deviation, etc etc. I have altogether 10 if statements, although at any one time only about 5 will be executed. I don't know if this is too many, but I know that decision making can slow down games immensely. I was wondering if anyone had any tips for testing states. I.e for right now I'm trying to have everything in set mathematical equations, and everything comes down to just changing the values of a variable. This is really my first time doing anykind of 'AI' (its just testing states and acting upon them) and I don't want to start going about this wrong.

EDIT:

I'll post the source if you want.
• 04-07-2003
confuted
A bit of source would probably be helpful if it isn't too long...also, you probably already know about it, but aihorizon.com has some cool articles about AI, maybe there is something there that can help you. I can't really tell what you are trying to do, though.
• 04-07-2003
Silvercord
I am literally doing what the name of the thread says which is testing for different conditions. I am just wondering if this will hurt me down the road if I'm not careful about my use of if statements and stuff (on top of having to execute a ridiculous amount of math for each entity that has view, up and strafe vectors)
It is quite a bit of code
EDIT:
and I did not know of that site, thanks!
Code:

``` void        Player::CheckMouse() {         char        asdf[50];         static float MiddleX = SCREEN_WIDTH / 2;         static float MiddleY = SCREEN_HEIGHT / 2;         char test[128];         POINT MousePos;         GetCursorPos(&MousePos);         SetCursorPos(MiddleX, MiddleY);         if(MousePos.x == MiddleX && MousePos.y == MiddleY) //if there is no change align spaceship         {                 //ZShipRotation is rotation ABOUT Z Axis                         if(ZShipRotation > 0)                                 ZShipRotation -= ZRightSpeed;                         if(ZShipRotation < 0)                                 ZShipRotation += ZRightSpeed;                 //when in positive clamping zone                 //XShipRotation is rotation ABOUT X Axis                         if(XShipRotation > 0 && XShipRotation < XRightSpeed)                                 //XShipRotation -= (.1*XShipRotation);                                        XShipRotation = 0;                         else                         if(XShipRotation > 0 )                                 XShipRotation -= XRightSpeed;                         if(XShipRotation < 0 && XShipRotation > -XRightSpeed)                         //        XShipRotation += (.1*XShipRotation);                                 XShipRotation = 0;                         else                         if(XShipRotation < 0 )                                 XShipRotation += XRightSpeed;                         //sprintf(test, "zship rotation: %d", (int)ZShipRotation);                         //SetWindowText(hWnd, test);                 return;         }         Rotating = true;         float YDeviation = (MiddleY - MousePos.y);                float XDeviation = (MiddleX - MousePos.x);                if(XDeviation)        //if Deviated left/right                 HorizChange = true;         else                 HorizChange = false; /* X / MaxZ = XDeviation / ScreenWidth        MaxZ * XDeviation = X * ScreenWidth X = (MaxZ * XDeviation) / ScreenWidth X / MaxX = YDeviation / SCREENHEIGHT MaxX * YDeviation = X * SCREENHEIGHT X = (MaxX * YDeviation) / SCREENHEIGHT */                 if(ZShipRotation > -MaxZRotation && ZShipRotation < MaxZRotation) {        //if we haven't reached the limit about Z                         if( (ZShipRotation > 0 && XDeviation < 0) || (ZShipRotation < 0 && XDeviation > 0) )                                 ZShipRotation += 2*((MaxZRotation * XDeviation) / SCREEN_WIDTH) * ZRotateSpeed; //double time it because actual rotation and deviation                         else                                                                                                                          //have different signs                                 ZShipRotation += (MaxZRotation * XDeviation) / SCREEN_WIDTH;                 }                 if(XShipRotation > -MaxXRotation && XShipRotation < MaxXRotation) {        //if we haven't reached the limit about X                         if( (XShipRotation > 0 && XDeviation < 0) || (XShipRotation < 0 && XDeviation > 0) )                                 XShipRotation += 2*((MaxXRotation * YDeviation) / SCREEN_HEIGHT) * XRotateSpeed;                         else                                 XShipRotation += (MaxXRotation * YDeviation) / SCREEN_HEIGHT;                 }         //        sprintf(test, "zship rotation: %d", (int)ZShipRotation);         //        SetWindowText(hWnd, test);         //XDegRad is how far to rotate ABOUT the x axis         //YDegRad is how far to rotate ABOUT the y axis         float XDegRad = ((2 * PI) * YDeviation) / SCREEN_WIDTH; //radians to rotate vector         float YDegRad = ((2 * PI) * XDeviation) / SCREEN_WIDTH;                 float cosXTheta = (float)cos(XDegRad);                float sinXTheta = (float)sin(XDegRad);                        float cosYTheta = (float)cos(YDegRad);                float sinYTheta = (float)sin(YDegRad);                        //YRotation is how far to rotate ABOUT the y axis         //XRotation is how far to rotate ABOUT the x axis         YRotation += ((360 * XDeviation) / SCREEN_WIDTH);                XRotation += ((360 * YDeviation) / SCREEN_WIDTH);         Locked = false;         if(XRotation >= 57.3) {                 XRotation = 57.3;                 XDegRad = 0;                 Locked = true;                }         if(XRotation <= -57.3) {                 XRotation = -57.3;                 XDegRad = 0;                 Locked = true;         }                 //calculate strafe vector         Strafe = CrossProduct(View - Position, Up);         Strafe.Normalize();         //rotate camera position         Vector        tempCamPos = CamPos - Position;         RotateVector(XDegRad, Strafe, tempCamPos);         RotateVector(YDegRad, YAxis, tempCamPos);         CamPos = tempCamPos + Position; //        update Up vector         RotateVector(XDegRad, Strafe, Up);         RotateVector(YDegRad, YAxis, Up);         //update View vector         RotateView(XDegRad, Strafe);         RotateView(YDegRad, YAxis);                }```
• 04-07-2003
confuted
In a lot of those tests, you are trying to set some variable (ZShipRotation, for example) to something a little bit closer to 0. You test if it is positive and if it is negative and then perform operations accordingly. Instead, you might want to try something like multiplying by .9 or whatever percentage you see fit, and then rounding the result (so that instead of just approaching 0, it will actually get there) For the ones that you aren't trying to get closer to 0, and instead want to be 53 or so, you could subtract 53, use the above method, and add 53 again. It might be faster.

If you want to keep a setup a bit more similar to what you have, you could probably set up a bit field to keep track of the parity on all the variables which can be either positive or negative, and then declare the variables as unsigned. That way you could try to minimize your number of tests by subtracting every time a correction was needed...although you'll run into some problems with keeping track of the parity and making sure you don't overcorrect (which looks like it might be a problem now, too)

Code:

```if(ZShipRotation > 0)                                 ZShipRotation -= ZRightSpeed;                         if(ZShipRotation < 0)                                 ZShipRotation += ZRightSpeed;```
Suppose that ZShipRotation == 1 and ZRightSpeed== 2...
1st iteration - ZShipRotation == -1
2nd iteration - ZShipRotation == 1
3rd iteration - ZShipRotation == -1
In a scenario such as this, which is not unlikely, ZShipRotation isn't going to zero out. You would need to make sure that ZRightSpeed is <=ZShipRotation, unless you handle it elsewhere already.

Overall, I would suggest a percentage based model, because it makes it easier and you can completely eliminate a bunch of tests. (0*.9 is still 0)
• 04-08-2003
That has been one of the largest problems I have been having. I actually tried the percentage based model but the approximation (what I posted) actually looked much better and has felt smoother. I still need to do more work on this. One thing though, if you mutltiply by a constant percent it can't ever reach zero, but it will get close (which should be fine).

I don't entirely understand what you meant by the parity thing.

I'll post the actual executable when I get something that is worth posting, thanks for replying
• 04-08-2003
confuted
I'm going to assume that Shadow12345 is SilverCord on a different name.

I realize that a model based only on percentages wouldn't ever quite reach zero, but if you rounded after everytime you multiplied (if it doesn't take too many clock cycles) you could eliminate the problem, because anything closer to 0 than .5 would round to 0.

The parity thing is kinda an idea that I had while I was typing, I'm not sure exactly how you would make it work. I was suggesting that you have one variable (one bit in a bit field) that would simply keep track of which direction it was spinning (positive or negative rotation as it is now) Then, whenever it was rotating in either direction, you could have the variable controlling the speed always be positive. Then, instead of testing to see if it was positive or negative, you could just subtract. But as I said, I don't know how that will work.

I also don't know how this would work out for you either, it's another idea I just came up with, and it's probably pretty slow...I think % is probably slower than an if, but I don't know.
Code:

```for (temp=rotationspeed;temp==0;temp--)     rotationspeed=rotationspeed%temp```
You would obviously not do it exactly like that, I was just throwing the modulus idea out there for you.
• 04-09-2003
Silvercord
Sorry for pulling that stunt on you, yes I am Silvercord on a different name (I switch back and forth periodically).

I like the bitfield idea, that means I'd be able to store like 16 variables in a single integer, I think I'll fool around with that. Because i haven't used them extensively I'm going to have to test the times on the bitwise operators, but I'm sure they'd be fast enough.
• 04-09-2003
Silvercord
Here I have a 'working' version, obviously there are still bugs and imperfections. It simply uses a percentage based model, i.e:
Code:

```        if(MousePos.x == MiddleX && MousePos.y == MiddleY) //if there is no change align spaceship         {                                         ZShipRotation *= .7;                                                         XShipRotation *= .7;                 return;         }```
I was wondering if you could download and test the executable and tell me how it feels in terms of smoothness. I think it is a step up from what I have previously, and it's pretty good. There is no gimbal lock (when view becomes up vector) however you can go upside down and I'm not sure if that's something I want (yes I know in a spaceship game you should have 360 degrees freedom about every axis).
The first part is the executable, the next part is the game data. Open the data folder and copy everything in the data folder (even the subfolder) into the same folder as the binary.
• 04-09-2003
Silvercord
And the data files:
EDIT: I forgot to add that the model belongs to Jverkoey, the tail isn't included so you can see the direction the nose is pointing (you can easily see the z axis levelling, but the tail got in the way of the X axis levelling)

This is just a testing version
• 04-09-2003
confuted
Since they weren't mentioned in your posts, I'm going to assume that the w,a,s, and d controls aren't supposed to be final yet, but they need to move the ship a lot faster relative to the speed with which the mouse works. Also, a couple notes about the upside down motion.

If you move the mouse up and up and up and keep going up, the space ship will suddenly flip upside down. (links 1 and 2 below) I think maybe your camera view is switching somehow, but anyway, it's a bit messed up. I would think that you would want the camera to stay in a constant position relative to the ship, such as directly behind it 30 degrees above horizonal. That way when you move the ship vertically, the camera will track behind it. If you want the vertical tilt thing, which is pretty cool, then I would think that it would be *really* cool would be to allow the camera to kinda lag behind up to 20 degrees worth of Y rotation either way of the normal position and then slowly drift back to normal (link 3 below)

Also, I think the ship might snap back to normal a bit fast.

In a lot of space simulation games, turning is just done by rotation over the Y axis (ship's Y axis, not world). Then roll is also allowed (around ship's Z axis) Personally, I find it *very* disorienting and kinda ackward to have controls like that, but one thing to consider on your controls is that roll isn't possible at all. It's very difficult to adequately represent 3D movement w/ just the mouse, and other controls can make for ackward use, so you have to make a decision. Perhaps you could allow for the arrow keys to control roll or something, I don't know where you are going with this, but overall, it looks like you have a pretty good start.

On the lighting effects...just a brief blurb...it looks like you have a spinning light or something in the background from the lighting on the ship, which is pretty strange. Also, the color changing stars...ditch 'em and go for some constant colors.

Good luck.

These two were generated with a very slight vertical mouse movement.
http://confuted.0catch.com/silvercord1.gif
http://confuted.0catch.com/silvercord2.gif

What I'm suggesting:
http://confuted.0catch.com/silvercord3.gif
• 04-09-2003
Silvercord
I'm sorry to say none of your links worked, however I understand everything you have mentioned. Your input is *greatly* appreciated. I think I am going to make a poll about the stars, I think they're cool the way they are now, but if the majority thinks they should be constant I'll proably just change them.
• 04-09-2003
confuted
Sorry about the links, I don't normally have that problem with that server. I guess the server noticed the high volume or something. Anyway, this should work...

http://confuted.0catch.com/silvercord.html

Wow, I'm really lazy when it comes to making websites, I could have used <img src="">
• 04-10-2003
Silvercord
the camera idea looks good (what you demonstrated in the last picture). That'll be an extra type of thing, but I think it's a good one to have (camera's in a lot of games do that sort of thing).