29.6 The cCritter serialize

29.6 The cCritter serialize

All the tricks we've discussed come into play with the cCritter::Serialize. A critter has a cCritter* _ptarget field that's a reference pointer, so when you save and reload the game file, which means saving and loading all of the critters, then the copy of the target critter is not going to be loaded into the exact same area of memory, and the old _ptarget pointer will no longer be correct. That's why we have the _targetindex field in the cCritter .

This reference pointer problem comes back in even stronger form with the armed critters, who have pointers to their bullets. You can look at the Serialize code inside the critterarmed.cpp file to see one way to work things out. In particular look for the fixPointerRefs methods .

The cCritter also has member pointer fields. As we explained in the last section, in order to load the pointer _psprite and _plistener fields of cCritter , we must first delete them and then use the overloaded operator>> to overwrite them with new pointers.

Note also that the CArray _forcearray has to be handled with Serialize and that, to avoid having a possible memory leak, you have to empty it out before you read into it. Here's some relevant code.

 void cCritter::Serialize(CArchive &ar)  {      CObject::Serialize(ar);          //Call the base class method to save the CRuntimeClass info.      if (ar.IsStoring()) //Writing data.      {          _forcearray.Serialize(ar);              //Generally you cant use << with a CArray.  //Sprite          ar << _psprite <<  //Listener          _plistener <<  //Personal variables          _age << _lasthit_age<< _oldrecentlydamaged << _health <<              _shieldflag <<          //........ETCETERA..........  //Pointer index variables.          if (_pownerbiota)              _targetindex = _pownerbiota->_index(_ptarget);                  //Prepare for a pointer reference.          else              _targetindex = cBiota::NOINDEX;          ar << _targetindex;  }  else //Reading data.  {          clearForcearray(); /* We have to empty out the array before              reading into it or we'll have a memory leak in case              something's in it. */          delete _psprite;              /* always delete a pointer before reading into it or you                  have a leak. */          delete _plistener;              /* always delete a pointer before reading into it or you                  have a leak. */          _forcearray.Serialize(ar); /* Read in. You usually can't use >>              with a CArray. */  //Sprite          ar >> _psprite >> /* Uses CreateObject to creates a new              cSprite* object of the correct child class, copies the new              object's fields out of the file, and places the pointer to              the new object in _psprite */  //Listener and force          _plistener >> // See the comment just above.  //Personal variables          _age >> _lasthit_age >> _oldrecentlydamaged >> _health >>              _shieldflag >>          //........ETCETERA..........  //Index for pointer reference variable.          ar >> _targetindex; /* cBiota::Serialize will call              cCritter::FixPointerRefs to replace this index              by a pointer. */      _ptarget = NULL; /* The cBiota::Serialize will call          all pcritter->fixPointerRefs for each critter to fix the          _ptarget, and also fix any pointer refs in the forces. */      }  } 

The cCritter::fixPointerRefs can only be called after all of the cCritter have been loaded and added to the cBiota array, with this array installed as the _powner biota of each cCritter . The fixPointerRefs does the following, in part.

 void cCritter::fixPointerRefs()  {      if (!_pownerbiota)          return;      else          _ptarget = _pownerbiota->GetAt(_targetindex);  } 

Software Engineering and Computer Games
Software Engineering and Computer Games
Year: 2002
Pages: 272

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net