ポーズ画面
-
ヨシタケ
ポーズ画面
たいていのゲームにあるだろポーズ画面をつくろうと思っています。
以前はたしかポーズ画面のフラグの変数を使って というようにポーズ画面のフラグがTRUEのとき各計算を止めるようにしていますた(ポーズ画面があったときの
ソース消してしまったため、かなりうろ覚えです。)
たしかそのときBGM・SEを止めるためにStopSoundMemを使ってなかたので,BGM,SE流れたままでした。
BGMのほうは変数mainbgmのみでステージが変わるごとにmainbgmの中身を変えるようにしているだけなので
ポーズ画面からゲーム画面にもどる時にPlaySoundMem(mainbgm,DX_PLAYTYPE_LOOP);とすれば良いのですが,
SEのほうは複数のSEが同時に再生こともあるため,ひとつだけ使うというわけにも行かず,int seall[20]というように
して複数のSEを読み込むようにしています。
ポーズ画面にいくときには、すべてのSEを止めるようにすればよいのですが,ポーズ画面を終了するとき上記の
コードのやり方だと特定のSEを再生する必要があります。
ポーズ画面のつくり方について良い方法知ってる方教えてください。お願いします。
以前はたしかポーズ画面のフラグの変数を使って というようにポーズ画面のフラグが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: ポーズ画面
SEを管理するモジュール/クラスを作ってポーズ時は、SEもポーズさせれば良いんじゃないでしょうか?
管理するモジュール/クラスに対してSEを鳴らす関数を呼び出す時にポーズ対象か対象じゃないかって種別が必要かとおもいます。
管理するモジュール/クラスに対してSEを鳴らす関数を呼び出す時にポーズ対象か対象じゃないかって種別が必要かとおもいます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
-
ヨシタケ
Re: ポーズ画面
DXライブラリに音声が再生中かどうか調べる関数がありことに気づいていませんでした。
とりあえず,
というようにしてみました。
ただ,SEにはDX_PLAYTYPE_BACKとDX_PLAYTYPE_LOOPの2つをつかっているのですが,これはどのようにて
調べるようにすれば良いのですか?または,どちらか1つにしたほうがようのでしょうか?
あと,例えば敵(enemy01)は攻撃の瞬間だけ再生されるように
というようにしているのですが,攻撃後少し経ってからポーズフラグ→ポーズフラグ解除
で再生中と判断され,再生されてしまいます。DX_PLAYTYPE_BACKでもStopSoundMemは必要ですか?
今回の件には,あまり関係ないのですが,CheckStatePadといったキーorパッド入力はひとつのソースに
まとめて書き込むべきですか。
とりあえず,
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: ポーズ画面
上に書いたようにSEの管理モジュールを作成すべきだと思います。
つまり、再生からポーズから、すべてを管理する関数群をまとめたcppファイルです。
再生時のパラメータを記録しておけばよいで、DX_PLAYTYPE_BACKとDX_PLAYTYPE_LOOPの区別は当然記録します。
これで、全て制御できると思いますが。
つまり、再生からポーズから、すべてを管理する関数群をまとめたcppファイルです。
再生時のパラメータを記録しておけばよいで、DX_PLAYTYPE_BACKとDX_PLAYTYPE_LOOPの区別は当然記録します。
これで、全て制御できると思いますが。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: ポーズ画面
リファレンスを御覧ください。
「DXライブラリ置き場 リファレンスページ PlaySoundMem」
http://homepage2.nifty.com/natupaji/DxL ... .html#R8N5
お望みの機能が書かれています。
「DXライブラリ置き場 リファレンスページ PlaySoundMem」
http://homepage2.nifty.com/natupaji/DxL ... .html#R8N5
お望みの機能が書かれています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
-
ヨシタケ
Re: ポーズ画面
今のプログラムだと複雑すぎて考えづらいと思い,
別のプログラムを作って試してみました。
ソースは
main.cpp
test1.cpp
test2.cpp
というようにしてあります。停止→再生ではとくに問題なかったと思います。
ただ,cnt1が150のとき2つ目のSEを再生するようにしているのですが,なぜか2ループ中に1回しか再生しませんでした。
あと,停止→再生時の音の再生ですがPlaySESound(0,DX_PLAYTYPE_LOOP,pauseflag);とSEの番号,再生タイプは
使わないので適当な値を入れています。普通に再生するときと停止→再生で関数を分けたほうがよいでしょうか?
別のプログラムを作って試してみました。
ソースは
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;
}
#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;
}
#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: ポーズ画面
TopPositionFlag がFALSEだからでは無いでしょうか?
あと出来るだけSESound内にパラメータは隠蔽したほうが良いと思います。
外部からの呼び出しは、Play,Stop,Pause,continueなど明確に分けたほうが使いやすくなると思います。
PlaySESound(0);で鳴らす。
PauseSESoound()でポーズ。
ね?分かりやすいですよね。
あと出来るだけSESound内にパラメータは隠蔽したほうが良いと思います。
外部からの呼び出しは、Play,Stop,Pause,continueなど明確に分けたほうが使いやすくなると思います。
PlaySESound(0);で鳴らす。
PauseSESoound()でポーズ。
ね?分かりやすいですよね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。
-
ヨシタケ
Re: ポーズ画面
void PlaySESound(int num,int type)のint type(再生するタイプ)を関数内で行ったほうがよいということでしょうか?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内にパラメータは隠蔽したほうが良いと思います。
実際のゲームだとSEによってDX_PLAYTYPE_LOOPとDX_PLAYTYPE_BACKの両方を使うのでこうしました。
- softya(ソフト屋)
- 副管理人
- 記事: 11677
- 登録日時: 15年前
- 住所: 東海地方
- 連絡を取る:
Re: ポーズ画面
最低限のパラメータにしたほうが良いです、
出来るだけ減らすことを考えてみてください。
DX_PLAYTYPE_LOOPとDX_PLAYTYPE_BACKもSE毎に決まっているのなら配列で持っても良い気がします。
出来るだけ減らすことを考えてみてください。
DX_PLAYTYPE_LOOPとDX_PLAYTYPE_BACKもSE毎に決まっているのなら配列で持っても良い気がします。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。