【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

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

【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

#1

投稿記事 by かけだしプログラマー » 13年前

先日質問した内容に答えてくださったお二人ありがとうございました。一通りメニュー・ゲーム画面・リザルト画面などの基本骨格が完成しまして、細かい処理を実装しようとしています。


今回質問します内容はタイトルの通り、メニュー → ステージなどの切り替え持のフェードイン・フェードアウトをアルファブレンディングを利用して実行する関数を実装しようとしています。
過去スレにはすべて目を通し、前に同じような質問のスレを発見しましたが解決に至らないので質問させていただきます。

コード:

//【main_menu】
#include "../include/GV.h"

void menu_control(){
	//選択制御
	if(CheckStatePad(configpad.up) == 1){
		menu.y -= 50;
		menu.num--;
		if(menu.y<0){
			menu.y=100;
			menu.num=2;
		}
	}
	else if(CheckStatePad(configpad.down) == 1){
		menu.y += 50;
		menu.num++;
		if(menu.y>100){
			menu.y=0;
			menu.num=0;
		}
	}
}

~略~

void menu_function(){

		if( CheckStatePad(configpad.shot) == 1 ){
		switch(menu.num)
		{
		case 0:
                        fade_flag=1;//フラグを立てる
			change_scene();//フェード処理
			func_state = 99;   //ゲーム開始
			break;
		case 1:
			func_state = 105;    //クレジット表示
			break;
		case 2:
			DxLib_End();		//ゲーム終了
			break;
		default:
			printfDx("不明なメニューが選択されました ");
			break;
		}
	}
}
void main_menu(){
	menu_control();
	menu_graph();
	menu_function();
	menu.cnt++;
}

//【effect.cpp】

~略~

//フェード処理実装中
void change_scene( ){
	
	int c;


	//fade_img = MakeGraph(640, 480);			|この3行は関係なし
	//GetDrawScreenGraph(0,0,640,480,fade_img);	|	
	//DrawBox(0,0,640,480,color[0],TRUE);		|
	
	
	if(fade_flag==1){	//フラグが立っていたら

		SetDrawScreen( DX_SCREEN_BACK ) ;				//描写先を裏画面に設定

		for(c=0; c<256;c++){
			ClearDrawScreen();							// 裏画面のデータを全て削除
			SetDrawBlendMode( DX_BLENDMODE_ALPHA, c );	//アルファブレンドを変更
			DrawBox(0,0,640,480,color[1],TRUE);			//640x480の黒い四角形を描写
			SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0 );//ブレンドモードを0に
			ScreenFlip();								//裏画面を表画面に描写
		}

		for(c=0; c<256;c++){
			ClearDrawScreen();							// 裏画面のデータを全て削除
			SetDrawBlendMode( DX_BLENDMODE_ALPHA, 255-c );	//アルファブレンドを変更
			DrawBox(0,0,640,480,color[1],TRUE);			//640x480の黒い四角形を描写
			SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0 );//ブレンドモードを0に
			ScreenFlip();								//裏画面を表画面に描写
		}

		fade_flag=0;	//フラグを0に戻す
		
	}
}


メニュー画面で特定のアイコン選択時にzキーを押すとゲーム開始します。
画面が変わる前にfade_flagを立てchange_scene関数を呼び出します(引数を渡すかも検討中)
SetDrawBlendModeの使い方はDXライブラリー本家とここのサンプルプログラムで拝見しましたが、とりあえず「メニュー画面 → 白にフェードアウト → 白からフェードイン ゲーム画面」と動くように期待して書きましたが、メニューからゲーム画面に移行する間は真っ黒なままでした。

どのようにすれば上記のような動きを実現できるでしょうか。
よろしければ回答おねがいします。


【付け足し】
ScreenFlip()をメインループに書いた方がいいのは理解してますが、SetDrawBlendModeの把握のために二重にしてあります。
最終的にはメニューからゲーム画面にフェードインする際にキャラクターの移動も可能にしたいと思っています。メニュー画面のスクリーンショットを保存し、ゲーム画面とアルファブレンディングすればいけるかなと思っていますが、普通のフェードイン・アウトすらもできないのでここは追々(・ω・)

【環境】
処理系  :Microsoft Visual C++ 2010 Express
使用言語:C言語のみ
DXライブラリー使用

アバター
kimuchi
記事: 163
登録日時: 13年前
住所: 東京

Re: 【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

#2

投稿記事 by kimuchi » 13年前

ScreenFlip関数の直後にClearDrawScreen関数で、
画面を削除していることが原因かもしれません。
ScreenFlip関数の直後にブレークポイントを挟んでみてはいかがですか?

かけだしプログラマー

Re: 【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

#3

投稿記事 by かけだしプログラマー » 13年前

