ポーズ画面

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ヨシタケ

ポーズ画面

#1

投稿記事 by ヨシタケ » 12年前

たいていのゲームにあるだろポーズ画面をつくろうと思っています。
以前はたしかポーズ画面のフラグの変数を使って

コード:

if(ポーズ画面のフラグ == FALSE){
//バーの計算の関数
//ボールの計算の関数
//必殺技の計算の関数
//各ステージの計算の関数
}
というようにポーズ画面のフラグがTRUEのとき各計算を止めるようにしていますた(ポーズ画面があったときの
ソース消してしまったため、かなりうろ覚えです。)
たしかそのときBGM・SEを止めるためにStopSoundMemを使ってなかたので,BGM,SE流れたままでした。
BGMのほうは変数mainbgmのみでステージが変わるごとにmainbgmの中身を変えるようにしているだけなので
ポーズ画面からゲーム画面にもどる時にPlaySoundMem(mainbgm,DX_PLAYTYPE_LOOP);とすれば良いのですが,
SEのほうは複数のSEが同時に再生こともあるため,ひとつだけ使うというわけにも行かず,int seall[20]というように
して複数のSEを読み込むようにしています。
ポーズ画面にいくときには、すべてのSEを止めるようにすればよいのですが,ポーズ画面を終了するとき上記の
コードのやり方だと特定のSEを再生する必要があります。
ポーズ画面のつくり方について良い方法知ってる方教えてください。お願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズ画面

#2

投稿記事 by softya(ソフト屋) » 12年前

SEを管理するモジュール/クラスを作ってポーズ時は、SEもポーズさせれば良いんじゃないでしょうか?
管理するモジュール/クラスに対してSEを鳴らす関数を呼び出す時にポーズ対象か対象じゃないかって種別が必要かとおもいます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヨシタケ

Re: ポーズ画面

#3

投稿記事 by ヨシタケ » 12年前

DXライブラリに音声が再生中かどうか調べる関数がありことに気づいていませんでした。
とりあえず,

コード:

static int saveseall[20];//再生中のSEを保存する変数
//-------------------------------------
//	関数名: void GameMainUpData()
//	処理:	 ゲーム画面での計算
//-------------------------------------
void GameMainUpData(){
//ポーズ画面かどうかのフラグ
		if(CheckStatePad(configpad.pause)%30==1){
			for(int i=0;i<20;i++){
//SEが再生中のときsavese[i]を1にする
				if(CheckSoundMem(seall[i])==1){
					savese[i] = 1;
				}
				StopSoundMem(seall[i]);
			}
			pauseflag = TRUE;
		}
	}else{
		if(CheckStatePad(configpad.back)%30==1){
			for(int i=0;i<20;i++){
//savese[i]が1のときseall[i]のSEを再生
				if(savese[i] == 1){
					PlaySoundMem(seall[i],DX_PLAYTYPE_BACK);
					savese[i] = 0;
				}
			}
			pauseflag = FALSE;
		}
	}
というようにしてみました。
ただ,SEにはDX_PLAYTYPE_BACKとDX_PLAYTYPE_LOOPの2つをつかっているのですが,これはどのようにて
調べるようにすれば良いのですか?または,どちらか1つにしたほうがようのでしょうか?
あと,例えば敵(enemy01)は攻撃の瞬間だけ再生されるように

コード:

	//弾の計算
	if(shot.flag == TRUE){
		//弾の初期位置の取得
		if(shot.cnt == 0){
			PlaySoundMem(seall[12],DX_PLAYTYPE_BACK);
			shot.x = ene.x + 25; shot.y = ene.y + 10;
		}
		shot.cnt++;
	}
というようにしているのですが,攻撃後少し経ってからポーズフラグ→ポーズフラグ解除
で再生中と判断され,再生されてしまいます。DX_PLAYTYPE_BACKでもStopSoundMemは必要ですか?


今回の件には,あまり関係ないのですが,CheckStatePadといったキーorパッド入力はひとつのソースに
まとめて書き込むべきですか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズ画面

