フェードイン、フェードアウトの作り方

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

フェードイン、フェードアウトの作り方

#1

投稿記事 by situmon » 16年前

ゲームプログラミングの館を見て実装しようとしたのですが、うまくいきませんでした。
どのように実装すればいいのでしょうか?ゲームに応用するのができません。
とくに選択画面で選択したときにどうすればいいのでしょう?

kazuoni

Re:フェードイン、フェードアウトの作り方

#2

投稿記事 by kazuoni » 16年前

どのようにうまくいかないか、もう少し具体的に書いたほうが
より詳しい回答が得られるかと思います。

本家にも参考がでていますが、
これでは不備があるでしょうか?

DXライブラリ置き場
ttp://homepage2.nifty.com/natupaji/DxLib/dxprogram.html#N9

situmon

Re:フェードイン、フェードアウトの作り方

#3

投稿記事 by situmon » 16年前

えっと選択画面をswitch形式にしているのですが
switch(choose_y){
		case 80:

if( CheckSoundMem( bgm[5] ) == 1 )
StopSoundMem( bgm[5] ) ;
if( CheckSoundMem( sound_effect[6] ) == 0 )
                    PlaySoundMem( sound_effect[6] , DX_PLAYTYPE_BACK ) ;
			main_flag=2;
			if(stage_flag!=1)
			stage_flag=1;
			break;
...省略
}
としているのですが、この選んでからゲームが始まるまでに(main_flag=2になるまでに)フェードインなどをしたいのです。

kazuoni

Re:フェードイン、フェードアウトの作り方

#4

投稿記事 by kazuoni » 16年前

とりあえずやっつけに書いてみました。

back.pngは自分で用意してください^^;
参考になるかどうか微妙ですが・・・。

チルチル

Re:フェードイン、フェードアウトの作り方

#5

投稿記事 by チルチル » 16年前

私の経験ですがフェードイン、フェードアウトは関数化しておくと後でかなり楽になります
前に送ったサンプルのSceneChange関数が参考になるかもしれません

1.ZとかXが押された時にカウンタをリセットして
2.カウンタでフェードイン
3.カウンタが半分まで進んだら画面を変える
4.カウンタでフェードアウト

この流れでどうでしょうか?
まあこれだけだと入力関係が不十分ですが・・

situmon

Re:フェードイン、フェードアウトの作り方

#6

投稿記事 by situmon » 16年前

// フェードイン処理
	for(int i = 0 ; i < 256 ; i++ )
	{
		// 描画輝度をセット
		SetDrawBright( 255 - i , 255 - i , 255 - i ) ;

		if(i==255){
if( CheckSoundMem( sound_effect[6] ) == 0 )
                    PlaySoundMem( sound_effect[6] , DX_PLAYTYPE_BACK ) ;

	        WaitTimer( 200 ) ;//0.2秒待つ
			main_flag=2;
			player.easy_flag=0;
			player.hard_flag=0;
			if(stage_flag!=4)
			stage_flag=4;
		}
	}
としたのですが、なぜか失敗してしまいます。
追記
失敗というのは真っ暗のままになってしまうのです。

kazuoni

Re:フェードイン、フェードアウトの作り方

#7

投稿記事 by kazuoni » 16年前

このfor文のなかにScreenFlip的な、
表描写もDraw系もないので、
このfor文を抜けるときには、輝度は0で、真っ暗かと思います。

コード全部が載っていないので、あくまで予想ですが・・・。

situmon

Re:フェードイン、フェードアウトの作り方

#8

投稿記事 by situmon » 16年前

#include "DxLib.h"
#include "Extern.h"