> KImuchiさん
遅くなってすいません。ブレークポイントというのが何を指すのかがわからなかったのでClearDrawScreen関数を削除しましたらメニュー画面より徐々にフェードアウトするようになりました。

私が理解してる範囲では
for分ループに入る
    ↓
 裏画面削除
    ↓
アルファブレンド値設定
    ↓
 画像表示
    ↓
アルファブレンド初期化(削除してもいいような気もしますが、サンプル通り記述)
    ↓
裏画面を表画面に描写
    ↓
 裏画面削除
    :
    :

となるので表画面に描写されたあとであれば裏画面を初期化してもいいだろうと思ってましたがやはり間違っているのでしょうか?

アバター
kimuchi
記事: 163
登録日時: 13年前
住所: 東京

Re: 【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

#4

投稿記事 by kimuchi » 13年前

理論的には間違っていないと思うのですが・・・
これについては私もよく分からないのです。すみません。
個人的に、ScreenFlip関数やClearDrawScreen関数をメインループ以外で使うと
不審な動作をすることが多かったのです。
特にScreenFlip関数は垂直同期待ちを行ったり、ビデオカードによっては動作が違ったりするので、あまり変なところで使わない方が良いと思います。

ブレークポイントというのはVC++の機能の一つなのですが、
これをコード上の特定の行に設定することで、その処理の直前で一時停止してくれるのです。
目に見えないスピードの出力や、その時々の変数の値等を確認出来たりするので便利です。
もしVC++をお使いでなければすみません。

ところで、「白にフェードアウト → 白からフェードイン」
とありますが実際に描画しているのは640x480の黒い四角形のようです。
実行結果は「黒にフェードアウト → 黒からフェードイン」なのでしょうか?

かけだしプログラマー

Re: 【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

#5

投稿記事 by かけだしプログラマー » 13年前

> Kimushiさん

なるほど・・・やはりメインループで使うほうがいいのですか。
分割して製作をつづけているのでメインループでどうやってフェードイン・アウトの関数を実装しようか・・・別の方法でフェードイン・アウトできないかなど一応探してみます。
ブレークポイントとはVC++の機能の一つでしたかっ。WaitTimer関数で待機させるのかと勘違いしてましたOrz

また、コメントのところですがご指摘の通り「白」ではなく「黒」でした。今はcolor[0]として白にフェードアウトしております。
ただフェードアウトできたもののまた問題が発生しまして、なんとかメニュー画面から白にフェードアウトするのですが真っ白になったあと2秒ほど真っ白のまま表示されます。そのあとでやっとゲーム画面が表示されます。
文章だと伝わりにくいかもしれないので以下流れと改変したコード・メインループのコードをのせておきます。(全然かわってませんが)
これらの症状もScreenFlipの怪しい挙動のせいならしかたないのですが、なんとも納得できないので・・・わかる方ご回答おねがいします。並行して自分でも色々試してみます。


メニュー画面
    ↓
白にフェードアウト
    ↓
真っ白の状態で約2秒待機
    ↓
ゲーム画面に移行

コード:

【main.cpp】

略

