動画再生の不具合

お久しぶりです。

2013/7/10に突然自分が関わっていた同人ゲームの不具合報告を頂いたのでその辺に関する情報を記載致します。

吉里吉里でwmv形式の動画を再生していたのですが、動画の上半分が真っ黒になるという現象。
発生当時は何が原因か全く解らなかったのですが、友人や色んな方のブログを元に緊急事態は一旦回避されました。

・原因
WindowsUpdateによるwmvの仕様が変わった模様。

なのでとある日に寝て起きてPC付けてゲーム起動すると突然画面半分真っ黒!!

・今のところの回避策
こちら参考にさせて頂いたブログを紹介させて頂きます。
http://pluseta.b.dlsite.net/

とても助かりました。本当にありがとうございます。
またそれ以外にも相談にのって頂いた方々に御礼申し上げます。

同様の現象に悩まれている方がこれで救われれば幸いです。

物理エンジンの流れ

前回くらいにPhysX、Bulletと簡単にセットアップまで行ったので実際に使ってみる。

基本的な流れはPhysX、Bullet共に同じ様な流れだと自分は感じました。

簡単にテキストで説明すると
1、物理エンジンを初期化
2、物理エンジンにオブジェクトを登録
3、オブジェクトにパラメーター(重さとか速度とか)を与える
4、物理エンジンをシュミレーションする
5、終了時に物理エンジンを破棄


ではちょっと詳しく書いてみる(Bulletの場合)
○1、物理エンジン初期化
これはまぁサンプルを見たほうが良いかと使いたい内容によって初期化する物も色々と違ってくると思います。

重要なのは「btDiscreteDynamicsWorldクラス」これが一つの物理空間みたいな物です。
この物理空間にオブジェクトを登録してシュミレーション(時間を進める)すると登録されたオブジェクトが法則に基づいて動いてくれるようです。


○2、物理エンジンにオブジェクトを登録
基本となるオブジェクトはデフォルトで大体そろってます。(箱、球体、カプセルなど)

↓剛体ボディ登録

 btDynamicsWorld* pWorld;

 btTransform start, center;
 start.setIdentity(); center.setIdentity();

 // 剛体のコリジョンは箱で作成
 btCollisionShape* pShapes = new btBoxShape(btVector3(1,1,1));
 btDefaultMotionState* pMotionState = new btDefaultMotionState(start, center);
 btVector3 localInertia(0,0,0);
		
 btRigidBody::btRigidBodyConstructionInfo rbInfo(1.0, pMotionState, pShapes, localInertia);
 btRigidBody* body = new btRigidBody(rbInfo);

 pWorld->addRigidBody(body);

※↑をそのままコピーしても実体の無いbtDynamicsWorldに登録してるのでエラーになります。


○3、オブジェクトにパラメーター(重さとか速度とか)を与える
剛体クラスには色々とメソッドが用意されているので呼び出せば使えます。
基本的に全て英語なので私自身もまだまだ関数の意味が全然わかってないです。


○4、物理エンジンをシュミレーションする

 pWorld->stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));


○5、終了時に物理エンジンを破棄
これも基本はサンプル通りで
removeしてdeleteすれば大体は大丈夫っぽいです。


以上簡単に書けばこんな感じ!!
もっと詳しくなったら後日細かく書いていきます。(今はあまり自信が無い><)

BulletPhysicsを使ってみる

前回PhysXだったので今回はBulletの環境構築。

まずはダウンロード!
http://bulletphysics.org/wordpress/

ダウンロードするとインストーラーではなくzipファイルなどになっていると思います。これを解凍するとソースコードなどが入っています。
ここでBulletの場合はソースコードをビルドして自分でlibファイルの作成を行わないといけません。

そのために解凍したmsvcフォルダ内にはVisualStudioのプロジェクトファイルがあるので、このプロジェクトをコンパイルすれば各libが作成できます。


そしてPHYSXの時と同じく今度はVC側の設定「ツール→オプション→プロジェクト及びソリューション」から解凍・ビルドしたSDKへリンクを繋げます。

インクルード
…\bullet-2.75\src
ライブラリ
…\bullet-2.75\out\debug8\libs
…\bullet-2.75\out\release8\libs

※…は解凍したフォルダまでのパスです。

ここまでで準備は完了!!
あとはソースをガリガリ書いて行くだけですね!

※これに関しても去年くらいの物なので現状でも動くかは解りません。

PhysXを使ってみる

まずは環境の構築のためSDKのダウンロード!

昔は解りませんが、現状だとNVIDIAさんのページから

http://www.nvidia.co.jp/object/physx_new_jp.html

「DeveloperZone」に飛んでアカウントを作成します。
「Request New Account」で情報を記入して送ればよかったはずです。
アカウントはリクエストすると数日でメールの返事が返ってきたと思います。

返答のあったメールに個別のアカウントページへのリンクか何かがあったと思うので、リンク先のページからPHYSXSDKがダウンロード出来たと思います。色んなプラットフォームに対応していたと思いますが、ひとまずテストするならWindows(PC)版で十分だと思いますし、使い易い気がします。

それでダウンロードしてきたインストーラーに従ってインストールすると準備完了。


そして今度はVC側の設定「ツール→オプション→プロジェクト及びソリューション」からインストールしたSDKへリンクを繋げます。

インクルードファイル
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.3\SDKs\Cooking\include
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.3\SDKs\PhysXLoader\include
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.3\SDKs\Physics\include
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.3\SDKs\Foundation\include

ライブラリファイル
C:\Program Files\NVIDIA Corporation\NVIDIA PhysX SDK\v2.8.3\SDKs\lib\Win32


