FPSを作ってみる@wiki
10)
最終更新:
slice
-
view
(2010/10/30)
ゲームとは直接関係ないけどDirectX11が気になる頃だね.
Vista=DirectX10をスキップしたけど7から入る人って結構居るんだろうか?
ジオメトリシェーダーやテッセレーションは名前しか知らないっす.
流行ってたHDRも触っただけで本当に「ちょっとやってみた」レベルだし・・
今だとテクスチャへ静的に影の焼付けなんて時代遅れかもわからんね.
こうなったらモバイル機器へ逃げるか?なんて思ったり思わなかったり.
片手に収まる機械で自作ゲームを動かすのは夢の一つでもあるから.
Vista=DirectX10をスキップしたけど7から入る人って結構居るんだろうか?
ジオメトリシェーダーやテッセレーションは名前しか知らないっす.
流行ってたHDRも触っただけで本当に「ちょっとやってみた」レベルだし・・
今だとテクスチャへ静的に影の焼付けなんて時代遅れかもわからんね.
こうなったらモバイル機器へ逃げるか?なんて思ったり思わなかったり.
片手に収まる機械で自作ゲームを動かすのは夢の一つでもあるから.
さて,現在は当たり判定ルーチンに取り掛かって・・って前回書いたわけだが.
先週はなんやかんやで別の作業してたな.
確かコリジョンのデータ配置,更新タイプ考えたり
メインで使うであろうゲームオブジェクト基底クラス(以後GObj)の整備
毎フレーム送られてくる"UPDATE"メッセージでは指定フレームだけ更新を停止するsleep()のような関数を用意.
これで move_left(), sleep(10), move_right(), sleep(10) ... とやれば左右に10フレーム周期で移動する処理が簡単に実現できる.
先週はなんやかんやで別の作業してたな.
確かコリジョンのデータ配置,更新タイプ考えたり
メインで使うであろうゲームオブジェクト基底クラス(以後GObj)の整備
毎フレーム送られてくる"UPDATE"メッセージでは指定フレームだけ更新を停止するsleep()のような関数を用意.
これで move_left(), sleep(10), move_right(), sleep(10) ... とやれば左右に10フレーム周期で移動する処理が簡単に実現できる.
GObjのメッセージ受信の仕組みは
のようにメッセージIDと対応する処理関数をテーブルとして一括記述し,これをステートと呼ぶ.
ステートとはオブジェクトの状態を表す物で例えばアクションゲームの主人公なら
「停止」「ジャンプ」「ダメージ食らいモーション中」... となる.
ステートを適用するにはGObj:setstate(ステート)と,GObjの専用メソッドを呼ぶ.
また特定部分だけ処理が違うけど他は同じにしたいという場合は
Luaのメタテーブルを利用し setmetatable(ステート, {__index=ベースステート})とすれば良い.
ステートとはオブジェクトの状態を表す物で例えばアクションゲームの主人公なら
「停止」「ジャンプ」「ダメージ食らいモーション中」... となる.
ステートを適用するにはGObj:setstate(ステート)と,GObjの専用メソッドを呼ぶ.
また特定部分だけ処理が違うけど他は同じにしたいという場合は
Luaのメタテーブルを利用し setmetatable(ステート, {__index=ベースステート})とすれば良い.
と長々説明してみたはいいが多くの人の感想は「なんのことやら」とか「だから何?」だろうな.
(自分が何をしたかの確認の為に書いただけなんで別にいいが)
(自分が何をしたかの確認の為に書いただけなんで別にいいが)
(2010/10/19)
Cでは配列インデックスは0からが普通だがLuaは1からッ
使っていれば案外慣れるもんだな.
Lua変数にアクセスする時に面倒くさい手続きが要るのもあってそこで思考が切り替わるようだ.
使っていれば案外慣れるもんだな.
Lua変数にアクセスする時に面倒くさい手続きが要るのもあってそこで思考が切り替わるようだ.
さておき,当たり判定の構造を表すIDを生成するルーチンなど実装.
最初におおまかな球で判定して当たってたら詳細なポリゴンで判定とか.
躓いたのは表現する手段.結論から言ってLuaではテーブルで表す事にした.
前提として基礎となる判定形式は球ならVolumeクラス,円柱ならCylinderクラスと言うように作りこんでおき
それぞれに1からの連番IDを付加.
(0からだとC++のルーチン実装の時に不便だったんで)
最初におおまかな球で判定して当たってたら詳細なポリゴンで判定とか.
躓いたのは表現する手段.結論から言ってLuaではテーブルで表す事にした.
前提として基礎となる判定形式は球ならVolumeクラス,円柱ならCylinderクラスと言うように作りこんでおき
それぞれに1からの連番IDを付加.
(0からだとC++のルーチン実装の時に不便だったんで)
例えば {COLLISION.VOLUME, COLLISION.CYLINDER} とすると最初に球,その後円柱で判定の意味になる
{COLLISION.VOLUME, {COLLISION.POLYGON}} ならば最初に球,次に複数のポリゴン・・・といった感じ.
{COLLISION.VOLUME, {COLLISION.POLYGON}} ならば最初に球,次に複数のポリゴン・・・といった感じ.
でまあC++からでもIDを生成したいよねってことでC++用の関数も用意.
こちらは int calcID(int c_id, ...) と,可変引数を使う.
判定が1つ終わった後に次のレイヤーを展開するかはコリジョンIDにフラグをOR合成.
引数終了判定はこのフラグが付いてない時とした.
Luaの例と同じ意味合をC++で生成すると
前者は calcID(VOLUME | PAIR, CYLINDER)
後者は calcID(VOLUME | NOTPAIR, POLYGON) となる.
こちらは int calcID(int c_id, ...) と,可変引数を使う.
判定が1つ終わった後に次のレイヤーを展開するかはコリジョンIDにフラグをOR合成.
引数終了判定はこのフラグが付いてない時とした.
Luaの例と同じ意味合をC++で生成すると
前者は calcID(VOLUME | PAIR, CYLINDER)
後者は calcID(VOLUME | NOTPAIR, POLYGON) となる.
まだコリジョン構造を数値で表現しただけの段階だが,これからボチボチ中身を実装しようかと思う
(2010/10/16)
リソースはマネージャで読んだ後はオブジェクト指向ぽく
[ハンドル]:[メソッド名]でいちいちマネージャを介さず各種情報へアクセスするようになり扱いは簡易になった.
それ関係の細かいバグ取り等もした.
進まない進まないと言いつつ,んまぁなんだかんだで.
[ハンドル]:[メソッド名]でいちいちマネージャを介さず各種情報へアクセスするようになり扱いは簡易になった.
それ関係の細かいバグ取り等もした.
進まない進まないと言いつつ,んまぁなんだかんだで.
今度は当たり判定の実装で悩む.
前のバージョンは極力条件分岐を減らす方向でテンプレートを駆使したコードを書いていたら
プログラムが肥大化して処理が本当に速くなってるかわからん状態だったし
挙句コンパイルするのに時間かかるわメモリ1.2GByte以上必要とかなってたんで.
本当はどちらが速いか比較検討したうえで決めるべきだけど
激しく面倒だから現バージョンでは汎用性重視で書く(と宣言して踏ん切りをつける魂胆)
今時のCPUなら条件分岐よりメモリアクセス減らした方が良くないか?
幾ら間接参照が遅いからといってもキャッシュに収まればほぼ問題ないわけでしょ?等の理由もある.
前に頑張って書いたから捨てたくないのは山々なわけだが
本当メンテナンス制が悪かった.倍以上速くなければ採用したくないくらい.
前のバージョンは極力条件分岐を減らす方向でテンプレートを駆使したコードを書いていたら
プログラムが肥大化して処理が本当に速くなってるかわからん状態だったし
挙句コンパイルするのに時間かかるわメモリ1.2GByte以上必要とかなってたんで.
本当はどちらが速いか比較検討したうえで決めるべきだけど
激しく面倒だから現バージョンでは汎用性重視で書く(と宣言して踏ん切りをつける魂胆)
今時のCPUなら条件分岐よりメモリアクセス減らした方が良くないか?
幾ら間接参照が遅いからといってもキャッシュに収まればほぼ問題ないわけでしょ?等の理由もある.
前に頑張って書いたから捨てたくないのは山々なわけだが
本当メンテナンス制が悪かった.倍以上速くなければ採用したくないくらい.
肝心の当たり判定の中身はどこに置くかについては流石にLua側に置いていては遅すぎると思ったのでC++側で.
(正確にはメモリ領域自体はLuaで確保してもらって中身の読み書きはC++で行う)
となるとオブジェクトが移動したら都度書き換え関数を呼んでもらう事になるが・・・こればっかりは仕方ない.
オブジェクトに更新フラグ持たせてそれが必要な時だけ転送というようにはするか.
結果的にC++とLuaで同じ意味合いのデータを持つ訳でちょっとスマートでは無いものの,これは妥協.
超大きいデータだったら毎フレームC++側から座標データを取り出して移動させてまたC++へ格納なんて手段も考えられなくはない.
遅いけど.
(正確にはメモリ領域自体はLuaで確保してもらって中身の読み書きはC++で行う)
となるとオブジェクトが移動したら都度書き換え関数を呼んでもらう事になるが・・・こればっかりは仕方ない.
オブジェクトに更新フラグ持たせてそれが必要な時だけ転送というようにはするか.
結果的にC++とLuaで同じ意味合いのデータを持つ訳でちょっとスマートでは無いものの,これは妥協.
超大きいデータだったら毎フレームC++側から座標データを取り出して移動させてまたC++へ格納なんて手段も考えられなくはない.
遅いけど.
(2010/10/11)
10月もそろそろ半ばだってのにまだメモリ周りいじってるんですけど・・
コードはあちこち書き換えてるハズなのに全然前に進まないの.もうやだ.
コードはあちこち書き換えてるハズなのに全然前に進まないの.もうやだ.
「処理の効率化のために極力間接呼び出しは使わない」とかやってた過去のコードに引きずられている.
ここ最近の作業は実は,型で処理分けしてた部分を汎用インタフェースに作り変えてるだけだったり.
ああ処理効率を追求すると本当に汎用性が下がるんだな~と実感.
だがスクリプト使う時点で諦めろと.
ここ最近の作業は実は,型で処理分けしてた部分を汎用インタフェースに作り変えてるだけだったり.
ああ処理効率を追求すると本当に汎用性が下がるんだな~と実感.
だがスクリプト使う時点で諦めろと.
(2010/10/03)
Luaでのリソースハンドルの扱い方がいろいろと矛盾してて試行錯誤
とりあえずコーディングまでは終わった(コンパイル通ったという意味)
デバッグはこれからだけど実際動かせる段階まで来れば気分が違うものだ.
とりあえずコーディングまでは終わった(コンパイル通ったという意味)
デバッグはこれからだけど実際動かせる段階まで来れば気分が違うものだ.
で,また仕様変更.
リソースの内部クラス初期化関数の引数はこれまでファイルを読む事しか想定してなかった.
だからstringか,又は無し(ファイルを読まないリソース.カメラ等)だったのだが
先日のインプットデバイス初期化云々によりGUID等も使う必要が生じたため
汎用の構造体を渡し,そこに必要な情報を設定するようにした.
・・・メモ帳でああだこうだやってたのに書いてみればこれだけか.
リソースの内部クラス初期化関数の引数はこれまでファイルを読む事しか想定してなかった.
だからstringか,又は無し(ファイルを読まないリソース.カメラ等)だったのだが
先日のインプットデバイス初期化云々によりGUID等も使う必要が生じたため
汎用の構造体を渡し,そこに必要な情報を設定するようにした.
・・・メモ帳でああだこうだやってたのに書いてみればこれだけか.
添付ファイル