Win32:位图实例化中断函数
Win32: Bitmap Instantiation Breaking Function
我的一个位图(它是一个精灵表)出现了这个奇怪的问题。我的游戏运行得很好,但GameStart函数,它初始化位图&精灵,如果我取消注释这行代码,就会中断:
g_pPowerup100Bitmap = new Bitmap(hDC, IDB_POWERUP_100, g_hInstance);
结果是,函数在到达该行代码时退出,但必须调用GamePaint(),因为位图被闪电式传输到屏幕上。我知道这个函数执行不正确,因为它们不是精灵,只是图像(音乐从不初始化)。精灵&音乐初始化是位图初始化下面的相同功能。
更令人沮丧的是,游戏实际上有效。。。有时。然后我可以正确地玩游戏&查看新的动画精灵。然而,在尝试调试了几十次之后,它根本无法正常构建。
我尝试过的:
1) Try/catch of entire GameStart() contents. Exception is not thrown
2) Extensive breakpoint checking - it's definitely this line
3) Spell-checking variable name - exact same as in header file
4) Re-saving bitmap as 24-bit RGB instead of 32-bit
5) Cleaning & rebuilding both the solution & project file
6) Restarting Visual C++ 2008
位图为64x1536。这是个问题吗?我有8GB的RAM和GTX 570分类。以下是整个功能:
void GameStart(HWND hWindow)
{
try
{
// Initialize global variables
g_iInputDelay = 0;
g_iNumLives = 3;
g_iScore = 0;
g_iGameState = 1;
g_iDifficulty = 1;
// Seed the random number generator
srand(GetTickCount());
// Create the offscreen device context and bitmap
g_hOffscreenDC = CreateCompatibleDC(GetDC(hWindow));
g_hOffscreenBitmap = CreateCompatibleBitmap(GetDC(hWindow),
g_pGame->GetWidth(), g_pGame->GetHeight());
SelectObject(g_hOffscreenDC, g_hOffscreenBitmap);
// Create and load the bitmaps
HDC hDC = GetDC(hWindow);
g_pHighwayBitmap = new Bitmap(hDC, IDB_HIGHWAY, g_hInstance);
g_pChickenBitmap = new Bitmap(hDC, IDB_CHICKEN, g_hInstance);
g_pCarBitmaps[0] = new Bitmap(hDC, IDB_CAR1, g_hInstance);
g_pCarBitmaps[1] = new Bitmap(hDC, IDB_CAR2, g_hInstance);
g_pCarBitmaps[2] = new Bitmap(hDC, IDB_CAR3, g_hInstance);
g_pCarBitmaps[3] = new Bitmap(hDC, IDB_CAR4, g_hInstance);
g_pChickenHeadBitmap = new Bitmap(hDC, IDB_CHICKENHEAD, g_hInstance);
g_pMainMenuBitmap = new Bitmap(hDC, IDB_MAIN_MENU, g_hInstance);
g_pHighScoresMenuBitmap = new Bitmap(hDC, IDB_HIGH_SCORES_MENU, g_hInstance);
g_pGameOverMenuBitmap = new Bitmap(hDC, IDB_GAME_OVER_MENU, g_hInstance);
g_pNormalModeBtnBitmap = new Bitmap(hDC, IDB_NORMAL_MODE_BTN, g_hInstance);
g_pHardModeBtnBitmap = new Bitmap(hDC, IDB_HARD_MODE_BTN, g_hInstance);
g_pHighScoresBtnBitmap = new Bitmap(hDC, IDB_HIGH_SCORES_BTN, g_hInstance);
g_pReplayBtnBitmap = new Bitmap(hDC, IDB_REPLAY_BTN, g_hInstance);
g_pMainMenuBtnBitmap = new Bitmap(hDC, IDB_MAIN_MENU_BTN, g_hInstance);
g_pPowerup100Bitmap = new Bitmap(hDC, IDB_POWERUP_100, g_hInstance);
RECT rcBounds = { 0, 0, 465, 400 };
//Button Sprites - Main Menu
Sprite* pBtnSprite = new Sprite(g_pNormalModeBtnBitmap, 77,228, 0,0, 1, rcBounds, BA_STOP);
pBtnSprite->SetStateChange(0);
g_pGame->AddSprite(pBtnSprite, 1);
pBtnSprite = new Sprite(g_pHardModeBtnBitmap, 254,228, 0,0, 1, rcBounds, BA_STOP);
pBtnSprite->SetStateChange(0);
g_pGame->AddSprite(pBtnSprite, 1);
pBtnSprite = new Sprite(g_pHighScoresBtnBitmap, 166,310, 0,0, 1, rcBounds, BA_STOP);
pBtnSprite->SetStateChange(3);
g_pGame->AddSprite(pBtnSprite, 1);
//Button Sprites - Game Over Menu
pBtnSprite = new Sprite(g_pReplayBtnBitmap, 167,249, 0,0, 1, rcBounds, BA_STOP);
pBtnSprite->SetStateChange(0);
g_pGame->AddSprite(pBtnSprite, 2);
pBtnSprite = new Sprite(g_pMainMenuBtnBitmap, 82,332, 0,0, 1, rcBounds, BA_STOP);
pBtnSprite->SetStateChange(1);
g_pGame->AddSprite(pBtnSprite, 2);
pBtnSprite = new Sprite(g_pHighScoresBtnBitmap, 252,332, 0,0, 1, rcBounds, BA_STOP);
pBtnSprite->SetStateChange(3);
g_pGame->AddSprite(pBtnSprite, 2);
//Button Sprites - High Scores Menu
pBtnSprite = new Sprite(g_pMainMenuBtnBitmap, 166,332, 0,0, 1, rcBounds, BA_STOP);
pBtnSprite->SetStateChange(1);
g_pGame->AddSprite(pBtnSprite, 3);
// Create the chicken and car sprites
g_pChickenSprite = new Sprite(g_pChickenBitmap, rcBounds, BA_STOP);
g_pChickenSprite->SetPosition(4, 175);
g_pChickenSprite->SetVelocity(0, 0);
g_pChickenSprite->SetZOrder(1);
g_pChickenSprite->SetNumFrames(2);
g_pChickenSprite->SetAsInputControlled(); //stops auto-frame update
//DEBUGGING ONLY!!!!!
g_pChickenSprite->SetID(1);
g_pGame->AddSprite(g_pChickenSprite, 0);
Sprite* pSprite = new Sprite(g_pCarBitmaps[0], rcBounds, BA_WRAP);
pSprite->SetPosition(70, 0);
pSprite->SetVelocity(0, 6);
pSprite->SetZOrder(2);
g_pGame->AddSprite(pSprite, 0);
pSprite = new Sprite(g_pCarBitmaps[1], rcBounds, BA_WRAP);
pSprite->SetPosition(160, 0);
pSprite->SetVelocity(0, 2);
pSprite->SetZOrder(2);
g_pGame->AddSprite(pSprite, 0);
pSprite = new Sprite(g_pCarBitmaps[2], rcBounds, BA_WRAP);
pSprite->SetPosition(239, 400);
pSprite->SetVelocity(0, -4);
pSprite->SetZOrder(2);
g_pGame->AddSprite(pSprite, 0);
pSprite = new Sprite(g_pCarBitmaps[3], rcBounds, BA_WRAP);
pSprite->SetPosition(329, 400);
pSprite->SetVelocity(0, -9);
pSprite->SetZOrder(2);
g_pGame->AddSprite(pSprite, 0);
// Load the background music
g_pGame->PlayMIDISong(TEXT("Music.mid"));
getHighScores(scoreData, g_scoreTop);
scoreData.close();
}
catch (int e)
{
cout << "An exception occurred. Exception Nr. " << e << endl;
system("PAUSE");
}
}
GameStart()在以下上下文中调用:
switch (msg)
{
case WM_CREATE:
// Set the game window and start the game
SetWindow(hWindow);
GameStart(hWindow);
return 0;
如果有人能解释为什么位图会破坏函数,我将不胜感激!
EDIT:Hans直接解决了问题——我勾选了"Win32异常"复选框&这行代码出现了内存访问错误:
CopyMemory(pBitmapBits, pTempBits, pBitmapInfo->bmiHeader.biSizeImage);
图像太大了吗?我会继续调查,但欢迎任何建议。
不要使用WM_CREATE消息初始化游戏。在64位操作系统上运行32位代码时,会出现一个非常特殊的问题,当消息处理代码中出现SEH异常(如访问违规)时,可能会导致SEH异常被吞噬。WM_CREATE是显示该问题的消息之一。在这个答案中,有很多关于这种行为的细节,尽管这是Winforms特有的。然而,当您用C或C++编写代码时,也存在完全相同的问题。
(通常)不需要使用WM_CREATE来初始化东西,您还可以在CreateWindowsEx()调用之后移动它,因为您应该只需要窗口句柄。调试器现在将再次提供帮助,并向您显示代码崩溃的位置。
如果您在WM_CREATE中确实需要它,那么请使用debug+Exceptions进行调试,选中Win32异常的Thrown复选框。还有验证这个答案是否准确的方法。
现在,在调用GetDC之后,必须调用ReleaseDC。但你打了三个GetDC电话。留下一个电话,存储HDC,最后释放它。
- deleteNode函数出现以中断连接列表
- clang格式:在 lambda 函数和外部块的大括号之前中断
- 如何在 Arduino 中使用 C++ 成员函数作为中断处理程序?
- 移动返回对象的构造函数会中断C++98 代码?
- 返回可中断线程的函数
- C 从另一个函数中断循环
- 为什么使用复制构造函数会导致此代码中断?
- Xcode 7调试器不会中断内联标头函数
- 用中断函数将Keil5C项目转换为C++项目错误
- 干净编码:如何从循环中的函数调用内部中断循环
- 自定义函数中断
- Win32:位图实例化中断函数
- 从函数返回类型中删除常量是否会中断 ABI
- 使用 std::weak_ptr 和别名构造函数中断循环引用:声音或有问题
- 带有 STL 向量的模板函数会因新的分配器而中断
- 循环:在构造函数中使用中断或状态变量
- 中断正在执行MKL或其他第三方函数的线程
- 正在中断构造函数中对象的创建
- 一个中断函数,用于修改动态确定的实例
- return语句何时中断函数