とりあえずここまで行えば後はプログラムをガリガリ書いていくだけです。

※去年くらいの物なので現状でも動くかは解りません。


■以下追記
使用する内容にもよりますが、インクルードした物に合わせて追加の依存ファイルも設定する事になると思います。

「プロパティ→構成プロパティ→リンカ→入力」の「追加の依存ファイル」
 PhysXLoader.lib
 PhysXCooking.lib
などが必要になると思います。

また、ランタイムライブラリに関してはAMD製などのグラボの場合に動作させるのに必要な内容が入っていますので、場合によっては別途インストールが必要になります。(実行時にエラーが出た場合などインストールすると解決する場合があります。)

変数の足し算

TJSなどのスクリプト言語を使っていると変数の演算で想定外の結果が出る時があります。

そもそもスクリプト言語では変数の型など気にしなくてもいいようにどんな型でも入るようになっていたりします。これがC言語だとchar型、int型、float型がそれぞれ文字列、整数、浮動少数などになっていたりするんですが、スクリプト言語TJSの場合はvar型に文字列も整数も少数も代入する事ができます。

そこで一つはまったのが整数同士の足し算

var a = 1;

var b = a + 1;

// ウインドウで文字を出力
System.inform( b );

上記のウインドウに出てくる結果はC言語で考えるなら2なんですけどTJSスクリプトだと結果は11となります。
乗算しても割り算してもそんな数字にはならないのですが、ここでなんでも入る型が問題になってきます。TJSだと特に指定の無い演算だと自分で型を判断して勝手に計算してくれます。
それがどうやらデフォルトだと文字列として判断しているらしく、文字1と文字1を足すと文字11になるという風に解釈されているらしいです。

さてこれを数値として計算するためには変数の値が数値という事を知らせて演算する必要があります。

var a = 1;

var b = +a + 1;

// ウインドウで文字を出力
System.inform( b );

このスクリプトの結果画面に表示される内容は2になります。
何が違うのかと言うと変数aの前に+という記号が付いています。
これを付けることによって変数aは数字ですよ!という事を伝えて演算してもらう事になります。

多分初歩中の初歩ですね。恐らくマニュアルにも書いてあると思われますが、こんな事で数時間悩んだ自分がいましたのでご注意下さい。

レイヤー上で動画を再生する

久しぶりに更新してみます。

とりあえず前回の更新でやった動画再生を今度はレイヤー上で行ってみます。

既に吉里吉里にはそういう機能があるようなのでkag命令を使えば出来るようなのですが、私が使用しているゲームだと他にもボタンとか色々と表示物があったのでkagを使わずに直接TJSを書いて実装しました。

とは言ってもほぼサンプルで使われてるのそのままの様な感じです。

[iscript]

// ビデオを表示させるレイヤを作成
var m_MovieLayer = new Layer(window, page);
with(m_MovieLayer)
{
  .visible = false;
  .type = ltOpaque; // 完全不透明
  .name = "ビデオ表示用レイヤ";
}

kag.movies[0].stop(); // 再生は停止する
kag.movies[0].close(); // クローズもする
kag.movies[0].mode = vomLayer; // vomLayerはレイヤー描画モード
kag.movies[0].layer1 = m_MovieLayer; // レンダリングするレイヤーを設定

[endscript]

とりあえず設定部分のみ貼り付け。

1、表示するためのレイヤーを作る。
  レイヤーの設定を完全不透明にしないと上手くいかないかもしれません。
2、Videoの設定をレイヤー描画モードにする
3、描画するレイヤーを設定する

上記設定後に動画を読み込んで、
m_MovieLayer.visible = true;
kag.movies[0].play();

とするとレイヤー上で動画が再生されるようです。
ここでレイヤーのvisibleがtrueになっていないと何も画面に表示されないので上手くいっているのか、いっていないのかが解らなくなるので気をつけて下さい。


レイヤー描画モードで動画を再生すると動画の上にボタンを置けたりとか出来ることの幅が増えるので面白いかもしれません。
2枚レイヤーを使って別々の動画を再生したりする事も可能なようなので、その辺もやっていきたいなぁ〜

動画を再生してみる

たまには変わった事をしてみる!!


ということで急遽必要になったので吉里吉里のお勉強始めましたww

吉里吉里というのは基本的にはアドベンチャーゲームを作るために開発された物でTJSというスクリプト言語を用いて作られているっぽい。


このシステムを使うとあんまり細かくプログラムを知らなくてもなんとなくやってれば画面上に自分の好きな画像や文字を表示することがいとも簡単に出来ちゃう素晴らしいシステムである。


とまぁ全然説明になっていないのですが、
実際に動画を表示するためにはどうするのか。だいぶ色々とショートカットして内容だけ書いてみる。


※以下kag命令

[video visible=true top=0 left=0 width=800 height=600]

[openvideo storage="動画のファイル名.wmv"]

[wp for="prepare"]

[playvideo]

[wv canskip="true"]

[stopvideo]

大体の流れとしては、
1、ビデオの設定を行って(動画を再生してくれるプレイヤーのような物)

2、ビデオリソースを読み込む

3、ビデオリソースの読み込みを待つ

4、ビデオを再生する

5、ビデオの再生終了を待つ

6、一応スキップされた時はビデオを停止しておく

多分上記の様な流れになっているはず。
結果、画面800×600のサイズで動画が再生されるはずである。

注意して欲しいのはどの拡張子のファイルでも再生できるわけではないようだ。ただプラグインを使えば初期よりも多くの拡張子に対応できるようで拡張性が高いのも吉里吉里の良さなのかな。


これからもっと詳しく色々と調べて少し高度な事を実験してみたいと思う。