狂ったお茶会のlog

後で起きる自分のためのメモ

Cocos2d-x: 画像を立体的に横にぐるぐる回す

やりたいこと

掲題のとおり

やったこと

OrbitCamera を使う
よくわからない引数が多いが

OrbitCamera * OrbitCamera::create(float t,      // 期間(秒)
                        float radius,           // 開始半径
                        float deltaRadius,     // 半径変化量
                        float angleZ,          // 開始角度(Z)
                        float deltaAngleZ,     // Z角度変化量
                        float angleX,          // 開始角度(X)
                        float deltaAngleX)     // X角度変化量

sprite がすでに create されてるとして、以下のようにする
(Repeat したくなければ Repeat は別に要らない)

int turnNum = 4;
auto turnAction = Repeat::create(OrbitCamera::create(1.0f, 1, 0, 0, 360, 0, 0), turnNum);
sprite->runAction(turnAction);

この動画のようになる
1秒に1回360度回転

f:id:dormouse666:20161225231217g:plain

(最初に一瞬出てきちゃってるのはスプラッシュ画像)

なお、上記の 360 を 180 にすると

auto turnAction = Repeat::create(OrbitCamera::create(1.0f, 1, 0, 0, 180, 0, 0), turnNum);

180度回転を繰り返す感じになる。微妙

f:id:dormouse666:20161225231819g:plain

その他

以下のように Zアングル を 90 から開始すると、真横から回転が始まり真横で終わる。

auto turnAction = Repeat::create(OrbitCamera::create(1.0f, 1, 0, 90, 360, 0, 0), turnNum);

f:id:dormouse666:20161225231903g:plain

以下のように Zアングル を 180 から開始すると、真後ろから回転が始まり真後ろで終わる。

auto turnAction = Repeat::create(OrbitCamera::create(1.0f, 1, 0, 180, 360, 0, 0), turnNum);

f:id:dormouse666:20161225231924g:plain

以上

URL

Cocos2d-x: OrbitCamera Class Reference

android SDK についてメモ

SDKのインストール

developer.android.com https://developer.android.com/studio/index.html?hl=ja

上記サイト->ダウンロードオプション->コマンドライン ツールのみ入手する
の各環境のもの(今回はMacOSX)

以下メモ

READMEを読むと
tools/android update sdk --no-ui
したらいいんじゃない的なことが書いてあるのでする
めっちゃアップデートされる

tools/android --help
をすると、ヘルプ一覧

tools/android sdk
をすると、Android SDK Manager が起動してくれるので、SDKをいろいろDLできる

tools の中にある monitor をダブルクリックすると、接続してるandroid端末のlogが見れるツールが立ち上がる べんり
Filter つけられて絞り込んでlogみれたりするのでよく使う

platform-tools の中にある adbちゃん
sudo ./adb shell pm list package
でインストールしてるアプリ一覧がみれたりする べんり
いろいろ出来るようだがまだよくわかってない

sudo ./adb
に出来ること一覧が書いてあるような気がする

const char* に std::string を代入するときの注意点

しばらく前に仕事で直したバグのmemo

const char* hoge;
if(piyo)
{
    std::string fuga = cocos2d::StringUtils::format("piyopiyo"); //生成
    hoge = fuga.c_str(); //代入
}

この場合fugaはif文の外に出ると破棄されて死ぬ(ここまではわかる)
hogeはif文の外で定義されているからこれ以降も使えるかと思いきや、
fugaが破棄されるときに、hogeが参照している先の実体が死ぬということなので、つまりhogeも死ぬ

で合ってるのかな...

とりあえず、逆にすれば問題なくなる

std::string hoge;
if(piyo)
{
    const char* fuga = "piyopiyo"; //生成
    hoge = cocos2d::StringUtils::format(fuga); //代入
}

Cocos2d-x: 違う親Nodeに乗っているSpriteを重ねて表示する

やりたいこと

Sprite* imgASprite* imgBが、
それぞれ違う場所にあるNodeの、しかもそのNodeから見て違う座標に乗っている場合(※)に、
imgAにimgBを重ねて表示したい@cocos2d-x

※このような状態から開始
f:id:dormouse666:20160709224437p:plain
AnchorPointはNodeもSpriteも0.5,0.5


前提

imgAおよびimgBのpositionを素直に取得すると、親Nodeのpositionから見てどこにいるか情報が帰ってくる

素直に取得する時

auto posImgA = imgA->getPosition();

↑こいつをそのままimgBにsetPositionしても、親Nodeのpositionが異なるので、うまくいかない

こうなっちゃう
f:id:dormouse666:20160709224507p:plain

逆に、それぞれのNodeの同じ位置に乗せたい〜とかならこれでいい
親Node同士のサイズが同じならだけど


やったこと

まずconvertToWorldSpaceを使ってimgAのpositionを絶対値に変換する

