こんばんわ。
いやいや、暑い。
今年はどのタイミングでクーラーの力を借りようか悩むところです

節電もしないとだめですし。
電気代値上げすんなよー。ヽ(`Д´)ノ

はい、今日はドラッグについてやってみます。

今のところはパネルをタッチして、もう一つパネルをタッチして、、、
という感じになっていますが、スムーズにパネル交換をするためには、
やっぱりドラッグでシュッっと交換したいですよね?。。。よね?

もちろん、今までの操作もできるようにしたままです。

ではPlayViewContorller.mに以下のようなコードを書いてみます。



- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (isFinished || state != PlayStateChoose) {
return;
}
if (!movingLayer1) {
return;
}

UITouch *aTouch = [touches anyObject];
CGPoint pos = [aTouch locationInView:self.view];
pos = [backView.layer convertPoint:pos toLayer:backView.layer.superlayer];

CALayer *layer = [backView.layer hitTest:pos];
if (movingLayer1 == layer || ![layer.name hasPrefix:@"panel"]) {
return;
}

// 2枚目のパネルの選択
if (movingLayer1) {
[movingLayer1 removeAnimationForKey:@"rotation"];
movingLayer2 = layer;
if (![self swapLayers]) {
movingLayer1 = nil;
movingLayer2 = nil;
}
}
}


このtouchesMoved:withEvent:っていうのは、いつ呼ばれるのかというと、
指が画面に触れた後、移動されると発生します。つまりドラッグですね。

これは、touchesBegan:withEvent:メソッドによくにてます

どこが違うのかというと、1枚目のパネルを選択するところの処理が無いだけで、あとはほぼ同じです。

これだけで、実装完了です!(*^ー^)ノ

なんででしょう。

想像してみてください。

①1枚目タッチ
   ↓
②ドラッグ(1枚目の枠の中を指が移動中)
   ↓
③ある瞬間となりのパネルの枠の中(2枚目)に入る!
// 2枚目のパネルの選択
のところにくる。→交換開始


①の1枚目タッチの時は、タッチイベントのメソッドが実行されます、
その後ドラッグ操作をすると、1枚目にタッチされたパネルがあるのは確かですよね。

②のドラッグ中はずっとこのtouchesMoved:withEvent:が何回も呼ばれますが、
交換する手前の条件分岐でうまい具合にreturnしてるのです。
パネル外を操作された時もreturnしてます。

なんとなくイメージできましたか??


では今日はこのへんで、失礼です(*v.v)。

応援よろしくお願いします!
にほんブログ村 IT技術ブログ iPhoneアプリ開発へ


にほんブログ村 携帯ブログ iPhoneへ



はい、こんにちわ。

既に暑苦しくていやですねー。

swapLayerメソッドの冒頭です。

- (BOOL)swapLayers {
CGPoint panelPos1 = movingLayer1.position;
CGPoint panelPos2 = movingLayer2.position;

int px1 = (panelPos1.x - 59) / (42 + 1);
int py1 = (panelPos1.y - 53) / (42 + 1);
int px2 = (panelPos2.x - 59) / (42 + 1);
int py2 = (panelPos2.y - 53) / (42 + 1);



さて、これはいったい何をやっているのかといいますと、
押されたレイヤがどの場所のレイヤなのか?というのを変換してます。
たとえば、下のように一つ目にタッチしたところがの場合、px1=1、py1=5 となり、、
をタッチした場合は、px1=4、py=5になるように変換してます。
むかし、このマス目を細かく指定したのはこういうときのためでした。

$無知の状態からiPhoneアプリ開発に挑んでみる-2011-6-9-1

同じように2回目のタッチはpx2、py2にそれぞれそのレイヤの場所が入ります。
入りうる値は0~5ですね。

そしてそして、次のようにxとの差分を計算して1回目と2回目のパネルが隣接してるか判断します。
もし、隣接していたら、state PlayStateChangeにして入替えアニメーションを実行します。

    int dx = px2 - px1;
int dy = py2 - py1;

if (dx == 0 && abs(dy) == 1 || abs(dx) == 1 && dy == 0) {
state = PlayStateChange;

     :
     :
}


交換アニメーションは実は簡単らしくて、指定したように0.4秒をかけて交換してるだけなのです。

   CABasicAnimation *anime1 = 
[CABasicAnimation animationWithKeyPath:@"position"];
anime1.duration = 0.4;
anime1.fromValue = [NSValue valueWithCGPoint:panelPos1];
anime1.toValue = [NSValue valueWithCGPoint:panelPos2];
movingLayer1.position = panelPos2;
[movingLayer1 addAnimation:anime1 forKey:nil];

CABasicAnimation *anime2 =
[CABasicAnimation animationWithKeyPath:@"position"];
anime2.duration = 0.4;
anime2.fromValue = [NSValue valueWithCGPoint:panelPos2];
anime2.toValue = [NSValue valueWithCGPoint:panelPos1];
movingLayer2.position = panelPos1;
[movingLayer2 addAnimation:anime2 forKey:nil];


これは、movingLayer1を移動させるためにpanelPos1からpanelPos2を設定してるのが分かると思います。
逆にmovingLayer2panelPos2からpanelPos1を設定してますね。
これで見た目(アニメーション)では移動はされますが、実際の位置の移動はされてません。
0.4秒後にすぐ戻ってしまいます。
そこでmovingLayer1のpositionを明示的に設定しています。
[NSTimer scheduledTimerWithTimeInterval:0.4
target:self
selector:@selector(finishChange:)
userInfo:nil
repeats:NO];

次のカタマリですが、パネルを位置交換のアニメーションが完了したら、実際にパネルを消す判定をします。
これは0.4秒後にfinishChangeメソッドを呼んで実現します。

- (void)finishChange:(NSTimer *)timer {
if (YES) { // TODO: あとでパネル消滅の判定を付ける
// 消せない場合、交換したパネルを元に戻す

CGPoint panelPos1 = movingLayer2.position;
CGPoint panelPos2 = movingLayer1.position;
movingLayer1.position = panelPos1;
movingLayer2.position = panelPos2;
movingLayer1 = nil;
movingLayer2 = nil;
state = PlayStateChoose;
}
}


で、これがfinishChangeメソッドです。
さきほどもカンタンに説明したとおり、今はパネルを消さず元に戻すことにしています。
このあとでやる予定です。
ここでは、positionプロパティの設定にはCABasicAnimation使っていません。
その場合は 勝手に0.25秒かけてpositionを設定するようになります。暗黙的にです。

そして最後に、state = PlayStateChoose としてパネル選択中の状態に設定しています。

さてどうでしょう。
イメージだけでもつかめましたでしょうか??
ぼくもぎりぎりです。( ̄Д ̄;;

がんばりましょうーヽ(;´ω`)ノ

