ゲームのロード画面について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
No_eru
記事: 6
登録日時: 8年前

ゲームのロード画面について

#1

投稿記事 by No_eru » 8年前

初めて質問させていただきます。
自分は今、ゲームのロード画面を作っているのですが、そこで少し困ったことになりました。
マルチスレッドを利用して、
『画像やサウンドの読み込み』をスレッドで、『NowLoading』を表示させアニメーションさせる処理をメイン関数に書いているのですが、
読み込みのスレッドが終わった瞬間に一緒にアプリケーションまで閉じてしまいます。どうすればいいのでしょうか

コードは以下の通りです

コード:

/*always.h*/
#ifndef DEF_ALWAYS
#define DEF_ALWAYS

#include "DxLib.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <direct.h>
#include <shlwapi.h>
#include <windows.h>
#include <process.h>
#pragma comment(lib,"shlwapi.lib")

#define PI 3.141592
#define PI2 6.283184

int KeyUpdate(int DebugFlag=FALSE);
int KeyInput(int KeyCode);
int ProcessLoop(int DebugFlag=FALSE);
int Initialize(char *Title="DxLib",int FullScFlag=TRUE,float extend=1.0,int OutLog=FALSE,int SysComOff=TRUE,int UsePMA=FALSE,int AlwaysRun=FALSE);
int MakeGraphAlpha(int x,int y,int GHan,int Alpha=255,double extend=1.0f,double angle=0);
int MakeGraphAdd(int x,int y,int GHan,int Add=255,double extend=1.0f,double angle=0);
int MakeGraphInv(int x,int y,int GHan,int Inv=255,double extend=1.0f,double angle=0);
int MakeGraphAlpha2(int x,int y,int GHan,int Alpha=255);
int MakeGraphAdd2(int x,int y,int GHan,int Add=255);
int MakeGraphInv2(int x,int y,int GHan,int Inv=255);
int randam(int min=0,int max=RAND_MAX);
int ScreenShot(int =KEY_INPUT_S);
float randam2(float min=0.0f,float max=1.0f);
float DegToRad(int Deg);
void FPSUpdate();
//float GetFPS();
int GetIntFps();
void FPSDraw(int x=570,int y=465);
void FPSWait();

void PlayerMove(float *x,float *y,float speed,int maxx,int minx,int maxy,int miny);
void AngleInput(float *x,float *y,float angle,float speed);
float GetPlayer(float ex,float ey,float px,float py);
int HitAnalize(float ex,float ey,float erange,float px,float py,float prange);

#endif


コード:


#include "always.h"

char gametitle[64];
float ver=0.0;//バージョン

//列挙体
typedef enum {
  begin,
  start,
  menu,
  modeselect,
  game,
  option,
  manual,
  ranking,
  end,
}SCENE_t;

SCENE_t scene1=begin;

int TIME;//ゲーム内時間

//メニュー
bool menu_loadcompflag=false;
int menu_IOFlag=0;

int menu_SelectNum=0;
int menu_back2X;

float menu_title_logo_extend=10;
int menu_title_logo_pal=0;

int menu_back1,menu_back2,menu_back3;//背景
int menu_backpal;//背景の透明、加算度
int menu_title_logo;//タイトルロゴ
typedef struct {
  int x,y;
  int pal;
  int menu_selection;
}SELECT_MENU_t;

SELECT_MENU_t menu_select[5];

void menu_init(void* arg)
{
  static char addressstr[128];
  //画像の読み込みとか
  menu_back1=LoadGraph("./data/graph/back/back1.png");
  menu_back2=LoadGraph("./data/graph/back/back2.png");
  menu_back3=LoadGraph("./data/graph/back/back3.png");
  menu_title_logo=LoadGraph("./data/graph/logo/TitleLogo.png");
  menu_backpal=0;
  menu_SelectNum=0;
  menu_IOFlag=0;
  menu_back2X=320;
  menu_title_logo_extend=10;
  menu_title_logo_pal=0;
  for(int i=0;i<5;i++)
  {
    sprintf(addressstr,"./data/graph/logo/menu_select%d.png",i);
    menu_select[i].menu_selection=LoadGraph(addressstr);

    //読み込み
    menu_select[i].x=50+randam(randam(-15,-5),randam(5,15));
    menu_select[i].y=140+(i*60);
    menu_select[i].pal=128;
  }
  menu_select[0].pal=255;

  menu_loadcompflag=true;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
  Initialize("読み込み中...",TRUE);

  sprintf(gametitle,"迷路 ver%.1f",ver);
  int cc=0;
  int announce=LoadSoundMem("./data/se/begin.wav");
  int circle_logo=LoadGraph("./data/graph/logo/CircleLogo.png");
  int load_logo=LoadGraph("./data/graph/logo/Load.png");
  SetWindowText(gametitle);

  while(ProcessLoop()==0)
  {
    if(scene1==begin)
    {
      DrawRotaGraph(320,240,0.5,0,circle_logo,TRUE);
      cc++;
      if(cc==2)PlaySoundMem(announce,DX_PLAYTYPE_BACK);
      if(cc==300)scene1=start;
    }

    if(scene1==start)
    {
      //更新
      _beginthread(menu_init,0,NULL);//ここで一緒にメイン関数まで抜けている?
      MakeGraphAlpha2(0,402,load_logo,180+sin(PI/2/20*TIME)*80);//画像を透明度付きで描写する関数です。気にしないでください
      DrawRotaGraph(320,240,0.5,0,circle_logo,TRUE);
      if(menu_loadcompflag==true)scene1=menu;
    }

    if(scene1==menu)
    {
      /*省略させていただきます*/
    }

    if(scene1==modeselect)
    {
      /*省略させていただきます*/
    }

    if(scene1==end)break;

    TIME++;
  }

  DxLib_End();
  return 0;
}

