1

Can someone suggest how I can vary the UIPushBehavior magnitude force by distance from source. To mirror the affect of the force of wind from a fan on another object. So the closer the object is to the fan the stronger the force.

if String(describing: identifier) == "fan1" {
                self.push = UIPushBehavior(items: [self.object], mode: .instantaneous)
                self.push.setAngle(.pi/4, magnitude: 1)
                self.animator.addBehavior(self.push)
                self.push.addItem(self.object)
                
            }

Guitarman4
  • 33
  • 5

1 Answers1

1

Use a UIFieldBehaviour to create a linear gravitational field in the direction of the fan. Then you can specify a falloff:

var forceField: UIFieldBehaviour!

// ...

forceField = UIFieldBehavior.linearGravityField(direction: CGVector(dx: 1, dy: -5))

// example values for a "fan" on the bottom left blowing mostly upwards:
forceField.position = CGPoint(x: view.bounds.minX, y: view.bounds.maxY)
forceField.region = UIRegion(radius: 3000)
forceField.minimumRadius = 100
forceField.falloff = 5
forceField.strength = 10
forceField.addItem(view1)
forceField.addItem(view2)
animator.addBehavior(forceField)

Have fun playing around with these values!

Adding collision, another gravity behaviour, and a dynamic item behaviour to two views, we get the following effect:

enter image description here

That feels like a fan on the bottom left to me!

You can also choose a radial gravitational field positioned at where the fan is, if your fan is in a corner and blows "radially", but note that you should use a negative value for strength in that case to say that the field repels rather than attracts.

Sweeper
  • 213,210
  • 22
  • 193
  • 313
  • Done. Been playing around with this and have a problem. If the fan is in the middle of the screen how can you only create a force in one direction and one side of the fan rather than a circular force? I can use CGSize instead of radius but this puts the fan in center of the rectangle. I can offset but this will affect the correct position of the force falloff. CGRect is not allowed for .region. Thanks – Guitarman4 Apr 16 '22 at 21:59
  • 1
    @Guitarman4 if I understand correctly, you should use a `CGSize` for the region, and set the `position` carefully as well. The position is the center of the rectangular region. – Sweeper Apr 16 '22 at 22:01
  • @Guitarman4 and `linearGravityField` ***is*** a force field in one direction, not a circular one. Did you misunderstand me and used `radialGravityField` instead? – Sweeper Apr 16 '22 at 22:04
  • Sorry yes. I did understand. But the linearGravityField has a circular region. So the linear effect will happen on both sides of fan and above and below. I think I found the way to sort by creating a boundary collision area in front of the fan and then implementing your code when a collision is detected in this area. Is this the best way. Seems to work but maybe you know a better way? – Guitarman4 Apr 16 '22 at 22:19
  • Sorry, I missed the fact you posted two comments simultaneously . I only read the second one! Yes, I have tried using CGSize for the region, however as I want the center of the fan to the be position of the force, the rectangular region will go to the left and right of the fan whereas I want it just to go to the right. If I offset the position to the right then the force will not be strongest closer to the fan? The strongest force will be half of the CGSize width to the right. Does that make sense? @Sweeper – Guitarman4 Apr 17 '22 at 17:22
  • @Guitarman4 I see the problem now. I don't know a better solution to this. :( – Sweeper Apr 17 '22 at 19:33
  • no problem. Do you have any idea about this question? https://stackoverflow.com/questions/71903781/swift-uikit-dynamics-add-collision-boundary-after-rotation-does-not-work-correc Not had any answers. Thought if anyone would, you you? @Sweeper – Guitarman4 Apr 20 '22 at 21:09