プロが教える店舗&オフィスのセキュリティ対策術

いつもお世話になっております。

今アクションゲームの基盤となる簡単な動きをさせるプログラムを作成したのですが、なぜだか時間が経つと止まるという不思議な現象に陥っています。

プログラムの内容はジャンプや移動をするだけの単純なもので、描画やキャラの移動はスレッドで個別に行っています。
キャラが止まったとき、FPSは動いていたので、描画の方のスレッドにたぶん問題はないと思っています。

キャラが止まると同時にゲーム自体もおかしくなってしまうのですが、それはキャラ動作のスレッドが異常によって止まってしまったからなのでしょうか?
解決法のわかる方、すみませんがご指導お願いいたします。

以下に問題のあると思われるスレッドを貼ります。
描画やプロシージャに問題があると思われる方がいましたら補足で追加いたします。


/*************** キャラクターを動かす ****************/

DWORD WINAPI CharacterMove(LPVOID vdParam) {
 HDC hdc;
 RECT rect;
 ThreadParam * param;
 HRGN hit = CreateRectRgn(0, 0, 0, 0);

 int JUMP = 0;
 int DBJUMP = 0;
 int position = 0;
 int flag = 0;

 param = (ThreadParam *)vdParam;
 GetClientRect(param->owner, &rect);


 while(TRUE){

  /* 左移動 */
  if(character.x > rect.left + 5){
   if(GetAsyncKeyState(37)){
    if(CombineRgn(
          hit,
          CreateEllipticRgn(character.x - 12, character.y, character.x - 12 + 25, character.y + 25),
          S_RGN, RGN_AND) == NULLREGION){

     character.x -= 12;
    }
   }
  }

  /* 右移動 */
  if(character.x + 25 < rect.right - 5){
   if(GetAsyncKeyState(39)){
    if(CombineRgn(
          hit,
          CreateEllipticRgn(character.x + 12, character.y, character.x + 12 + 25, character.y + 25),
          S_RGN, RGN_AND) == NULLREGION){

     character.x += 12;
    }
   }
  }

  /*** ジャンプ ***/
  if(CombineRgn(
        hit,
        CreateEllipticRgn(character.x, character.y + 1, character.x + 25, character.y + 1 + 25),
        S_RGN, RGN_AND) != NULLREGION){

   if(GetAsyncKeyState(38)){
    JUMP = 32;
   }
  }

  /***** ジャンプ時・落下時 *****/
  if(CombineRgn(
        hit,
        CreateEllipticRgn(character.x, character.y + 1, character.x + 25, character.y + 1 + 25),
        S_RGN, RGN_AND) == NULLREGION || JUMP == 32){


   /*** 一度キーを離さないと2段ジャンプは成立しない ***/
   if(!GetAsyncKeyState(38)){
    flag = 1;
   }

   /*** 2段ジャンプ ***/
   if(GetAsyncKeyState(38) && flag == 1 && DBJUMP < 1){
    JUMP = 26;
    DBJUMP++;
   }

   /*** 慣性 ***/
   if(CombineRgn(
         hit,
         CreateEllipticRgn(character.x, character.y - JUMP, character.x + 25, character.y - JUMP + 25),
         S_RGN, RGN_AND) != NULLREGION){

    flag = 0;
    DBJUMP = 0;

    if(JUMP < 0){
     while(CombineRgn(
            hit,
            CreateEllipticRgn(character.x, character.y + 1, character.x + 25, character.y + 1 + 25),
            S_RGN, RGN_AND) == NULLREGION){

      character.y++;
     }
    }else{
     while(CombineRgn(
            hit,
            CreateEllipticRgn(character.x, character.y -1, character.x + 25, character.y + 1 + 25),
            S_RGN, RGN_AND) == NULLREGION){

      character.y--;
     }
    }

    JUMP = 0;

   }else{
    character.y -= JUMP;
   }

   /* 最大落下速度 */
   if(JUMP > -20){
    JUMP -= 3;
   }
  }

  Sleep(16);

 }

 DeleteObject(hit);
 ReleaseDC(param->owner, hdc);

 return TRUE;
}

A 回答 (2件)

 こんにちは。



 リソースリークしているからではないでしょうか・・・。
 一箇所だけではなく、沢山有ります。

