UIKit Dynamics - 缓慢移动的物体不会反弹

Axe*_*eva 2 uikit game-physics ios

目标是创建一个环境,让球的图像在视图中非常缓慢地无休止地弹跳。我可以使无尽的弹跳以高速工作,但不能以慢速工作。

这是代码示例:

UIDynamicAnimator  *animator = [[UIDynamicAnimator alloc] initWithReferenceView: self.view];

UICollisionBehavior  *ballCollision = [[UICollisionBehavior alloc] initWithItems: @[largeBall, mediumBall, smallBall]];
[ballCollision setTranslatesReferenceBoundsIntoBoundary: YES];
[ballCollision setCollisionMode: UICollisionBehaviorModeBoundaries];

float force = 0.1;
int angle = 225;
NSNumber *rad = [NSNumber numberWithDouble: DEGREES_TO_RADIANS(angle)];

UIPushBehavior  *smallPush = [[UIPushBehavior alloc] initWithItems: @[smallBall] mode: UIPushBehaviorModeInstantaneous];
[smallPush setAngle: [rad floatValue]];
[smallPush setMagnitude: force];

UIDynamicItemBehavior *dynamicBehavior = [[UIDynamicItemBehavior alloc] initWithItems: @[smallBall]];
[dynamicBehavior setDensity: 0.0];
[dynamicBehavior setElasticity: 1.0];
[dynamicBehavior setFriction: 0.0];
[dynamicBehavior setResistance: 0.0];

[animator addBehavior: ballCollision];
[animator addBehavior: smallPush];
[animator addBehavior: dynamicBehavior];
Run Code Online (Sandbox Code Playgroud)

我的高中物理课一定没有沉浸其中,因为我不明白为什么这行不通。摩擦力为零,弹性为一,球应该永远弹跳,不是吗?

Rob*_*ier 5

请记住,UIKIt 动力学不是物理学。苹果在 WWDC 上煞费苦心地反复强调了这一点。这是“类似物理学”的。

UICollisionBehavior抑制低于 100p/s 的矢量分量(这没有记录;您可以通过实验来解决)。这通常是您想要的,这样事情就不会永远反弹,并且使一些常见用途更容易实现。UIDynamicItemBehavior并没有真正深入地融入我的经验中。它并没有真正定义项目的“基本”特征;它只是以类似于物理学的方式调整其他行为。

UIKit Dynamics 还存在各种舍入错误,当您推到可以容纳的边缘时,这些错误会使项目以非理想的方式表现float。UIKit Dynamics 的目的是添加一点反弹UIView,而不是模拟真实的物理交互。

我并不是说 UIKit Dynamics 的做法是正确的。我发现使用起来很有挑战性,而且它经常以这样不明显的方式表现出来。如果您需要更类似于物理的东西,您可能想探索 SpriteKit。如果这个特定问题对您有影响,我建议您打开雷达(bugreport.apple.com)。

您可以通过更简单的实现自行尝试:

- (void)viewDidLoad {
  // Variables to play with
  CGFloat force = .25; // At .25, will bounce forever.
  CGFloat angle = 0;  // Play with small values to see effect.

  [super viewDidLoad];
  UIView *ball = [[UIView alloc] initWithFrame:CGRectMake(400, 300, 50, 50)];
  ball.backgroundColor = [UIColor greenColor];
  [self.view addSubview:ball];

  self.animator = [[UIDynamicAnimator alloc] initWithReferenceView: self.view];

  UICollisionBehavior *ballCollision = [[UICollisionBehavior alloc] initWithItems: @[ball]];
  [ballCollision setTranslatesReferenceBoundsIntoBoundary:YES];

  UIPushBehavior *smallPush = [[UIPushBehavior alloc] initWithItems:@[ball]
                                                               mode:UIPushBehaviorModeInstantaneous];
  [smallPush setAngle:GetRadiansForDegrees(angle)];
  [smallPush setMagnitude: force];

  UIDynamicItemBehavior *dynamicBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[ball]];
  __weak id weakBehavior = dynamicBehavior;
  [dynamicBehavior setElasticity: 1];
  [dynamicBehavior setResistance: 0.0];
  dynamicBehavior.action = ^{
    NSLog(@"linear:%@", NSStringFromCGPoint([weakBehavior linearVelocityForItem:ball]));
  };

  [self.animator addBehavior: ballCollision];
  [self.animator addBehavior: smallPush];
  [self.animator addBehavior: dynamicBehavior];
}
Run Code Online (Sandbox Code Playgroud)