FPSを作ってみる@wiki
12)
最終更新:
slice
-
view
(2013/12/31)
一難去って
multiple definitionsエラーも苦戦したけど
今度はMinGWでコンパイルした時に限りalignas(16)と宣言した変数がアラインされてない。
もちろんnewで確保したのではなくスタック上だ。
クラス宣言の時にalignas(16), 変数確保時にもalignas(16)とやってみたけど見事に無視られる。
gccのattribute宣言も使ってみたけどこれも駄目。
わけがわからん。動く動かない以前の問題でつまりまくりで、正直勘弁してくれよという感じ。
そんな訳で年内は絶望視している。
今度はMinGWでコンパイルした時に限りalignas(16)と宣言した変数がアラインされてない。
もちろんnewで確保したのではなくスタック上だ。
クラス宣言の時にalignas(16), 変数確保時にもalignas(16)とやってみたけど見事に無視られる。
gccのattribute宣言も使ってみたけどこれも駄目。
わけがわからん。動く動かない以前の問題でつまりまくりで、正直勘弁してくれよという感じ。
そんな訳で年内は絶望視している。
SDL2 をLinuxからWindowsへクロスコンパイルした際のmultiple definitionエラー対処
あれこれ試行錯誤して調べたら、どうやら
SDLのヘッダをインクルードする前に#include<windows.h>、さらにその前に#include<intrin.h>の記述を徹底することで直るようだ。
なんでコレで良いのかわからんが、とにかくこれでコンパイルが通る。
クロスコンパイルする人があまり居ないせいかググってもほぼ出ないから要注意。
非常に大事なことだからもう一度言う。
SDLのヘッダをインクルードする前に#include<windows.h>、さらにその前に#include<intrin.h>の記述を徹底することで直るようだ。
なんでコレで良いのかわからんが、とにかくこれでコンパイルが通る。
クロスコンパイルする人があまり居ないせいかググってもほぼ出ないから要注意。
非常に大事なことだからもう一度言う。
#include <intrin.h>
#include <windows.h>
#include <SDLのヘッダ...>
この順番だ。
念の為にSDLを使ってなくてwindows.hだけのところでもその前にintrin.hをインクルードしておくといいだろう。
windows.hも他のヘッダより前が無難っぽい。
念の為にSDLを使ってなくてwindows.hだけのところでもその前にintrin.hをインクルードしておくといいだろう。
windows.hも他のヘッダより前が無難っぽい。
gcc(MinGW)のアラインメントの問題
アラインメントしてした空の構造体を使い、コンストラクタにthisポインタを出力して実際どのアドレスに割り当てられてるか
ちょっと試してみたら16byteアラインメント指定のみ上手く行ってない。8byteや32byteでは普通にアラインメントが効いている。
だけど16byteの時は0x0008, 0x0018, 0x0028...みたいにサイズは合ってるんだけど中途半端な位置で揃えられてしまう。
ちょっと試してみたら16byteアラインメント指定のみ上手く行ってない。8byteや32byteでは普通にアラインメントが効いている。
だけど16byteの時は0x0008, 0x0018, 0x0028...みたいにサイズは合ってるんだけど中途半端な位置で揃えられてしまう。
ただ不思議なのは、これは普段は発生しなくてどうもSDLをリンクした時だけなるようだ・・・詳細は追って報告する
(2013/12/30)
そういえばOpenSLのシリアライズまだ書いてなかった(死
ちょいと書けば動くのかもしれんけど経験上うまく行った試しがないので年内のAndroidバージョンは捨てる。
なんとかlinuxとwindowsで何か動くプログラムを上げられるか?といった所。
ぶっちゃけそれも危うい
ちょいと書けば動くのかもしれんけど経験上うまく行った試しがないので年内のAndroidバージョンは捨てる。
なんとかlinuxとwindowsで何か動くプログラムを上げられるか?といった所。
ぶっちゃけそれも危うい
clangでクロスコンパイル・・できなかった
clangで許されていた文法がgccではエラーになったりする箇所の修正など。
MinGWで各種ライブラリをビルドしてなくて、ビルド方法からググったりとか。
出来ればclangで統一できればこんな苦労はしなくて言い訳で、clangでMinGWなプログラムをビルド出来るんかねーとかやってた。
MinGWで各種ライブラリをビルドしてなくて、ビルド方法からググったりとか。
出来ればclangで統一できればこんな苦労はしなくて言い訳で、clangでMinGWなプログラムをビルド出来るんかねーとかやってた。
数時間試行錯誤した結果から言えば「まだ出来ないっぽい」
具体的にはC++例外機構を使わないプログラムだったらビルドして動かせるんだけどthrowやstd::coutなんか使うと途端にアウト。
具体的にはC++例外機構を使わないプログラムだったらビルドして動かせるんだけどthrowやstd::coutなんか使うと途端にアウト。
詳しいことはよくわからないが例外機構の仕様にはsjljとdwarf2とSEH(win専用?)があって、
それぞれの長所短所はともかく
dwarf2は構造上64bit環境で使えないから
64bitプログラムを出力できるのがウリのw64-mingwではdwarf2は対応しないとか言ってて、SEHは今対応を進めてるとかなんとか。
だからw64-mingwでビルドする時は基本的にsjljでね☆という。
凄くテキトーな説明だけど、そんな感じ。
それぞれの長所短所はともかく
dwarf2は構造上64bit環境で使えないから
64bitプログラムを出力できるのがウリのw64-mingwではdwarf2は対応しないとか言ってて、SEHは今対応を進めてるとかなんとか。
だからw64-mingwでビルドする時は基本的にsjljでね☆という。
凄くテキトーな説明だけど、そんな感じ。
で、clangでwindowsプログラムをビルドすると
clangはアセンブリコードに落とすとこまでやって後はgccに丸投げなのだが
undefined reference '___gxx_personality_v0' とかのエラーが出ることから
察するにclangの方はdwarf2のつもりでアセンブリを出力してるんだけどgcc(mingwのほう)はsjljなのでビルドが通らないか、
通っても実行時にSEGVで落ちる。
clangはアセンブリコードに落とすとこまでやって後はgccに丸投げなのだが
undefined reference '___gxx_personality_v0' とかのエラーが出ることから
察するにclangの方はdwarf2のつもりでアセンブリを出力してるんだけどgcc(mingwのほう)はsjljなのでビルドが通らないか、
通っても実行時にSEGVで落ちる。
この辺、自分がアセンブリコードを端から端まで読めればちゃんと原因がつかめると思うのだが
今まで単発の関数しか読み書きしたことが無いのでちょっと・・
今まで単発の関数しか読み書きしたことが無いのでちょっと・・
かといってw64-mingwをdwarf2でビルドしようにも前述の理由でエラーで出来なかった。八方塞がり
勿論色々とググってはみたんだけどこれといった解決策は見つからず。
gccが動くんだからいいじゃんと言われればそうなんだが。
勿論色々とググってはみたんだけどこれといった解決策は見つからず。
gccが動くんだからいいじゃんと言われればそうなんだが。
結局clangでクロスコンパイルは諦めた。
要するにこういうくだらないことで時間を潰してしまいましたと・・
要するにこういうくだらないことで時間を潰してしまいましたと・・
現在
gccでwindows用にバグを直しつつコンパイルを試みている。
8割方OKなのだが最後のリンクでintrinsic関数がmultiple definitionsと言われ、
ググってもやはりそれっぽい解答が見つからず困惑中。
ライブラリとか部分的にビルドしたり差し替えたりしてたからそれのバージョン違いかなあ?等と疑ってはいるが
ちょっと手間だよねえ・・とはいえそのくらいしか原因が思いつかないから粛々と構築し直している・・
8割方OKなのだが最後のリンクでintrinsic関数がmultiple definitionsと言われ、
ググってもやはりそれっぽい解答が見つからず困惑中。
ライブラリとか部分的にビルドしたり差し替えたりしてたからそれのバージョン違いかなあ?等と疑ってはいるが
ちょっと手間だよねえ・・とはいえそのくらいしか原因が思いつかないから粛々と構築し直している・・
(2013/12/27)
うわ。
うわぁ。
うわぁ。
ファイルの変更通知とかその自動テスト書いてたらもうこんな日付に。デモを上げる前に年が終わってしまう。
ファイル監視
結局Linux用のも含め作り直した。何時ものパターン。
githubを見てもらえれば分かるとおり
テストコードは今までのなんちゃって関数ではなく、
実際にランダムな構造でファイルを作ったり移動してファイルツリーの比較で正常な値が出てるか確認するという本格的なものだ(当社比
自動テストはコードの信頼性をかなり上げてくれるけれど、ヘタすると書くのに本体と同じくらい時間がかかるね。
テストコード自体にバグがあるケースも結構あるからその特定にも四苦八苦。
信頼性をとるか、開発のスピードをとるか・・悩ましい。
テストコードは今までのなんちゃって関数ではなく、
実際にランダムな構造でファイルを作ったり移動してファイルツリーの比較で正常な値が出てるか確認するという本格的なものだ(当社比
自動テストはコードの信頼性をかなり上げてくれるけれど、ヘタすると書くのに本体と同じくらい時間がかかるね。
テストコード自体にバグがあるケースも結構あるからその特定にも四苦八苦。
信頼性をとるか、開発のスピードをとるか・・悩ましい。
逆を言えば個人プロジェクトで「たまに上手く動かない時があるけども、それはその時で対処できる」なら
わざわざ倍位の時間をかけてテストコードを書かなくてもいいかもしれない。
ちなみにとりあえず動くデモを上げるだけだったら別にファイル監視なんて要らなかったじゃん。等と突っ込まないよう
わざわざ倍位の時間をかけてテストコードを書かなくてもいいかもしれない。
ちなみにとりあえず動くデモを上げるだけだったら別にファイル監視なんて要らなかったじゃん。等と突っ込まないよう
予定
MinGW環境ではstd::threadが使えない前提で引き続きビルド作業を進める所存。
モデル読み込みとかその辺が全然出来てないから表示するのは立方体でいいかな?
モデル読み込みとかその辺が全然出来てないから表示するのは立方体でいいかな?
(2013/12/24)
スクリプト
デモをリリースした後の話なんだけど。
やはりゲームはバランスが命なのでパラメータの調整が円滑に行えるようスクリプトの組み込みをしたい。
やはりゲームはバランスが命なのでパラメータの調整が円滑に行えるようスクリプトの組み込みをしたい。
巷ではC++コードのリアルタイム編集なんてのが流行ってる気がするが特定のゲームエンジン専用だったり
VisualStudio前提だったり、というかそもそも有料だったり自分が組み込むにはまだ敷居が高いように感じたので
やっぱりまたLuaで行こうかなと。
単純にスクリプトファイルが描き換えられた時にコンパイルかけて、エラーが無ければ関数を差し替えとすればプログラムのリアルタイム修正が出来る。
Lua自体マルチスレッドに対応していないからメタテーブルで変な事してない限りは大丈夫な筈。
VisualStudio前提だったり、というかそもそも有料だったり自分が組み込むにはまだ敷居が高いように感じたので
やっぱりまたLuaで行こうかなと。
単純にスクリプトファイルが描き換えられた時にコンパイルかけて、エラーが無ければ関数を差し替えとすればプログラムのリアルタイム修正が出来る。
Lua自体マルチスレッドに対応していないからメタテーブルで変な事してない限りは大丈夫な筈。
まぁ、クラスをサポートしたSquirrelでユーザーが自前のクラス作ってなんやかんや
するのも楽しいかもしれないけど下手にスクリプトの自由度高いと前みたいに
「何をするにもスクリプトで色々お約束事を書かなきゃならない」事態を招きかねんので・・
そんな訳で前回の教訓を生かしてスクリプトで対応する部分は限定的にするつもり。
するのも楽しいかもしれないけど下手にスクリプトの自由度高いと前みたいに
「何をするにもスクリプトで色々お約束事を書かなきゃならない」事態を招きかねんので・・
そんな訳で前回の教訓を生かしてスクリプトで対応する部分は限定的にするつもり。
あと「とりあえずスクリプトで実装してみて、遅いようだったらC++に移していく」作戦を考えていたけど、
現実的に難しそうだなと思った。
なぜかと言えば1つは単純に手間が増えるのと
これも前回痛感したけどスクリプトで複雑なアルゴリズムの記述や大量のリソースの管理等は向いてないというのが大きい。
なまじ連想配列に何でも突っ込めるせいであらぬデータ型が入ってたり、不正な値かチェックするのが静的型付けと違って少々面倒だったりとか。
そういうテストと調整の繰り返しが必要ないシステム寄りの所は最初からC++で書いてしまった方が良さそう。
現実的に難しそうだなと思った。
なぜかと言えば1つは単純に手間が増えるのと
これも前回痛感したけどスクリプトで複雑なアルゴリズムの記述や大量のリソースの管理等は向いてないというのが大きい。
なまじ連想配列に何でも突っ込めるせいであらぬデータ型が入ってたり、不正な値かチェックするのが静的型付けと違って少々面倒だったりとか。
そういうテストと調整の繰り返しが必要ないシステム寄りの所は最初からC++で書いてしまった方が良さそう。
(2013/12/23)
どっかで「libstdc++がやっとregexを実装した」という話を耳にしたんだけど、g++ 4.8.2をビルドして試してみたらやっぱりまだっぽい。
boostでいいだろという話だが、標準ライブラリにあれば心強いよね。
それとMinGWでのlibstdc++、std::threadもやっぱりまだ。こっちはSDLのthreadでなんとかしている。
boostでいいだろという話だが、標準ライブラリにあれば心強いよね。
それとMinGWでのlibstdc++、std::threadもやっぱりまだ。こっちはSDLのthreadでなんとかしている。
ファイル監視
半年以上前に書いたコードはゴミだと言う事を再確認。
やはり熟練者か、元からライブラリ用に設計したクラスでも無ければ古いコードを再利用など基本的に無いと思ったほうが良いみたいだ。
あるとすれば単発の文字列処理や、数値計算なんかの規模が小さいルーチン。これらは一応使いまわしが効く。
クラスを使いまわすのは要求レベルが高い。少なくとも自分にはまだ無理。
やはり熟練者か、元からライブラリ用に設計したクラスでも無ければ古いコードを再利用など基本的に無いと思ったほうが良いみたいだ。
あるとすれば単発の文字列処理や、数値計算なんかの規模が小さいルーチン。これらは一応使いまわしが効く。
クラスを使いまわすのは要求レベルが高い。少なくとも自分にはまだ無理。
何が言いたいかというとWindows用のディレクトリ監視クラスが自分で言うのもなんだが使えねぇ、と。そういう事である。
ファイル変更の検知にはFindFirstChangeNotificationというAPIを使っていて
WaitFor〜系の関数で変更があるまでスレッド待機、標準出力でその変更やパスを表示するのが
サンプルで紹介される定番の流れだ。
ファイル変更の検知にはFindFirstChangeNotificationというAPIを使っていて
WaitFor〜系の関数で変更があるまでスレッド待機、標準出力でその変更やパスを表示するのが
サンプルで紹介される定番の流れだ。
昔の自分はこれを真に受けたのか、クラス内部で別スレッドを走らせてwaitで監視し
変更があったらスレッド同期された変数にその旨を書き込むというルーチンを書いているんだけど
じゃあユーザーのプログラムでどうやって通知を受け取るかと言えばポーリングだったりして非常にアレ。
わざわざスレッドを作った意味がないという。
FindFirstChange〜では具体的にどのファイルが変更されたかを知るすべがなく、自分でファイルツリーを構築&比較しているので
ユーザーが結果を問い合わせてきた時に初めて待ち時間0でwaitをかけて変更があるとわかればツリーを比較すれば良い話で・・
変更があったらスレッド同期された変数にその旨を書き込むというルーチンを書いているんだけど
じゃあユーザーのプログラムでどうやって通知を受け取るかと言えばポーリングだったりして非常にアレ。
わざわざスレッドを作った意味がないという。
FindFirstChange〜では具体的にどのファイルが変更されたかを知るすべがなく、自分でファイルツリーを構築&比較しているので
ユーザーが結果を問い合わせてきた時に初めて待ち時間0でwaitをかけて変更があるとわかればツリーを比較すれば良い話で・・
ただ、使用するAPIがFindFirstChangeNotificationではなく
変更されたファイル名まで特定できるReadDirectoryChangesWならば上記のような
別途スレッドを走らせて結果をキューに貯めこんでいく実装も悪くないかと思う。
変更されたファイル名まで特定できるReadDirectoryChangesWならば上記のような
別途スレッドを走らせて結果をキューに貯めこんでいく実装も悪くないかと思う。
(2013/12/21)
スタブスタブ
WindowsやAndroidで動かすためのコンパイル作業など。
前回書いた通り一発で通るはずもなく
「非SSE時のベクトル比較関数の定義が足りてなかった」
や、
「あーまだMinGWにはstd::thread無かったね、SDLのスレッドに置き換えるかぁ」
など。
これくらい想定の範囲なので淡々と修正していく、のだが。
「非SSE時のベクトル比較関数の定義が足りてなかった」
や、
「あーまだMinGWにはstd::thread無かったね、SDLのスレッドに置き換えるかぁ」
など。
これくらい想定の範囲なので淡々と修正していく、のだが。
半ばを過ぎた頃に大物が出現。
「windows用のディレクトリ走査APIを全く実装してなかっただと・・・!」
調子狂う。
いや、放置してた自分が悪いんだが。
「windows用のディレクトリ走査APIを全く実装してなかっただと・・・!」
調子狂う。
いや、放置してた自分が悪いんだが。
具体的にはファイルの列挙とファイルの変更検知で、
visual studioで開発してた頃のソースを参考にしつつ書けばそんなに詰まる所では無さそうなのが救いか。
visual studioで開発してた頃のソースを参考にしつつ書けばそんなに詰まる所では無さそうなのが救いか。
あとアラインメントされたメモリを確保するposix_memalign()は、Android NDKにはあった気がするが
当然ながらWindows環境では無いので代替手段、例えば_aligned_malloc関数なんかを使用する事となる。
が、こいつで確保したメモリは_aligned_freeで解放しなければならない。
というかそもそもposix_memalign()の場合はfree()でOKだから使っていた訳で、どうせ解放も専用関数ならば
自前でちょっと多めに::mallocで確保してオフセット調整して返した方が
すべての環境で共通して使えるし良いのでは?と思った。
当然ながらWindows環境では無いので代替手段、例えば_aligned_malloc関数なんかを使用する事となる。
が、こいつで確保したメモリは_aligned_freeで解放しなければならない。
というかそもそもposix_memalign()の場合はfree()でOKだから使っていた訳で、どうせ解放も専用関数ならば
自前でちょっと多めに::mallocで確保してオフセット調整して返した方が
すべての環境で共通して使えるし良いのでは?と思った。
これまで何年もC++を書いていたにも関わらず使う気配すらなかった
メンバ関数のoperator new, operator deleteを、ようやく活用する時が来たようだ・・
(C++erな人にはあまり推奨されてない気がするが)
メンバ関数のoperator new, operator deleteを、ようやく活用する時が来たようだ・・
(C++erな人にはあまり推奨されてない気がするが)
(2013/12/19)
思えばサウンドの復帰に取り掛かる時
- サウンドの復帰だけに絞ってさっさと先に進む
か、
- クイックセーブを見据えてシリアライズをちゃんと実装する
かで迷って、結局後者の選択したのだけどこれは本当に正しかったのだろうか?
というのもこれでクイックセーブが動作する保証はないからだ。
ひとまずサウンドに関しては上手く動いてるようだが・・・?
というのもこれでクイックセーブが動作する保証はないからだ。
ひとまずサウンドに関しては上手く動いてるようだが・・・?
まぁ、何事も保証などない。「保証が欲しければ電化製品を買えばいい」と言われるくらいだし、良いとする。
デモ
いい加減に動くプログラムを上げないと不味そうなので
しょっぼいけどサウンドのテストとライティング無しのポリゴン表示だけのデモを近日中にアップしたい。
すぐじゃないのはMinGWでのコンパイルが一発で通る気がしないし動くかもわからんっていうのと
LinuxはLinuxでパッケージの作り方をまた忘れてしまった為。
Android版も上げてみたいのもある。今回のテーマはマルチプラットフォームなので。
しょっぼいけどサウンドのテストとライティング無しのポリゴン表示だけのデモを近日中にアップしたい。
すぐじゃないのはMinGWでのコンパイルが一発で通る気がしないし動くかもわからんっていうのと
LinuxはLinuxでパッケージの作り方をまた忘れてしまった為。
Android版も上げてみたいのもある。今回のテーマはマルチプラットフォームなので。
でもAndroidのNDKでなんかしばらくコンパイルすらしてないし
一日でコンパイルが通って不具合も直して動作させられれば大成功な風に捉えてるからあまり期待してはいけない
一日でコンパイルが通って不具合も直して動作させられれば大成功な風に捉えてるからあまり期待してはいけない
(2013/12/17)
サウンドの復元だけできれば良かったのに例のごとく大事になっちょる。
さよならKdevelop
開発環境がこれまでKdevelopだったのだが、QtCreatorに移行しようかと思ってる。
理由は、Gitで最新版を追っていてもKdevelopが全体的にバギーな事。
フリーの物にあれこれ言うのもアレかもしれないが・・以下のような不具合が起こる。
インテリセンスっぽい構文解析が動いてくれるのはいいんだが、これが時々フリーズしてアプリケーション全体が重くなって再起動を余儀なくされたり
時々キー入力がおかしくなって例えばAキーを連打してるのにdとかeとかが入力される始末。(これも再起動)
そもそも込み入ったソースになってくると補完が効かないし、
補完候補を出すのに0.1秒くらいかかるので自動で表示する設定にしとくと快適さが失われる。かといってマニュアルで出すのもひと手間かかる。
デバッガの変数表示が-gを付けてコンパイラの最適化をオフにしてるにも関わらず何故かoptimized outと表示され使い物にならない場合も多い。
他にもブレークポイントを付けて、その後ソースを編集するとブレークポイントの行がズレるといった基本的な所が未だに直ってないとか
ショートカットキーを設定しても暫くすると設定がデフォルトに戻っている等。
CMakeのオプション指定しても効いてないとか日常茶飯事である。
理由は、Gitで最新版を追っていてもKdevelopが全体的にバギーな事。
フリーの物にあれこれ言うのもアレかもしれないが・・以下のような不具合が起こる。
インテリセンスっぽい構文解析が動いてくれるのはいいんだが、これが時々フリーズしてアプリケーション全体が重くなって再起動を余儀なくされたり
時々キー入力がおかしくなって例えばAキーを連打してるのにdとかeとかが入力される始末。(これも再起動)
そもそも込み入ったソースになってくると補完が効かないし、
補完候補を出すのに0.1秒くらいかかるので自動で表示する設定にしとくと快適さが失われる。かといってマニュアルで出すのもひと手間かかる。
デバッガの変数表示が-gを付けてコンパイラの最適化をオフにしてるにも関わらず何故かoptimized outと表示され使い物にならない場合も多い。
他にもブレークポイントを付けて、その後ソースを編集するとブレークポイントの行がズレるといった基本的な所が未だに直ってないとか
ショートカットキーを設定しても暫くすると設定がデフォルトに戻っている等。
CMakeのオプション指定しても効いてないとか日常茶飯事である。
で、QtCreatorはといえば元々Qtを使ったプロジェクト用のツールなのでCMakeには一応対応してる程度だし
補完もQtに関する物以外あまり効いてくれない印象がある。
けどKdevelopも大概なのでこれについては気にならない。
何より設定した項目がちゃんと効いてくれるし、デバッガもサクサク動き
メモリ表示なんかもkdevelopみたいな直にアドレス入力して更新もマニュアルとかいう「何時の時代だよ!」と突っ込みたくなる代物ではない。
今まで移行しなかった理由はQt5でビルドしたバージョンだとUIのフォントに変なアンチエイリアスがかかってて見辛い事だったが
これは起動時のコマンドでqtcreator -style gtkとする事で一先ず解決できるというのがわかった。
補完もQtに関する物以外あまり効いてくれない印象がある。
けどKdevelopも大概なのでこれについては気にならない。
何より設定した項目がちゃんと効いてくれるし、デバッガもサクサク動き
メモリ表示なんかもkdevelopみたいな直にアドレス入力して更新もマニュアルとかいう「何時の時代だよ!」と突っ込みたくなる代物ではない。
今まで移行しなかった理由はQt5でビルドしたバージョンだとUIのフォントに変なアンチエイリアスがかかってて見辛い事だったが
これは起動時のコマンドでqtcreator -style gtkとする事で一先ず解決できるというのがわかった。
シリアライズ
boost::serializationの使用を含め本格的に内部状態をファイルに書き出して復元というのは今までやったことがなかったので割と苦戦中。
やっていて幾つか分かったことが。
やっていて幾つか分かったことが。
- シリアライズをする予定があるなら、最初からそれを想定して設計するべきだ
- 馬鹿正直に変数を全部書き出すと容量が増えるだけでなく復元の手間もかかる(特に外部APIに依存してる場合)
- クラスの内部クラスはいちいちboost::serializationに登録せず親クラスがserializeメソッドを直接呼んだ方が楽
- boost::serializationを使ったからと言ってシリアライズが凄く楽になるという訳ではない。あくまでもヘルパーの位置づけ。
ぶっちゃけ全部当たり前なんだけど。でもこういうのってやらないと分からない。
ネットでググって出てくるシリアライズのサンプルってクラスの変数を
全部ベタ書き、ベタ読みしてちゃんと数値が合ってますねーっていうのが多いからアレで油断する。
ネットでググって出てくるシリアライズのサンプルってクラスの変数を
全部ベタ書き、ベタ読みしてちゃんと数値が合ってますねーっていうのが多いからアレで油断する。
今の所リソースマネージャ全体を一括シリアライズ、大きなリソースの無駄な読み込みを抑えるために差分だけロードする機能
それらをチェックするテストコードを実装済み。
それらをチェックするテストコードを実装済み。
で、サウンド
大体は書き出しと復元できてる。
が、フェードインとフェードアウトで使う音量調整はあっちで処理したりこっちで処理したりしてて一貫性がなく
シリアライズした時に音量が0固定で聞こえなかったりするんでその辺書き直しかなと。
が、フェードインとフェードアウトで使う音量調整はあっちで処理したりこっちで処理したりしてて一貫性がなく
シリアライズした時に音量が0固定で聞こえなかったりするんでその辺書き直しかなと。
(2013/12/11)
サウンドの復元
タスクシステムとシーン遷移はソースを移植するだけですんなり行ったもののサウンドで躓く。
これも基本的にはソースの移植だったがサウンドの一時停止と復帰処理が少々面倒なことに。
これも基本的にはソースの移植だったがサウンドの一時停止と復帰処理が少々面倒なことに。
いかにPCのリソースをフルに使うゲームと言えど
ひとたびウィンドウが最小化されればなるべく他のアプリケーションの邪魔をしないのが礼儀なので
頂点バッファやテクスチャといったGPUリソースの類は一旦解放するような動作にしたし
当然サウンドも一時停止させたい訳である。
ひとたびウィンドウが最小化されればなるべく他のアプリケーションの邪魔をしないのが礼儀なので
頂点バッファやテクスチャといったGPUリソースの類は一旦解放するような動作にしたし
当然サウンドも一時停止させたい訳である。
OpenALの場合はalcSuspendContext()という関数があってこれを呼べばいいのかな?と思ったら
(恐らく)ドライバとデバイス間の通信をsuspendするという意味らしく、即サウンド停止とはならなかった。
というより自分の環境だと復帰関数であるalcProcessContext()を呼ばなくても
以後の関数呼び出しが失敗しないし効いているか疑問。
じゃあ何でウィンドウ最小化でサウンドが止まるかと言えば
ウィンドウ最小化中はデバイスに音声データを送る処理をしていないから再生すべきデータがなくなって停止しているだけだった。
ただ一応止まるからいいか、という感じはする。
(恐らく)ドライバとデバイス間の通信をsuspendするという意味らしく、即サウンド停止とはならなかった。
というより自分の環境だと復帰関数であるalcProcessContext()を呼ばなくても
以後の関数呼び出しが失敗しないし効いているか疑問。
じゃあ何でウィンドウ最小化でサウンドが止まるかと言えば
ウィンドウ最小化中はデバイスに音声データを送る処理をしていないから再生すべきデータがなくなって停止しているだけだった。
ただ一応止まるからいいか、という感じはする。
OpenSL ESは自分のアプリがスリープ状態の時に他のアプリがOpenSLを使って
その後こっちが復帰後にOpenSLを使おうとすると落ちるようなので
サウンドドライバの初期化からやり直さないといけない。
再生中のサウンドを記録して復元する仕組みが必要。
その後こっちが復帰後にOpenSLを使おうとすると落ちるようなので
サウンドドライバの初期化からやり直さないといけない。
再生中のサウンドを記録して復元する仕組みが必要。
早い話がシリアライズ。
シリアライズ
シリアライズとはクラスや構造体の情報をバイト列として書き出す事。
クラスの状態を記録してバッファに持っておき後で復元したりファイルに保存、あるいは何処かに送信したりとか。
クラスの状態を記録してバッファに持っておき後で復元したりファイルに保存、あるいは何処かに送信したりとか。
自分のプログラムではクイックセーブやロードを実装する時まで考えなくていいかなーと放置していた。
しかし前述のようにサウンドの再生状態を復元せねばならんので急遽取り組む形に。
しかし前述のようにサウンドの再生状態を復元せねばならんので急遽取り組む形に。
(2013/12/08)
スクリーンショット撮ろうかと思ったけど前回からあまりにも見栄えしないので止めた
進捗
カメラやフォント描画、タスクシステム組み込みとインプットのマウス関連が全然なってなかったのでそれの修正。
あとエフェクトファイル(DirectXで言うFxファイル)の何処にコメントを挟んでも大丈夫なようにした。
今出来るのはテクスチャを貼ったポリゴンの表示とマウス移動でのフリールック、方向キーでのカメラ移動。
あとエフェクトファイル(DirectXで言うFxファイル)の何処にコメントを挟んでも大丈夫なようにした。
今出来るのはテクスチャを貼ったポリゴンの表示とマウス移動でのフリールック、方向キーでのカメラ移動。
一番時間食ったのはマルチスレッドとOpenGLの連携(?)というか、結構前に触れたContext Sharing関係。
これについてはちょっと説明が必要。
PCでOpenGLを使う分にはDirectX10以前で言うデバイスロストが発生しないけどAndroidではある様なので
自分のプログラムではそれの対策としてデスクトップ版は
ウィンドウがフォーカスを失ったらゲームスレッドと描画スレッドを停止、更にウィンドウが最小化されたら
全てのOpenGLリソースをバックアップして解放し、ウィンドウの復元されたらリソースの再確保・・という動作とし、
Android版はアプリがバックグラウンドに回ったら = onPause() 即座にデスクトップ版のウィンドウ最小化と同じ挙動にした。
これについてはちょっと説明が必要。
PCでOpenGLを使う分にはDirectX10以前で言うデバイスロストが発生しないけどAndroidではある様なので
自分のプログラムではそれの対策としてデスクトップ版は
ウィンドウがフォーカスを失ったらゲームスレッドと描画スレッドを停止、更にウィンドウが最小化されたら
全てのOpenGLリソースをバックアップして解放し、ウィンドウの復元されたらリソースの再確保・・という動作とし、
Android版はアプリがバックグラウンドに回ったら = onPause() 即座にデスクトップ版のウィンドウ最小化と同じ挙動にした。
で、スリープに入る際に同期の仕方が不味いと
最悪PCごとフリーズしてコンソールも何も動かなくなってしまい再起動を余儀なくされるので時間がかかる。
多分一方のスレッドがOpenGLリソースを作成している間にもう片方がそれを使おうとするケースとは思うが
実際の所よくわからん。
glTexImage2D()はピクセルバッファを使わなければGPUの処理が終わるまでブロックされると思ったんだけど
メインスレッドのglTexImage2D()を呼んですぐ描画スレッドに「描画開始していいよー」とシグナルを送ってみたら上手く動かなかった。
でもglTexImage2D()の後シグナルを送る前にglFinish()を挟んだら全然フリーズしなくなった。
最悪PCごとフリーズしてコンソールも何も動かなくなってしまい再起動を余儀なくされるので時間がかかる。
多分一方のスレッドがOpenGLリソースを作成している間にもう片方がそれを使おうとするケースとは思うが
実際の所よくわからん。
glTexImage2D()はピクセルバッファを使わなければGPUの処理が終わるまでブロックされると思ったんだけど
メインスレッドのglTexImage2D()を呼んですぐ描画スレッドに「描画開始していいよー」とシグナルを送ってみたら上手く動かなかった。
でもglTexImage2D()の後シグナルを送る前にglFinish()を挟んだら全然フリーズしなくなった。
で、書いてて思った。
コマンドが辿る経路って 「アプリケーション」 -> 「ドライバ」-> 「GPU」 の順番なんだから
(ドライバのコマンドキューはコンテキスト毎に別になってる想定)
glTexImage2D()でブロックされるのはテクスチャのデータをユーザーメモリからドライバ管轄メモリにコピーするまでの間だけで
そこからGPUまではまだ渡ってないって事か?
だったらGPUの処理が終わるまで待つglFinishじゃなくてGPUにコマンドを渡すだけのglFlushでもいいのでは・・・と。
早速試すとやはりそうらしく、何度ウィンドウを最小化・復帰させてもフリーズすることはなかった。
コマンドが辿る経路って 「アプリケーション」 -> 「ドライバ」-> 「GPU」 の順番なんだから
(ドライバのコマンドキューはコンテキスト毎に別になってる想定)
glTexImage2D()でブロックされるのはテクスチャのデータをユーザーメモリからドライバ管轄メモリにコピーするまでの間だけで
そこからGPUまではまだ渡ってないって事か?
だったらGPUの処理が終わるまで待つglFinishじゃなくてGPUにコマンドを渡すだけのglFlushでもいいのでは・・・と。
早速試すとやはりそうらしく、何度ウィンドウを最小化・復帰させてもフリーズすることはなかった。
ちなみに一方がリソースを使用中にもう片方が削除するケースでは単にSEGVでプログラムが強制終了されるだけだったが・・この辺はドライバの実装依存かな?
予定
タスクシステム(シーン遷移など)のチェック、サウンドのチェックまで終わらせたら
次はモデルの表示、といったとこか。
とりあえず生ポリゴンのゲーム作りたい。
PCで動くサンプルの配布まで行けたらAndroidへも移植してみたい。
Zip書庫からの抽出処理はテストしきれて無いからそれもやらんと。
次はモデルの表示、といったとこか。
とりあえず生ポリゴンのゲーム作りたい。
PCで動くサンプルの配布まで行けたらAndroidへも移植してみたい。
Zip書庫からの抽出処理はテストしきれて無いからそれもやらんと。