ページ 11

関数の作り方

Posted: 2011年6月13日(月) 17:56
by ゆうき2
月一程度の割合でC++を勉強しているC++初心者です。

DXライブラリ
VC++2010
を使用しています。

まだ一つもゲームと言えるものを作った事がないです。
現在もテーマを決めてゲームを作っている訳でもないのですが
ゲームに使いそうな関数を勝手に妄想して作っています。

※抽象的な内容の件名にした割に具体的な質問になっています。
  これに限ったことではないと思いこの件名にさせていただきました。

例えばの話なのですが
画面切り替え時にはフェードアウトするように画面が切り替わることがゲームではよくあると考え
このときフェードアウトする関数を妄想し作ってみました。

コード:

//徐々に暗くする関数
void fadeout( static int x_o , static int y_o , static int G_Handle_o,static int f_o) 
//引数の内訳:画像の位置(x、y)、グラフィックハンドル、フェードアウトの速さ(低いほど速い)
 {   
	  static  char Key_o[256];
	  static  int  kido_o=255;
	  	   	  
 while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key_o ) && !Key_o[KEY_INPUT_ESCAPE])
 
            //↑メッセージ処理        ↑画面をクリア         ↑キーボード入力状態取得       ↑ESCが押されると終了
         {	 
	          kido_o=kido_o - 6;    //画面更新につき輝度を6づつ減らす
		     
	          DrawGraph( x_o,y_o, G_Handle_o, TRUE) ;//画像を描画
		      WaitTimer(f_o);//フェードアウトの速さを決定
              SetDrawBright( kido_o , kido_o , kido_o ) ; //輝度を画面に反映
  
    
	          if(kido_o <= 2 )//輝度が2以下になったら
	           {
				kido_o=255;//kidoを255に戻し
	                  break;       //ループから抜ける
	            }
  
          }
 SetDrawBright(kido_o,kido_o,kido_o);  //輝度255を画面に反映させ、フェードアウト関数終了
}

上の関数ではフェードアウトする直前の画像の識別番号と位置と速度を引数として受け取り実行します。
とりあえずうまくできたのですが、この関数だとフェードアウトする直前の画像が識別番号として存在する必要があります。


ですが、例えばRPGなどで戦闘画面からマップ画面に切り替わる時などには、画面には背景、戦闘後の経験値アップなどの文字列など各画像が挿入されていて、その画面を上から覆うようにフェードアウトしていかなければなりません。

上の関数ではこれは無理です。
文字は同時に暗くなってくれる事は確認済みですが
このフェードアウト関数内で文字を描写しなければならず、さらに言えば動きのある描写をフェードアウトする事も大抵の場合不可能であり、実用性はほとんどありません。

長くなってしまって申し訳ないのですが
フェードアウトという効果を実行しつつ、本来の処理(ゲームの進行)を行うにはどうしたらいいのでしょうか?

DXライブラリの音関連の関数には「音楽をBGMとして再生(ゲームの進行と平行して再生)」がありますがフェードアウト関数もこれと同じ要領で呼び出せるように設計できないものかと考えています。


また、関数うんぬんではなくC++において根本的にプログラムの作り方の概念を勘違いしているようでしたらその点に関してもご指導くださるようよろしくお願いします。

Re: 関数の作り方

Posted: 2011年6月13日(月) 18:09
by h2so5
ゆうき2 さんが書きました: 長くなってしまって申し訳ないのですが
フェードアウトという効果を実行しつつ、本来の処理(ゲームの進行)を行うにはどうしたらいいのでしょうか?
「本来の処理(ゲームの進行)」の中でフェードアウトを実行すればいいのではないでしょうか?

描画に関する処理は、背景の描画、文字の描画、フェードアウトの処理などを全て一箇所にまとめるべきであって、
フェードアウトだけ関数が別になっているのは設計として無理があるかと思われます。

また、私がフェードアウトの処理を作るのであればSetDrawBrightを使わず、
SetBlendModeを使って少しずつ不透明度を上げながら、DrawBoxで黒い四角を画面全体に描画する方法を使います。

Re: 関数の作り方

Posted: 2011年6月13日(月) 18:46
by softya(ソフト屋)
私もSetBlendModeとDrawBoxを使いますね。

で、フェードアウト/インのクラスを作ってメソッドで
・フェードアウト/イン 設定 ・・・ イン/アウトの種別やその時間の設定
・フェードアウト/イン 処理 ・・・ 時間をカウントして透明度決める。
・フェードアウト/イン 描画 ・・・ 実際に透明度に応じた半透明の黒を描画する。
の3つのメソッドを使って処理させると思います。
「フェードアウト/イン 描画」メソッドは描画の一番後ろに来るように最後に呼ぶようにします。

あとcodeタグ使ってくださいね。修正しておきます。

【追記】
内部にProcessMessageや画像の描画を内包していると汎用性に著しく欠けますので。

Re: 関数の作り方

Posted: 2011年6月13日(月) 20:38
by MoNoQLoREATOR
基本、関数の中に無限ループを入れないようにしましょう。

それと、WaitTimer()関数も使わないようにしましょう。(フェードアウトさせる時は別に構いませんが私は好きではありません)かわりに下記のようにしてはいかがでしょうか。

方法1
1ループにつき1づつ増える変数をつくる

その変数が、例えば4の倍数の時だけ処理を行う。

方法2
GetNowCount()関数を使い、あらかじめ時間を取得しておく。

もう一度その関数を呼び出し、さきほどの時間と比較する。

その差が一定以上なら処理を行う


フェードアウト関数に限って言うと、「不透明度を上げながら黒い四角形を描画する」という方針が一番良いと思います。
これを応用して、DrawBlendGraph()関数を使い、外側から中心にむかってだんだんと暗くなっていく演出をすることができますし。

Re: 関数の作り方

Posted: 2011年6月14日(火) 08:52
by bitter_fox
MoNoQLoREATOR さんが書きました:基本、関数の中に無限ループを入れないようにしましょう。
ゆうき2 さんが書きました:

コード:

	static  int  kido_o=255;

	while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key_o ) && !Key_o[KEY_INPUT_ESCAPE])
	//     ↑メッセージ処理         ↑画面をクリア           ↑キーボード入力状態取得          ↑ESCが押されると終了
	{
		kido_o=kido_o - 6;    //画面更新につき輝度を6づつ減らす  

		/* 略 */

		if(kido_o <= 2 )      //輝度が2以下になったら
		{
			kido_o=255;  //kidoを255に戻し
			break;       //ループから抜ける
		}
	}
(インデントが死んでいたので修正しました。)

ゆうき2さんのプログラムだと、無限ループではなく実行回数が一定(43回)のループですね。