Доступ к количеству элементов в массиве и применение гравитационного поведения
У меня проблемы с падением ВСЕХ элементов массива с помощью модуля Gravity. Мне удалось заставить элемент LAST в массиве упасть, а затем оставшиеся элементы просто остаются в верхней части экрана во время тестирования. После отладки
Я использую UIKit и хочу полностью понять этот язык, прежде чем использовать другие различные движки, такие как SpriteKit и GameplayKit.
func mainGame()
{
let cars = ["car5", "car1", "car6", "car3", "car2", "car4"]
var random2 = Int(arc4random_uniform(UInt32(cars.count))) + 1
for i in 1...random2
{
let image = UIImage(named: cars[i - 1])
let carView = UIImageView(image: image!)
carView.frame = CGRect(x:i * 52, y:0 , width: 40, height: 50)
view.addSubview(carView)
dynamicAnimator = UIDynamicAnimator(referenceView: self.view)
gravityBehavior = UIDynamicItemBehavior(items: [carView]) //cars falling
dynamicAnimator.addBehavior(gravityBehavior)
collisionBehavior = UICollisionBehavior(items: [carView, mainCar]) //collide
collisionBehavior.translatesReferenceBoundsIntoBoundary = false
gravityBehavior.addLinearVelocity(CGPoint(x: 0, y: 200), for: carView)
dynamicAnimator.addBehavior(collisionBehavior)
}
collisionBehavior.addBoundary(withIdentifier: "Barrier" as NSCopying, for: UIBezierPath(rect: mainCar.frame))
collisionBehavior.removeAllBoundaries()
}
В этой игре последний автомобиль в массиве падает, и автомобиль основного игрока, которым я управляю, имеет поведение при столкновении, что является для меня большим шагом!
2 ответа
Вы создаете новый UIDynamicAnimator
с каждой итерацией цикла и назначая его dynamicAnimator
, Вот почему работает только последний элемент, потому что он является последним, назначенным этой переменной.
Чтобы исправить это, просто переместите эту строку в то место, которое будет вызываться только один раз.
dynamicAnimator = UIDynamicAnimator(referenceView: self.view)
viewDidLoad
это возможное место, которое должно работать.
UIKitDynamics отстал от большинства подобных фреймворков. Вы не оживляете объект. У вас есть аниматор и прикрепить к нему объекты. Как отмечает Clever Error, в этом случае вам нужен только один аниматор.
Ключевым моментом является то, что вы не привязываете гравитацию к автомобилям; Вы привязываете автомобили к поведению (гравитации), а затем к аниматору. Да, это странно и задом наперед.
Я не проверял это, но правильный код был бы ближе к этому:
func mainGame()
{
let cars = ["car5", "car1", "car6", "car3", "car2", "car4"]
var random2 = Int(arc4random_uniform(UInt32(cars.count))) + 1
var carViews: [UIImageView] = []
dynamicAnimator = UIDynamicAnimator(referenceView: self.view)
// First create all the views
for i in 1...random2
{
let image = UIImage(named: cars[i - 1])
let carView = UIImageView(image: image!)
carView.frame = CGRect(x:i * 52, y:0 , width: 40, height: 50)
view.addSubview(carView)
carViews.append(carView)
}
// and then attach those to behaviors:
gravityBehavior = UIGravityBehavior(items: carViews) //cars falling
dynamicAnimator.addBehavior(gravityBehavior)
collisionBehavior = UICollisionBehavior(items: carView + mainCar) //collide
collisionBehavior.translatesReferenceBoundsIntoBoundary = false
dynamicAnimator.addBehavior(collisionBehavior)
collisionBehavior.addBoundary(withIdentifier: "Barrier" as NSCopying, for: UIBezierPath(rect: mainCar.frame))
collisionBehavior.removeAllBoundaries()
// You don't need this; it's built into Gravity
// gravityBehavior.addLinearVelocity(CGPoint(x: 0, y: 200), for: carView)
}
Основным отличием UIKitDynamics от большинства анимационных сред является то, что анимированные объекты не знают, что они анимированные. Вы не можете спросить автомобиль, какое у него поведение, потому что у него нет. UIDynamicAnimator в основном представляет собой цикл синхронизации, который обновляет center
а также transform
его целей. В этом нет ничего особенного (в отличие от чего-то вроде Core Animation, в котором происходит много причудливых вещей). Имея небольшой опыт работы с iOS, вы, вероятно, могли бы реализовать всю UIKitDynamics вручную с единственной GCD-очередью (она, вероятно, даже не нуждается в этом, так как она запускает все на main....)