[英]iOS view animation allow user interaction
I am making a game similar to Piano Tiles https://itunes.apple.com/us/app/piano-tiles-dont-tap-white/id848160327?mt=8 我正在制作类似于Piano Tiles的游戏https://itunes.apple.com/us/app/piano-tiles-dont-tap-white/id848160327?mt=8
you can tap a tile even when the earlier animation is not finished. 即使较早的动画尚未完成,您也可以点击图块。
Here is my implementation 这是我的实现
- (void)moveDown {
[UIView animateWithDuration:DURATION_MOVE_DOWN delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
for (Tile *t in self.tiles) {
if (t.y == NUM_TILES_Y - 1) {
t.y = 0;
}
else {
t.y++;
}
if (t.y == 0) {
//move down
//then place it to the top (in the completion handler)
t.frame = [Tile frameWithX:t.x y:NUM_TILES_Y];
}
else {
//move down
t.frame = [Tile frameWithX:t.x y:t.y];
}
}
} completion:^(BOOL finished) {
for (Tile *t in self.tiles) {
//if user tap while animating, just place the tile at its final position first, (then continue the new animation)
t.frame = [Tile frameWithX:t.x y:t.y];
}
[self assignTouchDontTouchWithRowY:0];
}];
}
the assignTouchDontTouchWithRowY method is to randomly pick a tile of a row to be TileTypeTouch(black tile) and the rest of the row to be TileTypeDontTouch (white tile) AssignTouchDontTouchWithRowY方法是随机选择一行的一个磁贴为TileTypeTouch(黑色磁贴),该行的其余部分为TileTypeDontTouch(白磁贴)
- (void)assignTouchDontTouchWithRowY:(int)y {
int touchX = [Helper randomIntInclusiveBetweenLow:0 High:NUM_TILES_X -1];
for (int x = 0; x < NUM_TILES_X; x++) {
Tile *t = [self tileWithX:x y:y];
if (x == touchX) {
t.type = TileTypeTouch;
}
else {
t.type = TileTypeDontTouch;
}
}
}
The problem is that, when I press a tile before the earlier animation is completed, some of the code is not executed (eg coloring a new row, moving down a row, and sometimes the bottom row gets translated above to the top instead of sliding down first, then place at the top) 问题是,当我在较早的动画完成之前按一个图块时,某些代码未执行(例如,为新行着色,向下移动一行,有时底部的行会从上方翻译到顶部而不是滑动首先向下,然后放在顶部)
When I use the option UIViewAnimationOptionBeginFromCurrentState
, the user interaction gets canceled when the earlier one is animating. 当我使用选项
UIViewAnimationOptionBeginFromCurrentState
,当较早的一个动画时,用户交互将被取消。 So it's not working either. 因此它也不起作用。
Edit: 编辑:
In the screenshot, the (0, 1) tile is the second last one tapped, it got translated to the top (without sliding down and being updated its color) 在屏幕截图中,(0,1)磁贴是倒数第二个,它被平移到顶部(不向下滑动并更新其颜色)
also note that above the (y=1) row, there is another row (y=0) outside the screen. 还请注意,在(y = 1)行上方,屏幕外还有另一行(y = 0)。 ie there are 5 rows, 4 of which are on screen and the first row (y=0) is at the top outside the screen.
即有5行,其中4行在屏幕上,第一行(y = 0)在屏幕外部的顶部。 When sliding down, the last row (y=4) slide down first, then place it at the top (y=0) in the completion handler
向下滑动时,最后一行(y = 4)首先向下滑动,然后将其放在完成处理程序的顶部(y = 0)
EDIT 3: just in case my logic is not clear: 编辑3:以防万一我的逻辑不清楚:
EDIT 4: error is illustrated in the video here 编辑4:此处的视频说明了错误
https://drive.google.com/file/d/0B-iP0P7UfFj0Q01neEhaZmtBY2c/edit?usp=sharing https://drive.google.com/file/d/0B-iP0P7UfFj0Q01neEhaZmtBY2c/edit?usp=sharing
the completion block is executed after the new animation (which happens immediately when you call -moveDown 完成块是在新动画之后执行的(调用-moveDown时会立即发生
when will the completion block get executed? 完工块什么时候执行? we don't know!
我们不知道! it's in the queue/future!
它在排队/未来!
so move the clean-up code for the previous animation to the beginning of moveDown (outside animiation, and dont forget to check if (finished) to save some unnecessary work 因此,将上一个动画的清理代码移到moveDown的开头(动画之外),并且不要忘记检查(完成)是否省去了一些不必要的工作
- (void)moveDown {
Tile *t = self.tiles[0];
if (t.layer.animationKeys.count) {
for (Tile *t in self.tiles) {
t.frame = [Tile frameWithX:t.x y:t.y];
}
[self assignTouchDontTouchWithRowY:0];
}
[UIView animateWithDuration:DURATION_MOVE_DOWN delay:0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
NSLog(@"anim");
for (Tile *t in self.tiles) {
if (t.y == NUM_TILES_Y - 1) {
t.y = 0;
}
else {
t.y++;
}
if (t.y == 0) {
//move down
//then place it to the top (in the completion handler)
t.frame = [Tile frameWithX:t.x y:NUM_TILES_Y];
}
else {
//move down
t.frame = [Tile frameWithX:t.x y:t.y];
}
}
} completion:^(BOOL finished) {
if (finished) {
for (Tile *t in self.tiles) {
if (t.y == 0) {
t.frame = [Tile frameWithX:t.x y:t.y];
}
}
[self assignTouchDontTouchWithRowY:0];
}
}];
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.