Arrays 访问数组中的元素数并应用重力行为
我在使用重力模块使阵列的所有元素下落时遇到问题。我已经设法让数组中的最后一个元素落下,然后剩下的元素在测试期间只停留在屏幕的顶部。调试后 我正在使用UIKit,希望在使用其他各种引擎(如SpriteKit和GameplayKit)之前彻底理解这种语言Arrays 访问数组中的元素数并应用重力行为,arrays,swift,uigravitybehavior,Arrays,Swift,Uigravitybehavior,我在使用重力模块使阵列的所有元素下落时遇到问题。我已经设法让数组中的最后一个元素落下,然后剩下的元素在测试期间只停留在屏幕的顶部。调试后 我正在使用UIKit,希望在使用其他各种引擎(如SpriteKit和GameplayKit)之前彻底理解这种语言 func mainGame() { let cars = ["car5", "car1", "car6", "car3", "car2", "car4"] var random2 = Int(arc4random_unifo
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()
}
到目前为止,游戏中的最后一辆车掉了下来,我控制的主要玩家的车有碰撞行为,这对我来说是一个很大的进步 在循环的每次迭代中,您都要创建一个新的
UIDynamicAnimator
,并将其分配给dynamicAnimator
。这就是为什么只有最后一个元素起作用,因为它是分配给该变量的最后一个元素
要修复它,只需将此行移动到只调用一次的某个位置
dynamicAnimator = UIDynamicAnimator(referenceView: self.view)
viewDidLoad
是一个可能的工作场所。UIKitDynamics是大多数类似框架的倒退。不设置对象的动画。您有一个动画师并将对象附加到它。正如聪明的错误所指出的,在这种情况下,您只需要一个动画师
关键的一点是,你不重视汽车的重力;将汽车附加到行为(重力),然后将行为附加到动画师。是的,这很奇怪,而且很落后
我尚未对此进行测试,但正确的代码更接近于此:
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基本上是一个定时循环,用于更新其目标的
中心
和变换
。它真的没有什么特别之处(与核心动画相比,核心动画有很多特别之处)。只要有一点iOS经验,您就可以用一个GCD队列手动实现所有UIKitDynamics(它甚至可能不需要,因为它在main上运行所有东西……)感谢您的快速回复。即使使用循环外的建议行,th数组的最后一个元素也会落在其他元素保持静止的位置。还有其他建议吗?虽然自下而上是一个值得学习的目标,但UIKitDynamics(包括UIDynamicMator)与SpriteKit非常不同,不是一项基础技术。UIKitDynamics非常笨拙(坦率地说,它是向后设计的)。自最初推出以来,它没有得到太多的更新,没有被广泛使用,而且文档记录也很差。如果你想学习SpriteKit,我建议你直接跳到SpriteKit。也就是说,如果你想要一些非平凡的例子(包括重力),请看我在UIKitDynamics第一次问世时写了很多关于UIKitDynamics的文章。我不知道还有很多其他的资料。如果您对此感兴趣,请参阅(这就是示例代码的来源)。您好,我理解您的方法和逻辑,但我对由此产生的几个错误有疑问。当我试图将汽车连接到重力行为和碰撞行为时,它抛出。重力:无法将“UIGravityBehavior”类型的值分配给“UIDynamicEmbehavior!”类型和冲突:无法使用类型为“(items:[UIImageView],UIImageView!)的参数列表调用类型“UICollisionBehavior”的初始值设定项是的……我忘记了UIDynamicBehaviors和UIDynamicBehaviors之间的区别。看看这真的很接近你在这里所做的。所以上面的答案不是我应该遵循的格式?我看了dynamics git,但它看起来与我想要的设计相去甚远。重力部分位于“-(IBAction)重力”下,其中我的汽车是以数组生成的图像,而不是放在故事板上。汽车在随机时间从屏幕顶部掉落,并在整个游戏过程中继续重生。你需要跟踪某个属性中的重力行为(我认为你已经这样做了),并在汽车出现或消失时添加/移除汽车。或者,您可以使用推送行为而不是重力,但仍然可以在创建项目时将其添加到行为中,并在项目消失时将其从行为中移除。