応援よろしくお願いします!
にほんブログ村 IT技術ブログ iPhoneアプリ開発へ


にほんブログ村 携帯ブログ iPhoneへ

こんにちわ!

さて早速始めましょう(‐^▽^‐)

2枚目のパネルを選択した時に、swapLayersメソッドを呼び出して、

交換して、交換できたらRETURNYESにして返すという話だけしました。よね?

その交換メソッドは、今のところはなにもせずにNOを返してました。
こんなふうに↓
- (BOOL)swapLayers {
return NO;
}

つまり交換できなかったということです。

今日はこの中身をコーディングします。

では、NOだけ返してるswapLayersを以下の様にしてみてください。


- (BOOL)swapLayers {
CGPoint panelPos1 = movingLayer1.position;
CGPoint panelPos2 = movingLayer2.position;

int px1 = (panelPos1.x - 59) / (42 + 1);
int py1 = (panelPos1.y - 53) / (42 + 1);
int px2 = (panelPos2.x - 59) / (42 + 1);
int py2 = (panelPos2.y - 53) / (42 + 1);

int dx = px2 - px1;
int dy = py2 - py1;

if (dx == 0 && abs(dy) == 1 || abs(dx) == 1 && dy == 0) {
state = PlayStateChange;
CABasicAnimation *anime1 =
[CABasicAnimation animationWithKeyPath:@"position"];
anime1.duration = 0.4;
anime1.fromValue = [NSValue valueWithCGPoint:panelPos1];
anime1.toValue = [NSValue valueWithCGPoint:panelPos2];
movingLayer1.position = panelPos2;
[movingLayer1 addAnimation:anime1 forKey:nil];

CABasicAnimation *anime2 =
[CABasicAnimation animationWithKeyPath:@"position"];
anime2.duration = 0.4;
anime2.fromValue = [NSValue valueWithCGPoint:panelPos2];
anime2.toValue = [NSValue valueWithCGPoint:panelPos1];
movingLayer2.position = panelPos1;
[movingLayer2 addAnimation:anime2 forKey:nil];

[NSTimer scheduledTimerWithTimeInterval:0.4
target:self
selector:@selector(finishChange:)
userInfo:nil
repeats:NO];
return YES;
}

return NO;
}



そして、もう一つ下のメソッドを追加してください。

- (void)finishChange:(NSTimer *)timer {
if (YES) { // TODO: あとでパネル消滅の判定を付ける
// 消せない場合、交換したパネルを元に戻す

CGPoint panelPos1 = movingLayer2.position;
CGPoint panelPos2 = movingLayer1.position;
movingLayer1.position = panelPos1;
movingLayer2.position = panelPos2;
movingLayer1 = nil;
movingLayer2 = nil;
state = PlayStateChoose;
}
}


これらはそんなに難しいことはしてないです。
解説は次回にしますが、座標の指定と計算と、アニメーションの設定と実行だけです。
下のfinishChangeメソッドは、パネルを交換した時に、消せるかどうかを判定しています。
でも消す処理を一緒にすると長くなるので、ひとまず消せなかったこと「YES」として、
処理を続行してパネルを元の位置に戻すことをしています。

それでは、実行して見ましょう。

プレイ画面から、パネルをひとつクリック!
「+」がくるくるまわります。

無知の状態からiPhoneアプリ開発に挑んでみる-2011-6-5-1

左の青い六角形をクリックすると、ツーっと入れ替わろうとします
無知の状態からiPhoneアプリ開発に挑んでみる-2011-6-5-2

けど、先ほど説明した通り、パネルを消すのは後回しにしたので、
ちゅるりんっと元に戻ります。

どうでしょう?

うまくできましたか?

では続きは次回に(^∇^)


にほんブログ村 IT技術ブログ iPhoneアプリ開発へ

にほんブログ村 携帯ブログ iPhoneへ