1

ビットマップの 1 つ (スプライトシート) でこの奇妙な問題が発生しています。私のゲームは完璧に動作しますが、次のコード行のコメントを外すと、ビットマップとスプライトを初期化する 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 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);

画像が大きすぎませんか?引き続き調査していきますが、何かアドバイスがあればよろしくお願いします。

4

2 に答える 2

3

ゲームの初期化に WM_CREATE メッセージを使用しないでください。64 ビット オペレーティング システムで 32 ビット コードを実行すると、メッセージ処理コードで発生した SEH 例外 (アクセス違反など) が飲み込まれる可能性があるという非常に特殊な問題があります。WM_CREATE は、問題を示すメッセージの 1 つです。Winformsに非常に固有のものですが、この回答のこの動作に関する多くの詳細。ただし、C または C++ でコードを記述する場合も、まったく同じ問題が存在します。

(通常) WM_CREATE を使用して初期化する必要はありません。ウィンドウ ハンドルのみが必要なため、CreateWindowsEx() 呼び出しの後に移動することもできます。デバッガーが再び役立つようになり、コードがクラッシュする場所が表示されます。

WM_CREATE で本当に必要な場合は、Debug + Exceptions を使用してデバッグし、Win32 例外の Thrown チェックボックスをオンにします。また、この回答が正確であることを確認する方法。

于 2012-12-15T20:16:19.537 に答える
1

GetDC を呼び出した後、ReleaseDC を呼び出す必要があります。ただし、GetDC 呼び出しを 3 回行います。通話を 1 つ残して、HDC を保存し、最後に解放します。

于 2012-12-15T20:02:04.257 に答える