It's free to join Gamasutra!|Have a question? Want to know who runs this site? Here you go.|Targeting the game development market with your product or service? Get info on advertising here.||For altering your contact information or changing email subscription preferences.
Registered members can log in here.Back to the home page.

Search articles, jobs, buyers guide, and more.


Code Listing

// Example 1.1
// Original
int IsFree(int Num, int Mode)
{
     int RangeX, RangeY;
     for(int i = 1; i <= g_MaxUnit; i++)
     {
          if(i != Num)
          {
               switch(Mode)
               {
                    case NX_NEAR_ALL:
                         RangeX = g_Units[Num].Width + g_Units[i].Width;
                         RangeY = g_Units[Num].Height + g_Units[i].Height;
                         break;
                    case NX_NEAR_ENEMY:
                    case NX_NEAR_ENEMYDANGER:
                         RangeX = g_Units[i].Range + g_Units[i].Width + g_Units[Num].Width;
                         RangeY = g_Units[i].Range + g_Units[i].Height + g_Units[Num].Height;
                         break;
                    default:
                         assert(false);
                         break;
               }
               if((abs(g_Units[i].X - g_Units[Num].X) < RangeX) &&
               (abs(g_Units[i].Y - g_Units[Num].Y) < RangeY))
               {
                    if(Mode == NX_NEAR_ALL) return i;
                    if((Mode == NX_NEAR_ENEMY) &&
                         (g_Units[i].Civilization] != g_Units[num].Civilization)) return i;
                    if((Mode == NX_NEAR_ENEMYDANGER) &&
                         (g_Units[i].Civilization != g_Units[num].Civilization) &&
                         (g_Units[i].Force > 0)) return i;
               }
          }
     }
     return 0;
}

[return to article]

// Example 1.2
// Version with meaningful names added
int GetNearUnit(int MyUnitIndex, int AcceptableType)
{
     int RangeX, RangeY;
     const SUnit& MyUnit=g_Units[MyUnitIndex];
     for(int OtherUnitIndex = 1; OtherUnitIndex <= g_CurrentUnitCount; OtherUnitIndex++)
     {
          const SUnit& OtherUnit=g_Units[OtherUnitIndex];
          if(MyUnitIndex != OtherUnitIndex)
          {
               switch(AcceptableType)
               {
                    case ANY_UNIT:
                         RangeX = MyUnit.Width + OtherUnit.Width;
                         RangeY = MyUnit.Height + OtherUnit.Height;
                         break;
                    case ENEMY_UNIT:
                    case DANGEROUS_ENEMY_UNIT:
                         RangeX = OtherUnit.Range + MyUnit.Width + MyUnit.Width;
                         RangeY = OtherUnit.Range + MyUnit.Height + MyUnit.Height;
                         break;
                    default:
                         assert(false);
                         break;
               }

               const int SeperationX=abs(OtherUnit.XPos - MyUnit.XPos);
               const int SeperationY=abs(OtherUnit.YPos - MyUnit.YPos);
               if ( (SeperationX<RangeX) &&
                    (SeperationY<RangeY))
               {
                    if(AcceptableType == ANY_UNIT) return OtherUnitIndex;

                    const bool OtherIsEnemy=(OtherUnit.Civilization] != MyUnit.Civilization);
                    if((AcceptableType == ENEMY_UNIT) && OtherIsEnemy) return OtherUnitIndex;

                    const bool OtherIsDangerous=(g_Units[OtherUnit].Force > 0);
                    if((AcceptableType == DANGEROUS_ENEMY_UNIT) && OtherIsEnemy && OtherIsDangerous) return OtherUnitIndex;
               }
          }
     }
     return 0;
}

[return to article]

// Example 2.1
// Bad
void
ProcessEverything(void) {

     g_Camera.Process();

}

void
CCamera::Process(void) {

     // lots and lots of code

     g_Player.rotY+=SomeMemberVariableThatGetsTheEffectWeWant;

     // lots more code

}

[return to article]

// Example 2.2
// Still bad, but a lot more visible!
void
ProcessEverything(void) {

     g_Camera.Process();

     // PW-HACK for Alpha!
     g_Camera.HACK_AlterPlayersYRotation();

}

void
CCamera::HACK_AlterPlayersYRotation(void) {
     g_Player.rotY+=SomeMemberVariableThatGetsTheEffectWeWant ;
}

void
CCamera::Process(void) {

          // lots and lots of code
     // no hack hidden away here, it's at a higher, more visible level, much more likely to get fixed
          // lots more code

}

[return to article]

// Example 3.1
// Classic example of problems
class C3DTriangle {
     // some data
     void Draw(void);
};

// This interface instantly cripples performance, no matter what the implementation is like
// Modern graphics architectures achieve their performance by dealing with large groups of
// triangles at once, it'd be almost impossible to do that with this interface

[return to article]

// Example 3.2
// Better, but still probably unacceptable for games
class C3DTriangle {
     // some data
};

class C3DTriangleRenderer {
     void DrawTriangleList(C3DTriangle* const pList,int nTriangleCount);
};
// This interface is a lot better, but is still a bad fit for a lot of rendering architectures
// The idea of a design like this is to hide platform specifics, but once you start altering
// the interface to fit the platforms characteristics as you'd have to here, you've lost any
// platform independence. All you end up with is an interface that apes a particular API, and
// so doesn't work well on any other platforms, and just adds an extra layer of complexity to
// the program to no good effect. Wrapping up an API doesn't give you platform independence!

[return to article]

 


join | contact us | advertise | write | my profile
news | features | companies | jobs | resumes | education | product guide | projects | store



Copyright © 2003 CMP Media LLC

privacy policy
| terms of service