boost study#4
DESCRIPTION
Boost.勉強会 #4 での「ゲーム開発のC++」TRANSCRIPT
m��ĝìO���
Boost.勉強会 #4 2011.02.26
2011年2月26日土曜日
m��ĝìO���Boost.って? 本当、素人ですみません
Boost.勉強会 #4 2011.02.26
2011年2月26日土曜日
自己紹介
id: Isoparametric(イソッパ)
blog: 神様なんて信じない僕らのために
work: 最近は、Django x Python
misc: C++は最近はさっぱりです
2011年2月26日土曜日
今日の話
特に面白い話はありません
為になる話もありません
話をきいてもゲームはつくれません
本スライドはBoost.とは一切関係がありません
2011年2月26日土曜日
m��ĝìĭ
2011年2月26日土曜日
��������� ��������
2011年2月26日土曜日
H=
2011年2月26日土曜日
2011年2月26日土曜日
ÏĞò5H=
2011年2月26日土曜日
趣旨
C++でのゲーム開発経験とか雰囲気が伝われば良いかなあと思ってます
あくまで一例なのでというのを踏まえて下さい
2011年2月26日土曜日
リモコン振り回したりとか
二画面でタッチパネルついてたりとか
そんなのの開発経験の話です(古い)
ハード特有の話はしません
ARM946E-S(67.028MHz)、RAM4Mbyteくらいを想定
ハード的には
2011年2月26日土曜日
2011年2月26日土曜日
KaG8IU-[R?a
2011年2月26日土曜日
BC2011年2月26日土曜日
���I2���I2
2011年2月26日土曜日
2011年2月26日土曜日
Y^;61ģ.;R=
2011年2月26日土曜日
m��ĝìIP
2011年2月26日土曜日
èÃ
2011年2月26日土曜日
2011年2月26日土曜日
2011年2月26日土曜日
2011年2月26日土曜日
2011年2月26日土曜日
ç·
2011年2月26日土曜日
2011年2月26日土曜日
そして、唸るワゴン画像と実在のプロジェクトは関係ありません、マジで
2011年2月26日土曜日
2011年2月26日土曜日
I)²`°=ČHPK6
+�Ú±Ñ,L¾.ċĊ³�I./1Č
2011年2月26日土曜日
à`«[î;G
2011年2月26日土曜日
AUAU
2011年2月26日土曜日
+���ĭ(ę.C^,
EG)ĉ_]B[;R?a2ĭ
2011年2月26日土曜日
A]HU
2011年2月26日土曜日
�����EDV/aH=2ĭ
2011年2月26日土曜日
���ę6K.H=2ĭ
2011年2月26日土曜日
��_K.aH=2ĭ
2011年2月26日土曜日
��EDV/ĭ
2011年2月26日土曜日
2011年2月26日土曜日
KaHĭ
2011年2月26日土曜日
Cは流石にないよね
今時Cのプロジェクトは時代錯誤
しかし、現実にはC99すら導入されてなくて涙目
変数宣言がブロック先頭のみとかね
BetterC的な意味合いでもC++
2011年2月26日土曜日
未だになぜ頑なにC?
C++は遅い、と真顔で言う人がいる
でも、単にC++憶えるのめんどいだけだよね
CもせめてC99いれればいいのにね
2011年2月26日土曜日
C++にあってCになくて欲しいもの
コンストラクタ/デストラクタ
クラス(仮想関数)
テンプレート(ジェネリックなコンテナ)
operatorオーバーロード
アロケータ機構(柔軟なメモリ管理)
名前空間、などなど
2011年2月26日土曜日
�I2Þî;aJ.
2011年2月26日土曜日
���Pę6K.
2011年2月26日土曜日
C++は遅くないし
関数のコストはCと同じ
メンバ関数も生成されるasmはCとほぼ同等
classの暗黙のthis渡しも構造化されたCでは、第一引数は何らかのインスタンスなので同じ
仮想関数の呼び出しは純粋な関数よりコストがかかるが抽象化に必須
2011年2月26日土曜日
ĉ.6\TG����EI8/@Ĥ
2011年2月26日土曜日
STLもBoost.も使えるよ
コンパイラはCodeWarriorやProDGだよ
RTTIも使えるよ(使わないけど)
スレッドも使えるよ(危ないけど)
例外も使えるよ(コードでかいけど)
ゲーム機で○○って使えるの?
2011年2月26日土曜日
諸注意
必ず計測はしよう
生成されるコードも見よう
ゲームでよく使われる局所のベクトル演算やマトリクス演算などには注意
operatorにする場合、インライン関数より遅いケースはある
ボトルネックがどこか、は見よう
2011年2月26日土曜日
ÉêI2
n�o��3³ÇÓUĜ.
�x�{ujס³�
2011年2月26日土曜日
ĝì3P<REBZ
2011年2月26日土曜日
ăEBm��ĝìL1.G
143DK8ILáÄ
2011年2月26日土曜日
ĈùħÿÅ
2011年2月26日土曜日
ĒĈù)s�*qurd*
2011年2月26日土曜日
�0Q)
2011年2月26日土曜日
GO�¯P³ËµL=\
AOĨ
2011年2月26日土曜日
全ての値型は大文字で書かなければならない
VOID、INT、FLOAT、BOOL、など
エディタの自動カラーリングがきかなくなるんだけど……
てか、意味を想像する事すら難しい規約
大変うざいことにBOOLがboolでなくint
virtual BOOL IsDead( VOID ){ return FALSE };
2011年2月26日土曜日
IL26v����xP
ðÝ=\
AOĩ
2011年2月26日土曜日
STLは勿論禁止(標準なのに)
自作も禁止
理由は、よくわからないから(主に本人が)
使わなきゃ憶えられないよ?
残念な事に多重継承も禁止で汎用インターフェイスが一切作れなかったり
あとコンテナもなかったり
2011年2月26日土曜日
d�~K��~cjp
O¾Ć
AOĪ
2011年2月26日土曜日
人名
hidekiUtil_RenderParticle
df3CharHitAtkAttrCalc
ゲーム名
bosActorCreate
ライブラリ名
2011年2月26日土曜日
Ùʦ;K.
AOī
2011年2月26日土曜日
一つのソースに何でも書く
魔法の処理なら処理をhogeMagic.cとかに1ファイルで全部書く
ソースのサイズを見ると700Kbとかある
行数は20,000行……
2011年2月26日土曜日
�prd�i�px
AOĬ
2011年2月26日土曜日
安全にキャストする気が無い
static_castとか頑なに使わない
Cスタイルキャストの方が楽だろ?とか言う
キャストミスっててメモリ破壊で死んでたりする
2011年2月26日土曜日
こんなの絶対おかしいよ
2011年2月26日土曜日
2011年2月26日土曜日
´3Z?2ĭ
2011年2月26日土曜日
èé3ďÍH4K.d�~KĈùħÿÅP
F6ZK.8I
ĜĆ
2011年2月26日土曜日
Ùʦ;G�ÞIȽ`»LĀ0\8I
ĜĆ
2011年2月26日土曜日
ĉĎ3Ê�=\ĜĆKÛĂPDVaI�/�
ĜĆ
2011年2月26日土曜日
2011年2月26日土曜日
-]�!!$%�OČPĭ
2011年2月26日土曜日
何勉強会だっけ……2011年2月26日土曜日
DXEIÀEGN
2011年2月26日土曜日
WEBÙÆÞ;.2P¢L;G
2011年2月26日土曜日
C++ Coding Standards101のルール、ガイドライン、ベストプラクティス
R>ĐU/)ĐRA/Ĥ
2011年2月26日土曜日
RTTIはOFF
ダウンキャストの安全性を考えるならdynamic_castを使うべき
しかし、バグ以外で絶対に成功することが解っているのに使うのは勿体ない
ダウンキャストはよく使うので特に
polymorphic_downcastで、デバッグ時だけdynamic_castするという手も
2011年2月26日土曜日
例外はOFF
例外を投げてエラーを管理したい、というのはかなり重要度が高い
けど、例外はほぼ不要な場合もコードを生成してしまう
また、例外安全性を組み込み環境で実現することは難しいのでoff
2011年2月26日土曜日
newは自作する
フリースタンディング環境では、OSがないため、メモリ管理は自前でがっつりやらないとダメ
アロケータやメモリブロックの管理は自前できちんとやる(アライメントとかもね)
アロケータにはdlmallocを用いたりした
2011年2月26日土曜日
多重継承は使う
java的なInterfaceの意味で多重継承を用いる
変にごちゃごちゃ継承するのはダメ
場所を持つもの、方向を持つもの、持ち上げられるもの、などを抽象化し、インターフェイスを実装する形にする
2011年2月26日土曜日
constは必ず使う
不変なインターフェイスは必ずconst
引数も変更があり得ないなら、ゼッタイにconstにする
mutable/immutableを意識すると、コンパイラがチェックしてくれるのでいろいろ嬉しい
2011年2月26日土曜日
テンプレートは使う
勿論、テンプレートは使う
複雑怪奇なテンプレートでない限り、生成されるコードはたいしたことない
スマートリンカが動けばコードサイズはきにならない
デバッガの表示はちょっと面倒
2011年2月26日土曜日
����%� ��#�����"��%�����#�#'
2011年2月26日土曜日
��2011年2月26日土曜日
g�g�n�vz
2011年2月26日土曜日
¬ĢP©�ë
2011年2月26日土曜日
「STLよくわからんからコンテナつくったー」「STLが不便だからコンテナつくったー」
2011年2月26日土曜日
A8LPäâIĕ6d�~K
d�r�~fdp3
2011年2月26日土曜日
Array() virtual ‾Array() void alloc(unsigned int size); void release(); void setFuncValid(FuncValid i); FuncValid funcValid(); void setFuncEqual(FuncEqual i); FuncEqual funcEqual(); void setFuncSort(FuncSort i); FuncSort funcSort(); bool valid(); unsigned int size(); T &operator[](unsigned int index); T &operator[](int index); Array<T> &operator=(const Array<T> &i); T *ptr(); void push(T&v); void pop(T &v); T *find(T &v); T *findInvalid(); void sort(); bool validAssert(); unsigned int count(FuncValid func); void clear(); void fill(T i);
え?なにこれ
2011年2月26日土曜日
そういうのに限って「STLって使えねえ」
2011年2月26日土曜日
����0GK.OP1£H=
2011年2月26日土曜日
謎自作ダメ。ゼッタイ。
namespaceも使わずにArrayだと……
イテレータとかガン無視だと……
STLのインターフェイス……
何がしたかったのかわからん
2011年2月26日土曜日
2011年2月26日土曜日
必要ならまずvectorを検討しよう
多くの場合std::vectorが最も高速で、高効率で最も要件を満たす
ある程度のサイズがあり、先頭に追加/削除したいときはdequeも検討しよう
listはメモリ効率などの関係であまりお勧めできない(ゲーム機では特に)
2011年2月26日土曜日
vectorのはまりどころ
clearを呼んでもメモリは解放されない
reserveせずに使うとメモリの確保/解放タイミングをコントロールできない
vectorをiterateしているときに要素を外そうとして不正なイテレータになったり、コンテナを壊すのに注意(割とよくある)
shrinkやメモリ解放はswap技法で
2011年2月26日土曜日
例えばprotected継承を使う
class Vector : protected std::vector<T, Allocator> で実装やインターフェイスを継承し、Vector≠std::vectorにできる
using std::vector<T>::empty; のようにインターフェイスを公開/非公開にできる
宣言時にreserve数を指定させると初期化時に期待した大きさにできるなど制御可
2011年2月26日土曜日
std::map、std::setを使う前に
hash_mapとhash_setがないか探そう
コンパイラのドキュメントに独自の名前空間で用意されていたりする
CodeWarriorならMetrowerks名前空間、gccなら__gnu_cxxなど(tr1の unordered_xxxでも可)
codepad、ideoneなどでも試せるよ
2011年2月26日土曜日
どうしてhash_xxx?
(大抵)赤黒木で実装されているstd::map、std::setより、ハッシュで実装された方が省メモリかつ高速
木は挿入、削除、検索が対数O(log N)
ハッシュは概ね定数O(1)
ハッシュが衝突しまくるとO(N)だけど
計測はしましょう!
2011年2月26日土曜日
デバッグ版STLも使おう
コンパイラベンダにもよると思うが、STLにはデバッグ版が用意されるケースがある
その場合、不正なイテレータの検知などをしてくれるようになる
切り替えられるようにしておくと便利
また、Boost.のようにエラーハンドリングも、エラー関数で出来る事が多い
2011年2月26日土曜日
K@8aK8ILà`Ě/2
2011年2月26日土曜日
m��ÛHO���OÌå¦P
§DþW2KßC2Z
2011年2月26日土曜日
���3���'%�ó.G.\õKOL����3I]K.
8I3ÐėLĔ4\
2011年2月26日土曜日
����3K.OH
�Ô?Mrd��kHzt���LßM
2011年2月26日土曜日
�u�`�Fñ¥;BÁL¨®�Í|�k
HôâßI2´H;Xĭ
2011年2月26日土曜日
HUJ/;GU
Ą�;B6KEBZ
2011年2月26日土曜日
��� ���%#! ���#%$����
2011年2月26日土曜日
EASTLとは
Electronic Artsによって実装されたゲーム開発向けのSTL
メモリ周りに色々気遣い
仕様>EASTL -- Electronic Arts Standard Template Library
実装>EAWebKit 1.10に含まれてます
2011年2月26日土曜日
STLと何が違う?
STLはポータブルなコードではないのでポータブルに実装されている(主張)
intrusive_container(侵入型コンテナ)などを実装してある
アロケータを使いやすくしてある
オブジェクトのコピーをムーブにしてコスト削減できる、などなど
2011年2月26日土曜日
オレオレと何が違う?
STLとほぼ同じインターフェイス、イテレータ、アルゴリズムを持つ
拡張は、高効率、明瞭性、デバッグのためのものである
STLに足りず、ゲームに必要であろうと思われるコンテナを追加してある
2011年2月26日土曜日
id:i-saintさんのEASTL から垣間見るゲームソフトウェア開発現場の現状が良い資料です!
2011年2月26日土曜日
�0Q8aKb�l�r
typedef eastl::list<int, fixed_allocator> IntList;typedef IntList::node_type IntListNode;
IntListNode buffer[200];IntList intList;intList.get_allocator().init( buffer, sizeof(buffer), sizeof(IntListNode), __alignof(IntListNode));
2011年2月26日土曜日
eastl::fixed_vectorと
eastl::vector軽く紹介
2011年2月26日土曜日
fixed_vector
固定長のvector
消費メモリが途中で増えるとか嫌です、という時に使う
引数で固定かのon/off制御できる
要素を増やせない場合は未定義の動作か例外
2011年2月26日土曜日
T = 言わずと知れた型 nodeCount = オブジェクトの最大数 bEnableOverflow = オブジェクトの最大数をオーバーフローできるか? Allocator = オーバーフロー時にのみ使われるアロケータ。 bEnableOverflowがtureの時だけ有効。 デフォルトだとグローバルヒープから取得する。
template <typename T, size_t nodeCount, bool bEnableOverflow = true, typename Allocator = EASTLAllocatorType>class fixed_vector
2011年2月26日土曜日
Example usage:fixed_vector<Widget, 128, true> fixedVector; fixedVector.push_back(Widget());fixedVector.resize(200);fixedVector.clear();
2011年2月26日土曜日
eastl::vector
std::vector風、動的配列コンテナ
void push_back(void);など拡張あり
例外を使わず動作するよ
vector<bool>はbit vectorじゃないよ
vector<SomeClass>(x).swap(x);の替わりにset_capacityがあるよ、などなど
2011年2月26日土曜日
ěPDVaIĐaHK.7Jæ.Pą.Ĥ
OH)ÎġªĀL
2011年2月26日土曜日
RCDVaI
ĐaHK.OHē¬LP
ö0Z]K.ĥºïĦ
2011年2月26日土曜日
A^A^ûđ
2011年2月26日土曜日
�!!$%��0QØLKEB2UNĤ
2011年2月26日土曜日
ý4R=
2011年2月26日土曜日
まぁ、めげずに、
C++を使いましょう!
2011年2月26日土曜日
A^A^�!!$%�
2011年2月26日土曜日
�0Qm��ĝìH
$��#��"%#�&����"%#`�EB
2011年2月26日土曜日
Z)}kEB
¤Ií³L
2011年2月26日土曜日
2011年2月26日土曜日
1. 腕の問題
2. 循環参照の問題
3. 生成/破棄タイミングの問題
なんでバグった?
2011年2月26日土曜日
自分の頭が悪かった
考え無しに何でもshared_ptrというわけにはいかない
shared_ptr/weak_ptrでは要件を満たせなかった
腕の問題
2011年2月26日土曜日
めぐりめぐって循環参照してたりする
お互いがお互いを監視するシーンが多かった
循環参照の問題
2011年2月26日土曜日
誰にも参照されなくなったタイミングで即座に消えると都合が悪い
リソースやインスタンスの生成/破棄はできるだけ意図したタイミングでやりたい
画面描画中に消えたりすると拙い(ラインバッファのゲームとか特に)
生成/破棄の問題
2011年2月26日土曜日
�0QĖ¹č¸¿`ċĊ=\
2011年2月26日土曜日
追尾誘導弾?
いわゆるホーミングミサイル
誘導弾が狙うべきターゲットを参照
誘導弾は発射したオーナーも参照
誘導弾は発生させるループエフェクトも参照
2011年2月26日土曜日
誘導弾
オーナーターゲット
エフェクト2011年2月26日土曜日
誘導弾
オーナーターゲット
エフェクト
座標参照 パラメータ参照
2011年2月26日土曜日
誘導弾
オーナーターゲット
エフェクト
座標参照 パラメータ参照
でも、めぐりめぐってこの誘導弾を見る人でてくるんじゃない?
2011年2月26日土曜日
例えばこんな話も
誘導弾ループエフェクト
エフェクトアタッチャ
2011年2月26日土曜日
例えばこんな話も
誘導弾ループエフェクト
誘導弾消滅時に減衰消滅させたい
エフェクトアタッチャ
エフェクトを追従させたい2011年2月26日土曜日
例えばこんな話も
誘導弾ループエフェクト
誘導弾消滅時に減衰消滅させたい
エフェクトアタッチャ
エフェクトを追従させたい
どこから消す?
2011年2月26日土曜日
ªãhe�rhpr�w��rC7HPğ;.
2011年2月26日土曜日
¶ L��`ćFTG.B.
2011年2月26日土曜日
KaCÜ;.OP
¼ªãKaCĤ
2011年2月26日土曜日
A/C|�y�÷è;Y/of{�ujK¼ªã|�y�`Ò7QĤ
2011年2月26日土曜日
// tuple!!#include <boost/tuple/tuple.hpp>
class HandleBase;
boost::tuple<unsigned long, unsigned long> RegisterHandle(void* object);void UnregisterHandle(HandleBase handle);
class HandleBase{public: // valid か? inline bool isValid() const
2011年2月26日土曜日
template <class T>class Handle : public HandleBase{public: Handle(unsigned long id, unsigned long index) : HandleBase(id, index) { }... // こんなのでアクセス T* operator->() const
2011年2月26日土曜日
モデル
テクスチャ
テクスチャ
動的リソース管理も弱参照で
2011年2月26日土曜日
�!!$%��EGN0000
2011年2月26日土曜日
boost::array = 生配列は全て置換してもいい
boost::tuple = 多値返しに使うと良い
boost::tribool = たまに不定も欲しい
boost::noncopyable = 安全のために便利
リソースやインスタンスの生成/破棄はできるだけ意図したタイミングでやりたいのでshared_ptrは避けた
小物は使いやすいよ
2011年2月26日土曜日
9TaY1111
2011年2月26日土曜日
Boost.使わないやつは
って言われそう2011年2月26日土曜日
RIT
2011年2月26日土曜日
C++は使う前が大変
使ってからも大変(変なプロジェクトだと)
でも、開発を楽にするには必須
STLもBoost.も色んな環境で動きます
メモリが4Mbyteしかなくて諦めない!
まとめ
2011年2月26日土曜日
Óúûđ�!!$%��EI7�""����#�LÂZ]\2Z
2011年2月26日土曜日
ø�Õ)üTGSBûÖ3)
8]CYĤĤ2011年2月26日土曜日
9Ġā-[3I/9:.R;B
2011年2月26日土曜日