スライド 1

プロジェクト演習Ⅱ
インタラクティブゲーム制作
イントロダクション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の値は?
違いのまとめ
• 値渡しだと、引数として「同じ値がコピーさ
れる」ので、関数側でいじってもコピー元に
は影響がない
• 参照渡しだと、引数として「その変数の箱自
体が渡される」ので、関数側でいじった結果
が反映される
– 多くの場合はこっちの挙動の方がうれしい
– だが、変数ではなく値を直書きしているものは受
け取れない
• キーの種類が参照渡しじゃないのはそのため
– 引数を意図せずにいじって混乱することもある