CCSpawnで複数アクションを動かし、片方だけ止めようとしたら失敗した話

複数アクションを動かして、途中で片方だけ中断したいと思い、次のコードを書きました。

CCMoveBy *mb = CCMoveBy::create(0.15f, ccp(30.0f, 0.0f));
CCFadeTo *ft = CCFadeTo::create(0.15f, 225);
ft->setTag(1);
CCSpawn *sp = CCSpawn::createWithTwoActions(mb, ft);

runAction(sp);

別の場所で

stopActionByTag(1);

CCFadeToのアクションだけ止めようとしたのですが、うまく行かず。

色々調べてみた結果、どうも片方だけ止める場合はCCSpawnでアクションを合成してはいけない模様。

CCMoveBy *mb = CCMoveBy::create(0.15f, ccp(30.0f, 0.0f));
CCFadeTo *ft = CCFadeTo::create(0.15f, 225);
ft->setTag(1);

runAction(mb);
runAction(ft);

別の場所で

stopActionByTag(1);

これで無事止まってくれました。

CCBlinkを止める時の注意点

スプライトをずっと点滅させるために

CCRepeatForever *rf = CCRepeatForever::create(CCBlink::create(0.3f, 2));
rf->setTag(1);
sprite->runAction(rf);

とかした後に、

sprite->stopActionByTag(1);
sprite->setOpacity(255);

とかして、点滅を止めたとき、必ず表示した状態でアニメーションを止めようとしたのですが、これがうまくいきません。

正しくはこちらでした。

sprite->stopActionByTag(1);
CCShow *show = CCShow::create();
sprite->runAction(show);

非表示状態で止めたい場合はこちら。

sprite->stopActionByTag(1);
CCHide *hide = CCHide::create();
sprite->runAction(hide);

こんなのあるんですね。

追記

もっとシンプルな方法ありました。

sprite->stopActionByTag(1);
sprite->setVisible(true);

シーケンスにアクションとして入れておく必要がない場合、これが一番綺麗ですね。

CC_SYNTHESIZE について

Cocos2d-xを触り始めたので、それについても少しずつ書いていこうと思います。
C++自体ちゃんと書くのが初めてなのでかなり初歩的な部分も書くことになるかもしれません。
Versionは2系です。


クラス内のprivateな変数に対して、Objective-Cで言うところの@synthesizeが無いか調べてみました。

結果、ありました。

CC_SYNTHESIZE

これを、private:部分の定義として使うといけます。

  • 使い方
CC_SYNTHESIZE(型, 変数名, get○○○の○○○の部分);

具体的には、

CC_SYNTHESIZE(bool, flag, Flag);

といった具合。

また、読み込み専用にする場合は

CC_SYNTHESIZE_READONLY(bool, flag, Flag);

retainする場合は

CC_SYNTHESIZE_RETAIN(CCObject *, object, Object);

といったようにすれば良いようです。

CopyPNGFILE Error の対処方法

XcodeでCopyPNGFILE Error なるエラーが出て1時間少し悩まされました。

ググったところ
・そもそもファイルが入っておらず、ファイル名のところが赤くなっているものがある
・Cleanしたらなおる
・Home/Developer/Xcode/DerivedData内のファイルを削除する
あたりでほとんど直るらしいのですが、全て試してみても直らない。

約1時間半後

結局プロジェクトのTARGETS内Build PhasesにあるCopy Bundle Resourcesのところで、ファイル名が赤くなり、実体が入っていないものがあり、それを削除すると見事Build成功。
まさかこんなところにリンクの一覧があるなんて…。



結構盲点でした。
同じエラーに悩まされている方の参考になれば幸いです。

Objective-Cで残り時間の計算

ある時間からの経過時間なら割りと簡単にできても、残り時間はちょっと面倒かも。
手っ取り早い方法でサクッと実装した。

●残り時間30秒の状況を想定したとき

  1. ある時間にスタートする。その時間+30秒の時間をendTimeに入れておく。
  2. 現在時刻からendTimeまでの時間をremainTimeとして表示する

これだけ。
ただし時間の幅を持たせるオブジェクトにはNSTimeIntervalというまた別の専用のモノを使う必要がある。

.h

NSDate *endTime
NSTimeInterval remainTime;

.m内の適切なメソッドにそれぞれ

