【发布时间】:2014-04-04 00:40:43
【问题描述】:
我正在努力在两个视图发生碰撞时发出警报,这里我使用两个图像视图在不同的方向上移动,它们将在一个点发生碰撞。我使用基本的动画代码将这些图像沿各自的方向移动。(注意:-不仅像下图一样,但是如果它们在方面发生碰撞,我们需要显示警报)
【问题讨论】:
标签: ios objective-c collision-detection uiviewanimation
我正在努力在两个视图发生碰撞时发出警报,这里我使用两个图像视图在不同的方向上移动,它们将在一个点发生碰撞。我使用基本的动画代码将这些图像沿各自的方向移动。(注意:-不仅像下图一样,但是如果它们在方面发生碰撞,我们需要显示警报)
【问题讨论】:
标签: ios objective-c collision-detection uiviewanimation
如果使用标准视图动画(例如基于块的animateWithDuration),您可以设置一个CADisplayLink(有点像计时器,但每次显示更新时都会调用)然后比较@987654325 @ 两个视图的值,看看它们是否相交。不过,诀窍是,在动画期间,视图的 frame 是“最终目标”帧,因此如果您想要在动画进行时保持原样的 frame,您可以查看它的“表示层”。
- (void)startDisplayLink
{
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}
- (void)stopDisplayLink
{
[self.displayLink invalidate];
self.displayLink = nil;
}
- (void)handleDisplayLink:(CADisplayLink *)displayLink
{
CALayer *view1PresentationLayer = self.view1.layer.presentationLayer;
CALayer *view2PresentationLayer = self.view2.layer.presentationLayer;
if (CGRectIntersectsRect(view1PresentationLayer.frame, view2PresentationLayer.frame)) {
NSLog(@"collision"); // report the collision; show alert if you want
[self.view1.layer removeAllAnimations]; // stop the animation if you want
[self.view2.layer removeAllAnimations];
self.view1.frame = view1PresentationLayer.frame; // but make sure to reset the frame to be the current position
self.view2.frame = view2PresentationLayer.frame;
[self stopDisplayLink]; // stop the display link if we don't need it any more
}
}
在上述方法中,我假设您想停止动画(这不仅涉及删除动画,还包括重置最终目的地以反映当前视图的位置),但可以做任何您想做的事情。
因此,您可以启动显示链接,启动动画,显示链接选择器方法会告诉我们是否有碰撞:
[self startDisplayLink];
[UIView animateWithDuration:1.0 animations:^{
self.view1.frame = CGRectMake(...);
self.view2.frame = CGRectMake(...);
}];
注意,在 iOS 7 中,您可能需要查看 UIKit Dynamics,您可以在其中添加行为来驱动视图的移动,还可以定义 UICollisionBehavior 来识别何时发生这种碰撞。使用 UIKit Dynamics 可能超出了这个问题的范围,但您应该参考 Apple 的 WWDC 2013 视频 Getting Started with UIKit Dynamics 和 Advanced Techniques with UIKit Dynamics。
但是,例如,在 iOS 7 中,您可以放弃 animateWithDuration,而是使用 UIKit Dynamics 进行动画处理,您可以在其中告诉两个视图捕捉到屏幕上的特定位置,但在它们发生碰撞时进行检测:
self.animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
UIDynamicItemBehavior *itemBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[self.view1, self.view2]];
itemBehavior.allowsRotation = NO;
itemBehavior.resistance = 10.0; // you can change this to affect the speed of the attachment behaviors
[self.animator addBehavior:itemBehavior];
UISnapBehavior *snap1 = [[UISnapBehavior alloc] initWithItem:self.view1 snapToPoint:newPoint1];
[self.animator addBehavior:snap1];
UISnapBehavior *snap2 = [[UISnapBehavior alloc] initWithItem:self.view2 snapToPoint:newPoint2];
[self.animator addBehavior:snap2];
// You can, alternatively use the following attachment behaviors, instead of the above
// snap behaviors, and you can then use resistance to control the speed with which they move
//
// UIAttachmentBehavior *attachment1 = [[UIAttachmentBehavior alloc] initWithItem:self.view1 attachedToAnchor:self.view1.center];
// [self.animator addBehavior:attachment1];
// attachment1.frequency = 1.0;
// attachment1.anchorPoint = newPoint1;
//
// UIAttachmentBehavior *attachment2 = [[UIAttachmentBehavior alloc] initWithItem:self.view2 attachedToAnchor:self.view2.center];
// [self.animator addBehavior:attachment2];
// attachment2.frequency = 1.0;
// attachment2.anchorPoint = newPoint2;
UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.view1, self.view2]];
collision.collisionDelegate = self;
[self.animator addBehavior:collision];
并且有一个UICollisionBehaviorDelegate 方法可以在发生碰撞时执行某些操作,例如删除行为,有效地结束动画:
- (void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id<UIDynamicItem>)item1 withItem:(id<UIDynamicItem>)item2 atPoint:(CGPoint)p
{
[self.animator removeAllBehaviors]; // for example, if they collide, you could remove the behaviors so they stop
// show alert if you want to
}
【讨论】:
如果您的目标是 iOS 7 及更高版本,那么您可以查看 UIKit Dynamics
https://developer.apple.com/library/ios/samplecode/DynamicsCatalog/Introduction/Intro.html
【讨论】: