ページ 1 / 1
ポーズ画面
Posted: 2013年6月22日(土) 18:59
by ヨシタケ
たいていのゲームにあるだろポーズ画面をつくろうと思っています。
以前はたしかポーズ画面のフラグの変数を使って
コード:
if(ポーズ画面のフラグ == FALSE){
//バーの計算の関数
//ボールの計算の関数
//必殺技の計算の関数
//各ステージの計算の関数
}
というようにポーズ画面のフラグがTRUEのとき各計算を止めるようにしていますた(ポーズ画面があったときの
ソース消してしまったため、かなりうろ覚えです。)
たしかそのときBGM・SEを止めるためにStopSoundMemを使ってなかたので,BGM,SE流れたままでした。
BGMのほうは変数mainbgmのみでステージが変わるごとにmainbgmの中身を変えるようにしているだけなので
ポーズ画面からゲーム画面にもどる時にPlaySoundMem(mainbgm,DX_PLAYTYPE_LOOP);とすれば良いのですが,
SEのほうは複数のSEが同時に再生こともあるため,ひとつだけ使うというわけにも行かず,int seall[20]というように
して複数のSEを読み込むようにしています。
ポーズ画面にいくときには、すべてのSEを止めるようにすればよいのですが,ポーズ画面を終了するとき上記の
コードのやり方だと特定のSEを再生する必要があります。
ポーズ画面のつくり方について良い方法知ってる方教えてください。お願いします。
Re: ポーズ画面
Posted: 2013年6月22日(土) 21:09
by softya(ソフト屋)
SEを管理するモジュール/クラスを作ってポーズ時は、SEもポーズさせれば良いんじゃないでしょうか?
管理するモジュール/クラスに対してSEを鳴らす関数を呼び出す時にポーズ対象か対象じゃないかって種別が必要かとおもいます。
Re: ポーズ画面
Posted: 2013年6月23日(日) 14:53
by ヨシタケ
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パッド入力はひとつのソースに
まとめて書き込むべきですか。
Re: ポーズ画面
Posted: 2013年6月23日(日) 18:38
by softya(ソフト屋)
上に書いたようにSEの管理モジュールを作成すべきだと思います。
つまり、再生からポーズから、すべてを管理する関数群をまとめたcppファイルです。
再生時のパラメータを記録しておけばよいで、DX_PLAYTYPE_BACKとDX_PLAYTYPE_LOOPの区別は当然記録します。
これで、全て制御できると思いますが。
Re: ポーズ画面
Posted: 2013年6月24日(月) 20:06
by ヨシタケ
まだ,前のsoftyaさんのアドバイスを頂いてどのような関数を書けばいいのか考えている最中ですが,
別の問題が見つかったので質問させていただきます。
基本,音楽聴きながら作業しているため,SEと違ってBGMは音量0にしていたため今まで気づきませんでした。
PlaySoundMemで流している音声を一度StopSoundMemで止めてからもう一度流すと
また最初からになってしまうことに気づきました。
止めたところからもう一度再生するにはどうすればよいのでしょうか。
Re: ポーズ画面
Posted: 2013年6月24日(月) 20:27
by softya(ソフト屋)
リファレンスを御覧ください。
「DXライブラリ置き場 リファレンスページ PlaySoundMem」
http://homepage2.nifty.com/natupaji/DxL ... .html#R8N5
お望みの機能が書かれています。
Re: ポーズ画面
Posted: 2013年6月29日(土) 14:34
by ヨシタケ
今のプログラムだと複雑すぎて考えづらいと思い,
別のプログラムを作って試してみました。
ソースは
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の番号,再生タイプは
使わないので適当な値を入れています。普通に再生するときと停止→再生で関数を分けたほうがよいでしょうか?
Re: ポーズ画面
Posted: 2013年6月29日(土) 21:31
by softya(ソフト屋)
TopPositionFlag がFALSEだからでは無いでしょうか?
あと出来るだけSESound内にパラメータは隠蔽したほうが良いと思います。
外部からの呼び出しは、Play,Stop,Pause,continueなど明確に分けたほうが使いやすくなると思います。
PlaySESound(0);で鳴らす。
PauseSESoound()でポーズ。
ね?分かりやすいですよね。
Re: ポーズ画面
Posted: 2013年6月30日(日) 01:06
by ヨシタケ
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の両方を使うのでこうしました。
Re: ポーズ画面
Posted: 2013年6月30日(日) 08:49
by softya(ソフト屋)
最低限のパラメータにしたほうが良いです、
出来るだけ減らすことを考えてみてください。
DX_PLAYTYPE_LOOPとDX_PLAYTYPE_BACKもSE毎に決まっているのなら配列で持っても良い気がします。
Re: ポーズ画面
Posted: 2013年6月30日(日) 09:18
by ヨシタケ
わかりました。
今は特に1つのSEで両方使うというのはないので,そのようにします。
ありがとうございます。