void Title_Draw(){
	if(bgm_select_flag!=0 ||stage_flag!=0){
		stage_flag=0;
		bgm_select_flag=0;
	}
DrawGraph( 0 , 0 , title_img , FALSE );

DrawStringToHandle( 20 , 420 , "タイトル" , white , font[2] );
DrawStringToHandle( 460 , 420 , "Ver 1.00 (test) " , white , font[3] );

DrawGraph( 50 , 100 , title_d_img[0] , TRUE );
DrawGraph( 50 , 156 , title_d_img[2] , TRUE );
DrawGraph( 50 , 212 , title_d_img[1] , TRUE );
DrawGraph( 10 , title_y+16 , title_d_img[3] , TRUE );

//上キー
if( CheckHitKey( KEY_INPUT_UP ) == 1 && t_count%5==0 ){
if( CheckSoundMem( sound_effect[0] ) == 0 )
                    PlaySoundMem( sound_effect[0] , DX_PLAYTYPE_BACK ) ;
if(title_y>100){
if(title_y==212&&clear_flag==0)
title_y-=112;
else
title_y-=56;
}
}
//下キー
if( CheckHitKey( KEY_INPUT_DOWN ) == 1 && t_count%5==0 ){
if( CheckSoundMem( sound_effect[0] ) == 0 )
                    PlaySoundMem( sound_effect[0] , DX_PLAYTYPE_BACK ) ;
if(title_y<212){
if(title_y==100&&clear_flag==0)
title_y+=112;
else
title_y+=56;
}
}
//escapeキー
if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1){
if( CheckSoundMem( sound_effect[0] ) == 0 )
                    PlaySoundMem( sound_effect[0] , DX_PLAYTYPE_BACK ) ;
	if(title_y!=212)
		title_y=212;
}

if( CheckHitKey( KEY_INPUT_Z ) == 1 || CheckHitKey( KEY_INPUT_RETURN ) == 1 ){
	switch(title_y){
		case 100:
if( CheckSoundMem( sound_effect[6] ) == 0 )
                    PlaySoundMem( sound_effect[6] , DX_PLAYTYPE_BACK ) ;

	        WaitTimer( 200 ) ;//0.2秒待つ
			main_flag=1;
			break;
		case 156:

if( CheckSoundMem( bgm[5] ) == 1 )
StopSoundMem( bgm[5] ) ;

if( CheckSoundMem( sound_effect[6] ) == 0 )
                    PlaySoundMem( sound_effect[6] , DX_PLAYTYPE_BACK ) ;

	        WaitTimer( 200 ) ;//0.2秒待つ
			main_flag=2;
			player.easy_flag=0;
			player.hard_flag=0;
			if(stage_flag!=4)
			stage_flag=4;
			break;
		case 212:
if( CheckSoundMem( sound_effect[6] ) == 0 )
                    PlaySoundMem( sound_effect[6] , DX_PLAYTYPE_BACK ) ;

			DxLib_End(); //終了
			break;
		default:
			break;
	}
}
}
となっていますが、
このfor文のなかにScreenFlip的な
>main.cppで書いているのですが・・・
表描写もDraw系もないので、
>ここにまた
DrawGraph( 50 , 100 , title_d_img[0] , TRUE );
DrawGraph( 50 , 156 , title_d_img[2] , TRUE );
DrawGraph( 50 , 212 , title_d_img[1] , TRUE );
DrawGraph( 10 , title_y+16 , title_d_img[3] , TRUE );
とかくのでしょうか??

situmon

Re:フェードイン、フェードアウトの作り方

#9

投稿記事 by situmon » 16年前

