カテゴリー

アクセスカウンター


since 1996/06/14

Count per Day

  • 11今日の訪問者数:
  • 48昨日の訪問者数:
  • 1266月別訪問者数:
  • 0現在オンライン中の人数:

通信制御

 今回は一連のDirectXがプログラミングの続きですが、DirectXとはあまり関係ないプログラムのネタです。通信対戦ゲームやMMORPGのようなゲームには、ネットワーク経由での通信制御が必要です。では、通信をどうやって実現しようか…?  今回考えた候補は以下の通り。 DirectPlay(DirectXのモジュールの一つで、ネットワーク通信専用モジュール。 フリーのソレっぽいモジュール(今回はHawkNLを使ってみた) 気合いで一から書く。  まぁ、最近blogでこのネタを扱わなかったのは、この辺でモンモンとしていたからです。  まず、DirectPlay。これは評判が悪いですね。何でかよく知らないけど。  まぁ、でも評判云々の前に、まるで通信対戦の概念を知らない私が選り好みをしてる方がアフォっぽいので、コーディングしてみた。  結果は、まず参考となるサイトが少ないですね。DirectX SDKのサンプルとかチュートリアルも、今使っている2007/Febには付いて無くて、2003/Summerまで遡ってGETしましたが、参考になるのがソレとHELPくらいしか無いので、非常に辛いです。サーバ/クライアントで繋がるくらいまで組んだけど、よく分からない分制御がしづらいのでDirectPlayはやめにしました。  次は、HawkNL。英語サイトしか無いのでわからん(笑。 まぁ、コードは組んだけど、せっかくこういうモジュールを使うなら、完全なブラックボックスで、あまり中身を意識しなくてもいいような使い方をしたい。SocketとかMulti Threadとかの機能があるけど、結局通常のAPIの焼き直しっぽくて、、、まぁ、不採用。 Amazon:4797330449  で、結局Socket(winsock)を使って自前で組みました。winsockのプログラミングって過去にやった記憶があったので本棚を漁ったら→こんな本を発見(リンク先は最近の本だけど、うちにあったのは同じやつの1998年度版)。既に10年近くの本だけど、winsock自体の仕様がほとんど変わってないってのは嬉しいね。  とりあえず、思いだし程度に1、2時間程度でサラっと読み返して、後はインターネットでサンプルコードを探してコーディング。いきなり現状のクライアントに組み込むのもアレなので、テストクライアントも作成って感じです。 現状はここまで。  簡単な通信は実現できたから、あとはマルチタスク化して多量の通信でも難なくこなせるような仕組みにしたいな。まだもうちょっといろいろと時間がかかりそうです。  以下、買ってないけど参考になりそうな本。これからこういうプログラミングをする人は参考にしてみて下さい。 Amazon:4797328479 Amazon:4797328460

目が〜

 右目が真っ赤になっちゃいました。どうも、まぶたの内側に変な腫物ができたようで、それが眼球を刺激しているようです。そんな訳で、今は左目だけでブログを書いています。  こういうときこそブログを書かなくては!…と言っても、左目は運転免許所をメガネ無しでギリギリ通る程度の視力なので、あまり見えません。ぶっちゃけ、ディスプレイの文字もかなりボヤけてます…。明日…仕事休んで眼科へ行ってきます…  ま、それはそれとして、上の画像は毎度おなじみDirectXなプログラミングネタ。  3Dゲームとかで、画面をクリックすると、そこに向かってキャラが走り出したりしますよね。この前の土日は、その「画面をクリックと仮想世界との連動」のプログラムをしてました。  「画面」という平面をクリックした場合、そこは仮想世界(3D)のどこをクリックしたのかを計算しなければなりません。これはさほど難しくなく、仮想世界のどこかにあるカメラから見ているので、そのカメラの中心位置からのマウスの相対位置で求めることが出来ます。  ちなみに仮想世界の視点は「点」ではなく、その点から少し離れた面としています(たぶん)。  クリックした場所がわかったら、こんどはそこから仮想世界の中で線を引きます。 線と仮想世界の地面の交点が、「クリックした場所」になるわけです。  ちなみに、「線」というのは、

2つの点 1つの点と方向

 

のいずれかがわかれば引けます。これは、小学校の算数で習います。しかし、「クリックした場所」という一点しか求めていません。もう一つの情報である「方向」を与えます。方向というのは「カメラの向いている方向」というのがあります。ちなみに、「カメラの向いている方向」と完全に平行にはなりません。カメラで見た世界は「奥ほど広い」ので、「クリックした場所」が中心でないかぎり、距離が遠くなるほどに、カメラの向いている方向から離れます。  まぁ、その辺の微妙な演算をしてくれる関数が存在しているので、ペロっとデータを与えれば計算してくれます。  これで、クリックした点とそこからの線が求まりました。しかし、これでもまだ終わりじゃないです。その求めた「線」と仮想世界の中の地面という「面」の交点を求めなければなりません。  まぁ、この交点を求めるのも、関数+αで計算出来ます。  で、上の画像ですが、今回、テクスチャにちょっと細工をしました。四角いマス1つに「●」というマークを付けています。この世界は●という「面」の集合で出来ています。この画面の中には700くらいの●(面)があるでしょう。  つまり、一回クリックするごとに、このすべての●に対して、クリックしたポイントからの線と交わっているかを計算します。当然700●なら、700回計算です。  しかも、デコボコなので、手前の●と奥の●とかもあります。  最後の計算は結局力業なので、その分繰り返してやります。で、そんな計算地獄を2日間ほどかけてやってクリックした場所にカーソル(上の画像の赤丸で囲んでいる所にある赤いオブジェクト)が行くようになりました。  ちなみに画面描画をしながらこんな計算をしたら、画面が一瞬とまっちゃうので、この計算はバックグラウンドでガシガシやっちゃいます。  日頃、何気なくゲームでクリックとかしてると思いますが、裏ではこんなことをやってるんですよ。ホントに疲れます。  目がおかしくなるのもわかるでしょ?

 

[…]

鎧を着たり、武器を装備したり

 またかなり時間が開いてしまいましたが、今回はキャラクターモデル系のプログラムを書いていました。あと、そのネタ用のモデルデータを作るのも一週間くらいかかっちゃったかな。  まずは、人が走っているところ。 剣を装備したり。 盾を装備したり。 〜こっから技術的な話  モデルデータを表示するだけならかなり簡単です。モデルデータを市販のツールで書いてロードするだけでほとんど終わりですから。  アニメーションはちょっと面倒です。市販のツールでアニメーションデータを作るまでは問題無いですが、そのモーションデータをロードして骨格をシミュレーションしたりとか・・・まぁ、ほとんどどこぞのソースコードをコピペですが、、、。  で、今回の難関。そういったモデルデータを一部分だけ変更するというもの。たとえば剣を持たせたり。  やり方はいろいろありますが、何より市販のツールから読み込んで勝手にうまくやってくれる処理の中身を分解して自前で書いたりとか、だんだん三次元情報を数値と計算でコネコネしてやらないとダメになります。  申し訳ないが、そんなコード作る気合いも根性も無いですえぇ。で、かなり手抜きですが、今回の方法は以下の通り。  まず、素体君を作ります。素体君データはポリゴンモデルは適当です。むしろポリゴンもテクスチャもマテリアルもいりません。必要なのはボーン(骨格)とアニメーションデータです。  で、素体君をプログラム上で走らせたり歩かせたりします。これは、普通のアニメーションのコードでかけます。  ここからがキモですが、アニメーションってのは、たとえば肘が何度曲がったとか、腰がどのくらい折れたかとか、「時間と角度」だけのデータです。  なので、素体君が一コマ動いたら、その関節の角度をすべて記録します。  だいたいこんな感じ。

//初期化処理(関節の個数分、マトリックスの変数を準備) D3DXMATRIXA16 savemat = new D3DXMATRIXA16関節の数; 〜ざっくり略〜 //アニメーション処理 D3DXMATRIXA16 mat; 〜ざっくり略〜 D3DXMatrixMultiply( &mat, ほげふが );//←関節の回転角度を計算 m_pD3DDev->SetTransform( ほげふが, &mat );←回転させる savematx = mat; //←回転角度を関節の個数分の配列に保存

 素体君の役割はここまで。 次に実際に描画したいモデルを準備。このモデルは関節毎にバラバラです。ただ、素体君がアニメーションしてない時と、関節の角度や腕などのパーツの位置は、寸分違わず作ります。で、バラバラに保存します(あとでばらせるなら、一緒に保存してもいい)。  で、バラバラのパーツを一つずつ読み込んで、素体君がアニメーションした時の関節角度と同じだけ、パーツを回転させます。  これであとは、必要なパーツだけ読み込めばオッケーです。剣を装備したいなら剣のオブジェクトを読み込んで、「手」と同じ角度分回転させればあたかも剣を装備したように見えます。  まぁ、これだと問題なのはマントやスカートみたいに、オブジェクトを歪ませるのは出来ません。それをやるには「オブジェクト毎の回転」ではなく、「ポリゴンの頂点毎に移動/回転」をさせなければなりません。  とりあえず、今回は技術的なことはなるべく二の次にして、やりたいことをやるのが最優先なので、そういうオブジェクトの変形はパスです。  それに、いずれもっといろんな服とか装備とか作らないとならないっすからね。  で、この人はまだ一カ所を走っているフリなので、今度は特定の箇所をクリックしたらそこに向かって走っていく…なんていう面倒な処理を考えナイト。

 

[…]

人が降り立った

 前回から大分時間が経ちましたがまたDirectXなプログラミングネタです。とりあえず、以下のような機能ができあがりました。

世界が広がった。 人が降り立った。

 前回の舞台は100×100ポリゴン(実際にポリゴンは三角形なので、1×1の中には2枚のポリゴンが居ます)でしたが、今回は1000×1000ポリゴンです。

 …と簡単に書きましたが、ここでいろいろやっています。まず、1000×1000のフィールドデータを一つ一つ作るのは面倒なので、お絵かきツールで地図を描いてそれを読み込むっていうのをまずやりました。まぁ、そこは難しくないけどね。

 

さらに、地平線の彼方にメモリを食われるのは勿体ないので、それを分割して、ある程度移動する毎に必要なデータを読み込むという処理をしています。簡単に書いたけど、案外計算が面倒です。  なので、データさえ作れば1000×1000以上も余裕で可能。さらに、フィールドデータの無いエリアを越えるとどうなるかというと、永遠と海が続きます。見えない壁にぶつかるのは虚しいですからね。  あとは、読み込む時に一瞬止まるので、データ読み込みとかを別スレッドで動かせればなぁと考えつつ、まだやってません。  「人」は、身動きしないモデルデータを読み込むのは簡単だけど、アニメーションするモデル(歩いたり走ったり)を処理するのはちょっと大変でした。次はたとえば剣を持ったら剣を表示とか、そういうオブジェクトの合成を考えないと…って感じ。  その辺まで出来れば、木とか建物とかのオブジェクトを管理するモジュールを作って、仮想世界の中にばらまけばソレっぽくなるかな。  ちなみに、この仮想世界の中でカメラを動かせますが、そこにもいくつか問題があります。たとえば、マウスをクリックするとそこに移動とか。  3Dモデルは、適当に3次元のベクトル座標を食わせれば、内部で擬似的に3D空間を作りつつ、カメラの位置にあわせで2Dに変換して画面へ表現するってことをほぼ自動でやってくれます。  しかし、2D空間でクリックした場合、それを3次元空間に変換して、クリックされたのは目の前のオブジェクトか、先のオブジェクトか〜なんて判定をしてやらないとなりません。…これってどうやるんだろう?(^^;  あと、キャラクターの移動は単純に考えています。マビノギや、リネージュ、FFXIのようにスムーズにどこでも移動とは考えていません。仮想空間の中に擬似的に50cm四方の「マス」が存在していて、そこに移動します。つまり、ラグナロクオンラインみたいに、移動先は四角いマスの中になります。しかも、8方向の移動しか考えてません。  リアリティには欠けるけど、その先にある、人と人、人と物の衝突判定は、その50cm四方だけを考えればいいので、処理的には全然楽になります。  いろいろ書いたけど、まぁまだまだやることはいっぱいあるって感じ。

 

[…]

DirectXなネタ

なんか、最近プログラミングなネタばっかりですみません。 ってことで、また最近熱が入っているDirectXなネタ。  前回、影のコントロールが出来たので、今回は地形データをいじってみた。前回までは配列に手で一つ一つデータを入れていたんだけど、今回はペイントで描いた平面図をデータ変換して読み込ませてみた。ちょっと中国の山々みたいだけどね…  モデルデータサイズも前回は20×20ポリゴンから、今回は100×100ポリゴンまで増やしてます(あ、あと海面も付加)。  あとは、モデルの中を移動する際に、動的に必要な分だけポリゴンをモデリングする機能を作れば、仮想世界の中での移動ができそう。  テクスチャとか、影の落とし方とかがショボいけど、テクニカルな部分は後回し。

法線その2(昨日の続き)

かんぺき♪ やっと美しい影が付きました。 …今日のブログはこれだけw

法線

 本題に入る前に〜…いや、DirectX(3Dゲームでよく使われるプログラムの基盤みたいなの)でプログラミングをしている訳ですが、ここまで作るのに実は一ヶ月くらいかかってるのよ。ウインドウを汎用的に表示てきるモジュールと、地面っぽいのを出すモジュール。まぁ、地面っぽいのはまだ制作途中だけど。  で、本題ですが、この地面おかしくないですか?立体なんですが、影がありません。 いろんな本とかネットで調べた結果、原因が分かりました。  こういう3D画像って「面」の集まりだけど、その一つの面に垂直な線を引きます(そういうイメージをしてみて下さい)。で、光はその面に当たると、面に垂直な線を軸にその反対側へ反射しますよね?その軸のことを「法線」って言います。  実は、この地面。その法線がすべて上を向いています。だから、どこの面に光が当たっても平らな地面と同じ反射の仕方をします。なので、陰影が無いと… … めんどくせぇな…そのくらい上手くやってよ… と、思いつつ法線計算ロジックを探しながら、一晩かけて作ってみました。 ※3Dモデリングツールとかで作れば、勝手に計算してくれるんだけどね。これは動的に地面を生成したいので、こつこつ計算して作ってます。 結果 なんか、この影嘘臭くね? 続きは明日でいいや…orz

DirectXっぽい備忘録

 管理者のメモです。まぁ、興味のある人は読んでも損にはならないかも。 2007年5月時点での情報なので、鮮度にご注意を。 DirectX Microsoftが作ったマルチメディア処理用API群。 最新はDirectX10だけど、WindowsVista以降にしか入ってないし入らない。 以下のコンポーネントを含んでいる。 DirectX Graphics…2D/3D処理。Direct3DとかDirectDrawとか言われていたものが統合されたモノ。 DirectX Audio…BGMとかSEの再生。 DirectInput…主にキーボードとマウスとジョイスティック制御。 DirectPlay…ネットワーク系。 DirectShow…動画再生とか? Managed DirectX  .NET FrameworkベースのアプリからDirectXを呼ぶ為のAPI。 今後はMicrosoft XNAに置き換わる。 Microsoft XNA  いろんなプラットホームに対応するように見せかけた、ゲーム開発用フレームワークで、WindowsとXBox360に対応している。年間一万円くらい払えばこれでXBox互換ゲームも作れる(作ってもプレイヤーも年間一万円くらい払わないと出来ない)。 開発言語はC#。 ボーンスキャニング、ネットワーク系のコンポーネントが遅れてる? OpenGL オープンソースのグラフィックライブラリ。マイクロソフトとは直接関係ない。  純然たるDirectX以外の最近のテクノロジーはまだまだって感じ。ある程度形がしっかりしたらいい感じになるのかな(でも今からC#なんて覚えたくない)。 開発ツールが無料になった分、マイクロソフトも成長したなぁと思う。

キャレット

 カーソルには、マウスカーソルとワープロとかで文字を打つ場所にあるカーソルの二種類あるわけですが、文字を打つ場所にあるカーソルのことを「キャレット(caret)」って言います。  Windowsが出来る前の時代は普通にカーソルって言っていましたが、Windows時代になってキャレットって言うようになったそうな。  つうか、そんなのプログラマーくらいしか知らないよ。  で、4/29のブログにDirectXっぽいネタを書きましたが、今は3D描画では無くて、UI(ユーザインターフェース)…つまり文字とかコマンドを入力するようなところにチャレンジしています。  普通のWindowsのプログラムなら、画面上にボタンとかテキストボックスとかをペタペタ貼るだけで作れます。しかし、DirectXにはそんなものはありません。ボタンなら、ボタンの四角い枠から、ボタン上の文字、ボタンをクリックしたという処理とか、クリックした時に凹んだ画像までそういうプログラムを全部書きます。  文字入力のコピペ処理なんて、文字の選択中は選択範囲の色を反転させるとか、CTRL+Cを押すとどうのとか、考えるだけでイヤになります。 …ってのはまぁ面倒なので、DirectXのSDK(Software Development Kit:ソフトウェア開発キット)にDXUTというオマケが付いているので、今回はそれを利用。  だがしかし!うまく動きませんorz テキストボックスにメッセージを入力すると、普通はカーソル(キャレット)は右に移動しますが、移動しません(T_T  DXUTのサンプルでCustomUIというのがありますが、それも同様。試しに別のパソコン(Windows2000)で試しても同じ。 う〜む。  ググってもそれっぽい情報が出てこないんだよなぁ〜。うちだけの問題なのかなぁ。 とりあえず、DXUTのソースを追ってみると、

CDXUTEditBox::Render(エディットボックスの描画処理)内にあるm_nCaretがどうもカーソルの位置を示しているっぽい。 「hr = m_Buffer.CPtoX( m_nCaret, FALSE, &nCaretX );」ってところで、m_nCaretと文字情報から、実際の相対座標をnCaretXに格納してるっぽいが、nCaretXには常にゼロが入っている。 ↑のCPtoX(CUniBuffer::CPtoX)を辿ると、「Analyse();」という関数が常にE_NOTIMPL(そんなオブジェクトねぇよ)を返している。 ↑のAnalyse(CUniBuffer::Analyse)を辿ると、_ScriptStringAnalyseが常にE_NOTIMPLを返している。

って感じ。それ以上先はわからん。ScriptStringAnalyseはusp10.dllってところで処理が動いているみたいだけど、このDLLのバージョンを変えてみたりとかしてもダメだったので、とりあえずギブ。 …  あぁ〜。今日の昼に食べた寿司は旨かったなぁ…(←現実逃避) …  とりあえず、m_nCaretにカーソルの位置が入っているので、その分の適当な数字をCPtoXの中でnCaretXに入れてやるとうまく動く感じ(実際には全角1文字も半角1文字と判断しているようで、全角文字を入れるとおかしくなる)。 まぁ、この辺はフォントクラスから情報を貰ってごにょごにゅすればうまくいくのかな。いい加減時間をかけるのが勿体ないので、そんな方向で逃げよう。  そういえば、マビノギ(ネットワークゲーム)でも最近のパッチで文字入力(漢字変換)がおかしくなったけど、ゲームの開発者も同じような苦悩をしているのかな。

[…]

ネットゲー

G/W中いくつかやりたいことの一つで、3D(DirectX)のプログラミングに挑戦中。 とは言っても過去に挫折している上、今回は2週間でやっと

平らな板の表示。 光源設定。 カメラを自由に動かす。 中心位置を自由に動かす。

…ができたくらい(しかもこっそり例外エラーが出てるし)。キャラクターとか細かいものは後回しで、とりあえず頭で思い描いているモノが出来ればいいなぁ。