拙iPhoneアプリ『ういろう』でのboost成分
Upcoming SlideShare
Loading in...5
×
 

拙iPhoneアプリ『ういろう』でのboost成分

on

  • 3,011 views

2013/10/19 boost勉強会@仙台で発表したスライドです。 ...

2013/10/19 boost勉強会@仙台で発表したスライドです。

C++三年目のプログラマが作ったiPhoneアプリで役立ったboostのライブラリに関しての発表です。

Statistics

Views

Total Views
3,011
Views on SlideShare
1,267
Embed Views
1,744

Actions

Likes
3
Downloads
4
Comments
0

6 Embeds 1,744

http://blog.livedoor.jp 1579
https://twitter.com 139
http://cloud.feedly.com 21
http://webcache.googleusercontent.com 3
http://reader.aol.com 1
http://translate.googleusercontent.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

拙iPhoneアプリ『ういろう』でのboost成分 拙iPhoneアプリ『ういろう』でのboost成分 Presentation Transcript

  • iPhoneアプリ『ういろう』 でのboost成分 C++三年目で初めて触れたboostでアプリを作ってみた 西山信行
  • • 各種パソコン • SS C • N64 • PS、PS2 • GC • DC • PSP 2011~ アセンブラ 1996~ 1990~ 自己紹介 C++ • iPhone • Windows • OSX
  • • Cで書いた最後 のゲーム • Win&OSX こなへん • C++で初めて 作ったゲーム • Win&OSX&iPhone 2013 TieGunner 2012 2011 最近の活動 ういろう • C++11とboostで 作ったゲーム • Win&OSX&iPhone
  • ちょいとDEMOタイム せっかくなので、ゲームも観てもらいます;)
  • 今日の内容 C++三年目のiPhoneアプリで 初めて使ったboostについての報告
  • みなさんにお願いしたい!! なにぶんC++初心者なので… なにかあればぜひ、 その場で挙手をお願いします
  • よっしゃboost使うぜ!! • 使おうとしたのがC++11でけっこう実現されてる… • for_each • 範囲ベースfor文 • random • std::random • lexcal_cast • std::to_string
  • いろいろ検証してみて • 拙作『ういろう』ではこの4つを使いました • boost::noncopyable • boost::signals2 • boost::any • boost::bind • どれもヘッダをインクルードするだけなのでお手軽!! • ビルドはiPhone向けがしんどい(armv7、armv7s、arm64、i386…)
  • boost::noncopyable
  • boost::noncopyable • コピーされたくない型が継承するだけでよい #include <boost/noncopyable.hpp> class X : private boost::noncopyable {}; int main() { X a; X b = a; } // エラー!
  • boost::noncopyable • コピーされたら困る型を扱う時のうっかりミスを防げた • ポインタやstd::unique_ptrを内包してるとか struct Hoge : private boost::noncopyable { /* いろいろ定義 */ }; std::vector<Hoge> objects; Hoge obj; objects.push_back(obj); for (Hoge obj : objects) { // いろいろ処理 } // エラーにできる // エラーにできる
  • boost::noncopyable • OpenGLのハンドルを扱う時にも struct Texture { GLuint id; Texture() { glGenTextures(1, &id); } ~Texture() { glDeleteTextures(1, &id); } }; int main() { Texture hoge; Texture fuga = hoge; } // コンストラクタでOpenGLのハンドルを生成 // デストラクタでハンドルを破棄 // この操作でidが二重化されてしまい、破棄の際に動作が未定義になる
  • boost::noncopyable • これならコンパイル時にミスを発見できる struct Texture : private boost::noncopyable { GLuint id; Texture() { glGenTextures(1, &id); } ~Texture() { glDeleteTextures(1, &id); } }; int main() { Texture hoge; Texture fuga = hoge; } // エラー! この操作を禁止できる
  • boost::noncopyable ここまでで 気になった点や疑問点は ありますか??
  • boost::signals2
  • boost::signals2 #include <iostream> #include <boost/signals2/signal.hpp> struct Hoge { void step(const int value) { std::cout << "Hoge:" << value << std::endl; } }; struct Fuga { void draw(const int value) { std::cout << "Fuga:" << value + 1 << std::endl; } }; int main() { boost::signals2::signal<void (const int)> signal; Hoge hoge; signal.connect(boost::bind(&Hoge::step, &hoge, _1)); Fuga fuga; signal.connect(boost::bind(&Fuga::draw, &fuga, _1)); signal(10); } • 登録した関数をまとめて呼び出し てくれる • 関数の引数と戻り値の型が一致し ているだけでよく、抽象クラスを 継承したりする必要がない • std::shared_ptrを利用すると、登 録元が消滅したときに自動的に登 録を解除してくれる(別項で説明)
  • boost::signals2 • ういろうでは、ほぼすべてのオブジェクトを boost::signals2に登録して、更新や描画、オブジェクト間 通信を処理しました ゲームロ ジック 黒ういろう 白ういろう メニュー signals 背景
  • boost::signals2 enum Msg { UPDATE, DRAW }; void mainLoop() { // 全オブジェクトに更新を通知 sendMessage(Msg::UPDATE); // 全オブジェクトに描画を通知 sendMessage(Msg::DRAW); } メインの処理は、こんな感じになっ ています
  • boost::signals2 // signals2に登録されている関数 void getMessage(const int msg) { switch (msg) { case Msg::UPDATE: // 更新 update(); return; case Msg::DRAW: // 描画 draw(); return; } default: return; } 各オブジェクトではこういう感じに 実装されています • 描画の必要のないオブジェクトなら、 その分岐を書かないだけでよい
  • boost::signals2 例えば、プレイヤーの攻撃を実装 する場合には… // プレイヤーの更新処理 void update() { ... // 攻撃を全オブジェクトに通知 sendMessage(Msg::PLAYER_JUMPATTACK); ... } • プレイヤー側は、「オレの攻撃を受 けてみろ!!」とメッセージを送信
  • boost::signals2 // signals2に登録されている関数 void getMessage(const int msg) { switch (msg) { case Msg::UPDATE: // 更新 update(); return; case Msg::DRAW: // 描画 draw(); return; } case Msg::PLAYER_JUMPATTACK: // プレイヤーからのジャンプアタックを処理 hitCheck(); return; } 攻撃対象のオブジェクトは、攻撃 メッセージを受け取った時の処理 を追加 • プレイヤー側では、どのオブジェク トが攻撃対象かを知る必要がない • 「攻撃演出」も、他のオブジェクト で独立して簡単に処理できる
  • boost::signals2 • ただし、気を付けないとめっちゃネストして処理が重くなる ので注意です プレイ ヤー 攻撃を 送信 敵 攻撃で やられ たのを 送信 ゲーム ロジッ ク スコア 計算を 送信
  • boost::signals2 ここまでで なにか気になった点や疑問点は ありますか??
  • boost::any
  • boost::any • boost::signals2の話できっとこう思われたでしょう 「値のやりとりはしてないの??」 と…
  • boost::any // signals2に登録されている関数 void getMessage(const int msg, params) { switch (msg) { case Msg::UPDATE: // 更新 update(params); return; case Msg::DRAW: // 描画 draw(params); return; } メッセージ送信で問題になったの が、値の受け渡しでした • メッセージごとに構造体を作ったと して…それをどうやって関数に渡そ う。キャスト?? • ういろうでは50種類ほどメッセージ が存在します
  • boost::any • これを解決してくれたのが、どんな値も格納できる boost::anyと、コンテナとの組み合わせです #include <iostream> #include <string> #include <boost/any.hpp> int main() { boost::any x = 1; x = std::string("Hello"); } // int値を格納 // std::string値を格納 // 格納されている型をチェック if (x.type() == typeid(std::string)) { // 元の型に変換 std::cout << boost::any_cast<std::string>(x) << std::endl; } else { std::cout << "not string" << std::endl; }
  • boost::any • boost::signals2に登録する関数をこんな感じにしました // signals2に登録されている関数 void getMessage(const int msg, std::map<std::string, boost::any> params) { switch (msg) { case Msg::UPDATE: // 更新 update(params); return; case Msg::DRAW: // 描画 draw(params); return; }
  • boost::any • これで「値の名前と型さえ知っていればやり取り可能」が実 現しました typedef map<string, boost::any> Params; // 更新処理 void update(Params params) { // 処理時間を取り出す float delta_time_sec = boost::any_cast<float>(params.at(“delta_time”)); ... // 何か値を書き込む Hoge result; params.insert(Params::value_type(“result", result)); }
  • boost::any • ただし、気を付けないとめっちゃ値が増えてこんがらかりま す!! 更新 描画 プレイヤー攻撃 • 経過時間 • 描画プリミティブ • 画面サイズ • プレイヤーの位置 • プレイヤーの大きさ アイテムゲット 惑星操作 • アイテムの種類 • アイテムの位置 • 回転量 • カメラ情報
  • boost::any ここまでで なにか…!!
  • boost::bind
  • boost::bind • boost::signals2にstd::shared_ptrを登録する時に必須で した struct Hoge { void CallBack(int value) { /* 何らかの処理 */ } }; typedef boost::signals2::signal<void (int value)> Signal; Signal signal; void connect(std::shared_ptr<Hoge> object) { // boost::bindが使われている signal.connect(Signal::slot_type(&Hoge::CallBack, object.get(), _1).track_foreign(object)); }
  • boost::bind ここま…!!
  • まとめ • boostが、コードの正確さや簡潔さにすごく貢献してくれた • boostjpがほんとうに素晴らしい • boostjpがほんとうに素晴らしい!! • boostjpのURLは https://sites.google.com/site/boostjp/
  • おまけ • 拙作アプリ『こなへん』と『ういろう』をよろしくね☆ 2013 10.14 西山信行 twitter: @5mingame2 Facebook: 5mingame2