while(ProcessLoop()==0){//メインループ
		music_ini();
		switch(func_state){
			case 0://初回のみ入る処理
				load();		//データロード
				first_ini();//初回の初期化
				func_state=89;
				break;
			case 89://メインメニューの初期化
				ini_menu();
				func_state=90;
			case 90://メインメニュー
				main_menu();
				effect_main();
				break;
			case 99://STGを始める前に行う初期化
				ini();
				load_story();
				func_state=100;
				break;
			case 100://通常処理
								 //enter_func_tm("最初");
				fantasy_check();
				check_result();
				calc_ch();       /*enter_func_tm("キャラ計算");*/
				ch_move();       /*enter_func_tm("キャラ移動");*/
				cshot_main();    /*enter_func_tm("自機ショットメイン");*/
				enemy_main();	 /*enter_func_tm("敵処理メイン");*/
				boss_shot_main();/*enter_func_tm("ボスショットメイン");*/
				shot_main();	 /*enter_func_tm("ショットメイン");*/
				out_main();  	 /*enter_func_tm("当たり判定");*/
				effect_main();   /*enter_func_tm("エフェクトメイン");*/
				calc_main();	 /*enter_func_tm("計算メイン");*/
				graph_main();    /*enter_func_tm("描画メイン");*/
				bgm_main();		 /*enter_func_tm("BGMメイン");*/
				if(boss.flag==0)
					stage_count++;
				break;
略

-------------------------------------------------------------------------------

【main.menu.cpp】

略

void menu_function(){

		if( CheckStatePad(configpad.shot) == 1 ){
		switch(menu.num)
		{
		case 0:
			func_state = 99;   //ゲーム開始
			fade.flag=2;
			fade_out();//フェードアウト処理
			break;
		case 1:
			func_state = 99;    //クレジット表示
			break;
		case 2:
			fade.flag=2;
			fade_out();//フェードアウト処理
			DxLib_End();		//ゲーム終了
			break;
		default:
			printfDx("不明なメニューが選択されました ");
			break;
		}
	}
}
void main_menu(){
	menu_control();
	menu_graph();
	menu_function();
	menu.cnt++;
}

-------------------------------------------------------------------------------

【effect.cpp】

略


//フェードアウト処理実装中
void fade_out( ){
	
	if(fade.flag==2){	//フラグが立っていたら

		SetDrawScreen( DX_SCREEN_BACK ) ;				//描写先を裏画面に設定
		for(int c=0; c<256;c+=2){
			SetDrawBlendMode( DX_BLENDMODE_ALPHA, c );	//アルファブレンドを変更
			DrawBox(0,0,640,480,color[0],TRUE);			//640x480の白い四角形を描写
			SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0 );//ブレンドモードを0に
			ScreenFlip();								//裏画面を表画面に描写
		}
		
		fade.flag=0;	//フラグを0に戻す
	}
}



アバター
kimuchi
記事: 163
登録日時: 13年前
住所: 東京

Re: 【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

#6

投稿記事 by kimuchi » 13年前

コード:

void fade_out( ){
    static int c=0;
    if(fade.flag==2){   //フラグが立っていたら
 
        SetDrawScreen( DX_SCREEN_BACK ) ;               //描写先を裏画面に設定

        SetDrawBlendMode( DX_BLENDMODE_ALPHA, c );  //アルファブレンドを変更
        DrawBox(0,0,640,480,color[0],TRUE);         //640x480の白い四角形を描写
        SetDrawBlendMode( DX_BLENDMODE_NOBLEND, 0 );//ブレンドモードを0に

        c += 2;
        if(c>255){
            fade.flag=0;    //フラグを0に戻す
            c = 0;  //一応0に戻す
        }
    }
}
もしmainループの方でScreenFlip関数による描画を行っていれば、
これで上手くいくかもしれません。

かけだしプログラマー

Re: 【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

#7

投稿記事 by かけだしプログラマー » 13年前

今帰宅しました。

>> もしmainループの方でScreenFlip関数による描画を行っていれば、これで上手くいくかもしれません。

ためしにやってみましたが一瞬でメニュー → ゲームに切り替わり、フェード処理がなされないようになりました。


よくよく考えてみれば龍神録のサンプルプログラムのキャラ移動やボム時の輝度変更でもメインループ内でのScreenFlipだけで賄ってたようなのでもう一度見直してみます

アバター
kimuchi
記事: 163
登録日時: 13年前
住所: 東京

Re: 【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

#8

投稿記事 by kimuchi » 13年前

すみません。ひとつ忘れていたことがありました。
かけだしプログラマーさんのコード57行目の

コード:

func_state = 99;   //ゲーム開始
を、私のコードの12~15行目に移して下さい。
そうしないとfade_out関数がループしませんでした。

かけだしプログラマー

Re: 【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

#9

投稿記事 by かけだしプログラマー » 13年前

動作確認しました。これならホワイトフェードアウトができました!
kimuchiさん、何度も回答していただいてありがとうございました(__)

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: 【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

#10

投稿記事 by ISLe » 13年前

SetDrawBlendMode( DX_BLENDMODE_ALPHA, n);
というのは、既に裏画面に描いてある内容に、これから描く内容をアルファブレンドしますよ、という意味です。
なので上手くいっているように見えても実際には以前描いたVRAM上のゴミをフェードしている状態ですよ。

メインループの最後に一個あるScreenFlipで画面を表示できるようになればフェードイン・フェードアウトだけでなくいろんなことを容易に実装できるようになります。
ゲームのメインループというのは1周1フレームのトラックの周回ではなくて、1フレームでゴールの短距離を繰り返すイメージですかね。
敵キャラの移動とか複数のキャラを並行して動かすことができているなら分かっているはずですけど。

かけだしプログラマー

Re: 【アルファブレンド】【フェードイン】ステージ切り替え時のフェードイン・フェードアウトについて

#11

投稿記事 by かけだしプログラマー » 13年前

>ISLeさん

龍神録のキャラ描写などの前半部分はまだC言語を学んだばかり&DXライブラリへの理解が浅かったために基本的な処理部分への理解が足りてませんでした。


昨日からメインループでのScreanFlip関数ひとつで表画面への描写を行うために、上記void fade_out関数を描写部分(アルファブレンディング処理の実行)と値の計算部分で分けて最終的にScreenFlip関数で描写するように実装しなおしました。
ご指摘ありがとうございます。

閉鎖

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