auto posImgAWorld = imgA->getParent()->convertToWorldSpace(imgA->getPosition());

上記の時、imgAの親Node(nodeA)からconvertToWorldSpaceを呼ばないとダメ
なのでgetParent()してある


そして得られたposAをimgBに設定したいのだが、
素直にsetPositonしてしまうと、
imgBの親Node(nodeB)から見てのpositionに上記の値が設定されてしまうので、

これは

imgB->setPosition(posImgAWorld);

こうなっちゃう
f:id:dormouse666:20160709224716p:plain

↑imgBが画面外のどっかにいってしまった、かなしい


ので、nodeBの相対値に座標を直さないとならない
convertToNodeSpaceを使用して変換する

imgB->setPosition(imgB->getParent()->convertToNodeSpace(posImgAWorld));

ここでもちゃんとimgB自身の親Nodeから呼ぶ

こうなって、完了
f:id:dormouse666:20160709224630p:plain

めでたしめでたし


というのを試したコード

auto nodeA = Node::create();
nodeA->setContentSize(Size(50.0f, 50.0f));
nodeA->setPosition(200.0f, 100.0f);
nodeA->setAnchorPoint(Point(0.5f, 0.5f));
auto colorA = LayerGradient::create(Color4B(200, 200, 200, 255), Color4B(50, 50, 50, 255), Point(1, 1));
colorA->setContentSize(nodeA->getContentSize());
nodeA->addChild(colorA);

auto imgA = Sprite::create("適当な画像1");
imgA->setPosition(Size(25.0f, 25.0f));
imgA->setAnchorPoint(Point(0.5f, 0.5f));
nodeA->addChild(imgA);
this->addChild(nodeA);

auto nodeB = Node::create();
nodeB->setContentSize(Size(50.0f, 50.0f));
nodeB->setPosition(270.0f, 100.0f);
nodeB->setAnchorPoint(Point(0.5f, 0.5f));
nodeB->setAnchorPoint(Point(0.5f, 0.5f));
auto colorB = LayerGradient::create(Color4B(200, 200, 200, 255), Color4B(50, 50, 50, 255), Point(1, 1));
colorB->setContentSize(nodeB->getContentSize());
nodeB->addChild(colorB);

auto imgB = Sprite::create("適当な画像2");
imgB->setPosition(Size(50.0f, 50.0f));
imgB->setAnchorPoint(Point(0.5f, 0.5f));
nodeB->addChild(imgB);
this->addChild(nodeB);

auto posImgA = imgA->getPosition();
auto posImgB = imgB->getPosition();
CCLOG("posImgA x:%f, y:%f", posImgA.x, posImgA.y);
CCLOG("posImgB x:%f, y:%f", posImgB.x, posImgB.y);

auto posImgAWorld = imgA->getParent()->convertToWorldSpace(imgA->getPosition());
CCLOG("posImgAWorldA x:%f, y:%f", posImgAWorld.x, posImgAWorld.y);

auto pos = imgB->getParent()->convertToNodeSpace(posImgAWorld);
imgB->setPosition(pos);
CCLOG("pos x:%f, y:%f", pos.x, pos.y);

出力されるログはこうなる

posImgA x:25.000000, y:25.000000
posImgB x:50.000000, y:50.000000
posImgAWorldA x:200.000000, y:100.000000
pos x:-45.000000, y:25.000000


感想

親Nodeのpositionが同じだとか、親Nodeのサイズが画面サイズと同じだとかになっていれば途中の工程まででいけるので
そもそも画面の構成をめんどくさくないようにしろという話なのかもしれない

ランダムな値を取得する

やりたいこと

1〜10のランダムな値を取得したい@cocos2d-x

1. rand() を使う

rand()で、0からRAND_MAX(マクロで設定されてる)までの範囲の乱数値を得ることができるので、
それを割った余り(10で割っているのであまりは0〜9の範囲となる)を出し、それに1を足すことで1〜10となる

こう

static const int NUM_MAX = 10;

int num = (rand() % NUM_MAX) + 1;

ただrand()は、毎回同じ値の羅列を出してくるっぽい(疑似乱数)
割る値がコロコロ変わる場合はこいつだけでもよさそうだが、今回はNUM_MAXが固定なのでちょっとダメ

2. srand() で初期化もする

なので、srand([ランダムな値])で毎回初期化してから使うとよい
[ランダムな値]には現在時刻を入れるのがポピュラーっぽい(毎秒違う値になるので)
つまりこう

srand((unsigned int)time(NULL));
int num = (rand() % NUM_MAX) + 1;

3. arc4random() を使う

上記を1つにまとめた関数があり、それがarc4random()
かんたんべんり

int num = (arc4random() % NUM_MAX) + 1;

