zoukankan      html  css  js  c++  java
  • UIDynamic(物理仿真)

    简介

    1. 什么是UIDynamic
      • UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架
      • 可以认为是一种物理引擎,能模拟和仿真现实生活中的物理现象
      • 如: 重力、弹性碰撞等现象
    2. 物理引擎的价值
      • 广泛用于游戏开发,经典成功案例是“愤怒的小鸟”
      • 让开发人员可以在远离物理学公式的情况下,实现炫酷的物理仿真效果
      • 提高了游戏开发效率,产生更多优秀好玩的物理仿真游戏
    3. 知名的2D物理引擎
      • Box2d
      • Chipmunk

    三大概念

    1. 三大概念

      1. 物理仿真元素(Dynamic Item)
        • 谁要进行物理仿真?
      2. 物理仿真行为(Dynamic Behavior) 
        • 执行怎样的物理仿真效果?怎样的动画效果
      3. 物理仿真器(Dynamic Animator) 
        • 让物理仿真元素执行具体的物理仿真行为
    2. 物理仿真元素

      1. 注意
        1. 不是任何对象都能做物理仿真元素
        2. 不是任何对象都能进行物理仿真
          1. 哪些对象才能做物理仿真元素
        3. 任何遵守了UIDynamicItem协议的对象
        4. UIView默认已经遵守了UIDynamicItem协议,因此任何UI控件都能做物理仿真
        5. UICollectionViewLayoutAttributes类默认也遵守UIDynamicItem协议
    3. 物理仿真行为

      1. UIDynamic提供了以下几种物理仿真行为
         UIGravityBehavior:重力行为
         UICollisionBehavior:碰撞行为
         UISnapBehavior:捕捉行为
         UIPushBehavior:推动行为
         UIAttachmentBehavior:附着行为
         UIDynamicItemBehavior:动力元素行为
        
      2. 物理仿真行为须知
        1. 上述所有物理仿真行为都继承自UIDynamicBehavior
        2. 所有的UIDynamicBehavior都可以独立进行
        3. 组合使用多种行为时,可以实现一些比较复杂的效果
    4. 物理仿真器

      1. 物理仿真器须知

        • 它可以让物理仿真元素执行物理仿真行为
        • 它是UIDynamicAnimator类型的对象
      2. UIDynamicAnimator的初始化

        • - (instancetype)initWithReferenceView:(UIView )view;
        • view参数:是一个参照视图,表示物理仿真的范围
      3. UIDynamicAnimator的常见方法

             - (void)addBehavior:(UIDynamicBehavior *)behavior;
             添加1个物理仿真行为
        
             - (void)removeBehavior:(UIDynamicBehavior *)behavior;
             移除1个物理仿真行为
        
             - (void)removeAllBehaviors;
             移除之前添加过的所有物理仿真行为
        
      4. UIDynamicAnimator的常见属性

             @property (nonatomic, readonly) UIView* referenceView;
             参照视图
        
             @property (nonatomic, readonly, copy) NSArray* behaviors;
             添加到物理仿真器中的所有物理仿真行为
        
             @property (nonatomic, readonly, getter = isRunning) BOOL running;
             是否正在进行物理仿真
        
             @property (nonatomic, assign) id <UIDynamicAnimatorDelegate> delegate;
             代理对象(能监听物理仿真器的仿真过程,比如开始和结束)
      5. 使用步骤

        1. 创建一个物理仿真器(顺便设置仿真范围)

        2. 创建相应的物理仿真行为(顺便添加物理仿真元素)

        3. 将物理仿真行为添加到物理仿真器中 -> 开始仿真

         

        Demo

        1. 环境准备
          1. 创建项目
          2. 设置不使用autolayout(这里仅仅是为了简单,物理仿真支持autolayout,在愤怒的小鸟中演示)
          3. 设置屏幕的尺寸为5.5 因为Xcode7 默认使用是iPhone6 s Plus
          4. 拖入一个View,颜色设置蓝色,大小设置为100,100
          5. 连线到控制器中,属性为blueView
        2. 让蓝色View执行仿真重力仿真行为,代码如下:

              - (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
              {
                  //  创建一个物理仿真器,并指定参照系为控制器的View
                      UIDynamicAnimator *dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
                  //  创建重力仿真行为并指定仿真元素为蓝色的view
                      UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.blueView]];
                  //  把仿真行为添加到仿真器中
                      [dynamicAnimator addBehavior:gravity];
              }
          

          点击控制器的View,没有任何反应,这是因为还要没有执行动画物理仿真器就销毁,所以我们需要对物理仿真器有一个强引用 懒加载物理仿真器

          1. 定义物理仿真器属性

                 @property (nonatomic, strong) UIDynamicAnimator *dynamicAnimator;
            
          2. 懒加载物理仿真器器

                 - (UIDynamicAnimator *)dynamicAnimator
                 {
                     if (_dynamicAnimator == nil) {
                         //  创建一个物理仿真器,并指定参照系为控制器的View
                         _dynamicAnimator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
                     }
                     return _dynamicAnimator;
                 }
            
            1. 修改touchesBegan方法

               - (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
              {
              //  创建重力仿真行为并指定仿真元素为蓝色的view
                UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.blueView]];
              //  把仿真行为添加到仿真器中
                [self.dynamicAnimator addBehavior:gravity];
              }
              
            2. 运行,点击控制器View,蓝色View向下运动,然后从下面出去了
        3. 如果想让blueView到底部停止还需要添加一个碰撞行为

                  - (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
                   {
                   //  创建重力仿真行为并指定仿真元素为blueView
                       UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.blueView]];
          
                   //  创建一个碰撞的仿真行为并指定仿真元素为blueView
                       UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.blueView]];
                   //  设置仿真边界为碰撞边界
                       collision.translatesReferenceBoundsIntoBoundary = YES;
                   //  添加碰撞行为到仿真器中
                       [self.dynamicAnimator addBehavior:collision];
          
                   //  把仿真行为添加到仿真器中
                       [self.dynamicAnimator addBehavior:gravity];
                   }
          
        4. 在storyboard上添加一个添加一个红色View,在蓝色的View下方,运行程序蓝色的View会从红色的View上方飘过,这是因为此时红色的View并没有添加到仿真器中,如果你希望蓝色的View撞到红色的View那么就需要把红色的View添加到碰撞的仿真行为中 1.红色View的拖线到控制器中,属性名称为redView 2.把红色View添加到碰撞仿真行为中

               UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.blueView,self.redView]];
          
          1. 运行程序,点击屏幕,红色的View被推下去了;把红色的View放到蓝色View能砸到其角上的一个位置,测试,会有惊喜发现哦!
        5. 添加碰撞边界

          1. 添加直线边界

                 - (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
                 {
                 //  创建重力仿真行为并指定仿真元素为blueView
                     UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:@[self.blueView]];
            
                 //  创建一个碰撞的仿真行为并指定仿真元素为blueView
                     UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:@[self.blueView]];
                 //  设置仿真边界为碰撞边界
                     collision.translatesReferenceBoundsIntoBoundary = YES;
            
                 //  添加直线碰撞边界
                     [collision addBoundaryWithIdentifier:@"line" fromPoint:CGPointMake(0, self.view.frame.size.height * 0.5) toPoint:CGPointMake(self.view.frame.size.width, self.view.frame.size.height)];
            
                 //  添加碰撞行为到仿真器中
                     [self.dynamicAnimator addBehavior:collision];
            
                 //  把仿真行为添加到仿真器中
                     [self.dynamicAnimator addBehavior:gravity];
                 }
            
          2. 添加一个贝塞尔曲线碰撞边界,把添加直线碰撞边界的代码修改如下代码

                 //  添加贝塞尔曲线碰撞边界
                 UIBezierPath *bezierPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.width)];
                 [collision addBoundaryWithIdentifier:@"bezier" forPath:bezierPath];
            
        6. 重力行为的常见属性

           ////  设置重力的角度,默认为M_PI_2(向下),0为右,M_PI向左
           //    gravity.angle = 0;
           ////  设置重力的大小,默认是1
           //    gravity.magnitude = 2;
          
           //  设置重力向量,(0,0) -> (1,1) 之间的连线,大小为:根号2
               gravity.gravityDirection = CGVectorMake(1, 1);
          
        7. 捕获行为

            //  相同类型仿真行为只能添加到仿真器一次,所以在添加仿真行为之前,移除之前添加仿真行为
               [self.dynamicAnimator removeAllBehaviors];
          
           //  获取描述用户点击的对象
               UITouch *touch = [touches anyObject];
           //  获取用户点击的位置
               CGPoint loc =  [touch locationInView:self.view];
           //  创建一个捕获行为
               UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.blueView snapToPoint:loc];
          
           //  设置减震效果,取值范围为 0.0 to 1.0. 0表示最小减震效果,也就是振幅最大
               snap.damping = 0;
          
           //  把捕获行为添加到仿真器中
               [self.dynamicAnimator addBehavior:snap];
        8. Demo2  愤怒的小鸟

            1. 视图
  • 相关阅读:
    js鼠标事件/onclick/鼠标点击/光标移开
    搭建PHP环境
    SQL语法的一些整理
    DataTime格式大全啊!
    分页存储过程
    jquery中获取键盘按键
    中国历史朝代歌(完整)
    js键盘事件
    js鼠标、键盘事件实例代码
    《.NET Compact Framework移动开发指南》答疑一
  • 原文地址:https://www.cnblogs.com/YRFios/p/4963221.html
Copyright © 2011-2022 走看看