情報は力ではない

UE4 とか Blender とか。

ゲームエンジン・アーキテクチャ第2章

第2章のタイトルは「仕事用ツール」。この章では主にバージョン管理システムMicrosoft Visual Studio、それからプロファイリングツールメモリリーク、メモリ破壊の検出について記述している。

2.1 バージョン管理

バージョン管理システムを幾つか紹介した後、SubversionTortoiseSVNを用いてコミットやマージについて説明している。

2.2 Microsoft Visual Studio

ソースファイルは翻訳単位。コンパイラが見るものは全て翻訳単位。

リンカの仕事

  • 全てのマシンコードの最終的な相対アドレスを計算する
  • それぞれの翻訳単位における関数やグローバルデータに対する全ての外部参照が必ず適切に解決されるようにすること

一般的なビルド構成

  • Debug, Release
  • 製品ビルド
    • 全てのデバッグ情報を取り除き、アサートは無効化する。最適化も行う。
  • ツールビルド
    • よくわかっていない。
  • ハイブリッドビルド
    • 翻訳単位の大部分がリリースモードでビルドされ、少しの部分がデバッグモードでビルドされている構成。
    • Visual Studioでは翻訳単位ごとのビルド構成を設定できないので設定するのが面倒らしい。

コードのデバッグ

Visual Studioのウォッチウィンドウは便利っぽい。
今までちゃんとVisual Studioのデバッガを学んで使ったことがなかったので知らないことがちらほらあった。

  • CやC++の指揮をウォッチウィンドウに入力することが出来ることや関数を呼び出すことが出来る
  • ウォッチウィンドウの中で式にサフィックスを付けることでデータを表示する方法を変更できる
    • ",d", ",x"というサフィックスはそれぞれ10進、16進でデータが表示されるようにする
    • ",n"(nは非負整数)はn個の要素を持つ配列として値を処理することができるようにする
  • データブレークポイント

2.3 プロファイリングツール

大まかに2種類ある

  • 統計的プロファイラ
  • 計測的プロファイラ

CやC++プログラマは全員、少なくとも目的とするCPUのアーキテクチャをそれなりに熟知していなければならない(p.91)

なるほどなぁ。

ゲームエンジン・アーキテクチャ第1章

www.amazon.co.jp
今読んでいる本です。ゲームエンジンの作りに興味があるので読むことにしました。
本を読んでいるとインプットばかりでアウトプットをしないことが多くなるのが自分の悪いところなので、不定期にアウトプットをしようと思い、メモを残すことにしました。

この本で学習すること(p.4)

など

1.3 ゲームエンジンとは何か?

この節では「ゲームエンジンとはこういうものだ」ということが書いていないように思うけど3次元グラフィックスレンダリングシステムやコリジョン検出システムやオーディオシステムなどをまとめたものか?
ゲームとエンジンの境界線は曖昧なことが多い。

1.4 ジャンルごとのエンジンの違い

ゲームエンジンは多少なりともジャンルに特化しているのが一般的。

1.5 ゲームエンジンの調査

  • Quake
  • Unreal
  • Source Engine
  • Frostbite
  • CryENGINE
  • PhyreEngine
  • XNAゲームスタジオ
  • Unity

など

Quake

Quakeソースコードgithubで入手できる。github.com
著者によると、デバッガを仕様しながらエンジンの動きを分析するのがお勧め。

Unreal Engine 4

UE4のソースコードgithubのEpicGamesのプライベートリポジトリにあるので、unrealengine.comのアカウントを取得し、githubアカウントを紐付けることで見れるはず。

Vimで条件に一致する要素の個数を返す関数

ふとVimで条件に一致する要素の個数を返す関数みたいなの欲しいなと思ったので実装してみた。

条件に一致する要素の個数を返す関数

簡単なものであれば動くと思う。
例えば

let s:list = range(10)
echo s:count_if(s:list, 'v:val < 3')
" => 3

他のみなさんはこうしたい時どうしているんだろうか。

replaceScene()とEventListener

普段、cocos2dxで開発している訳ではなく、あまりcocos2dxを知らないのだけれど、少し疑問が湧いたのでそれを書いてみる。

疑問: replaceScene()したあと、それまでに登録していたEventListenerはどうなるのか

例えば、あるシーンをタッチすると次のシーンに移る、というようなことをしたいとき
次のように書くことが出来ると思う。

