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

时间:2013-11-05 20:14:11

标签: ios uikit game-physics

目标是创建一个环境,在这种环境中,球的图像会在视图 非常缓慢 内无休止地反弹。我可以以高速度进行无尽的弹跳,但速度不是很慢。

以下是代码示例:

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];

我的高中物理课不能沉没,因为我无法弄清楚为什么这不起作用。摩擦是零,弹性是一,球应该永远弹跳,不应该吗?

2 个答案:

答案 0 :(得分:4)

请记住,UIKIt Dynamics不是物理学。苹果公司在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];
}

答案 1 :(得分:0)

这可能不适用于您的用例,但它适用于我的工作,我不希望我的项目在减速时彼此卡住

我添加了一个代表来检测碰撞发生的时间,并在碰撞的相反方向上对每个项目添加了一个小推动,这样物品就永远不会被卡在一起