2012-12-15 30 views
1

我有一個奇怪的問題與我的一個位圖(這是一個spritesheet)。我的遊戲完美運行,但如果我取消這行代碼的GameStart功能,初始化位圖&精靈,打破:Win32:位圖實例化破解函數

g_pPowerup100Bitmap = new Bitmap(hDC, IDB_POWERUP_100, g_hInstance); 

結果是,函數只是退出當它擊中該行的代碼,但是GamePaint()必須被調用,因爲位圖是blitted到屏幕上的。我知道這個函數沒有正確執行,因爲它們不是精靈 - 只是圖像(並且音樂從不初始化)。精靈&音樂初始化低於相同功能中的位圖初始化。

更令人沮喪的是,遊戲實際上工程...有時。然後我可以正確地玩遊戲&看到新的動畫精靈。然而,在試圖調試這個東西幾十次之後,它根本無法正確構建。

我已經試過:

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 Classified。這裏是整個函數:

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; 

如果還有人能夠解釋爲什麼該位被查殺功能的一些情況,我將不勝感激!

編輯:漢斯擊中問題正確的頭 - 我選中的是「Win32異常」複選框&內存訪問錯誤,出現了這行代碼:

CopyMemory(pBitmapBits, pTempBits, pBitmapInfo->bmiHeader.biSizeImage); 

圖像是否過大?我會繼續調查,但歡迎任何建議。

+1

你不應該等到'WM_CREATE'使用該窗口之後嗎? – chris

+0

該函數只是將資源加載到內存中。 GamePaint()是將它們粘貼到窗口的那個,並在程序的後面調用。 – KongMD

+0

它用你的窗口作爲參數調用'GetDC'。我會想象那需要一個完成的窗口。檢查'hDC'以確保它不爲空。 – chris

回答

3

不要使用WM_CREATE消息來初始化您的遊戲。在64位操作系統上運行32位代碼時,如果在消息處理代碼中引發SEH異常(如訪問衝突)時被吞下,則存在非常特殊的問題。 WM_CREATE是展示問題的消息之一。在this answer中有關於此行爲的大量詳細信息,儘管它對Winforms非常具體。然而,當你用C或C++編寫代碼時,存在完全相同的問題。

有沒有(通常)任何需要使用WM_CREATE來初始化的東西,你也可以在CreateWindowsEx()調用後移動它,因爲你應該只需要窗口句柄。現在調試器會再次提供幫助,並向您顯示代碼崩潰的位置。

如果你確實需要它在WM_CREATE中,然後使用Debug + Exceptions進行調試,請勾選Win32異常的Thrown複選框。也是驗證這個答案是否準確的方法。

1

就像我現在調用GetDC之後,你必須調用ReleaseDC。 但是你做了三次GetDC調用。 留下一個電話,存儲HDC並在最後釋放它。

+0

+1,無論OP嘗試做什麼,甚至在WM_CREATE處理程序中都允許,這個答案對於正確的DC管理至關重要。 – WhozCraig