開発環境
OS:Windows 8.1
コンパイラ:borland C++ 5.5.1
ライブラリ:Dxライブラリ

あんどーなつ
記事: 171
登録日時: 8年前
連絡を取る:

Re: ゲームのロード画面について

#2

投稿記事 by あんどーなつ » 8年前

_beginthreadのMSDNヘルプのコード例2にWaitForSingleObjectでスレッドの終了を待つやり方が書いてあります。

https://msdn.microsoft.com/ja-jp/library/kdzttdcb.aspx

No_eru
記事: 6
登録日時: 8年前

Re: ゲームのロード画面について

#3

投稿記事 by No_eru » 8年前

>>あんどーなつさん

スレッド終了を待って、次の処理を書くということでよいのでしょうか?

hide

Re: ゲームのロード画面について

#4

投稿記事 by hide » 8年前

安易にマルチスレッドに手を出すと死ぬのでライブラリに任せた方がいいのでは。
http://dxlib.o.oo7.jp/function/dxfunc_other.html#R21N1

derok
記事: 51
登録日時: 12年前

Re: ゲームのロード画面について

#5

投稿記事 by derok » 8年前

hide さんが書きました:安易にマルチスレッドに手を出すと死ぬのでライブラリに任せた方がいいのでは。
http://dxlib.o.oo7.jp/function/dxfunc_other.html#R21N1
そもそもDXライブラリは基本的にスレッドセーフでないようなので、ライブラリの関数に任せないとダメそうですね。
#define DX_THREAD_SAFEしてやればスレッドセーフになるようですが、かなり負荷が高いようですし。

No_eru
記事: 6
登録日時: 8年前

Re: ゲームのロード画面について

#6

投稿記事 by No_eru » 8年前

>>hideさん
>>derokさん
ありがとうございます!やってみますね!
皆様、アドバイスありがとうございました!!

No_eru
記事: 6
登録日時: 8年前

Re: ゲームのロード画面について

#7

投稿記事 by No_eru » 8年前

コード:


void menu_init()
{
  static char addressstr[128];
  //画像の読み込みとか
  SetUseASyncLoadFlag(TRUE);
  DrawFormatString(0,0,0,"読み込み:%d",GetASyncLoadNum());
  menu_back1=LoadGraph("./data/graph/back/back1.png");
  menu_back2=LoadGraph("./data/graph/back/back2.png");
  menu_back3=LoadGraph("./data/graph/back/back3.png");
  menu_title_logo=LoadGraph("./data/graph/logo/TitleLogo.png");
  for(int i=0;i<5;i++)
  {
    sprintf(addressstr,"./data/graph/logo/menu_select%d.png",i);
    menu_select[i].menu_selection=LoadGraph(addressstr);

  }
  SetUseASyncLoadFlag(FALSE);
  menu_backpal=0;
  menu_SelectNum=0;
  menu_IOFlag=0;
  menu_back2X=320;
  menu_title_logo_extend=10;
  menu_title_logo_pal=0;
  for(int i=0;i<5;i++)
  {
    //読み込み
    menu_select[i].x=50+randam(randam(-15,-5),randam(5,15));
    menu_select[i].y=140+(i*60);
    menu_select[i].pal=128;
  }
  menu_select[0].pal=255;
  if(GetASyncLoadNum()==0)
  {
    menu_loadcompflag=true;
  }
}

関数をこのようにしてみたのですが、いつまで経っても次に進みません。
どうすればよいでしょうか?

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: ゲームのロード画面について

#8

投稿記事 by みけCAT » 8年前

No_eru さんが書きました:関数をこのようにしてみたのですが、いつまで経っても次に進みません。
どうすればよいでしょうか?
まず、この関数をどのように呼び出しているかを開示するべきだと思います。

そして、おそらくメインループでGetASyncLoadNum()をポーリングするべきである気がします。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

No_eru
記事: 6
登録日時: 8年前

Re: ゲームのロード画面について

#9

投稿記事 by No_eru » 8年前

>>みけCATさん

この関数はメインループの中で呼び出しています。
すみません、最初に提示したコードに書いてあるので、大丈夫と思ったのですが、わかりにくかったようですね。本当に申し訳ありません。
なので、GetASyncLoadNum()はメインループの中で実行していると思うのですが、それではダメなのでしょうか

No_eru
記事: 6
登録日時: 8年前

Re: ゲームのロード画面について

#10

投稿記事 by No_eru » 8年前

いろいろ試してみた結果、どうやら非同期処理を毎フレーム行っていたことが原因だったようです!
読み込み終了時にフラグを立てたところ、うまいこと動いてくれました。
皆様方、本当にありがとうございました!

閉鎖

“C言語何でも質問掲示板” へ戻る