A Day In The Life

とあるプログラマの備忘録

特定のスプライトすべて削除する

最近 Cocos2d-x で2Dゲームを作ってます。
スプライトに名前つけて追加したあと、その名前のスプライトを検索して削除する時にハマったのでメモです(Cocos2d-x のバージョンは3.3です)。
まずはダメなコードから

bool HalloWorldScene::init()
{
  // nameという名前で大量にスプライトを追加する
  for (int i = 0; i < 100; i++) {
    auto sprite = Sprite::create("hoge.png");
    this->addChild(sprite, 0, "hoge");
  }

  // タッチイベント
  auto listener = EventListenerTouchOneByOne::create();
  listener->onTouchBegan = CC_CALLBACK_2(HelloWorld::onTouchBegan, this);
  auto dip = this->getEventDispatcher();
  dip->addEventListenerWithSceneGraphPriority(listener, this);
  dip->setPriority(listener, 0);
}

bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
{
  // だめ。たまに消えないスプライトがある
  for (auto node : this->getChildren()) {
    if (node->getName() == "hoge") {
      node->removeFromParent();
    }
  }
  // 以下もダメ
  this->enumerateChildren("hoge", [](Node *node) -> bool {
    node->removeFromParent();
    return false;
  });
  return true;
}

以下がうまく行ったコードです(initの処理は同じなので省略してます)。

bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
{
  // nameという名前のスプライトを検索する
  this->enumerateChildren("hoge", [](Node *node) -> bool {
    // スプライトを削除するアクション
    auto action = RemoveSelf::create();
    node->runAction(action);
    return false;
   });  
  return true;
}

RemoveSelf アクションは結構使いどころが多くて重宝してます。その他にも特定のアクションを実行されてからスプライトを削除する時なんかに使ってます。例えばこんな感じです。

bool HelloWorld::onTouchBegan(Touch* touch, Event* event)
{
  auto sprite = Sprite::create("hoge.png");
  this->addChild(sprite, 0, "hoge");
  auto moveTo = MoveTo::create(1, Vec2(100, 100));
  auto seq = Sequence::create(moveTo, RemoveSelf::create(), NULL);
  sprite->runAction(seq);
}

パーティクルを作成するときなんかに使えます。

C++のコード

このブログでC++のコードを書いたことがなかったんですね(話題にしたことはあったんですが)。記念すべき第1回目となりました。C++も11になってずいぶん使いやすくなったと思います。