bool AScene::init() {
  // ...
  auto listener = EventListenerTouchOneByOne::create();
  listener->onTouchBegan = [this](Touch* touch, Event* event) {
    Director::getInstance()->replaceScene(AnotherScene::create());
  }
  this->getEventDispatcher()->
    addEventListenerWithSceneGraphPriority(listener, this);
  // ...

画面をタッチして次のシーンに移ったあとでもEventDispatcherに登録しているEventListenerは
EventDispatcherの中にまだ残っているのではないかと思う。
replaceScene()するときには手動でEventListenerを削除しないといけないのかなと思いながら
documentを読んでみるとちゃんと書いてた。

EventDispatcher Mechanism | Cocos2d-x

One more thing to keep in mind: if you add a _fixed priority_ listener to a node, you need to remove the listener manually when the node is removed. However, in the case of a _scene graph priority_ listener, the listener is bound to the node: when the node's destructor is called, the listener will be removed automatically.

document曰く、addEventListenerWithFixedPriority()を使う場合、Listenerに対応させたいNodeを削除するときに手動でListenerを消してね。addEventListenerWithSceneGraphPriority()を使う場合はListenerとNodeは対応しているので、Nodeのデストラクタが呼ばれるときに自動的にListenerも削除されるよ。
ってことらしい。なるほど。

上の例でいくとおそらく、replaceScene()をするとASceneのデストラクタが呼ばれ、そのタイミングでASceneに対応づけられたListenerが破棄されるという感じなんだろう。

Nodeの実装を見てみると確かにNodeのデストラクタでEventListenerを削除していた。
https://github.com/cocos2d/cocos2d-x/blob/v3/cocos/2d/CCNode.cpp#L207

_eventDispatcher->removeEventListenerForTarget(this);

ただ、replaceScene()を呼んだからといってすぐにASceneのデストラクタが呼ばれる訳ではないような気がするけど
その辺りはcocos2dxのGCが上手くやってくれているのだろう。

終わりに

今回思ったのは、欲しい情報にヒットするdocumentをすぐに探せるかはわからないんだけど
documentは読みましょうということでした。自分のフローにしておかねば。

:forでリストを受け取れる

昨日、vim-threesのコードを読んでいたときに:forでリストを受け取れることを知ったのでメモ。github.com

for [ x, y ] in [ [1, 2], [3, 4], [5, 6] ]
  " do_something
endfor

といった感じでforでリストを受け取ることが出来る。

for [ x; y ] in [ [ 1, 2, 3 ] ]
  echo x
  echo y
endfor
" => 1
"    [2, 3]

というようにリストのアンパックを使用することも可能っぽい。

まだまだ知らないことが多いので勉強になる。

参考文献

:help :for

normalコマンドとgetchar()関数

Vim scriptでゲームを作るときにキー入力を受け付けてない気がするなぁと思うことがあって
多分normalコマンドが悪さしている気がするなぁと思ったので、次のようなコードを書いてみた。

2秒間s:foo()が処理を行うのでその間にキー入力をして、そのキーがgetchar(0)で取得できるかを試すコード。
実行した結果を見てみると、入力されたキーが出力されていなかった。
どうやらnormalコマンドを処理するときに入力されたキーがどこかへ行ってしまうようだ。

今作っているコード内でnormalコマンドを所々使っているのでnormalコマンドを使わないように変更しよう。

Osaka.vim #4に参加してきた

昨日、Osaka.vim #4に参加してきた。
Osaka.vim #4 - connpass

自分は、前から作りたかったvimで動くゲームをひたすら作っていた。5時間ほどしかコーディングしていないのだけれど、一応遊べる感じにまでなった。他に追加したい仕掛けやステージがあるのでまだまだ完成ではない。早めに完成を目指そうと思う。

もくもく会に初めて参加したのだけれど、みんなが一斉にもくもくしている中で作業するのは集中出来て非常に良かった。普段からこれくらいの集中力を発揮していきたい。

途中でLTが入って、@kozo2さんのT-Codeのお話があった。T-Codeを全く知らなかったので学びがあった。日本語は英語に比べてタイプ数が多くなるし、ひらがなを打った後に漢字に変換しないといけないので非常に面倒というところでの漢字直接入力は面白いなぁと思った。

もくもく会が終わって、自分は予定があったので懇親会には行けなかったけど、次回はぜひ行きたいと思った。

主催者の皆様、会場に来ていた皆様、お疲れ様でした。次回、開催されるのを楽しみにしてます!