switch(title_y){
		case 100:
if( CheckSoundMem( sound_effect[6] ) == 0 )
                    PlaySoundMem( sound_effect[6] , DX_PLAYTYPE_BACK ) ;
for(int i=0;i<256;i+=4){
		// 描画輝度をセット
		SetDrawBright( 255 - i , 255 - i , 255 - i ) ;
		DrawGraph( 0 , 0 , title_img , FALSE );
		ScreenFlip() ;
}
for(int i=0;i<256;i++){
		// 描画輝度をセット
		SetDrawBright( i , i , i ) ;
		DrawGraph( 0 , 0 , title_img , FALSE );
		ScreenFlip() ;
		if(i==255){		
main_flag=1;
		}
}
			break;
とすることにより実装できましたが考え的には、
DrawGraph( 0 , 0 , title_img , FALSE );

DrawGraph( 50 , 100 , title_d_img[0] , TRUE );

DrawGraph( 50 , 156 , title_d_img[2] , TRUE );

DrawGraph( 50 , 212 , title_d_img[1] , TRUE );

DrawGraph( 10 , title_y+16 , title_d_img[3] , TRUE );

で描いた(映した)画像の上にまた新たにまたDrawGraph( 0 , 0 , title_img , FALSE );
で同じ画像を描いているわけだと思うのですが、これでいいのですか?

kazuoni

Re:フェードイン、フェードアウトの作り方

#10

投稿記事 by kazuoni » 16年前

確かに、反映されているので、それで成功するかと思います。
ただ、プログラムの各所に表描写反映(ScreenFlip)を書くと、
いつか、管理しにくくなってくるかと思います。
なので、反映する関数はmainループに一度だけ書くことをお勧めします。

>描いた(映した)画像の上にまた新たにまたDrawGraph( 0 , 0 , title_img , FALSE );
>で同じ画像を描いているわけだと思うのですが、これでいいのですか?

プログラムは上から流れてきますので、そうですね。
裏描写のクリアもしていないので、Drawするたびに、上書きしていっています。

situmon

Re:フェードイン、フェードアウトの作り方

#11

投稿記事 by situmon » 16年前

その場合、どうすればいいのでしょう。
それだけ消すのか、そのままでは問題ないのでしょうか?
自分の考えではDrawするたび少しですが、パソコンに、負担がかかると思うのですが。

kazuoni

Re:フェードイン、フェードアウトの作り方

#12

投稿記事 by kazuoni » 16年前

>その場合、どうすればいいのでしょう。
>それだけ消すのか、そのままでは問題ないのでしょうか?

「その場合」がどの場合で、それだけの「それ」がどれかはっきり分かりませんが、
確かに、画面内に動きがない場合はこれでも画面のフェードインアウトはいいと思います。
ただ、もし、次に、キャラクターがぐるぐるフィールド上を
回っている最中にフェードアウトし、フェードインでは次の場面にしたい
なんてなった場合、この書き方では使えないですよね?
なので、根本的な見直しをする必要があるかと思います。

>自分の考えではDrawするたび少しですが、パソコンに、負担がかかると思うのですが。
それはそのとおりです。

ちょっと勘違いをしているかもしれないので付け加えを。
「裏描写の内容は動きのないものだから、一回描写して、
あとはSetDrawBrightで輝度を下げればいいんじゃないの?」
ってことを言いたいのでは?と勝手に決め打ちしますが、
SetDrawBrightはあくまで、描写のモードを決めるだけであって、
今裏描写にあるものの輝度とは別物です。
この関数を読んだ以降のDrawはすべてSetDrawBrightで決めた輝度にセットしますよ
ってな感じです。

situmon

Re:フェードイン、フェードアウトの作り方

#13

投稿記事 by situmon » 16年前

よくわかりました。
ありがとうございました。
これからもよろしくお願いします。
実装は一応できました。

おむすび

Re:フェードイン、フェードアウトの作り方

#14

投稿記事 by おむすび » 16年前

横スレ失礼いたします。
わたしも以前フェードイン、アウトの処理を使ったのですがうまくいきませんでした。
フェードではなく一瞬で色が変わってしまいます。
// フェードイン処理
int FadeIn( int Color , int Speed ){
	for(int i = 0 ; i < 255 ; i += Speed ){
		// 描画輝度をセット
		SetDrawBright( i , i , i ) ;
		// グラフィックを描画
		DrawBox( 0 , 0 , 640 , 480 , Color , true ) ;
		if(i < 255) return true;
	}
	return false;
}

// フェードアウト処理
int FadeOut( int Color , int Speed ){
	for(int i = 0 ; i < 255 ; += Speed ){
		// 描画輝度をセット
		SetDrawBright( 255 - i , 255 - i , 255 - i ) ;
		// グラフィックを描画
		DrawBox( 0 , 0 , 640 , 480 , Color , true ) ;
		if(i < 255) return true;
	}
	return false;
}

	if(CheckHitKey(KEY_INPUT_B)){
		FadeIn(RGB(0,0,0),1);
	}	
	if(CheckHitKey(KEY_INPUT_A)){
		FadeOut(RGB(0,0,0),1);
	}

kazuoni

Re:フェードイン、フェードアウトの作り方

#15

投稿記事 by kazuoni » 16年前

Drawを表描写にしているのか、裏描写にしているのか定かではないのであれですが・・・
もし、裏描写なら
>フェードではなく一瞬で色が変わってしまいます。
になります。

フェードイン、アウト共に、表描写(ScreenFlip)していないからです。
この関数だと、裏描写には淡々と描写していますが、
それを表描写しなければ、画面には反映されません。

おむすび

Re:フェードイン、フェードアウトの作り方

#16

投稿記事 by おむすび » 16年前

たぶんScreenFlipしておりますので書き方が悪いのかと思います。
サンプル置き場にあるものを実行したら問題なかったので・・・。
現在のソースを書かせていただきます。

// フェードイン処理
bool FadeIn( int Color , int Speed ){
	for(int i = 0 ; i < 255 ; i += Speed ){
		// 描画輝度をセット
		SetDrawBright( i , i , i ) ;
		// グラフィックを描画
		DrawBox( 0 , 0 , 640 , 480 , Color , true ) ;
//		ScreenFlip();
		if(i < 255) return true;
	}
	return false;
}

// フェードアウト処理
bool FadeOut( int Color , int Speed ){
	for(int i = 0 ; i < 255 ; i += Speed){
		// 描画輝度をセット
		SetDrawBright( 255 - i , 255 - i , 255 - i ) ;
		// グラフィックを描画
		DrawBox( 0 , 0 , 640 , 480 , Color , true ) ;
//		ScreenFlip();
		if(i < 255) return true;
	}
	return false;
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){

	ChangeWindowMode(true);						//  ウインドウの変更 フルスクリーン・ウインドウ
	SetDrawScreen( DX_SCREEN_BACK ) ;           // 描画先を裏画面に設定


	// DXライブラリ初期化処理
	if( DxLib_Init() == -1 ){
		 return -1;				// エラーが起きたら直ちに終了
	}
	//  処理
	while(1){

		// BMP画像の表示
		ClearDrawScreen();	
		if(CheckHitKey(KEY_INPUT_B)){
			FadeIn(RGB(0,0,0),1);
		}	
		if(CheckHitKey(KEY_INPUT_A)){
			FadeOut(RGB(0,0,0),1);
		}
		ScreenFlip();

		// 処理の終了
		if(CheckHitKey(KEY_INPUT_ESCAPE)) break;

	}
	DxLib_End() ;				// DXライブラリ使用の終了処理
	
	return 0 ;				// ソフトの終了
}

Dixq (管理人)

Re:フェードイン、フェードアウトの作り方

#17

投稿記事 by Dixq (管理人) » 16年前

今コンパイラが手元にないので詳しく書けませんが・・。
ScreenFlip();
はあちこちに書かないほうがいいです。
メインループの中に一度だけ書くようにしてください。
必ずメインに戻しても処理が出来るはずですから。

「輝度」なる変数を用意し、それを変更することで明るさを調整するといいと思いますよ。

おむすび

Re:フェードイン、フェードアウトの作り方

#18

投稿記事 by おむすび » 16年前

管理人さま
ご回答ありがとうございます。

ScreenFlipなのですが現在コメントにしてありますので一回しか書いてありません。
とても便利な関数なのですがよくどちらに書いたかわからなくなるので・・・ww

やはりフェードインしませn。

Justy

Re:フェードイン、フェードアウトの作り方

#19

投稿記事 by Justy » 16年前


>やはりフェードインしません

 1回分の whileループ(1フレーム)の中の処理を日本語で書き出してみましょうか。

1  [color=#d0d0ff" face="sans-serif]ClearDrawScreen();[/color]
 画面を消す。

2  [color=#d0d0ff" face="sans-serif]if(CheckHitKey(KEY_INPUT_B)) { FadeIn(RGB(0,0,0),1); }[/color]
 Bのキーが押されてたら輝度を{ 0, 0, 0 }から { 254, 254, 254 }まで
255回 DrawBox関数で全画面塗りつぶす。

3  [color=#d0d0ff" face="sans-serif]if(CheckHitKey(KEY_INPUT_A)) { FadeOut(RGB(0,0,0),1); }[/color]
 Aのキーが押されてたら輝度を{ 255, 255, 255 }から { 1, 1, 1 }まで
255回 DrawBox関数で全画面塗りつぶす。

4  [color=#d0d0ff" face="sans-serif]ScreenFlip();[/color]
 裏画面と表画面を交換して、1以降で描画した内容を画面に表示する

5  [color=#d0d0ff" face="sans-serif]if(CheckHitKey(KEY_INPUT_ESCAPE)) break;[/color]
 ESCキーが押されたら、whileループを抜ける
 これが1回分の whileループの処理です。

 さて、ここで2や3の処理をみて下さい。
 SetDrawBright~DrawBoxを 255回も行って描いていますが、
当然これ全て1フレームで処理されてしまっています。

 透明属性の指定はないので、最終的には 255回目に描いたものが一番上になり
見た目には 1回目~ 254回目までの描画はなかったことになります。

 これでは一瞬で色が変わってしまいますよね。

 なので、何フレーム~何十フレームもかけて輝度を変化させて表示するように
変更してみて下さい。

おむすび

Re:フェードイン、フェードアウトの作り方

#20

投稿記事 by おむすび » 16年前

できました><

ありがとうございます。

閉鎖

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