Итак, я создаю приложение с функцией, в которой случайный круг случайным образом подпрыгивает по экрану, мне удалось добиться этого с помощью UIKitDynamics. Для справочного представления аниматора установлено значение self.view (вид для экрана). Я добавил UICollisionBehavior к аниматору и установил для свойства translatesReferenceBoundsIntoBoundary UICollisionBoundary значение true, чтобы круг подпрыгивал по экрану. скольжение вверх и вниз или влево и вправо по одному углу. После расследования я видел много сообщений о переполнении стека с той же проблемой, в которой говорилось, что это проблема в собственном физическом движке Swifts и многих других, связанных с тем, как они работают со значениями с плавающей запятой. Говорят, что решения обеспечивают столкновение с UICollisionBehaviorDelegate и добавляют отскок назад со слегка смещенным углом и / или скоростью. Я не могу понять, как реализовать решение с помощью UIKitDynamics.
Мои вопросы:
Как я могу ссылаться на границу эталонного представления в UICollisionDelegate с учетом поведения столкновения Функция принимает идентификатор границы или 2 разных элемента UIDynamics, и translatereferenceboundsintoboundary не является ни одним из них. Для добавления новой границы требуется либо 2 CGPoints, либо UIBezierPath, так что, возможно, создать UIBezierPath в форме экрана? Как мне это сделать?
После того, как вопрос первый будет решен, как я могу go смещать значение, чтобы оно никогда не застревало при движении вперед и назад в углу? Приведенные решения включают использование applyImpulse из SpriteKit, но я не могу найти аналогичный метод в UIKitDynamics. Ближайшие вещи - addAngularVelocity и addLinearVelocity под UIDynamicItemBehavior.
Вот мой код.
import UIKit
class ViewController: UIViewController, UICollisionBehaviorDelegate {
// Reference for circles button in code, initilization of animator for circle movement
@IBOutlet var selfie: UIButton!
var animator: UIDynamicAnimator?
// If the circle is touched trigger popup
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self.view)
if self.selfie.layer.presentation()!.hitTest(touchLocation) != nil {
performSegue(withIdentifier: "toMessageView", sender: self)
}
}
override func viewDidLoad() {
super.viewDidLoad()
animator = UIDynamicAnimator(referenceView: self.view)
// Initial push for circles
let push = UIPushBehavior(items: [selfie], mode: .instantaneous)
push.magnitude = 3
push.angle = CGFloat.random(in: 0...2*CGFloat.pi)
animator?.addBehavior(push)
// Add collision boundary around edges of the screen
let boundaries = UICollisionBehavior(items: [selfie])
boundaries.translatesReferenceBoundsIntoBoundary = true
// Add collision detection to circles, circles
boundaries.collisionDelegate = self
func collisionBehavior(_ behavior: UICollisionBehavior, endedContactFor item: UIDynamicItem, withBoundaryIdentifier identifier: NSCopying?) {
// 1. Figure out how to reference boundary for collision
// 2. Figure out how to add bounce back to slightly offsetted angle and speed
}
animator?.addBehavior(boundaries)
// Properties for circles
let circleProperties = UIDynamicItemBehavior(items: [selfie])
circleProperties.elasticity = 1
circleProperties.friction = 0
circleProperties.resistance = 0
circleProperties.density = 1
circleProperties.allowsRotation = false
animator?.addBehavior(circleProperties)
}
}