countof
自作ライブラリ、手始めに型情報クラスを実装。
それに伴う最低限必要な機能をあれこれ実装した。
アサートマクロとか、コンパイラ毎の違いを吸収するマクロとか。
で、配列の要素数があっているかチェックする静的アサートのマクロも
実装しておこうと思って、C++11以降での配列要素数取得について調査。
仕事でプログラムかいてた時はC++03までしか触れられなかったので
マクロで対応していたけど、C++11以降なら constexpr でスマートに書けるはず!
まあその情報はすぐに出てきて想像通りだったので
素直に countof 関数を実装したんだけど、
C++17以降は size 関数で同様の機能が提供されるらしい。
生の配列でも、sizeメンバ関数を持つコンテナでもOK。
↓のサイトが参考になった。
Better array 'countof' implementation with C++ 11 (updated)
型情報クラスについてはまた次の機会に書きたいと思う。
compattelrunner
前から自宅PCの動作が重いことが多く、
まあそんなスペック高く無いからなーと思ってたのだが、
どうもディスクアクセスが常に100%近くの負荷になっていて、
最近幾つか対処した。
まずはデフラグ。
HDDの最適化が定期的に実行されるようにスケジュールされていて、
普段は毎日PC起動するわけではなかったので、
どうも起動するたびに最適化が走っていたようだ。
というわけでスケジュールを無効化。
続いて、どうも compattelrunner とやらが常にHDDにアクセスしているようだ。
google先生に聞くとあっさり情報が出てきたので、
こちらはタスクスケジューラから無効化。
ひとまずこれで、それなりにサクサク動くようになった。めでたしめでたし。
ID Managerの世代バックアップ保存失敗
以前から、ID Managerの設定を保存するたびに
世代バックアップの保存に失敗したっていうメッセージが出てて、
まあ世代バックアップだったらいいかなって流してたけど、
全然良くない事に今更気づきました…
これで作られるファイルをID Managerのバックアップとしてコピーしてたから、
全く更新されていない設定ファイルを保存し続けてました。
ファイルスタンプがなんと2013年…
解決方法としては、ツールの 設定>データ保存先 で、
指定した場所を使用するにして、ProgramFilesの外のディレクトリを設定。
今回、Dropboxのディレクトリを設定したので、
これまで定期的に手動バックアップしてたよりも楽で安全になりました。
…が、そもそも今の時代にパスワード管理がID Managerでいいものか?
最近iPhoneでは1Password使ってるけど、そろそろパスワード管理整理しないとなー。
角度クラス 構想
環境整備もなかなか進まないので、
取り敢えず家にいなくてもできる事ってことで、
このブログで書きたかった事を進めることにしようかと。
まず1つ目にやりたかった、角度クラスについて。
ゲーム開発でも、浮動小数でradianやdegreeを扱って、
必要に応じて deg2rad や rad2deg とかって関数で変換するのが多いです。
で、よく問題になるのが、関数はradianを要求しているのに、間違ってdegreeを渡してしまうとか、
そもそも関数がどっちを要求してんだよ!ってことですね。
radianとdegreeの扱いについて、↓の様な記事もあります。
魔導書に触発されてRadian⇔Degree変換をやってみた - C++でゲームプログラミング
角度のstrong typedef - Faith and Brave - C++で遊ぼう
で、自分がやりたいのは、radianかdegreeかをあまり気にしなくて済むことです。
この関数はどっちを要求してるの?とか、この変数はどっち?とか。
なので、radianとdegreeは暗黙的に変換してほしい。
例えば、
// Radianクラスを引数にとるサイン関数 float sin( Radian rad ) {...} // Degreeクラスを渡すと、暗黙的にRadianに変換してくれる。 Degree deg( 180 ); float s = sin( deg );
という感じで。
あと、クラス化して幾つかメソッドも追加したいですね。
0度~360度に正規化するメソッドや、
2つの角度間で最小の角度差を求めるとか。
そもそも三角関数も、角度クラスのメソッドにあってもいいかもしれないですね。
ここまでが、結構前から考えてた角度クラスの実装です。
で、ちょっと前に思いついたのが、
そもそも角度をradianとdegreeで扱うのってどうなの?ということ。
1周を360度とか円周率x2で扱わなくていいんじゃないかと。
もちろん、それが必要な時もあるけど、途中の計算で必要になることってあまりない。
プログラム中で 180 とか 360 って書くのは、
普通なら「マジックナンバー使うな!」と起こられるようなことだし、
円周率みたいな無理数を扱うのって冷静に考えたらあんまり良くない。
で、どうするかって言うと、1周を 1.0 として扱ってしまう。
これ、すごく自然だと思うんですよね。
180度は0.5、90度は0.25。
30度とかは流石に直値では書けないので、30 / 360.f って書くのがわかりやすいだろうけど。
まあ、これはradianで計算している時も一緒ですね。
一周が1.0だから正規化するのも楽だし、
例えば「30フレームかけて2回転させる」とかって、
「2.0 / 30.f * time」
みたいな計算だけでOK。
degreeだと「360 * 2.0 / 30.f * time」って計算になっちゃいますね。
使い方は↓みたいな感じで。
// Angleクラスを引数にとるサイン関数 float sin( Angle angle ) {...} Angle angle( 0.5f ); // 180度 float s = sin( angle ); sin( Degree(180) ); // degreeの方がわかりやすい時はこんな感じで
以上がざっくりとした構想です。
さ、これからこの実装を進めて行きますよ。進め、自分。