【问题标题】:How to identify the collision of two imageviews when they are moving with animation?当两个图像视图与动画一起移动时,如何识别它们的碰撞?
【发布时间】:2014-04-04 00:40:43
【问题描述】:

我正在努力在两个视图发生碰撞时发出警报,这里我使用两个图像视图在不同的方向上移动,它们将在一个点发生碰撞。我使用基本的动画代码将这些图像沿各自的方向移动。(注意:-不仅像下图一样,但是如果它们在方面发生碰撞,我们需要显示警报)

【问题讨论】:

    标签: ios objective-c collision-detection uiviewanimation


    【解决方案1】:

    如果使用标准视图动画(例如基于块的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 DynamicsAdvanced 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
    }
    

    【讨论】:

      【解决方案2】:

      如果您的目标是 iOS 7 及更高版本,那么您可以查看 UIKit Dynamics

      https://developer.apple.com/library/ios/samplecode/DynamicsCatalog/Introduction/Intro.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多