#4

投稿記事 by softya(ソフト屋) » 12年前

上に書いたようにSEの管理モジュールを作成すべきだと思います。
つまり、再生からポーズから、すべてを管理する関数群をまとめたcppファイルです。
再生時のパラメータを記録しておけばよいで、DX_PLAYTYPE_BACKとDX_PLAYTYPE_LOOPの区別は当然記録します。
これで、全て制御できると思いますが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヨシタケ

Re: ポーズ画面

#5

投稿記事 by ヨシタケ » 12年前

まだ,前のsoftyaさんのアドバイスを頂いてどのような関数を書けばいいのか考えている最中ですが,
別の問題が見つかったので質問させていただきます。

基本,音楽聴きながら作業しているため,SEと違ってBGMは音量0にしていたため今まで気づきませんでした。

PlaySoundMemで流している音声を一度StopSoundMemで止めてからもう一度流すと
また最初からになってしまうことに気づきました。
止めたところからもう一度再生するにはどうすればよいのでしょうか。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズ画面

#6

投稿記事 by softya(ソフト屋) » 12年前

リファレンスを御覧ください。
「DXライブラリ置き場 リファレンスページ PlaySoundMem」
http://homepage2.nifty.com/natupaji/DxL ... .html#R8N5
お望みの機能が書かれています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヨシタケ

Re: ポーズ画面

#7

投稿記事 by ヨシタケ » 12年前

今のプログラムだと複雑すぎて考えづらいと思い,
別のプログラムを作って試してみました。
ソースは
main.cpp

コード:

#include "main.h"
int Key[256]; // キーが押されているフレーム数を
 //キーの入力状態を更新する
int gpUpdateKey(){
        char tmpKey[256]; // 現在のキーの入力状態を格納する
        GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
        for( int i=0; i<256; i++ ){ 
                if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
                        Key[i]++;     // 加算
                } else {              // 押されていなければ
                        Key[i] = 0;   // 0にする
                }
        }
        return 0;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
		bool pauseflag = FALSE;
		int mainbgm;
		mainbgm = LoadSoundMem("サウンド/stage03.ogg");
		SoundIni();
        // while(裏画面を表画面に反映, メッセージ処理, 画面クリア)
        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0 && gpUpdateKey()==0 ){
			if(pauseflag == FALSE){
				//TestIni(&mainbgm,seall);
				TestIni(mainbgm);
				if( Key[KEY_INPUT_Z] >= 1 ){ // 右キーが押された瞬間なら
					StopSoundMem(mainbgm);
					StopSESound();
                    pauseflag = TRUE;
                }

			}else if(pauseflag == TRUE){
				if( Key[KEY_INPUT_X] >= 1 ){ // 右キーが押された瞬間なら
					PlaySoundMem(mainbgm,DX_PLAYTYPE_LOOP,FALSE);
					PlaySESound(0,DX_PLAYTYPE_LOOP,pauseflag);
                    pauseflag = FALSE;
                }
			}
        }

        DxLib_End(); // DXライブラリ終了処理
        return 0;
} 
test1.cpp

コード:

#include "main.h"

void TestIni(int bgm){
	static int cnt1 = 0;
	if(cnt1 == 0)
		PlaySoundMem(bgm,DX_PLAYTYPE_LOOP);
	//1つ目のSEを鳴らす
	if(cnt1 == 60)
		PlaySESound(0,DX_PLAYTYPE_BACK,FALSE);
	
	//2つ目のSEを鳴らす
	if(cnt1 == 120)
		PlaySESound(1,DX_PLAYTYPE_BACK,FALSE);
	cnt1++;
	if(cnt1 == 150)
		cnt1 = 10;
}
test2.cpp

コード:

#include "main.h"

