原書中GameEngine的代碼有兩處bug,源代碼分別爲:
void GameEngine::CleanupSprites()
{
// Delete and remove the sprites in the sprite vector
vector<Sprite*>::iterator siSprite;
for (siSprite = m_vSprites.begin(); siSprite != m_vSprites.end(); siSprite++)
{
delete (*siSprite);
m_vSprites.erase(siSprite);
siSprite--;
}
}
void GameEngine::UpdateSprites()
{
// Check to see if the sprite vector needs to grow
if (m_vSprites.size() >= (m_vSprites.capacity() / 2))
m_vSprites.reserve(m_vSprites.capacity() * 2);
// Update the sprites in the sprite vector
RECT rcOldSpritePos;
SPRITEACTION saSpriteAction;
vector<Sprite*>::iterator siSprite;
for (siSprite = m_vSprites.begin(); siSprite != m_vSprites.end(); siSprite++)
{
// Save the old sprite position in case we need to restore it
rcOldSpritePos = (*siSprite)->GetPosition();
// Update the sprite
saSpriteAction = (*siSprite)->Update();
// Handle the SA_KILL sprite action
if (saSpriteAction & SA_KILL)
{
// Notify the game that the sprite is dying
SpriteDying(*siSprite);
delete (*siSprite);
m_vSprites.erase(siSprite);
siSprite--;
continue;
}
// See if the sprite collided with any others
if (CheckSpriteCollision(*siSprite))
// Restore the old sprite position
(*siSprite)->SetPosition(rcOldSpritePos);
}
}
這兩段代碼在VC6編譯器能正常運行,但在VS2008以後的編譯器編譯之後運行時產生錯誤,分別修正如下:
void GameEngine::CleanupSprites()
{
// Delete and remove the sprites in the sprite vector
vector<Sprite*>::iterator siSprite;
for (siSprite = m_vSprites.begin(); siSprite != m_vSprites.end(); siSprite++)
{
delete (*siSprite);//注意這裏
}
m_vSprites.clear();//注意這裏
}
//=================================================
//或
void GameEngine::CleanupSprites()
{
// Delete and remove the sprites in the sprite vector
vector<Sprite*>::iterator siSprite;
for (siSprite = m_vSprites.begin(); siSprite != m_vSprites.end();)//注意這裏
{
delete (*siSprite);
siSprite = m_vSprites.erase(siSprite); //注意這裏
}
}
//=====================================================
void GameEngine::UpdateSprites()
{
// Check to see if the sprite vector needs to grow
if (m_vSprites.size() >= (m_vSprites.capacity() / 2))
{
m_vSprites.reserve(m_vSprites.capacity() * 2);
}
// Update the sprites in the sprite vector
RECT rcOldSpritePos;
SPRITEACTION saSpriteAction;
vector<Sprite*>::iterator siSprite;
for (siSprite = m_vSprites.begin(); siSprite != m_vSprites.end();)//注意這裏
{
// Save the old sprite position in case we need to restore it
rcOldSpritePos = (*siSprite)->GetPosition();
// Update the sprite
saSpriteAction = (*siSprite)->Update();
// Handle the SA_KILL sprite action
if (saSpriteAction & SA_KILL)
{
// Notify the game that the sprite is dying
SpriteDying(*siSprite);
delete (*siSprite);
//siSprite--;
siSprite = m_vSprites.erase(siSprite); //注意這裏
continue;
}
// See if the sprite collided with any others
if (CheckSpriteCollision(*siSprite))
{
// Restore the old sprite position
(*siSprite)->SetPosition(rcOldSpritePos);
}
siSprite++;//注意這裏
}
}
分析:vector.erase(p)之後,所有指向p所指的內存的迭代器全部失效,但是它的返回值是指向下一個元素的迭代器。以前的編譯器之所以能夠成功運行,應該是之前的標準並不清晰或者編譯器內部實現的問題,VS2008之後嚴格按照標準來之後就出現運行時錯誤。
PS :
《BEGINNING GAME PROGRAMMING》 中還有個問題:程序要是換用了修改了BMP圖像資源,結果是圖像不能正常顯示變黑的了。
http://blog.csdn.net/dkink/article/details/2310564 給出瞭解決辦法,但還有點小問題,下面給出原因和改正辦法。
這裏作者忽略了一個小小的問題,...........無壓縮BMP文件的
pBitmapInfo->bmiHeader.biSizeImage 裏面的值不一定是圖像的真實大小,可能是0或者隨意的值。 所以需要重新計算,在Bitmap.cpp裏面,Bitmap類的 兩個Create函數的下面這個位置添加計算biSizeImage的代碼。
// Store the width and height of the bitmap
BITMAPINFO* pBitmapInfo = (BITMAPINFO*)pBitmapImage;
m_iWidth = (int)pBitmapInfo->bmiHeader.biWidth;
m_iHeight = (int)pBitmapInfo->bmiHeader.biHeight;
// 計算biSizeImage填充回去,是增加的代碼
//注意這裏
int lineByte=(m_iWidth*pBitmapInfo->bmiHeader.biBitCount/8+3)/4*4; //位圖每行佔多少個字節
pBitmapInfo->bmiHeader.biSizeImage = m_iHeight*lineByte;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get a handle to the bitmap and copy the image bits
PBYTE pBitmapBits;
m_hBitmap = CreateDIBSection(hDC, pBitmapInfo, DIB_RGB_COLORS,
(PVOID*)&pBitmapBits, NULL, 0);
參考資料:
1.C++Primer中文版(第四版)P282~283
2.http://www.cplusplus.com/forum/beginner/47420/
3.http://blog.csdn.net/dkink/article/details/2330905
4.http://blog.csdn.net/vhshiwen/article/details/4808867
5.http://www.cnblogs.com/buxianghe/archive/2012/06/25/2560713.html