情報は力ではない

UE4 とか Blender とか。

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を全く知らなかったので学びがあった。日本語は英語に比べてタイプ数が多くなるし、ひらがなを打った後に漢字に変換しないといけないので非常に面倒というところでの漢字直接入力は面白いなぁと思った。

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

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

vim-themis, vim-owlを使えるようにした

vim scriptのテストを書きたいと思ったので、テストフレームワークを用意した。
vim-themisとvim-owlの2つを用意。github.com
github.com

vim-themisはvimspecの記述が気に入っている。
けれども、自分の知識が無いためだろうけどスクリプトローカルな関数を
テストすることがvim-themisでは出来ないような感じだったので
スクリプトローカルな関数をテストするためにvim-owlも用意した。

vim-owlを用意して最初のテストを通す際に詰まったことがあったので
備忘録として記述しておく。

テスト関数にabortを付けない

自分の癖で関数にはよくabortをつけるのだけれど、vim-owlのテスト関数にabortをつけると

Error detected while processing function owl#run:
Vim(call):E488: Trailing characters

といったエラーが出てくる。といってもテストはちゃんとしてくれてる。
まぁ、エラーは鬱陶しいのでテスト関数にはabortを付けないようにする。

テストする前にスクリプトローカルな関数を定義しているファイルをsourceしておく。

非常に当たり前のことだったが、これに気づくのに2時間くらいかかった。
自分の中で勝手に

let owl_SID = owl#filename_to_SID("file/to/path/hoge.vim")

とすると、そのhoge.vimをsourceしてくれると勘違いしていた。
実際には、:scriptnamesのリストの中から"file/to/path/hoge.vim"に一致するものを探して
そのSIDを取っている感じだった。
事前に"hoge.vim"をsourceしておかないと:scriptnamesの中には現れないので
owl#filename_to_SID()は0を返してくるのでスクリプトローカルな関数を呼んでも
エラーになるので注意。

Heap sort

Twitterで友達が「ヒープ考案した人、すごい」と言っていたので、誰なのか気になって調べた。
wikipediaによるとJ. W. J. Williamsという方がヒープソートと一緒に考案したそうだ。

Heapsort - Wikipedia, the free encyclopedia

詳しくは1964年に出版された"Algorithm 232: Heapsort"という記事に載っているっぽい。

また、ヒープソートはRobert W. Floyd先生が1962年に出した"Algorithm 113: Treesort"に記述されているTreesortの改良版のらしい。さらにFloyd先生はヒープソートを改良してTreesort 3というアルゴリズムを考案したようだ。Treesort 3に関しては1964年に出た"Algorithm 245: Treesort 3"に詳しく載っている。この記事はネットで拾えたのでリンクしておく。

http://bioinfo.ict.ac.cn/~dbu/AlgorithmCourses/Lectures/FloydHeap1964.pdf

"Treesort => Heapsort=> Treesort 3"という流れは、このサイトに載っていた。

ヒープソートにはこういう歴史?があり、50年以上に渡って使われているんだなあという小学生並みの感想を持った。

ちなみに、Robert W. Floyd先生はワーシャル・フロイド法で有名なFloyd先生です。

プログラミング言語C++ 7.5

  • ポインタが指すオブジェクトが定数
int x = 3;
int y = 4;
const int* pc = &x; // 定数へのポインタ
pc = &y; // OK
  • ポインタそのものが定数
int x = 3;
int y = 4;
int *const cp = &x; // 定数ポインタ
cp = &y; // エラー: cpは定数
  • 定数を指すポインタに、非constな変数のアドレスを代入できる。理由は、実害が無いからだそうだ
// 上のコードより
int x = 3;
const int* pc = &x;
  • 逆に、定数のアドレスを非constのポインタに代入することは出来ない
const int x = 3;
int* p = &x; // エラー: const int*によりint*を初期化をしている