static int seall[20];		//SEのデータ
static bool playseflag[20];//再生中かどうかのフラグ
static int savese[20];		//再生中のSEの保存
static int savesetype[20];	//再生中のSEの再生タイプを保存
//SEの初期化
void SoundIni(){
    seall[0] = LoadSoundMem("サウンド/1up.wav"); // サウンド/1up.wavをロードし、識別番号をHandleに格納
	seall[1] = LoadSoundMem("サウンド/ghostvoice.ogg");
}
//SEの再生
void PlaySESound(int num,int type,bool flag){
	if(flag == FALSE){

		savese[num] = seall[num];
		savesetype[num] = type;
	
		PlaySoundMem(seall[num],type,FALSE);
	}else{
		for(int i=0;i<20;i++){
			if(playseflag[i]== TRUE)
				PlaySoundMem(savese[i],savesetype[i],FALSE);
		}
	}
}
//SEの停止
void StopSESound(){
	for(int i=0;i<20;i++){
		if(CheckSoundMem(seall[i]) == 1){
			playseflag[i] = TRUE;
		}
		StopSoundMem(seall[i]);
	}
}
というようにしてあります。停止→再生ではとくに問題なかったと思います。
ただ,cnt1が150のとき2つ目のSEを再生するようにしているのですが,なぜか2ループ中に1回しか再生しませんでした。
あと,停止→再生時の音の再生ですがPlaySESound(0,DX_PLAYTYPE_LOOP,pauseflag);とSEの番号,再生タイプは
使わないので適当な値を入れています。普通に再生するときと停止→再生で関数を分けたほうがよいでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズ画面

#8

投稿記事 by softya(ソフト屋) » 12年前

TopPositionFlag がFALSEだからでは無いでしょうか?
あと出来るだけSESound内にパラメータは隠蔽したほうが良いと思います。
外部からの呼び出しは、Play,Stop,Pause,continueなど明確に分けたほうが使いやすくなると思います。
PlaySESound(0);で鳴らす。
PauseSESoound()でポーズ。
ね?分かりやすいですよね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヨシタケ

Re: ポーズ画面

#9

投稿記事 by ヨシタケ » 12年前

softya(ソフト屋) さんが書きました:TopPositionFlag がFALSEだからでは無いでしょうか?
quote]
TRUEに変更したら直りました。
softya(ソフト屋) さんが書きました: 外部からの呼び出しは、Play,Stop,Pause,continueなど明確に分けたほうが使いやすくなると思います。
quote]
一応,

コード:

//SEの再生
void PlaySESound(int num,int type){

	savese[num] = seall[num];
	savesetype[num] = type;
	
	PlaySoundMem(seall[num],type,TRUE);
}
void ContinueSESound(){
	for(int i=0;i<20;i++){
		if(playseflag[i]== TRUE)
			PlaySoundMem(savese[i],savesetype[i],FALSE);
	}
}

//SEの停止
void StopSESound(){
	for(int i=0;i<20;i++){
		if(CheckSoundMem(seall[i]) == 1)
			playseflag[i] = TRUE;
		else
			playseflag[i] = FALSE;
		StopSoundMem(seall[i]);
	}
}
というように変更しました。
softya(ソフト屋) さんが書きました: あと出来るだけSESound内にパラメータは隠蔽したほうが良いと思います。
void PlaySESound(int num,int type)のint type(再生するタイプ)を関数内で行ったほうがよいということでしょうか?
実際のゲームだとSEによってDX_PLAYTYPE_LOOPとDX_PLAYTYPE_BACKの両方を使うのでこうしました。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: ポーズ画面

#10

投稿記事 by softya(ソフト屋) » 12年前

最低限のパラメータにしたほうが良いです、
出来るだけ減らすことを考えてみてください。
DX_PLAYTYPE_LOOPとDX_PLAYTYPE_BACKもSE毎に決まっているのなら配列で持っても良い気がします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ヨシタケ

Re: ポーズ画面

#11

投稿記事 by ヨシタケ » 12年前

わかりました。
今は特に1つのSEで両方使うというのはないので,そのようにします。
ありがとうございます。

閉鎖

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