原书中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.youkuaiyun.com/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.youkuaiyun.com/dkink/article/details/2330905
4.http://blog.youkuaiyun.com/vhshiwen/article/details/4808867
5.http://www.cnblogs.com/buxianghe/archive/2012/06/25/2560713.html