プロジェクト演習Ⅱ インタラクティブゲーム制作 イントロダクション2 第11回 プログラミングサプリ グラフィック素材編 今日の内容 • 2次元画像の扱い方 – 画像を読み込んで表示 – 文字表示 • 3次元モデルデータの扱い方 • 関数(メソッド)の扱い方 – 関数の作り方・使い方 – 値の渡し方・受け取り方 今週のプロジェクト • 授業資料ページからダウンロードします – 落としたZipファイルを解凍して、 出てきたフォルダを好きなところに配置 • 今週のFKUT更新情報 – ゲームパッド対応を強化 – fk_Sceneクラスのオブジェクトを使い分ける ことで画面切り替えが容易に やっぱり2次元もいいよね! 画像素材との付き合い方 画像データとは • 言うまでもないですが、 色のついた点の集まり – FKで扱える画像形式 • ビットマップ(BMP) – きれいだがでかい • PNG – きれいでコンパクト – 透過処理もできる • JPEG(JPG) – きちゃないけど超コンパクト 表示するには • fkut_SpriteModel – 色々お節介焼きな便利変数です – 画像の表示を絶望的に簡単にできます • 詳しくはお品書きを読んでね – FKUT/SpriteModel.h を参照 – できることが書いてあります – それに加えてModel系の命令も使えるよ 基本手順 • fkut_SpriteModel型の変数を作る – fkut_SpriteModel spr; • 表示させたい画像を読み込む – spr.readPNG(“hoehoe.png”); • readBMP/PNG/JPGを形式に合わせて使う • ウィンドウにエントリーする – window.entry(spr); • 先にカメラの設定を済ませておくこと • カメラモデルを変更したら再エントリー 位置やサイズの調整 • glMoveTo()やglTranslate()などが利用可能 – 画像の中心点がどこにくるかを指定 • ただし、有効なのはX,Y座標値のみ – 座標の軸の取り方にも注意(次スライド参照) • setPositionLT()で、画像の左上がどこにくる か基準での位置指定が可能 • 表示サイズは基本的に画像自体のサイズが そのまま適用される – 変更したい場合はsetSpriteSize()を使う 座標系の注意 • ウィンドウが800x600の場合 (-400,300) (0,0) (400,-300) 文字表示の手順 • 文字データ(フォント)を読み込む – initFont()を使う – Vista,7の場合は「メイリオ」をおすすめ • C:/Windows/fonts/Meiryo.ttc • 表示させたい文字をdrawText()で指定 – drawText()を呼ぶたびに文字が付け足される – 改行したい場合は”\n”と書く – 後で書き直すこともできる • 再度drawText()を呼んだり、clearText()で消したり • 数値の表示についてはサンプル参照 • 色の変更や細かい装飾はWeb上の資料を参照 3次元空間中に表示したい場合 • SpriteModelは画面上に貼り付ける専門の 変数なので、別の変数を用意する • サンプル中に「背景に画像を敷く」 コードがあるので、それを参考に – エリアコメントを解除してみよう 単なる手順の話でしかないですが 形状モデルデータの扱い方 FKにおける「形状」と「モデル」 • ポリゴンがどんな形をしているのか、 画像がどう張り込まれているのか、を FKでは「形状」と呼ぶ – 球、ブロック、モデリングデータは「形状」 • 「形状」が乗っかった台座に相当して、 位置や向きを保持するのが「モデル」 – 「形状」を「モデル」にセットして使う • SphereModelやBlockModelはこれらを ミックスさせていたもの MQOやXを単純に読む場合 • fk_IFSTextureクラスのオブジェクトを用意 – ifsとする • ifsに対してテクスチャ画像を読み込む – 画像形式に応じてreadXXX関数を使う • ifsに対して形状データを読み込む – readMQO()かreadD3DX()を使う • ModelのオブジェクトにsetShape(&ifs) – さらにモデルにマテリアルを設定し、 ウィンドウにエントリーしてようやく表示 モーションを手軽に付けた モデルを扱いたい場合 • FK Performerを使ってみる – MQO形式のデータに対応 • 作ったモデルとモーションを fkut_Performerクラスで扱う – 形状とモデルとモーションをセットにした クラス – 詳細はサンプル参照 当たり判定は球かブロックで近似 • MQOやXを読み込んだ場合でも、 FK Performerを利用する場合でも、 当たり判定用にBlockModelか SphereModelを用意しておく – create()はするが、entry()はしない – 形状をセットしたモデルを親子関係にして、 移動処理などは当たり判定モデルをベースに 行う 使えてる人、そうでない人いるでしょうが 関数を使ってスマートに書こう 関数とは • 以下の3つの特徴を持ちます。 – いくつかの処理を1つのカタマリにしておき、 必要に応じて呼び出せる。呼び出した処理が 終わったら元の場所に戻ってくる。 – 呼び出す際に必要な値を引き渡せる。 要らなければ渡さなくてもいい。 • これを利用すると大幅に処理が効率化できる。 – 戻ってくる際に計算結果を返すことができる。 要らなければ返さなくてもいい。 このコードを見て、 無駄だと思わないかい? // se0のキー操作(a)による再生 if(window.getKeyStatus('a') == FKUT_SW_DOWN) { se0_play = true; se0.seek(0.0); } if(se0_play == true) { se0_play = se0.play(); } // se1のキー操作(s)による再生 if(window.getKeyStatus('s') == FKUT_SW_DOWN) { se1_play = true; se1.seek(0.0); } if(se1_play == true) { se1_play = se1.play(); } 赤くしたところが違うだけで、 処理の流れや構造は一緒だ // se0のキー操作(a)による再生 if(window.getKeyStatus('a') == FKUT_SW_DOWN) { se0_play = true; se0.seek(0.0); } if(se0_play == true) { se0_play = se0.play(); } // se1のキー操作(s)による再生 if(window.getKeyStatus('s') == FKUT_SW_DOWN) { se1_play = true; se1.seek(0.0); } if(se1_play == true) { se1_play = se1.play(); } こういう感じで 差し替え効くように書けると素敵 // key, flag, seの所は状況に応じて差し替えたい if(window.getKeyStatus(key) == FKUT_SW_DOWN) { flag = true; se.seek(0.0); } if(flag == true) { flag = se.play(); } • playSoundByKey()関数 – 判定するキーの種類、鳴らしたいSEの変数、 再生フラグ変数を引数として渡している お品書きと本体 • 関数を作る時の 返値の種類 関数名(引数リスト); の部分をこの授業ではお品書きと呼ぶ – 正確には「プロトタイプ宣言」と呼ぶ • お品書きはヘッダー(.h)に書く – 本体を書く.cppファイルと、その関数を 利用したい.cppファイルでインクルードする • 本体はC++ファイル(.cpp)に書く インクルードとは • 使いたい関数(やその他もろもろ)のヘッ ダーファイル(お品書き)を取り込む命令 – FKUTの機能もインクルードすることで 使えるようになっている • 動作としては、ファイルに書かれている 内容をその場にコピペするのと大差ない – なので、プロトタイプ宣言を直書きしても、 ヘッダーをインクルードしても動作は一緒 ゲームでよく使う関数の作り方 • 返値は要らない場合が多い – 座標や数値の計算をしたい場合は返値を返すように 作るとよい – int, doubleの他に、bool, fk_Vectorなどが返値とし てよく用いられる • 引数は「参照渡し」にした方がよい – 引数で受け取る変数名の前に「&」を付ける – 値を参照するためだけに渡すものは型名の前に 「const」を付ける • 付けないと’a’やFK_ENTERなどの定数が渡せない – fkut系の変数は必須 • fk系も基本的に参照渡しの方が問題が起きない その他注意点 • 配列を渡したい場合の引数リスト – int *iArray や fk_Model *mArray など • *で渡した先で、[0]や[i]で要素を参照できる • SpecialKeyのコード – const fk_SpecialKey &spKey • 普通のキーコード – const char &key • 文字列を渡したい – string &text • (関数内でいじらないならconst string &text) より詳しい人のために • 構造体やクラスの利 用は推奨します – ただし、ある程度独学 で頑張れるチームのみ – 分かってる人だけが使 うのではなく、チーム 全体で出来るだけ理解 レベルを統一して開発 にあたりましょう • グローバル変数の利 用は極力避けるべし – トラブルのもとです – ゲームを通じて必要な 変数はmain関数に作 り、面倒でも引数で しっかり渡すように 値渡しと参照渡しの違い 値渡し(通常)の関数 参照渡しの関数 void func(int iA) { iA *= 2; } void func(int &iA) { iA *= 2; } // 以下main内だとする // 以下main内だとする int iValue = 10; func(iValue); int iValue = 10; func(iValue); // ここでのiValueの値は? // ここでのiValueの値は? 違いのまとめ • 値渡しだと、引数として「同じ値がコピーさ れる」ので、関数側でいじってもコピー元に は影響がない • 参照渡しだと、引数として「その変数の箱自 体が渡される」ので、関数側でいじった結果 が反映される – 多くの場合はこっちの挙動の方がうれしい – だが、変数ではなく値を直書きしているものは受 け取れない • キーの種類が参照渡しじゃないのはそのため – 引数を意図せずにいじって混乱することもある
© Copyright 2024 ExpyDoc