質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.93%

cocos2dxで他クラスのメンバを参照する方法

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 2,267

score 21

Cocos2dxを使っていて他クラスのメンバを参照したくなったときはどうすればいいですか?

たとえばAppleクラスからBananaクラスのseedメンバを参照する時、自分はAppleクラスの中でBanana::create()->seedとやって呼び出していました。CREATE_FUNCの中身を見るとこうすることでBananaクラスの実体にアクセスできる気がしたので…

しかし、最近気づいたのですが、この方法だとBananaクラスを呼び出すたびにBananaクラスのinit()関数が実行されているのです。vectorのサイズが異常に大きくなっていたので気づきました。

そこで質問なのですが、cocos2dxには他クラスのメンバを参照できるような仕組みはありますか?自分の方法以外で、何かいい方法はないでしょうか。

ここから追記です。あれから考えたのですが、要するにinit()関数を呼ばずに参照したいクラスのアドレスを
取得できればいいので、以下のようにしました。(seedはspriteです)

cocos2d::Layer* bananaLayer;

bool GameScene::init(){
    if(!Scene::init())
        return false;

    bananaLayer = banana::create();
    this->addChild(bananaLayer);

    return true;
}

bool apple::init(){
    if(!layer::init())
        return false;

    bananaLayer->seed->getPosition();

    return true;
}


このようにグローバル変数を使わざるを得ませんでした。気持ち悪いですが...

逆に、

bool apple::init(){
    if(!layer::init())
        return false;

    auto bananaLayer = new banana;
    bananaLayer->seed->getPosition();

    return true;
}


とやってもうまく行きませんでした。
これって、新しく宣言したbananaLayerはメモリが与えられただけでinit()されてないので、
init()内にあるseed = Sprite::create()も実行されていないのが原因なんじゃないでしょうか?
つまり、seedというメンバはbananaLayerのメンバとしてアドレスをもらってはいるけど
spriteクラスとしての実体は持っていない、といったような。

c++のクラスとcocos2d::Nodeの違う点としては、このようにメンバの本当の意味での実体が
init()を実行しないと取得できないことだと勝手に解釈しています。
...とここまで書いてコンストラクタでinit()すればいいのか?とも思ったのですが、
c++でもあるインスタンスAのメンバにアクセスしたいときはそのインスタンスA自体を参照すればよくて、
新しい別のインスタンスBを宣言する必要はないですよね。

やっぱり大元のSceneにaddChild()するためにcreate()した時に返ってきたアドレスをなんらかの方法
で保持しておくしか方法はなくないですか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

cocos2d::Node を継承しているクラスのオブジェクトを作成する場合は、参照カウントを意識する必要があります。CREATE_FUNC()マクロの中身を読めばわかりますが、CREATE_FUNC()が作成する Xxx::create() メソッドは「インスタンスをnewして」「init()を呼んで」「正常ならautorelease()を呼ぶ」まで実行します。
このあたりを理解して保持するようにしないとリークします。

で、どうやって保持するかですが、CC_SYNTHESIZE_RETAIN()マクロでプロパティ作ってsetXxx()やgetXxx()で設定、取得する方法、あるいは子ノードになっているのであればgetChildByTag()で取得する方法などが考えられます。

CC_SYNTHESIZE_RETAIN などのマクロはcocos2d-x独自のシンセサイザ(プロパティ)作成用マクロです。
cocos2d-xマクロまとめ などに説明があります。

class Banana : public cocos2d::Layer
{
public:
    virtual bool init();
    virtual ~Banana() {}
    CREATE_FUNC(Banana);

    // 参照カウント付きシンセサイザ(ほんとは最後に release必要だからね)
    CC_SYNTHESIZE_RETAIN(cocos2d::Sprite*, _seed, Seed);
};

class GameScene : public cocos2d::Layer
{
public:
    static cocos2d::Scene* createScene();
    virtual bool init();
    virtual ~GameScene() {}
    CREATE_FUNC(GameScene);

    CC_SYNTHESIZE_RETAIN(Banana*, _bananaLayer, BananaLayer);
};


bool GameScene::init()
{
    if (!Layer::init()) {
        return false;
    }

    auto banana = Banana::create();
    setBananaLayer(banana);  // CC_SYNTHESIZE_RETAIN()で作成したプロパティに set

    auto pos = getBananaLayer()->getSeed()->getPosition(); // bananaのseed取得

    return true;
}

bool Banana::init()
{
    if (!Layer::init()) {
        return false;
    }

    auto seed = Sprite::create();
    setSeed(seed);  // プロパティにset

    // あるいは子ノードであれば getChildByTag<>() で取得できる
    addChild(seed, 1, 12345);
    auto childSeed = getChildByTag<Sprite*>(12345);

    return true;
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/12 00:38

    回答が遅くなってしまいすみません!
    そうかもしれません。。今すぐコードを載せさせていただきます!

    キャンセル

  • 2018/11/12 12:01

    cocos2d-x限定の話だと思ったので回答を全面的に書き換えました。

    キャンセル

  • 2018/11/13 01:24

    プロパティを作れるマクロがあったとは。。
    本当に助かりました。ありがとうございます!!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.93%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る