UIDynamic 物理仿真引擎全面了解
UIDynamic 是从 iOS 7开始引入的一种新技术,隶属于UIKit框架可以认为是一种物理引擎,能模拟和仿真现实生活中的物理现象,如:重力、弹性碰撞等现象
物理引擎的价值
广泛用于游戏开发,经典成功案例是“愤怒的小鸟”。
知名的2D物理引擎
Box2d
Chipmunk
三个概念
1.仿真元素(Dynamic Item)(也就是运动的那个元素)
物理仿真元素要素:
任何遵守了UIDynamicItem协议的对象
UIView 默认已经遵守了 UIDynamicItem 协议,因此任何 UI 控件都能做物理仿真 UICollectionViewLayoutAttributes 类默认也遵守 UIDynamicItem 协议
2.仿真行为(Dynamic Behavior)(也就是仿真元素的几种物理状态)
执行怎样的物理仿真效果?怎样的动画效果?
UIDynamic提供了以下几种物理仿真行为:
UIGravityBehavior:重力行为
UICollisionBehavior:碰撞行为
UISnapBehavior:捕捉行为
UIPushBehavior:推动行为
UIAttachmentBehavior:附着行为
UIDynamicItemBehavior:动力元素行为
上述所有物理仿真行为都继承自 UIDynamicBehavior
所有的 UIDynamicBehavior 都可以独立进行,组合使用多种行为时,可以实现一些比较复杂的效果 ( 意思就是都可以单独实现,放在一起可以 实现复杂的效果:如:一个物理UIGravityBehavior下降,发生UICollisionBehavior)
2.物理仿真器(Dynamic Animator)(也就是仿真元素的几种物理状态)
让物理仿真元素执行具体的物理仿真行为,UIDynamicAnimator 类型的对象
物理仿真器 相关方法:
-(instancetype)initWithReferenceView:(UIView *)view; (view意思是在那个视图为参考视图,并非范围)
UIDynamicAnimator 的常见方法:
//添加1个物理仿真行为
- (void)addBehavior:(UIDynamicBehavior*)behavior;
//移除1个物理仿真行为
- (void)removeBehavior:(UIDynamicBehavior*)behavior;
//移除之前添加过的所有物理仿真行为
- (void)removeAllBehaviors;
//参照视图
@property(nonatomic,readonly)UIView* referenceView;
//添加到物理仿真器中的所有物理仿真行为
@property(nonatomic,readonly,copy)NSArray* behaviors;
//是否正在进行物理仿真
@property(nonatomic,readonly, getter = isRunning)BOOLrunning;
//代理对象(能监听物理仿真器的仿真过程,比如开始和结束
@property(nonatomic,assign)id delegate;
使用步骤
要想使用UIDynamic来实现物理仿真效果,大致的步骤如下
1.创建一个物理仿真器(顺便设置仿真范围)
2.创建相应的物理仿真行为(顺便添加物理仿真元素)
3.将物理仿真行为添加到物理仿真器中开始仿真
UIGravityBehavior 重力行为
常用方法:
- (instancetype)initWithItems:(NSArray*)items; // UIGravityBehavior的初始化,item参数 :里面存放着物理仿真元素
- (void)addItem:(id)item; // 添加1个物理仿真元素
- (void)removeItem:(id)item; // 移除1个物理仿真元素
UIGravityBehavior常见属性
@property(nonatomic,readonly,copy)NSArray* items; // 添加到重力行为中的所有物理仿真元素
@property(readwrite,nonatomic)CGVectorgravityDirection; // 重力方向(是一个二维向量)
@property(readwrite,nonatomic)CGFloatangle; // 重力方向(是一个角度,以x轴正方向为0°,顺时针正数,逆时针负数)
@property(readwrite,nonatomic)CGFloatmagnitude; // 量级(用来控制加速度,1.0代表加速度是1000 points /second²)
UICollisionBehavior 碰撞行为
可以让物体之间实现碰撞效果,可以通过添加边界(boundary),让物理碰撞局限在某个空间中
UICollisionBehavior 边界相关的方法
- (void)addBoundaryWithIdentifier:(id)identifier forPath:(UIBezierPath*)bezierPath;
- (void)addBoundaryWithIdentifier:(id)identifier fromPoint:(CGPoint)p1 toPoint:(CGPoint)p2;
- (UIBezierPath*)boundaryWithIdentifier:(id)identifier;
- (void)removeBoundaryWithIdentifier:(id)identifier;
@property(nonatomic,readonly,copy)NSArray* boundaryIdentifiers;
- (void)removeAllBoundaries;
UISnapBehavior 捕捉行为
可以让物体迅速冲到某个位置(捕捉位置),捕捉到位置之后会带有一定的震动
UISnapBehavior的初始化
- (instancetype)initWithItem:(id)item snapToPoint:(CGPoint)point;
UISnapBehavior常见属性
// 用于减幅、减震(取值范围是0.0 ~ 1.0,值越大,震动幅度越小)
@property(nonatomic,assign)CGFloatdamping;
UIPushBehavior 推动行为
UIPushBehavior*pushBehavior = [[UIPushBehavioralloc] initWithItems:@[self.image] mode:UIPushBehaviorModeInstantaneous];
// vector 矢量 ,控制 push 的方向
pushBehavior.pushDirection=CGVectorMake((velocity.x/10) , (velocity.y/10));
// magnitude 的属性控制 push 的快慢 必须慢慢试才能找出最合适的值
pushBehavior.magnitude= magnitude
// ThrowingVelocityPadding;
self.pushBehavior= pushBehavior;
[self.animatoraddBehavior:self.pushBehavior];
UIAttachmentBehavior:附着行为
具体来说就是我手怎么动,UIAttachmentBehavior 指定的 view 就怎么动
- (IBAction)handleAttachmentGesture:(UIPanGestureRecognizer*)pan{
// 在手势开始时添加 物理仿真行为
if(pan.state==UIGestureRecognizerStateBegan) {
// 首先要移除物理仿真行为
[self.animatorremoveAllBehaviors];
// 获取手势在 view 容器中的位置
CGPointlocation = [pan locationInView:self.view];
// 获取手势在 lightBlueView 中的位置
CGPointboxLocation = [pan locationInView:self.lightBlueView];
// 以 lightBlueView 为参考坐标系,计算触摸点到 lightBlueView 中点的偏移量
UIOffsetoffset =UIOffsetMake(boxLocation.x-CGRectGetMidX(self.lightBlueView.bounds), boxLocation.y-CGRectGetMidY(self.lightBlueView.bounds));
// 创建物理仿真行为
self.attach= [[UIAttachmentBehavioralloc] initWithItem:self.lightBlueViewoffsetFromCenter:offset attachedToAnchor:location]; [self.animatoraddBehavior:self.attach];
}
[self.attachsetAnchorPoint:[pan locationInView:self.view]];
}
下面介绍一下 UIAttachmentBehavior 的属性:
@property(readonly,nonatomic)UIAttachmentBehaviorType attachedBehaviorType;
// 该锚点关联物理仿真元素附着的点,在这个例子中,就是你的手指所触摸的那个点,
// lightBlueView 是围绕这个点在运动的。
@property(readwrite,nonatomic)CGPointanchorPoint;
@property(readwrite,nonatomic)CGFloatlength;// 衰减,经测试,这个值越大,可以减震@property(readwrite,nonatomic)CGFloatdamping;// 该值越大,物理仿真元素运动越剧烈@property(readwrite,nonatomic)CGFloatfrequency;// 反抗旋转的程度@property(readwrite,nonatomic)CGFloatfrictionTorqueNS_AVAILABLE_IOS(9_0);
@property(readwrite,nonatomic)UIFloatRangeattachmentRangeNS_AVAILABLE_IOS(9_0);
UIDynamicItemBehavior:动力元素行为
具体作用:给一个仿真元素设置各种物理属性。比如:
allowsRotation :是否允许旋转
resistance: 抗阻力 0~CGFLOAT_MAX ,阻碍原有所加注的行为(如本来是重力自由落体行为,则阻碍其下落,阻碍程度根据其值来决定)
friction: 磨擦力 0.0~1.0 在碰撞行为里,碰撞对象的边缘产生
elasticity:弹跳性 0.0~1.0
density:密度 0~1
- (UIView*) newViewWithCenter:(CGPoint)paramCenter backgroundColor:(UIColor*)paramBackgroundColor{
UIView*newView = [[UIViewalloc] initWithFrame:CGRectMake(0.0f,0.0f,50.0f,50.0f)];
newView.backgroundColor= paramBackgroundColor;
newView.center= paramCenter;
returnnewView;
}