目前知名的2D物理引擎有 Box2d,和Chipmunk,這些是跨平台的。但蘋果本身也封裝了一個物理引擎, UIDynamic是從iOS 7開始引入的一種新技術,隸屬於UIKit框架。這可以讓開發人員可以在遠離物理學公式的情況下,實現炫酷的物理仿真效果。在游戲開發中會經常用到。本文主要是玩一些較淺的功能,就不說那些游戲中框架中的高級用法了。畢竟我也入門這個沒多久啊只會些簡單點的,可以用在普通應用界面中偶爾炫酷一下足矣。
如果你不是在董鉑然博客園看到本文,請點擊查看原文
懶加載方法創建 物理仿真器
- (UIDynamicAnimator *)animator { if (!_animator) { // 創建一個物理仿真器 _animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.view]; } return _animator; }
重力行為有一個屬性是重力加速度,設置越大速度增長越快。默認是1
gravity.magnitude = 100;
添加元素,告訴仿真器哪些元素可以重力行為
[gravity addItem:self.sxView];
簡單演示:
// 創建重力行為 UIGravityBehavior *gravity = [[UIGravityBehavior alloc] init]; // magnitude越大,速度增長越快 gravity.magnitude = 100; [gravity addItem:self.sxView]; // 添加到仿真器中開始仿真 [self.animator addBehavior:gravity];
可以看到只是從圖中掉下,(注意這不是勻速動畫,他是模擬物體以重力加速度落下的)
碰撞行為需要先添加元素,告訴物理仿真器哪些元素允許碰撞。如
[collision addItem:self.sxView];
其次是設置碰撞的邊界,有個參數默認是以屏幕為邊界。
collision.translatesReferenceBoundsIntoBoundary = YES;
把碰撞行為和重力行為結合演示
// 1.創建重力行為 UIGravityBehavior *gravity = [[UIGravityBehavior alloc] init]; // magnitude越大,速度增長越快 gravity.magnitude = 2; [gravity addItem:self.sxView]; // 2.創建碰撞行為 UICollisionBehavior *collision = [[UICollisionBehavior alloc] init]; [collision addItem:self.sxView]; [collision addItem:self.bigBlock]; [collision addItem:self.smallBlock]; // 設置碰撞的邊界 collision.translatesReferenceBoundsIntoBoundary = YES; // 3.開始仿真 [self.animator addBehavior:gravity]; [self.animator addBehavior:collision];
(圖中之所以那兩個控件會往上飄,是因為他們雖然都添加了碰撞行為,但是沒有添加重力行為)
如果覺得屏幕作為邊界不好,可以自己設置一條邊可以是普通的邊
[collision addBoundaryWithIdentifier:@"line2" fromPoint: CGPointMake(self.view.frame.size.width, 0) toPoint: CGPointMake(self.view.frame.size.width, 400)];
也可以是個貝塞爾路徑。(注意這裡的路徑是不會顯示的,想要能看見得在view中畫一個和你設置的邊界一樣的圖形)
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect: CGRectMake(0,150, self.view.frame.size.width, self.view.frame.size.width)]; [collision addBoundaryWithIdentifier:@"circle" forPath:path];
效果如圖
捕捉行為需要在創建時就給與一個點。
UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.sxView snapToPoint:point];
捕捉行為有一個防震系數屬性,設置的越大,振幅就越小
snap.damping = 1;
因為默認只能移動一次,如果想多次移動,就在模擬仿真前清空之前的仿真器
[self.animator removeAllBehaviors];
結合演示,鼠標點哪,移動到哪
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 1.獲得手指對應的觸摸對象 UITouch *touch = [touches anyObject]; // 2.獲得觸摸點 CGPoint point = [touch locationInView:self.view]; // 3.創建捕捉行為 UISnapBehavior *snap = [[UISnapBehavior alloc] initWithItem:self.sxView snapToPoint:point]; // 防震系數,damping越大,振幅越小 snap.damping = 1; // 4.清空之前的並再次開始 [self.animator removeAllBehaviors]; [self.animator addBehavior:snap]; }
還有一些在此就不一一演示了 頭文件都很簡單能看懂的。
UIGravityBehavior:重力行為 UICollisionBehavior:碰撞行為 UISnapBehavior:捕捉行為 UIPushBehavior:推動行為 UIAttachmentBehavior:附著行為 UIDynamicItemBehavior:動力元素行為 所有物理仿真行為都繼承自UIDynamicBehavior 所有的UIDynamicBehavior都可以獨立進行 組合使用多種行為時,可以實現一些比較復雜的效果 如果你不是在董鉑然博客園看到本文,請點擊查看原文比如重力還可以設置重力方向,碰撞還能監聽整個碰撞過程,附著動畫類似於iOS8的iMessage短信聊天界面(上下拖動)等等,有興趣的可以自行研究,偶爾在應用中做個“撒紅包”“砸金蛋” 等動畫啥的可以用這些方法。