2014年8月7日木曜日

ゲームをポーズ(一時停止)しよう


cocos2dxには予めpauseSchedulerAndActions()
というメソッドがあるので、一時停止処理(ポーズ)なんて
簡単でしょう…などとたかをくくっていたら
思いのほか苦戦したでござる。っていう話。



何にどう苦戦したかというと、
pauseSchedulerAndActions()は確かに
色々なアクションやらスケジュールやらを
ストップしてくれる便利なメソッドなんだけど、
その停止対象の指定の仕方と効果範囲を把握するのに
ちょっと悩んだという感じ。

pauseSchedulerAndActions()は、
レイヤーやアクションに対して使用するという事なんで、

this->pauseSchedulerAndActions();

って記述すればそのレイヤーにあるものは全て止まるんでしょ?
とか思ってたら全然停止せず。

上記記述で止まるのはthis(親レイヤ)に
直接指定してるscheduleだけ。
…そういえば以前、スプライト単体に対して
pauseSchedulerAndActions()を実行した時は
そのスプライト単体に対してpauseSchedulerAndActions()をしたなぁ。

ということは、レイヤー上にある色々なスプライトの
runActionをストップさせるにはそれぞれのスプライトに対してpauseSchedulerAndActions()を実行していく必要があるのかしら。
oh…結構、大変ですぜ。

というわけで、thisレイヤ上でaddChildされているspriteをgetしてきて、
foreachループでそれぞれのspriteに対して
pauseSchedulerAndActions();を実行する処理を書いてみる。

//レイヤー内のchildrenをゲットしてきてポーズする
for (auto* childs : this->getChildren())
{
 Sprite *spritechilds = (Sprite *)childs;
 spritechilds -> pauseSchedulerAndActions();
}

…書いてみる、とかサラッと言ったけど、
この処理を上の文章でできるようになるのにだいぶ時間を費やしてる。
foreach文とか初めてだし。

で、一部止まったけどまだ全ては止まらない。
これはアレだ。BatchNodeに登録したものが止まってない。
上記文章がthisにaddChildされたSpriteに対しての処理なので
BatchNodeに登録したrunActionを停止するには、
thisにaddChildされたBatchNodeにaddChildされたSpriteに対してpauseSchedulerAndActions()しなければいけない、
という理屈なんでしょうね。おそらく。
BatchNodeいっぱい作っちゃったよ…

//アイテム用バッチノードの呼び出し
auto* ItemBatch = this->getChildByTag(★);
//レイヤー内のアイテムバッチノードからchildrenをゲットしてきてポーズする
for (auto* Ibatch : ItemBatch->getChildren())
{
  Sprite *spriteIbatch = (Sprite *)Ibatch;
  spriteIbatch -> pauseSchedulerAndActions();
}

これで全部止まったかしら?

はいダメー。物理演算が止まらないー。
物理演算はrunActionなわけではないので、
pauseSchedulerAndActions()じゃ止まらないですねー。

//キャラクターのスプライトと剛体を取得
Sprite* player = (Sprite *)this->getChildByTag(★);
auto* playerPb = player->getPhysicsBody();
//キャラの物理演算を切る
playerPb->setEnable(false);

というわけで、やっと停止処理の完成。
scheduleと、thisやBatchNode内にいるSprite(のrunAction)の
個々に対してpauseSchedulerAndActions()をして、
物理演算を入れてる場合はそれも切る必要があると。
あ、その理屈だとParticleBatchNodeを使用してる場合は
それも止める必要がありますね。
あと、すべてにポーズをかけたあと、
ボタンだけはポーズを解除しておかないと
二度と再開できないという悲劇に見舞われます。

BGMを止めたりするのも忘れずに。

というわけで、以下全文。
今回自分の場合は停止ボタンを押した時の
コールバックとしてメソッドをまとめたので、
最初の部分でボタンのtrue or falseを切り替えて
それによって処理を分岐させています。

void HelloWorld::PauseSwitch(Ref* pSender)
{
 Size winSize = Director::sharedDirector()->getWinSize();
 //ポーズ判定をチェンジさせる
 PauseNow = !PauseNow;

 if (PauseNow == true) //ポーズがトゥルーになったら全てを停止する
 {
  CCLog("停止してるやで");

  //BGMを一時停止
  SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic();

  // グレイアウトのため空のスプライトを最前面に配置
  Sprite* Glayout = Sprite::create();
  Glayout->setTextureRect(Rect(0, 0, winSize.width, winSize.height));
  Glayout->setColor(ccc3(100,100,100));
  Glayout->setOpacity(150);
  Glayout->setTag(★);
  Glayout->setPosition(ccp(winSize.width/2, winSize.height/2));
  this->addChild(Glayout);

  //キャラクターのスプライトと剛体を取得
  Sprite* player = (Sprite *)this->getChildByTag(★);
  auto* playerPb = player->getPhysicsBody();
  //キャラの物理演算を切る
  playerPb->setEnable(false);

  //レイヤーに対してポーズをかけてschedule類を止める
  this -> pauseSchedulerAndActions();

  //レイヤー内のchildrenをゲットしてきてポーズする
  for (auto* childs : this->getChildren())
  {
   Sprite *spritechilds = (Sprite *)childs;
   spritechilds -> pauseSchedulerAndActions();
  }

  //アイテムバッチノードの呼び出し
  auto* ItemBatch = this->getChildByTag(★);
  //レイヤー内のアイテムバッチノードからchildrenをゲットしてきてポーズする
  for (auto* Ibatch : ItemBatch->getChildren())
  {
   Sprite *spriteIbatch = (Sprite *)Ibatch;
   spriteIbatch -> pauseSchedulerAndActions();
  }

  //エネミーバッチノードの呼び出し
  auto EnemyBatch = this->getChildByTag(★);
  //レイヤー内のエネミーバッチノードからchildrenをゲットしてきてポーズする
  for (auto* Ebatch : EnemyBatch->getChildren())
  {
   Sprite *spriteEbatch = (Sprite *)Ebatch;
   spriteEbatch -> pauseSchedulerAndActions();
  }

  //最後にポーズボタンだけポーズ解除させておかないと再開できないので注意
  auto* pMenu = (Menu *)this->getChildByTag(★);
  pMenu -> resumeSchedulerAndActions();

  //ポーズがトゥルーでなければ全てを再開する
  } else {
   CCLog("再開やで");

   //ここにポーズした時と全く同じ手順で再開する処理を書く。
   //再開メソッドはresumeSchedulerAndActions()

 }
}

※ここにあるソースは自分で作ってるプロジェクトを
 まんまコピペ、ではなく多少調整、変更したソースで載せてます。
 なのでソースの誤字脱字などもあるかもしれません。
 上記ソースを流用する場合は自己責任でお願いします。
※★は任意のタグでってことで。


☆★というわけでcocos2d-xで制作しました★☆
☆★ポーズ機能ももりもり入っています★☆

レッド・ザ・パニッシャー ―スタイリッシュレトロアクション―
カテゴリ: アクション
Google Playで詳細を見る

今なら(永久に)無料! 今すぐチェック!!

0 件のコメント:

コメントを投稿