FPSを作ってみる@wiki
08)
最終更新:
slice
-
view
(2011/08/21)
デッドロックとダイアログ
今回は画像なし.
EditBox, IME関連が終わったのでTwitterAPIに戻る.
EditBox, IME関連が終わったのでTwitterAPIに戻る.
TwitterAPIクラスはロクにテストしてない事もあってバグが多数.
特に終了処理でスレッドがデッドロックするのが致命的だった.
原因はこんな感じ.
前提としてTwitterAPIクラスはLuaとC++の双方からマルチスレッドでアクセスできる様ハンドルでリソース管理されている.
各メソッドを呼ぶ時にはロックをかけるわけだ.
通信スレッドはTwitterAPIにパケットを受け取ったら通知出来るようにTwitterAPIクラスのハンドルを持っている.
特に終了処理でスレッドがデッドロックするのが致命的だった.
原因はこんな感じ.
前提としてTwitterAPIクラスはLuaとC++の双方からマルチスレッドでアクセスできる様ハンドルでリソース管理されている.
各メソッドを呼ぶ時にはロックをかけるわけだ.
通信スレッドはTwitterAPIにパケットを受け取ったら通知出来るようにTwitterAPIクラスのハンドルを持っている.
Lua上でTwitterAPIクラスが削除される -> Luaを動かしてるスレッドからデストラクタが呼ばれる ->
TwitterAPIクラス内部に通信スレッドを幾つか持っているので,これを解放するために
通信スレッドのタスクキューに終了タスクを追加(次のタイミングでスレッドが終了する) ->
でももし通信スレッドが丁度パケットを受け取り終えてTwitterAPIに通知しようとロックを試みたら・・ ->
通常ならロック失敗して待つのだが,デストラクタが呼ばれている間はリソースとは別にマネージャ自体がロックされている
(リソース配列の管理とかする時にロックする) ->
でも通信スレッドが全て終了しないとデストラクタが終われない・・
TwitterAPIクラス内部に通信スレッドを幾つか持っているので,これを解放するために
通信スレッドのタスクキューに終了タスクを追加(次のタイミングでスレッドが終了する) ->
でももし通信スレッドが丁度パケットを受け取り終えてTwitterAPIに通知しようとロックを試みたら・・ ->
通常ならロック失敗して待つのだが,デストラクタが呼ばれている間はリソースとは別にマネージャ自体がロックされている
(リソース配列の管理とかする時にロックする) ->
でも通信スレッドが全て終了しないとデストラクタが終われない・・
非常にわかりにくいが,自分用に整理しただけと思っていただきたい.
ちなみに同一スレッドからは多重ロックを許すように作ってあるので他スレッドが絡んでこない限り問題にならない.
結局これは各通信スレッドを取りまとめるマネージャを置く事で解決した.
要はハンドルにアクセスしたらアウトなんで別途セマフォ装備の終了フラグを置くだけ.
ちなみに同一スレッドからは多重ロックを許すように作ってあるので他スレッドが絡んでこない限り問題にならない.
結局これは各通信スレッドを取りまとめるマネージャを置く事で解決した.
要はハンドルにアクセスしたらアウトなんで別途セマフォ装備の終了フラグを置くだけ.
で,続き.
OAuth認証のアクセストークンを取得する為の確認コードを入力してもらうダイアログボックスを出し
コードを基に処理を続行する・・・が,ここで再び問題が.
:Windowsのダイアログを使った場合
ダイアログボックスを出すまではいいのだがWindowsでは各コントロールのIDを16bitの数値型として扱い,
それを名前でdefineして使うのでコントロール名はコンパイル時点で失われてしまう.
もし何らかの手段でIDを知ったとしても理想的にはコントロール名を指定してコントロールを操作したい.
:自前GUIのウィンドウを使った場合
リソースを予め変換しておく必要がある
OAuth認証のアクセストークンを取得する為の確認コードを入力してもらうダイアログボックスを出し
コードを基に処理を続行する・・・が,ここで再び問題が.
:Windowsのダイアログを使った場合
ダイアログボックスを出すまではいいのだがWindowsでは各コントロールのIDを16bitの数値型として扱い,
それを名前でdefineして使うのでコントロール名はコンパイル時点で失われてしまう.
もし何らかの手段でIDを知ったとしても理想的にはコントロール名を指定してコントロールを操作したい.
:自前GUIのウィンドウを使った場合
リソースを予め変換しておく必要がある
そもそもどっちかにしろよという突っ込みは置いておいて.
どちらにせよ前処理としてソースを解析,配置座標やコントロールのIDをLuaテーブル等で保存しておくのは変わらない.
(あるいは実行時にファイル指定でやってもいいだろうが,実行時もソースが要るのはダサすぎる)
まぁリソースエディタが吐いたリソーススクリプトを解析して自前GUIの配置データに変換する,というのは
前々からやろうと思っていたんで悲観までは行かないか.
当面はVC++のリソースだけに対応すれば良さそうだし.
どちらにせよ前処理としてソースを解析,配置座標やコントロールのIDをLuaテーブル等で保存しておくのは変わらない.
(あるいは実行時にファイル指定でやってもいいだろうが,実行時もソースが要るのはダサすぎる)
まぁリソースエディタが吐いたリソーススクリプトを解析して自前GUIの配置データに変換する,というのは
前々からやろうと思っていたんで悲観までは行かないか.
当面はVC++のリソースだけに対応すれば良さそうだし.
ってなわけで改めてリソーススクリプトのフォーマットを調べると割とシンプル.
一瞬「ん?」となったのはダイアログリソースのサイズ指定はフォントサイズ基準であり,単純なピクセルではなく
横がフォント平均幅の4分の1,縦がフォント高の8分の1だそうだ.
これの利点はフォントサイズが変わっても一定のレイアウトを保てる点で云々(細かい説明は省略
自前GUIでも継承すべきか,否か・・
一瞬「ん?」となったのはダイアログリソースのサイズ指定はフォントサイズ基準であり,単純なピクセルではなく
横がフォント平均幅の4分の1,縦がフォント高の8分の1だそうだ.
これの利点はフォントサイズが変わっても一定のレイアウトを保てる点で云々(細かい説明は省略
自前GUIでも継承すべきか,否か・・
(2011/08/18)
ラスボスIME その4
ラスボス倒した~?と思いきや細かいバグが頻発.まあ大体できたけど.
候補ウィンドウのページ数ズレの問題を解決,
改行もさることながらカーソル上下にも対応しカーソルを自由に移動させられるように.
選択範囲が右端にちょっと出てるのは改行文字の分で,仕様ですキリッ
候補ウィンドウのページ数ズレの問題を解決,
改行もさることながらカーソル上下にも対応しカーソルを自由に移動させられるように.
選択範囲が右端にちょっと出てるのは改行文字の分で,仕様ですキリッ
あとLuaからダイアログメッセージとメッセージボックスを出せるように機能を追加.
ボタンが押された等のイベントはLuaのオブジェクトへ送られる予定(まだそこまでは実装できてない)
ボタンが押された等のイベントはLuaのオブジェクトへ送られる予定(まだそこまでは実装できてない)
本来のMessageBox()で出すメッセージボックスはモーダル(OKボタン押すまで他の動作が止まる)だと他のウィンドウ宛のメッセージも止まるし
描画も止まるので使えない.
なので自前でそれっぽいダイアログ作ってモードレスで表示するようにした.
でも作ってから気づいた.自前でGUIウィンドウ出せるんなら要らないじゃん!まじどうすんの・・はぁ
描画も止まるので使えない.
なので自前でそれっぽいダイアログ作ってモードレスで表示するようにした.
でも作ってから気づいた.自前でGUIウィンドウ出せるんなら要らないじゃん!まじどうすんの・・はぁ
(2011/08/17)
ラスボスIME その3
コピペを実装.っても画像だと全然わからないから雰囲気だけ.
あとはキーリピートによるカーソル連続移動とかマウスとキーボードの範囲選択なんぞもやったがこれも画像だと(ry
普段は選択範囲を指定したままカーソル入力やマウス入力でどんな挙動をするか細かく意識してないからメモ帳で確認したり.
しかしなんだな.自分で実装したエディットボックスからクリップボード通して外部のアプリケーションとやり取りできるとちょっと嬉しい.
残るは候補ページ番号表示とIMEの切り替え判定を時々ミスる件(こうなると一端他にフォーカス移さないと入力できないという・・)
とまだマルチライン編集に対応させてないのでそれをやれば一通り完成となる.
長かったEditBoxもようやく終わりが見えてきた.
あとはキーリピートによるカーソル連続移動とかマウスとキーボードの範囲選択なんぞもやったがこれも画像だと(ry
普段は選択範囲を指定したままカーソル入力やマウス入力でどんな挙動をするか細かく意識してないからメモ帳で確認したり.
しかしなんだな.自分で実装したエディットボックスからクリップボード通して外部のアプリケーションとやり取りできるとちょっと嬉しい.
残るは候補ページ番号表示とIMEの切り替え判定を時々ミスる件(こうなると一端他にフォーカス移さないと入力できないという・・)
とまだマルチライン編集に対応させてないのでそれをやれば一通り完成となる.
長かったEditBoxもようやく終わりが見えてきた.
(2011/08/16)
ラスボスIME その2
1日で文節表示を終えるはずだったがluaの罠にはまって1回休み.
普段と同じ様にカーソルキー又は数字キーで候補を選択するのだが現状だと例えば候補の2ページ目以降を表示中に1を押すと
1ページ目,1番目の候補が選択されてしまう.
原因は一応把握済みだが・・面倒なので後でいいや.放置.
それより範囲選択ちゃんと実装しないとなぁ・・ああ,候補ページ番号も表示して無いじゃん.
普段と同じ様にカーソルキー又は数字キーで候補を選択するのだが現状だと例えば候補の2ページ目以降を表示中に1を押すと
1ページ目,1番目の候補が選択されてしまう.
原因は一応把握済みだが・・面倒なので後でいいや.放置.
それより範囲選択ちゃんと実装しないとなぁ・・ああ,候補ページ番号も表示して無いじゃん.
(2011/08/13)
ラスボスIME その1
単なる途中経過.例のEditBoxは英文字に加え日本語入力が可能になった.
入力中の文字はバックを黒っぽい半透明にして描画とか.
入力中の文字はバックを黒っぽい半透明にして描画とか.
候補ウィンドウは仮なので少々見づらいし.いろいろ修正すべき箇所はある.
残るは文節の表示とマウスによる候補選択,範囲選択か.ここまで来て後に引けないし頑張る.
残るは文節の表示とマウスによる候補選択,範囲選択か.ここまで来て後に引けないし頑張る.
(2011/08/10)#2
文字列処理
さて進捗を,といいつつ前回から2週間近く経ってしまっている.
当初の予定ではとっくにGUIは完成している筈だったが未だにEditBoxの途中.
Subversionの履歴を見るに7月いっぱいはソケット通信クラスやHTTP,Luaとのやり取りを実装していて
8月に入ってからはサロゲートペア問題とか文字列描画の抜本的な見直しをしていたようだ・・
当初の予定ではとっくにGUIは完成している筈だったが未だにEditBoxの途中.
Subversionの履歴を見るに7月いっぱいはソケット通信クラスやHTTP,Luaとのやり取りを実装していて
8月に入ってからはサロゲートペア問題とか文字列描画の抜本的な見直しをしていたようだ・・
描画が遅い問題は文字列の描画を前に書いた通りの方法で解決.
ウィンドウの矩形や枠も一括描画したい所だがバッファを一本化までは手間が掛かりすぎると判断して保留.
それでもフレームレートは大幅に改善したからOKとする.
これとは別に頂点バッファやインデックスバッファ,テクスチャなどのリソースでソートをかけて描画の効率化を図る計画も進行中.もう少し時間が掛かりそうだ.
ウィンドウの矩形や枠も一括描画したい所だがバッファを一本化までは手間が掛かりすぎると判断して保留.
それでもフレームレートは大幅に改善したからOKとする.
これとは別に頂点バッファやインデックスバッファ,テクスチャなどのリソースでソートをかけて描画の効率化を図る計画も進行中.もう少し時間が掛かりそうだ.
で,前々から先延ばしにしていた問題.サロゲートペアを表示するかどうか.一瞬悩んだが,折角作るからにはという事で対応させた.
1文字に要するバイト数が可変だと処理が後々面倒なので
テキスト管理クラスは1文字32bitでバッファを取り(独自の制御文字含めた)全ての文字を32bit固定とした.
指定位置の文字列挿入や文字列描画整形関数を着々と実装していく.
1文字に要するバイト数が可変だと処理が後々面倒なので
テキスト管理クラスは1文字32bitでバッファを取り(独自の制御文字含めた)全ての文字を32bit固定とした.
指定位置の文字列挿入や文字列描画整形関数を着々と実装していく.
が,ここで問題発生.サロゲートペアが正常に描画されてない.
当初はBMP文字と同じ様にGetGlyphOutline()の引数にUTF32変換した文字コードを渡せばいいかとやってみたが,これが駄目(豆腐が返ってくる)
ならばとUTF16の2バイト * 2を入力してみるが変わらず.
もしやXPは対応してない?と思ってググると,どうやら対応してるらしい.但し対応フォントじゃないと化けると.
今回はMSが提供しているメイリオを使っているのでこの点は大丈夫な筈.
当初はBMP文字と同じ様にGetGlyphOutline()の引数にUTF32変換した文字コードを渡せばいいかとやってみたが,これが駄目(豆腐が返ってくる)
ならばとUTF16の2バイト * 2を入力してみるが変わらず.
もしやXPは対応してない?と思ってググると,どうやら対応してるらしい.但し対応フォントじゃないと化けると.
今回はMSが提供しているメイリオを使っているのでこの点は大丈夫な筈.
(長くなるので中略)
とにかく調べた.最早自力でファイルから読むしかないのかとバイナリエディタとにらめっこしつつ
TrueType形式のファイルフォーマットを調べたりもした.又は凄い人のページを見つけて凹んだり.
結論としてはフォントファイルを自前解析する必要もなくGetGlyphOutline()で可能だった訳だが詳細はTipsページへ書いた.
TrueType形式のファイルフォーマットを調べたりもした.又は凄い人のページを見つけて凹んだり.
結論としてはフォントファイルを自前解析する必要もなくGetGlyphOutline()で可能だった訳だが詳細はTipsページへ書いた.
サロゲートは倒したので気を取り直しGUIの完成へ向けて作りかけの部品を実装していく.中でもEditBoxがかなりの曲者である.
英文字だけならキーの入力を読んでカーソル移動させーのバックスペースだのコピペを書くだけで(いや,これも結構大変だけど)よかった.
そこからマウスによるテキスト範囲選択,プロポーショナルフォント対応(文字幅が可変)と骨の折れる作業が続き
最後に大ボスの「IME日本語入力」が立ちはだかる <= イマココ!
英文字だけならキーの入力を読んでカーソル移動させーのバックスペースだのコピペを書くだけで(いや,これも結構大変だけど)よかった.
そこからマウスによるテキスト範囲選択,プロポーショナルフォント対応(文字幅が可変)と骨の折れる作業が続き
最後に大ボスの「IME日本語入力」が立ちはだかる <= イマココ!
一応下調べはMSDNやhttp://msdn.microsoft.com/ja-jp/library/bb206300%28v=vs.85%29.aspxを参考に
サンプルプログラムを組むなど入念にしておいた.
普段全く意識していない概念,用語がそこかしこ.コンポジションウィンドウって何だ?読み文字列?ロケールとは??そんな感じ.
フルスクリーンで動くアプリケーションにおいてIMEを使う事の何が大変かって,
候補ウィンドウとか入力途中の文字列,文節のアンダーライン等を自分で描画しなければならないのだ.
キー入力管理をしてまずはひらがなで記憶して変換候補の選定・・・とかは流石に向こうでやってくれるものの.
サンプルプログラムを組むなど入念にしておいた.
普段全く意識していない概念,用語がそこかしこ.コンポジションウィンドウって何だ?読み文字列?ロケールとは??そんな感じ.
フルスクリーンで動くアプリケーションにおいてIMEを使う事の何が大変かって,
候補ウィンドウとか入力途中の文字列,文節のアンダーライン等を自分で描画しなければならないのだ.
キー入力管理をしてまずはひらがなで記憶して変換候補の選定・・・とかは流石に向こうでやってくれるものの.
(2011/08/10)
現状確認とか
今月も引き続きTwitterクライアントに専念.
ゲームからどんどん離れて行ってるけどこのサイトももう3年だし
いい加減何か完成品がないとモチベーションが死にそうなのでご容赦願いたい.
いや,寄り道自体は前から度々あったが今回は結構本気で取り組んでいる.つまり完成するまではゲームに戻らない方針.
ゲームからどんどん離れて行ってるけどこのサイトももう3年だし
いい加減何か完成品がないとモチベーションが死にそうなのでご容赦願いたい.
いや,寄り道自体は前から度々あったが今回は結構本気で取り組んでいる.つまり完成するまではゲームに戻らない方針.
まずは現時点で出来ている事を整理してみよう
- 通信
Luaからアクセス可能で,ブロッキングしないソケット通信クラス
(簡単の為TwitterAPIに特化させてある.OAuth認証も含む)
今のところREST-APIのみ対応.サーバから応答があればLuaへメッセージが送られる.
常に通信が成功する前提で書かれていて,途中で何かエラーが発生した場合の対処が不十分.
ストリームを個々のHTTPパケットに沿って分割する処理も怪しい.
TCP-IPだからデータ破損とかは考えなくていいか?
(簡単の為TwitterAPIに特化させてある.OAuth認証も含む)
今のところREST-APIのみ対応.サーバから応答があればLuaへメッセージが送られる.
常に通信が成功する前提で書かれていて,途中で何かエラーが発生した場合の対処が不十分.
ストリームを個々のHTTPパケットに沿って分割する処理も怪しい.
TCP-IPだからデータ破損とかは考えなくていいか?
- データ解析
JSON: データの読み書き,ファイルへの保存,検索など一通り
HTTP: リクエストの生成とレスポンス解釈,バグはありそうだが一応
HTTP: リクエストの生成とレスポンス解釈,バグはありそうだが一応
- GUI
Luaで動く自前のGUIシステム.この手はWindowsAPIしか触った事がない為,GUI部品間のメッセージ等がWindowライクな仕様になっている.部品は
BG(矩形.色を変えたり半透明にしたり等.線描画の枠やテキストも表示できる)
EditBox(BGにテキスト編集を足したような物)
Window(BGを2つ持っていて,それぞれタイトルバーとメイン領域に使用.子を持てる)
Button(クリックされたら親部品に通知するBG.テキストボタン)
TexButton(Buttonの見た目をテクスチャに変更したバージョン.独自形式のスプライトを用いる)
RadioBox(いわゆるラジオボックス.ボタンの見た目はスプライトで定義)
CheckBox(いわゆるチェックボックス.複数チェック入れられる以外は上と同様)
がある.最後2つの説明が投げやりだけど,そうとしか・・
他にSlider(範囲から数値を選択するアレ)とかも欲しいが優先度は低い.
BG(矩形.色を変えたり半透明にしたり等.線描画の枠やテキストも表示できる)
EditBox(BGにテキスト編集を足したような物)
Window(BGを2つ持っていて,それぞれタイトルバーとメイン領域に使用.子を持てる)
Button(クリックされたら親部品に通知するBG.テキストボタン)
TexButton(Buttonの見た目をテクスチャに変更したバージョン.独自形式のスプライトを用いる)
RadioBox(いわゆるラジオボックス.ボタンの見た目はスプライトで定義)
CheckBox(いわゆるチェックボックス.複数チェック入れられる以外は上と同様)
がある.最後2つの説明が投げやりだけど,そうとしか・・
他にSlider(範囲から数値を選択するアレ)とかも欲しいが優先度は低い.
GUI部品のトップにはGUIマネージャクラスがあって,そこでクリック処理やフォーカスの遷移を管理している.
ウィンドウの部品配置をJSONで定義し,JSONをLuaのテーブルに変換する関数を通してGUIマネージャに読み込ませる機能も装備.
あわよくばVisualC++のリソースエディタからJSONにコンバートできれば最高だがまだそこまでは至ってない.
ウィンドウの部品配置をJSONで定義し,JSONをLuaのテーブルに変換する関数を通してGUIマネージャに読み込ませる機能も装備.
あわよくばVisualC++のリソースエディタからJSONにコンバートできれば最高だがまだそこまでは至ってない.
- サウンド
ずっと前にXAudioで実装した物を使う.
と,こんな所だ.
目下やらなければならない事はGUIの完成,HTTPパケットのエラー処理・・・
それとDirectXデバイスがロストした際の復帰処理もきちんと書くべきだろうが,まだいいだろう.
目下やらなければならない事はGUIの完成,HTTPパケットのエラー処理・・・
それとDirectXデバイスがロストした際の復帰処理もきちんと書くべきだろうが,まだいいだろう.