ただし、arc4random()の戻り値はunsigned intなので注意
intの上限である2147483647より大きい値が来ることがあり、それをintにcastするとオーバーフローして死ぬ(マイナス値になったりする)
上記のように、2147483647以下の値で割った余りとかの場合は、それ以下の値にしかならないので問題ないという認識

4. 乱数エンジンを使う

乱数エンジンを使う方法
C++11 から使える様子 あまりよくわかってない

std::random_device rnd; //乱数エンジンのシードにする乱数を生成
std::mt19937 mt(rnd()); //乱数エンジン(こいつはメルセンヌ・ツイスタというやつ、生成値はuint32_t)で乱数を生成する

auto num = mt(); //生成された乱数

上記のmt()のままでも使えるが、ディストリビューションというやつを使うと使い勝手がいい模様
たとえばランダムな角度を求めたい時

//今回は-89〜89度の範囲の角度が欲しいとする
double degreeA = -89.0;
double degreeB = 90.0;

//degreeA以上degreeB未満のdouble値を返す設定のディストリビューションを作成
std::uniform_real_distribution<double> randDegree(degreeA, degreeB);

//上記で作成したディストリビューションに乱数エンジンを渡すと、設定した範囲の乱数が取得できる
double degree = randDegree(mt);

蛇足: 角度をラジアンに変換する

static const double PI = 3.141592653589793; //円周率

double radian = randDegree(mt) * PI / 180.0;

以上

参考

ロベールのC++教室 - 第75章 乱数 -
【cocos2dx】乱数を生成し、ランダムに値を取り出す方法 | albatrus.com
乱数の使用
C言語 「角度からラジアンに変換」 と 「ラジアンから角度に変換」 | 勇躍のゴミ箱

Cocos2d-xで新規プロジェクトを作成する

掲題の通り

いつも忘れるのでmemo

やること

ダウンロードしてくるのは割愛
ダウンロード後に新しいプロジェクトを作るにあたっての話

だいたい
How to Start A New Cocos2D-X Game | Cocos2d-x
に記載ある通りなのだがこのページたまにurl変わってたりするような...(昔は日本語ページもあった気がした)

記載の通りざっくり以下をやる

$ cd cocos2d-x
$ ./setup.py
$ source ~/.bash_profile # may be ~/.bash_login or ~/.profile, depends on your environemnt
$ cocos new MyGame -p com.MyCompany.MyGame -l cpp -d ~/MyCompany

MyGame: 作成したいプロジェクトの名前
-p com.MyCompany.MyGame: androidのパッケージ名
-l cpp: 使用する言語 使用できるのはC++lua
-d ~/MyCompany: プロジェクトを保存するディレクトリ

実際やったこと

ちょっと前にやったののログ

$ cd cocos2d-x-3.8.1      //DLしたcocos2d-xのフォルダに移動
$ ./setup.py         //この後NDK_ROOTとANDROID_SDK_ROOTとANT_ROOTを聞かれるが一旦skip
$ source ~/.bash_profile
$ cocos new TestProject -p com.dormouse.TestProject -l cpp -d ~/dormouseApp     //~/dormouseApp/TestProjectフォルダが生成される

この後で
XCodeならTestProject->proj.ios_mac->TestProject.xcodeprojを起動すればok

プロジェクトの画面を縦にする

プロジェクトファイル->General->Device Orientation->Portraitにする
ダメだったらソースをいじる(参考url参照)

cpp-test(cocos2d-xについてくるサンプル)を見る

DLしてきたcocos2d-xフォルダ->build->cocos2d_tests.xcodeproj
を開いて、
XCodeの左上の環境とかを選ぶところで cpp-tests iOS を選択してbuildする

参考

How to Start A New Cocos2D-X Game | Cocos2d-x
[cocos2dx]画面の向きを設定する | studycocos2dx
How to run cpp-tests on iOS | Cocos2d-x

GitHubを久々に使ったらエラーが出た話

掲題の通り

半年ぶりくらいにプロジェクト作ってpushしようとしたら以下のエラーが出た。

Warning: Permanently added the RSA host key for IP address '192.30.252.130' to the list of known hosts.
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

やったことその1

githubの、Setting->SSH keys にて、鍵が停止されてる気配があったので、Approve ボタン押下
したんだけど、治らなかった。

治る場合もあるもよう。memo
Github.comへのgit cloneでsshの認証がエラーになった

やったことその2

公開鍵の登録し直し

ホームで $ ls ~/.ssh で確認して id_rsaid_rsa.pub がちゃんと存在してたので
$ pbcopy < ~/.ssh/id_rsa.pub で内容をクリップボードにコピーして、
SSH Keysの設定ページで新しいKeyとして追加する。

治った。

参考

SSHの公開鍵を作成しGithubに登録する手順 - mon_sat at Co-Edo(半年前の自分への教科書 / 別院)

追記

別件だけどこういうことも起きた。
mac再起動したら、GithubにSSHでアクセスできなくなった - 狂ったお茶会のlog