// endTimeをセット
[endTime release];
endTime = [[NSDate dateWithTimeIntervalSinceNow:30.0f] retain];
// 残り時間の計算
remainTime = [endTime timeIntervalSinceDate:[NSDate date]];

終わり。


追記

NSTimeInterval *remainTime;

NSTimeInterval remainTime;

に修正しました。
前のままだとエラーが出てしまいました。

this class is not key value coding-compliant for the key

これからObjective-CによるiPhoneアプリ開発でハマった箇所などメモ書き程度に書いていこうかと思う。
備忘録、そして誰かの参考になれば。

                    • -

this class is not key value coding-compliant for the key

昨日はこのエラーが出てずっと悩んでた。

簡潔に言うと、
Viewファイル(.hと.mm)と、それに関連する箇所の名前を変えたときに、nibファイルのviewにおけるReferencing Outletsに以前の名前のものとのつながりが残されたままだったため、名前が見つからない状態になっていたらしい。
紐付けを解いたらあっけなくバグは消えました。

Viewファイルの名前を変更するときは気を付けなければなりませんね。

                  • -

[追記 12/02/10]

別の原因でもう一度このエラーが出ました。

@property (nonatomic, retain) IBOutlet UILabel *labelTest;

はしてるのに、@synthesizeをし忘れてた、というシンプルな原因。

もし最初に挙げた箇所を確認してもダメなときは初心に振り返ってこのへんもチェックすると良いかも。

PE Problem 83

Project Euler Problem 83

PEの解いていない問題の中から、幅優先探索っぽい問題を探し出して解いてみた。
幅優先探索で解いたとはいえ、実際は距離というより合計値がキーになってくる問題。
うまく枝刈りをしていって、1分以内に終わるようにしました。
大したことしてないけど。

#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
#define INF 10000000
#define MAX 80
#define FOR(a,start,end) for(long long int a=(start);a<(end);++a)
using namespace std;

//現在の場所用構造体
struct cell{
	int i;
	int j;
};

typedef pair<cell, int> P;

int mat[MAX][MAX];	//入力された行列
int d[MAX][MAX];	//合計値の暫定最小値テーブル

int bfs(){
	//4方向用
	int vi[4] = {0, 0, -1, 1}, vj[4] = {-1, 1, 0, 0};

	FOR(i, 0, MAX){
		FOR(j, 0, MAX){
			d[i][j] = INF;
		}
	}

	queue<P> que;

	cell obj;
	obj.i = 0;
	obj.j = 0;

	que.push(pair<cell, int>(obj, 0));


	while(!que.empty()){
		P p = que.front();
		que.pop();

		int i = p.first.i;
		int j = p.first.j;
		int sum = p.second + mat[i][j];

		//(i, j)までの合計値が更新される時
		if(sum < d[i][j]){
			d[i][j] = sum;

			//右下についたらこれ以上探索しない
			if(i == MAX-1 && j == MAX-1) continue;

			//next_i, next_j
			int ni, nj;
			FOR(k, 0, 4){
				ni = i + vi[k];
				nj = j + vj[k];
				
				if(ni < 0 || ni >= MAX || nj < 0 || nj >= MAX) continue;

				//push用の構造体
				cell new_obj;
				new_obj.i = ni;
				new_obj.j = nj;

				que.push(pair<cell, int>(new_obj, sum));
			}
		}
	}

	return d[MAX-1][MAX-1];
}

int main(){
	FILE *fp;
	fp = fopen("083_txt.txt", "r");

	FOR(i, 0, MAX){
		FOR(j, 0, MAX){
			fscanf(fp, "%d", &mat[i][j]);
			if(j != MAX) fscanf(fp, "%*c");
		}
	}

	cout << bfs() << endl;

	fclose(fp);
}

実は、最小値テーブルが更新されたら、更新するようなルート以外の探索をすぐ終わるべきなんだけれども、
それをしない状態で試しに実行してみたところ割りと早く終わったので枝刈りしませんでした。
というか、実装しようと思ったけど若干面倒臭そうだったのでやめました。

今回新しくやったことといったら、構造体をpairの要素として持たせたってことぐらいですかね。

最初pairにpairを要素として持たせたら、何故かうまくコンパイルができませんでした…。
ちゃんと出来るのであればやったのですが、よくわからず。
どうやるんだろうか…。