2Dスプライトを表示する |
Sprite.bmpという画像ファイルをスプライトにする例。抜け色は黒。
SPRITE_2D sp;
sp.Load("Sprite.bmp",D3DXCOLOR(0,0,0,255));
sp.Draw(NULL);
実際は、Load関数は1回だけ実行するので、完全なコードはだいたい次のようになります。
SPRITE_2D sp;
void MY_NEGAA::OneTime()
{
sp.Load("Sprite.bmp",D3DXCOLOR(0,0,0,255));
}
VOID MY_NEGAA::Main()
{
sp.Draw(NULL);
} |
抜け色を任意の色にする |
xxx.Load("Sprite.bmp",D3DXCOLOR(0,0,0,255)); (xxxは、そのスプライトのインスタンス)
Load()関数の第2引数が抜け色です。たとえば青(完全な青)のRGB値は0,0,255ですので、
xxx.Load("Sprite.bmp",D3DXCOLOR(0,0,255,255));としてロードすれば、青が抜けます。
また、抜け色をたとえば黄色にした場合、黄色(完全な黄色)は赤と緑が半々なので、
xxx.Load("Sprite.bmp",D3DXCOLOR(255,255,0,255));とすればいいのです。
|
位置座標をセットする |
xxx.vPos=D3DXVECTOR2(100,100); (xxxは、そのスプライトのインスタンス)
vPosメンバに直接ベクトル(2次元ベクトル)を代入します。
2Dスプライトなので、成分は”ピクセル単位”です。 |
平行移動する |
2通りの方法があります。
その1
vPosメンバを増減する。
xxx.vPos.x+=0.1; など
その2
Move()関数を使う。
xxx.Move(0.1,0); など
この場合、毎フレーム、x軸プラス方向に0.1ピクセル進みます。これからわかるとおり、Move()関数の第1引数はx成分の増加値、第2引数はy成分の増加値です。
|
姿勢(角度)をセットする |
xxx.SetAngle()関数を使います。 (xxxは、そのスプライトのインスタンス)
30度傾けたいときは、
xxx.SetAngle(30);
と書きます。 |
回転する |
xxx.Rotate()関数を使います。 (xxxは、そのスプライトのインスタンス)
xxx.Rotate(1); これで、毎フレーム1度の角速度で回転します。回転方向は時計回りが正方向です。
|
位置を初期座標に戻す |
(xxxは、そのスプライトのインスタンス)
xxx.ResetPosition(); |
姿勢(角度)を初期姿勢に戻す |
(xxxは、そのスプライトのインスタンス)
xxx.ResetAngle(); |
スケーリング(拡大縮小)する |
(xxxは、そのスプライトのインスタンス)
xxx.scale+=0.1; など |
初期スケールに戻す |
(xxxは、そのスプライトのインスタンス)
xxx.ResetScale(); |
画像の一部だけをスプライトにする |
(xxxは、そのスプライトのインスタンス)
矩形(RECT構造体)を指定します。例えば画像の左上から50ピクセル×50ピクセルだけを使用したい場合、次のように書きます。
RECT rect;
rect.top=0;
rect.left=0;
rect.right=50;
rect.bottom=50;
xxx.Draw(&rect);
|
カラーキー(抜け色)を指定する |
(xxxは、そのスプライトのインスタンス)
xxx.Load("media\\Sprite.bmp",D3DXCOLOR(0,0,255,255));
Load()関数を実行するときの第2引数が抜け色です。この場合、完全な青を抜け色に指定しています。
D3DXCOLOR()の部分は”抜け色”の指定です。抜け色とは、透過させたい色の値であり、絵の周りの色のことです。左から順にR,G,B,Aの値を0〜255の値を指定します。例えば、抜け色が黒なら0,0,0,255と指定し、抜け色が青なら0,0,255,255、抜け色が黄緑なら0,255,255,255、白なら255,255,255,255という具合です。 |
2Dスプライトのインスタンス同士を交換する |
SwapSprite2D()を使います。
memcpy()などで直接交換しないでください。(内部の管理情報が更新されず、レンダリングに支障がでるからです。)
例えば今、二つのインスタンスがあるとします。
SPRITE_2D sp1;
SPRITE_2D sp2;
この2つを交換(中身を入れ替える)するときは次のように書きます。
SwapSprite2D(&sp1、&sp2);
|
キーボード、押されたキーを検知する |
Key()関数が、キーボードを検知する関数です。Key()関数は、指定したキーが押されれば、true(真)を返します。
例えば、キーボードのスペースキーを押したら"hello world"という文字列を表示するというコードは次のように書けます。
if( Key(DIK_SPACE) )
{
RenderString("hello world",10,10);
}
Key()関数の引数には、DIK_から始まるキーボード定数を指定します。上の場合はスペースキーを検知したいのでDIK_SPACEとしました。DIK_OOは、キーボード定数で、キーの数だけあります。例えば、リターンキーならDIK_RETURN、左矢印キーなら DIK_LEFT、aキーならDIK_A、F1キーならDIK_F1という具合です。
|
マウス、押されたボタンを検知する |
マウスの左ボタンの場合、MouseLeftButton()関数が押下をtrueで返します。
例えば、マウスの左ボタンを押したら"hello world"という文字列を表示するというコードは次のように書けます。
if( MouseLeftButton() )
{
RenderString("hello world",10,10);
}
同様に、右ボタンは、MouseRightButton()関数。
3つボタンマウスの場合、真ん中ボタンはMouseMiddleButton()関数になります。
|
マウスカーソルの位置を得る |
MousePosition()関数を実行すると、戻り値としてマウスカーソルの現在位置(座標)をPOINT構造体で返します。
たとえば、現在のマウスポインタの位置を表示するコードは次のとおりです。
POINT pt;
pt=MousePosition();
char sz[100];
sprintf(sz,"x=%d y=%d",pt.x,pt.y);
RenderString(sz,10,10);
|
マウスカーソルの位置増分を得る |
MousePositionDelta()関数を実行すると、戻り値としてマウスカーソルの”前回位置からの座標の増分”をPOINT構造体で返します。
たとえば、前回位置からの座標の増分を表示するコードは次のとおりです。
POINT pt;
pt=MousePositionDelta();
char sz[100];
sprintf(sz,"x=%d y=%d",pt.x,pt.y);
RenderString(sz,10,10); |
3Dスプライト(テクスチャ付の板ポリゴン)を表示する |
Sprite.bmpという画像ファイルを3Dスプライトにする例。抜け色は黒。
SPRITE_3D sp;
sp.Load("Sprite.bmp",D3DXCOLOR(0,0,0,255));
sp.Draw(NULL);
実際は、Load関数は1回だけ実行するので、完全なコードはだいたい次のようになります。
SPRITE_3D sp;
void MY_NEGAA::OneTime()
{
sp.Load("Sprite.bmp",D3DXCOLOR(0,0,0,255));
}
VOID MY_NEGAA::Main()
{
sp.Draw(NULL);
}
なお、2Dスプライトと異なり、3Dスプライトは法線を持っていて、ライトを影響させることができます。
シーンにライトが無いと暗く見えるかもしれません。 |
ビルボード(常にこちらを向くテクスチャ付の板ポリゴン)を表示する |
Sprite.bmpという画像ファイルを3Dスプライトにする例。抜け色は黒。
BILLBOARD sp;
sp.Load("Sprite.bmp",D3DXCOLOR(0,0,0,255));
sp.Draw(NULL);
実際は、Load関数は1回だけ実行するので、完全なコードはだいたい次のようになります。
BILLBOARD sp;
void MY_NEGAA::OneTime()
{
sp.Load("Sprite.bmp",D3DXCOLOR(0,0,0,255));
}
VOID MY_NEGAA::Main()
{
sp.Draw(NULL);
}
なお、2Dスプライトと異なり、3Dスプライトは法線を持っていて、ライトを影響させることができます。
シーンにライトが無いと暗く見えるかもしれません。 |
3Dスプライト、ビルボードの位置座標をセットする |
xxx.vPos=D3DXVECTOR3(1,2,3); (xxxは、その3Dスプライト、ビルボードのインスタンス)
vPosメンバに直接ベクトル(3次元ベクトル)を代入します。
2Dスプライトは”ピクセル単位”でしたが、3Dスプライトは"ピクセル単位ではありません”。
|
3Dスプライト、ビルボードを平行移動する |
2通りの方法があります。 (xxxは、その3Dスプライト、ビルボードのインスタンス)
その1
vPosメンバを増減する。
xxx.vPos.x+=0.01; など
その2
Move()関数を使う。
xxx.Move(0.1,0,0); など
この場合、毎フレーム、x軸プラス方向に0.1単位(ピクセルではりません)進みます。これからわかるとおり、Move()関数の第1引数はx成分の増加値、第2引数はy成分、第2引数はz成分の増加値です。 |
3Dスプライト、ビルボードの姿勢(角度)をセットする |
xxx.SetAngle()関数を使います。 (xxxは、その3Dスプライト、ビルボードのインスタンス)
2Dスプライトと異なり、3Dスプライトは3つの軸を持っているので、回転角度も3つあります。(オイラー角)
Y軸まわりにだけ30度傾けたいときは、
xxx.SetAngle(30,0,0);
と書きます。
X軸周りだけに30度なら、
xxx.SetAngle(0,30,0);
Z軸周りだけに30度なら、
xxx.SetAngle(0,0,30);
という具合です。
では、ちょっと複雑に、Y軸周りに30度、かつX軸周りに30度の”姿勢”にしたい場合、
xxx.SetAngle(30,30,0);
と書きます。
ただし、オイラー角で意図した姿勢にするのは難しいです。回転の順序を知っている必要があります。
NEGAAでのオイラー角は、Y-X-Zの軸の順番で回転します。
|
3Dスプライト、ビルボードを回転する |
2Dスプライトと異なり、3Dスプライトは3つの軸を持っているので、回転も3種類あります。 (xxxは、その3Dスプライト、ビルボードのインスタンス)
ヨー回転(Y軸周り)、ピッチ回転(X軸周り)、ロール回転(Z軸周り)です。
xxx.Rotate()関数は引数を3つとり、それぞれヨー、ピッチ、ロールの回転角速度を意味します。
SetAngle()は角度そのものを指定したのに対し、Rotate()関数は”角速度”つまり、Rotate()を実行するたびに、角度は変化します。(SetAngle()は何回実行しても引数が変化しなければ角度も変化しません)
例えばロール回転だけをしたい場合、
xxx,Rotate(0,0,1);
などと書きます。単位は360度単位の度数です。(ラジアンではありません)
こう書けば、角速度 1(度/フレーム) つまり、毎フレームに1度ずつ 回転します。
|
3Dスプライト、ビルボードの位置を初期座標に戻す |
(xxxは、その3Dスプライト、ビルボードのインスタンス)
xxx.ResetPosition(); |
3Dスプライト、ビルボードの姿勢(角度)を初期姿勢に戻す |
(xxxは、その3Dスプライト、ビルボードのインスタンス)
xxx.ResetAngle(); |
3Dスプライト、ビルボードをスケーリング(拡大縮小)する |
(xxxは、その3Dスプライト、ビルボードのインスタンス)
xxx.scale+=0.1; など |
3Dスプライト、ビルボードを初期スケールに戻す |
(xxxは、その3Dスプライト、ビルボードのインスタンス)
xxx.ResetScale(); |
画像の一部だけを利用する |
(xxxは、その3Dスプライト、ビルボードのインスタンス)
矩形(RECT構造体)を指定します。例えば画像の左上から50ピクセル×50ピクセルだけを使用したい場合、次のように書きます。
RECT rect;
rect.top=0;
rect.left=0;
rect.right=50;
rect.bottom=50;
xxx.Draw(&rect);
|
カラーキー(抜け色)を指定する |
(xxxは、その3Dスプライト、ビルボードのインスタンス)
xxx.Load("Sprite.bmp",D3DXCOLOR(0,0,255,255));
Load()関数を実行するときの第2引数が抜け色です。この場合、完全な青を抜け色に指定しています。
D3DXCOLOR()の部分は”抜け色”の指定です。抜け色とは、透過させたい色の値であり、絵の周りの色のことです。左から順にR,G,B,Aの値を0〜255の値を指定します。例えば、抜け色が黒なら0,0,0,255と指定し、抜け色が青なら0,0,255,255、抜け色が黄緑なら0,255,255,255、白なら255,255,255,255という具合です。 |
3Dスプライト、ビルボードのインスタンス同士を交換する |
SwapSprite3D()を使います。
memcpy()などで直接交換しないでください。(内部の管理情報が更新されず、レンダリングに支障がでるからです。)
例えば今、二つのインスタンスがあるとします。
SPRITE_3D sp1;
SPRITE_3D sp2;
この2つを交換(中身を入れ替える)するときは次のように書きます。
SwapSprite3D(&sp1、&sp2); |
|
3Dメッシュを表示する |
基本形状(ボックス、スフィア、シリンダー、トーラス、ティーポット) と Xファイルメッシュ でロード部分が若干異なるので分けて述べます。ロード以外は基本的に同じです。
基本形状とXファイルでの根本的な違いは、Xファイルメッシュはその名のとおり、”Xファイルといういわば外部ファイル”が必要であるのに対し、基本形状は”計算的に形状を作成”できるので外部ファイルをロードする必要がないことです。
その違いにより、ロード部分が異なり、Xファイルメッシュのロード関数は”ファイル名(Xファイル名)”を引数にとります。
基本形状のロード関数は引数がありません。すべてのジオメトリを手続き的、プログラム的に内部で構築します。
Xファイルの場合の例。
XMESH xm;
void MY_NEGAA::OneTime()
{
xm.Load("Chips.x");
}
VOID MY_NEGAA::Main()
{
xm.Draw();
}
基本形状(ボックス、スフィア、シリンダー、トーラス、ティーポット)の場合の例。
ボックスだとして、
BOX box;
void MY_NEGAA::OneTime()
{
box.Load();
}
VOID MY_NEGAA::Main()
{
box.Draw();
}
なお、2Dスプライトと異なり、3Dスプライトは法線を持っていて、ライトを影響させることができます。
言い方を変えると、シーンにライトが無いと暗く見えるかもしれません。
ライトを追加します。平行ライトを追加したコードは次のとおりです。
Xファイルの場合の例。
XMESH xm;
DISTANT_LIGHT light;
void MY_NEGAA::OneTime()
{
xm.Load("Chips.x");
}
VOID MY_NEGAA::Main()
{
light.Illuminate();
xm.Draw();
}
基本形状(ボックス、スフィア、シリンダー、トーラス、ティーポット)の場合の例。
BOX box;
DISTANT_LIGHT light;
void MY_NEGAA::OneTime()
{
box.Load();
}
VOID MY_NEGAA::Main()
{
light.Illuminate();
box.Draw();
}
|
3Dメッシュの位置座標をセットする |
xxx.vPos=D3DXVECTOR3(1,2,3); (xxxは、そのメッシュのインスタンス)
vPosメンバに直接ベクトル(3次元ベクトル)を代入します。 |
3Dメッシュをワールド軸で平行移動する |
そのメッシュの向きがどうであろうと、とにかく絶対軸に沿って移動します。
MoveWorld()関数を使います。
xxx.MoveWorld(0.1,0,0); など
この場合、毎フレーム、x軸プラス方向に0.1単位(ピクセルではりません)進みます。これからわかるとおり、Move()関数の第1引数はx成分の”増加値”、第2引数はy成分、第2引数はz成分の”増加値”です。
このような移動が便利なときもありますが、たとえばフライトシミュレーターの飛行機の動きは、これでは不自然です。
|
3Dメッシュをローカル軸で平行移動する |
そのメッシュ自身の軸に沿って移動します。
MoveLocal()関数を使います。
xxx.MoveLocal(0.1,0,0); など
この場合、毎フレーム、x軸プラス方向に0.1単位(ピクセルではりません)進みます。これからわかるとおり、Move()関数の第1引数はx成分の”増加値”、第2引数はy成分、第2引数はz成分の”増加値”です。
ローカル軸なので、たとえば、90度傾いている姿勢の状態で左に移動するとワールド的に見れば上に移動しているように見え、いっぽう1人称視点では、画面に対し常に上下左右の移動に見えます。 |
3Dメッシュの姿勢(角度)をセットする |
xxx.SetAngle()関数を使います。 (xxxは、そのメッシュのインスタンス)
メッシュは3つの軸を持っているので、回転角度も3つあります。(オイラー角)
Y軸まわりにだけ30度傾けたいときは、
xxx.SetAngle(30,0,0);
と書きます。
X軸周りだけに30度なら、
xxx.SetAngle(0,30,0);
Z軸周りだけに30度なら、
xxx.SetAngle(0,0,30);
という具合です。
?
では、ちょっと複雑に、Y軸周りに30度、かつX軸周りに30度の”姿勢”にしたい場合、
xxx.SetAngle(30,30,0);
と書きます。
ただし、オイラー角で意図した姿勢にするのは難しいです。回転の順序を知っている必要があります。
NEGAAでのオイラー角は、Y-X-Zの軸の順番で回転します。 |
3Dメッシュを回転する |
(xxxは、そのメッシュのインスタンス)
メッシュは3つの軸を持っているので、回転も3種類あります。
ヨー回転(Y軸周り)、ピッチ回転(X軸周り)、ロール回転(Z軸周り)です。
xxx.Rotate()関数は引数を3つとり、それぞれヨー、ピッチ、ロールの回転角速度を意味します。
SetAngle()は角度そのものを指定したのに対し、Rotate()関数は”角速度”つまり、Rotate()を実行するたびに、角度は変化します。(SetAngle()は何回実行しても引数が変化しなければ角度も変化しません)
例えばロール回転だけをしたい場合、
xxx,Rotate(0,0,1);
などと書きます。単位は360度単位の度数です。(ラジアンではありません)
こう書けば、角速度 1(度/フレーム) つまり、毎フレームに1度ずつ 回転します。 |
3Dメッシュの位置を初期座標に戻す |
(xxxは、そのメッシュのインスタンス)
xxx.ResetPosition(); |
3Dメッシュの姿勢(角度)を初期姿勢に戻す |
(xxxは、そのメッシュのインスタンス)
xxx.ResetAngle(); |
3Dメッシュをスケーリング(拡大縮小)する |
(xxxは、そのメッシュのインスタンス)
xxx.scale+=0.1; など |
3Dメッシュを初期スケールに戻す |
(xxxは、そのメッシュのインスタンス)
xxx.ResetScale(); |
3Dメッシュの透明度を変える |
(xxxは、そのメッシュのインスタンス)
xxx.alpha=0.5; など |
3Dメッシュのアニメーションスピードを変更する |
(xxxは、そのメッシュのインスタンス)
xxx.m_fAnimSpeedメンバがアニメーションのスピードを意味します。
このメンバを増加すればアニメーションスピードは速くなりますし、減少させればアニメーションスピードは遅くなります。
したがって、アニメーションをストップさせたい場合、xxx.m_fAnimSpeed=0;とすれば止まることになります。 |
3Dメッシュののインスタンス同士を交換する |
SwapOOOD()系の関数を使います。OOOの部分はBoxとかSphereとかXmeshになります。
memcpy()などで直接交換しないでください。(内部の管理情報が更新されず、レンダリングに支障がでるからです。)
例えば今、XMESH型の2つのインスタンスがあるとします。
XMESH xm1;
XMESH xm2;
この2つを交換(中身を入れ替える)するときは次のように書きます。
SwapXmesh(&xm1,&xm2); |
鼻先(向いている方向)を調整する |
AdjustFaceDirection()メンバ関数を使います。例えば、姿勢行列(mOrientation)とは独立して、”見た目の向きだけ”を変えたい場合、Xファイルでキャラを右向きに作ってしまったが、実際は左向きを初期方向にしたときなど、
xxx.AdjustFaceDirection(180,0,0); (xxxは、そのメッシュのインスタンス)
このように書くと、”見た目”の向きが180度変化してくれます。引数は左から ヨー、ピッチ、ロールの意味です。
|
アニメーション内のフレーム位置を得る(セットする) |
GetAnimTime()メンバ関数により、アニメーションの現在フレーム位置が分かります。
また、SetAnimTime()メンバ関数により、アニメーションのフレームを任意の位置に進める(戻す)ことができます。
これにより、複数のモーションを1つのトラックで収録しているXファイルメッシュにおいて、モーションの切り替えが可能になります。
double frame=0;
xxx.GetAnimTime(&frame);
frameに現在フレーム位置が入ります。
xxx.SetAnimTime(3.5);
アニメーションのフレーム位置が3.5の位置に切り替わります。 |
文字列を表示する |
RenderString("hello world",300,200);
横300,縦200ピクセルの位置にHello Worldの文字列を表示します。
第2、第3引数はピクセル単位の座標になります。 |
変数等の値を表示する |
int i=7;
変数 i の値(7)を表示したいとき、
char str[200];
sprintf(str,"i= %d",i);
RenderString(str,300,200);
と書けば、座標(300,200)の位置に i=7 と表示されます。 |
フォントを変更する |
フォントのサイズ、フォントの色、あるいはフォントの種類そのものを変更したい場合があると思います。
NEGAAの文字列表示用に用意されているフォントは文字通り情報表示用の簡易なもので、フォントの属性を変更できるようにはなっていません。
自分なりに好きなようにフォントの属性を作成したい場合は、FONT型のインスタンスを作成します。
FONT font;
void MY_NEGAA::OneTime()
{
font.Load("arial",12,12,D3DCOLOR_XRGB(255,255,255));
}
VOID MY_NEGAA::Main()
{
font.Draw("hello world");
}
Load関数の第1引数はフォント名です。
文字の表示位置を指定する場合、vPosメンバに座標を代入します。
font.vPos=D3DXVECTOR2(300,200); |
フォントを3Dメッシュとして表示する |
FONT_MESH型のインスタンスを作成します。
FONTMESH fm;
void MY_NEGAA::OneTime()
{
fm.Load(L"hello world");
}
VOID MY_NEGAA::Main()
{
fm.Draw();
}
Load()関数に渡す文字列はワイド文字列である必要がありますので、先頭にLを付けます。 |
平行ライトを作成する |
DISTANT_LIGHT light; |
点ライトを作成する |
POINT_LIGHT light; |
スポットライトを作成する |
SPOT_LIGHT light; |
ライトを点ける |
Illuminate()メンバ関数を実行します。
そのライトのインスタンス名がlightであるとして、
light.Illuminate();
このように書きます。
|
ライトを平行移動する |
基本的に3Dメッシュと同じ挙動をします。
ワールド軸で平行移動するMoveWorld()関数 と
ライト自身のローカル軸で平行移動するMoveLocal()関数を持っています。
それぞれの意味、動作について不明であれば3Dメッシュの当該部分を参照してください。 |
ライトを回転させる |
基本的に3Dメッシュと同じ挙動をします。
RotateXXX()系のメンバ関数を持っています。
それぞれの意味、動作について不明であれば3Dメッシュの当該部分を参照してください。 |
ライトの姿勢(角度)をセットする |
基本的に3Dメッシュと同じ挙動をします。
SetAngle()メンバ関数を持っています。
それぞれの意味、動作について不明であれば3Dメッシュの当該部分を参照してください。 |
ライト自体をメッシュとして表示(非表示)する |
ライトの位置を確認したり、ライトの角度(姿勢)を確認したりしたい場合があります。
ライト自体をメッシュとして表示する機能があります。インスタンス名がlightだとして、次のように書きます。
light.boShowGeometry=true;
light.Draw();
逆に、ライトメッシュを表示したくない場合、はDraw()関数を実行しなければ当然表示されません。あるいは、boShowGeometry=false としても表示されなくなります。 |
輝度を変更する |
インスタンス名がlightだとして、輝度を2倍にしてみましょう。次のように書きます。
light.SetLuminance(2,2,2);
ただ通常は、0.0 - 1.0の間の値にします。 |
光の色を変更する |
インスタンス名がlightだとして、光の色を赤にしてみましょう。次のように書きます。
light.SetColor(255,0,0); |
カメラの位置座標をセットする |
SetPosition()メンバ関数を使います。たとえば、
xxx.SetPosition(1,0,0);
xxx部分は、そのカメラのインスタンス名です。(デフォルトのカメラはCamera) |
カメラをワールド軸で平行移動する |
例えば、絶対x軸方向に0.1単位/フレーム 移動するなら次のように書きます。
xxx.MoveWorld(0.1,0,0);
xxx部分は、そのカメラのインスタンス名です。(デフォルトのカメラはCamera) |
カメラをローカル軸で平行移動する |
例えば、そのカメラの姿勢によるローカルx軸方向に0.1単位/フレーム 移動するなら次のように書きます。
xxx.MoveLocal(0.1,0,0);
xxx部分は、そのカメラのインスタンス名です。(デフォルトのカメラはCamera)
|
注視点座標を指定する |
vLookメンバを直接変更します。
たとえば次のように。
xxx.vLook=D3DXVECTOR3(1,2,3);
xxx部分は、そのカメラのインスタンス名です。(デフォルトのカメラはCamera) |
視線ベクトルを指定する |
vPosとvLookのペアで視線を定義する方法以外で、視線を定義する方法が、この視線ベクトルの指定です。
アプリケーションによっては視線ベクトルを指定するほうが都合が良い場合もあると思います。
SetEyeDirection()メンバ関数を使います。たとえば次のように、
D3DXVECTOR3 v(0,0,1);
Camera.SetEyeDirection(&v); |
カメラを回転させる |
基本的に3Dメッシュと同じ挙動をします。
RotateXXX()系のメンバ関数を持っています。
それぞれの意味、動作について不明であれば3Dメッシュの当該部分を参照してください。
|
カメラの姿勢(角度)をセットする |
基本的に3Dメッシュと同じ挙動をします。
SetAngle()メンバ関数を持っています。
それぞれの意味、動作について不明であれば3Dメッシュの当該部分を参照してください。 |
カメラ自体をメッシュとして表示(非表示)する |
カメラの位置を確認したり、カメラの角度(姿勢)を確認したりしたい場合があります。
カメラ自体をメッシュとして表示する機能があります。インスタンス名がCameraだとして、次のように書きます。
Camera.boShowGeometry=true;
Camera.Draw();
逆に、カメラメッシュを表示したくない場合、はDraw()関数を実行しなければ当然表示されません。あるいは、boShowGeometry=false としても表示されなくなります。 |
ズームイン(アウト)する |
Zoom()メンバ関数を使います。
たとえば2倍にズームしたい場合は、
xxx.Zoom(2.0);
と書きます。1.0が通常です。
xxx部分は、そのカメラのインスタンス名です。(デフォルトのカメラはCamera) |
新たなカメラを追加する |
CAMERA型のインスタンスを追加し、SetCamera()関数に、そのインスタンスのアドレスを渡せば新しいカメラに切り替わります。
たとえば、camという新たなカメラを作成し、それに切り替えたい場合、次のように書きます。
CAMERA cam;
SetCamera(&cam); |
|
WAVファイルを再生する |
WAVファイルは、主に効果音に使われます。
再生するにあたって、まず行わなければならないことは、サウンドソース(サウンドファイル)の”ロード”(読み込み)です。
”ロード”した後に、”再生”できます。この、”ロード” → ”再生” という手順はMIDIでも同様です。
次の例は、boon.wavというwavファイルを読み込み、そして再生するコードです。
DWORD dwIndex=0;
LoadSound(&dwIndex,"boon.wav",NULL,NULL,true);
Play(dwIndex,true);
Load()は一度だけ行えばいい処理です。というよりもLoad()の実行は一度である必要があります。なぜ、ロードを一度しか実行したくないかと言うと、(同じサウンドとして)ロードを何回も実行すると、無駄なメモリーを食いつぶすことになるからです。もちろん、異なるサウンドをロードする場合は、また新たにロードすることにはなります。
サウンド(WAV、MIDI両方)の停止は、それぞれのインスタンスのStop()メソッドにより停止します。 |
MIDIファイルを再生する |
MIDIファイルはBGMに使われます。(SEには向きません)
再生するにあたって、まず行わなければならないことは、サウンドソース(サウンドファイル)の”ロード”(読み込み)です。
”ロード”した後に、”再生”できます。この、”ロード” → ”再生” という手順はWAVでも同様です。
次の例は、music.midというMIDIファイルを読み込み、そして再生するコードです。
DWORD dwIndex=0;
LoadMIDI(&dwIndex,"music.mid",true);
Play(dwIndex,true);
Load()は一度だけ行えばいい処理です。というよりもLoad()の実行は一度である必要があります。なぜ、ロードを一度しか実行したくないかと言うと、(同じサウンドとして)ロードを何回も実行すると、無駄なメモリーを食いつぶすことになるからです。もちろん、異なるサウンドをロードする場合は、また新たにロードすることにはなります。
サウンド(WAV、MIDI両方)の停止は、それぞれのインスタンスのStop()メソッドにより停止します。 |
ループ再生する(しない) |
Play()関数の第2引数がループの有無を意味しています。(WAV,MIDIともに)
第2引数をtrueにするとループし、falseにするとループせずに1度きりの再生になります。 |
アプリにフォーカスが無いとき、鳴るように(鳴らないように)する |
WAVの場合は、LoadSound()関数の第5引数が、MIDIの場合は、LoadMIDI()関数の第3引数が、グローバル再生するかしないかを意味します。
trueにすると、グローバル再生します。つまり、アプリケーションにフォーカスが無いとき(フルスクリーンアプリが起動したり、ウィンドウが隠れたときなど)でも、音が聞こえます。
falseにすると、グローバル再生しません。つまり、アプリケーションにフォーカスがあるときのみ、音が聞こえます。
|
WAV、MIDIのボリュームを変更する |
SetVolume()関数を使います。
第1引数に、そのサウンドのインデックス(ロードしたときに受け取ったDWORD値)を、第2引数にボリュームを-10000から0の間で指定します。(0が最大ボリューム) |
WAV、MIDIの再生速度を変更する |
SetSpeed()関数を使います。
第1引数に、そのサウンドのインデックス(ロードしたときに受け取ったDWORD値)を、第2引数にスピードを指定します。
スピードは、現在のスピードに対する倍率で指定します。したがって、2.0とsれば現在の2倍のスピードに、また、0.5などとすれば半分のスロー再生になります。 |
WAV、MIDIに基本エフェクトをかける(解除する) |
エフェクトをかける場合、Add_Effector ()関数を使います。
エフェクトを解除する場合は、Sub_Effector()関数を使います。
これらは、エフェクト単位で指定できます。つまり、ひとつのサウンドに複数のエフェクトをかけたり、複数のエフェクトの中から特定のエフェクトのみを解除することができます。
アプリケーション側では、それぞれのエフェクトを、エフェクトのハンドルで識別します。(サウンドをDWORD型のハンドルで管理するのと同じです)
Add_Effector ()関数の引数の意味は次のとおりです。
第1引数、サウンドソースのインデックスを指定します。このインデックスは、LoadSound系メソッドの第1引数で返されたインデックスです。
第2引数、エフェクターの追加に成功したら、そのエフェクターのハンドル(インデックス)が返ります。通常は、追加した順番での連番が返ってきます。
第3引数、使用しません。NULLにしてください。
第4引数、EFFECTOR列挙定数でエフェクターの種類を指定します。
EFFECTOR列挙定数は次のとおり定義しています。
enum EFFECTOR
{
EFFECTOR_NULL,
GARGLE,
CHORUS,
FLANGER,
ECHO,
KODAMA,
DISTORTION,
COMPRESSOR,
PARAEQ,
I3DL2,
WAVES
};
ガーグル、コーラス、フランジャーなど、そのままの名前です。
Sub_Effector()関数の引数の意味は次のとおりです。
第1引数、サウンドソースのインデックスを指定します。このインデックスは、LoadSound系メソッドの第1引数で返されたインデックスです。
第2引数、エフェクターのハンドルを指定します。このハンドルはAdd_Effectorメソッドの第2引数で返されたインデックスです。 |
WAV、MIDIに
プリセットエフェクト をかける(解除する) |
NEGAAには、面白いエフェクター(以降 プリセット)が実装されています。
レンガの壁に反射した音、銭湯の中、水中・・・など、とくにNorthBrainが気に入っているのは“外人”(識別子GAIJIN)です。GAIJINをかけると、そのサウンドはイントネーションが不自然になります。とくに音声にかけると、笑いがおこるのは必至です!
プリセットをかける場合、Add_Preset()関数を使います。
プリセットを解除する場合は、Sub_Preset()関数を使います。
これらは、プリセット単位で指定できます。つまり、ひとつのサウンドに複数のプリセットをかけたり、複数のプリセットの中から特定のプリセットのみを解除することができます。
アプリケーション側では、それぞれのプリセットを、プリセットのハンドルで識別します。(サウンドをDWORD型のハンドルで管理するのと同じです)
Add_Preset()関数の引数の意味は次のとおりです。
第1引数、サウンドソースのインデックスを指定します。このインデックスは、LoadSound系メソッドの第1引数で返されたインデックスです。
第2引数、プリセットの追加に成功したら、そのプリセットのハンドル(インデックス)が返ります。通常は、追加した順番での連番が返ってきます。
第3引数、EFFECT_PRESET列挙定数でプリセットの種類を指定します。
EFFECT_PRESET列挙定数は次のとおり定義しています。
enum EFFECT_PRESET
{
EFFECT_PRESET_NULL,
//現実系
TUNNEL,
MOUNTAIN_ECHO,
BRICK_BIG_WALL,
WATER,
BIG_WIND,
TRANSCEIVER,
SENTOU,
OLD_RADIO,
//変換系
CREATURE,
ROBOT,
SPACEMAN,
CLEAR_VOICE,
CLEAR_VOICE2,
TAPE_FF,
TAPE_FF_x2,
TAPE_FF_x4,
TAPE_SLOW,
TAPE_SLOW_x2,
TAPE_SLOW_x4,
GAIJIN,
};
名前から、だいたいその効果が想像できるでしょうか。
Sub_ Preset()関数の引数の意味は次のとおりです。
指定した種類のプリセットを削除します。(指定したプリセットの効果だけを消します)
第1引数、サウンドソースのインデックスを指定します。このインデックスは、LoadSound系メソッドの第1引数で返されたインデックスです。
第2引数、プリセットのハンドルを指定します。このハンドルはAdd_Presetメソッドの第2引数で返されたハンドルです。
第3引数、EFFECT_PRESET列挙定数でプリセットの種類を指定します。 |
WAVを3Dサウンドとして再生する |
3Dサウンドとして再生したい場合は、ロード時点から3Dサウンドとしてロードする必要があります。(LoadSound3D()関数でロードします。)
WAVファイルからサウンドソースを3Dサウンドとして読み込みます。
サウンドファイルはモノラルWAVでなければなりません。2チャンネル以上(ステレオ以上)である場合、ロードはされますが、通常のWAVとしてロードされ、3Dメソッドは使用できません。
第1引数、pdwIndex 読み込みが成功したら、サウンドソースのインデックスが返ります。通常は、ロードした順番での連番が返ってきます。
第2引数、pcFileName ロードするWAVファイルのファイル名を指定します。
第3引数、 fDamping3Dサウンドにおいて、この値以上の距離になると、音の減衰が始まります。
第4引数、dwNumNotify ストリーミングしたい場合に指定します。単位区間内で何個のイベントメッセージを発生させるか、その回数です。通常は2個から4個の範囲で問題ありません。これを設定したなら、同時に dwSecsも設定してください。
第5引数、dwSecs 通知区間の長さを秒単位で指定します。通常は2秒から10秒程度にすると思われます。これを設定したなら、同時にdwNumNotifyも設定しなくてはなりません。
第6引数、boVirtual 使用しません。
第7引数、HRTFLevel 頭部伝播関数の精度を指定します。HRTF_LEVEL列挙定数により3段階の精度を指定します。
第8引数、boGlobal アプリケーションがバックグラウンドになっても依然として音を鳴らすか鳴らさないかのフラグです。これをtrueにするとバックグラウンドでも鳴るようになります。
HRTF_LEVEL列挙定数は次のように定義しています。
HRTF_LEVEL_NULL…NULL
HRTF_NONE…HRTFをかけない。
HRTF_LOW…HRTF計算を中程度おこなう。
HRTF_HIGH…HRTF計算をフルに行う。 |
ドップラー特性を変更する |
HRESULT EnableDopplerEffect(BOOL boEnable)
ドップラー効果を有効または無効にします。boEnableをtrueにすれば有効に、falseにすれば無効になります。
HRESULT SetDopplerEffect(FLOAT fCoefficient,FLOAT fMeasure)
ドップラー効果の度合いを変更します。
ドップラー効果は、個々のサウンドに対してではなく、耳に対しての属性です。したがってサウンドのインデックスを指定する必要はありません。
第1引数、fCoefficient1で自然なドップラー効果になります。効果を増幅させたい分だけ数値を増やします。2で2倍、3で3倍、、、という具合です。
第2引数、fMeasure ドップラー効果が変化する単位メートルを指定します。例えばこれを5とすると、5メートルおきにドップラー効果が変化します。また例えばこれを100とすると100メートル以内の移動であればドップラー効果がかからないことになります。 |
3Dサウンドの位置を変更する |
HRESULT MoveSound(DWORD dwIndex,FLOAT x,FLOAT y,FLOAT z)
3D空間内で”音源”を移動します。3D空間ではこの”音源”、それから”リスナー(耳)”という2つの主体により音場を表現します。耳は聞き手そのものを、音源は文字通り音を出すものを表します。
3D音場において、耳を動かすことと音源を動かすことは相対的に見ると同じことです。
相対位置が変化すれば音量が変わり、変化の途中(つまり、相対速度がある場合)では音程も変わります。
第1引数、dwIndex サウンドソースのインデックスを指定します。このインデックスは、LoadSound系メソッドの第1引数で返されたインデックスです。
第2から第4引数は3D空間での座標を表しています。
”耳”がアプリケーション内に一つだけなのに対し、音源はサウンドのことなので複数存在しえます。 |
3Dサウンドのリスナーの位置を変更する |
HRESULT MoveEar(FLOAT x,FLOAT y,FLOAT z)
3D空間内で”耳”を移動します。3D空間では、この”耳”と”音源”という2つの主体により音場を表現します。耳は聞き手そのものを、音源は文字通り音を出すものを表します。
3D音場において、耳を動かすことと音源を動かすことは相対的に見ると同じことです。
相対位置が変化すれば音量が変わり、変化の途中(つまり、相対速度がある場合)では音程も変わります。
3つの引数は3D空間での座標を表しています。
音源はサウンドのことなので複数存在しえますが、耳はただ一つしか存在しません。したがってサウンドのインデックスを指定する必要はありません。
HRESULT RotateEar(FLOAT fYaw,FLOAT fPitch,FLOAT fRoll)
3D空間内で”耳”を回転します。
ちょうど現実において、自分の頭を回転(首を曲げて方向を変える)のと同じことです。
第1引数、ヨー回転(Y軸周りの回転)成分
第2引数、ピッチ回転(X軸周りの回転)成分
第3引数、ロール回転(Z軸周りの回転)成分
音源はサウンドのことなので複数存在しえますが、耳はただ一つしか存在しません。したがってサウンドのインデックスを指定する必要はありません。 |