if(CombineRgn(hit,
       CreateEllipticRgn(character.x - 12, character.y, character.x - 12 + 25, character.y + 25),//ココ
       S_RGN, RGN_AND) == NULLREGION)
{
character.x -= 12;
}

↓---------------------------------------------------------------------------------------------------------

//後始末しないといけません。
HRGN hRgn = CreateEllipticRgn(character.x - 12, character.y, character.x - 12 + 25, character.y + 25);
if(CombineRgn(hit, hRgn,S_RGN, RGN_AND) == NULLREGION)
{
character.x -= 12;
}

::DeleteObject(hRgn);

この回答への補足

お早いご回答ありがとうございます。

毎回上書きして最後にWM_DESTOROYメッセージが出た時にまとめてDeleteしているので大丈夫だと思います。
文字数の関係ですべてのプログラムが書けないので情報が少ないですね・・・すみません。

以下がプロシージャの記述です。

LRESULT CALLBACK WindowProc(
 HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){

 HDC hdc;
 PAINTSTRUCT ps;
 static ThreadParam param;
 static HBITMAP hBitmap;
 DWORD dwID;
 RECT rect;

 switch(uMsg){

  case WM_DESTROY:
   postQuitMessage(0);
   DeleteObject(S_RGN);
   DeleteObject(C_RGN);
   DeleteDC(param.hScreenDC);
   return 0;
  case WM_CREATE:
   param.size.cx = 1000;
   param.size.cy = 600;
   param.owner = hWnd;
   param.dwFps = 60;
   hdc = GetDC(hWnd);
   hBitmap = CreateCompatibleBitmap(hdc, param.size.cx, param.size.cy);
   param.hScreenDC = CreateCompatibleDC(hdc);
   SelectObject(param.hScreenDC, hBitmap);
   SelectObject(param.hScreenDC, GetStockObject(WHITE_PEN));
   SelectObject(param.hScreenDC, GetStockObjec(WHITE_BRUSH));
   SelectObject(param.hScreenDC, GetStockObjec(SYSTEM_FONT));
   SetTextColor(param.hScreenDC, RGB(0, 0, 0));
   SetBkMode(param.hScreenDC, TRANSPARENT);

   ReleaseDC(hWnd,hdc);

   CreateThread(NULL, 0, PICTURE_FUNC, (LPVOID)¶m, 0, &dwID);
   CreateThread(NULL, 0, CharacterMove, (LPVOID)¶m, 0, &dwID);

   return 0;
  }
 return DefWindowProc(hWnd, uMsg, wParam, lParam);

}

補足日時:2008/11/30 11:29
    • good
    • 0
この回答へのお礼

あ、もしかしてif文の判定条件で生成してるリージョンでしょうか?
条件文の中で作成してるので忘れてました・・・

ということは判定の前に作成して、それを判定後削除、という形を取らなければいけないのでしょうか?

お礼日時:2008/11/30 11:58

★アドバイス


>あ、もしかしてif文の判定条件で生成してるリージョンでしょうか?
 ↑
 はい。その通りです。
>ということは判定の前に作成して、それを判定後削除、という形を取らなければいけないのでしょうか?
 ↑
 はい。その通りです。
・回答者 No.1 さんのアドバイスが最も適切な回答となります。
 できれば CreateEllipticRgn 関数でも戻り値でエラーをチェックすべきです。
 めったにエラーが起こらないとは思いますが、CombineRgn でエラーチェックしているなら
 一緒にエラーチェックした方が好ましいです。念のために。
 また、エラーで CombineRgn の hit が作られなかったときを考えて
 当たり判定なども修正する必要があると思います。
・またスレッドの終了条件が見つかりませんが大丈夫でしょうか。
 『while(TRUE)』のため次の2行は処理されない気がします。
>DeleteObject(hit);
>ReleaseDC(param->owner, hdc);
 ↑
 文字数の関係で記述を省略しているなら良いですが。
 どうなんでしょうか?
    • good
    • 0
この回答へのお礼

ネットにつなげられなかったためにお礼が大分遅くなってしまいました、すみません。

おかげ様で解決することができました。
while(TRUE)は条件を一時ループにしているだけなので問題ないです。

お礼日時:2008/12/07 00:50

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!