The movement of a physics body circle is too erratic for what I want to achieve. I would like to restrict it so it follows a certain path touching specific points (or a range of points) as shown in the image below. How can I set the physics properties to traverse a similar path?
物理体圈的运动对于我想要达到的目标来说太不稳定了。我想限制它,以便它遵循某个特定点(或一系列点)的路径,如下图所示。如何设置物理属性以遍历类似的路径?
2 个解决方案
#1
6
how to set physics properties for a circle so it follows given path
如何设置圆的物理属性,使其遵循给定的路径
So essentially you are looking to move a node to a particular point using real-time motion. I have an answer here showing how to do this, however given the number of up votes this question has received, I will provide a more detailed answer.
因此,基本上您希望使用实时运动将节点移动到特定点。我在这里有一个答案显示如何做到这一点,但是考虑到这个问题已经收到的票数,我将提供更详细的答案。
What the answer I linked to doesn't provide is traversing a path of points. So below I have provided a solution showing how this can be done below. It simply just moves to each point in the path, and each time the node reaches a point, we increment the index to move to the next point. I also added a few variables for travel speed, rate (to make the motion more smooth or static) and whether or not the node should repeat the path. You could further expand upon this solution to better meet the needs of your game. I would definitely consider subclassing a node and building this behavior into it so you can re-use this motion for multiple nodes.
我所链接的答案没有提供的是遍历点的路径。所以下面我提供了一个解决方案,展示了如何在下面完成。它只是移动到路径中的每个点,每次节点到达一个点时,我们递增索引以移动到下一个点。我还为行进速度,速率(使运动更平滑或静态)以及节点是否应重复路径添加了一些变量。您可以进一步扩展此解决方案,以更好地满足您的游戏需求。我肯定会考虑将节点子类化并将此行为构建到其中,以便您可以将此运动重用于多个节点。
One final note, you may notice the calculation for the impulse varies between my solution below and the answer I linked to above. This is because I am avoiding using angle calculation because they are very expensive. Instead I am calculating a normal so that the calculation is more computationally efficient.
最后一点,你可能会注意到冲动的计算在我的解决方案和我上面提到的答案之间有所不同。这是因为我避免使用角度计算,因为它们非常昂贵。相反,我正在计算法线,以便计算更有效。
One final note, my answer here explains the use of the rate factor to smooth the motion and leave room for motion distortions.
最后一点,我在这里的答案解释了使用速率因子来平滑运动并为运动扭曲留出空间。
import SpriteKitclass GameScene: SKScene { var node: SKShapeNode! //The node. let path: [CGPoint] = [CGPoint(x: 100, y: 100),CGPoint(x: 100, y: 300),CGPoint(x: 300, y: 300),CGPoint(x: 300, y: 100)] //The path of points to travel. let repeats: Bool = true //Whether to repeat the path. var pathIndex = 0 //The index of the current point to travel. let pointRadius: CGFloat = 10 //How close the node must be to reach the destination point. let travelSpeed: CGFloat = 200 //Speed the node will travel at. let rate: CGFloat = 0.5 //Motion smoothing. override func didMoveToView(view: SKView) { node = SKShapeNode(circleOfRadius: 10) node.physicsBody = SKPhysicsBody(circleOfRadius: 10) node.physicsBody!.affectedByGravity = false self.addChild(node) } final func didReachPoint() { //We reached a point! pathIndex++ if pathIndex >= path.count && repeats { pathIndex = 0 } } override func update(currentTime: NSTimeInterval) { if pathIndex >= 0 && pathIndexI did this pretty quickly so I apologize if there is a mistake. I don't have time now but I will add a gif showing the solution later.
我很快就这样做了,所以如果有错误我会道歉。我现在没有时间,但我会在后面添加一个显示解决方案的gif。
A note about collisions
关于碰撞的说明
To fix the erratic movement during a collision, after the 2 bodies collide set the "rate" property to 0 or preferably a very low number to reduce the travel velocity impulse which will give you more room for motion distortion. Then at some point in the future (maybe some time after the collision occurs or preferably when the body is moving slow again) set the rate back to its initial value. If you really want a nice effect, you can actually ramp up the rate value over time from 0 to the initial value to give yourself a smooth and gradual acceleration.
为了在碰撞过程中修复不稳定的运动,在2个物体发生碰撞后,将“速率”属性设置为0或最好是一个非常低的数字,以减少行进速度脉冲,这将为您提供更大的运动失真空间。然后在将来的某个时刻(可能在碰撞发生后的某个时间或者最好在身体再次缓慢移动时)将速率设置回其初始值。如果你真的想要一个很好的效果,你实际上可以随着时间的推移将速率值从0增加到初始值,以给自己一个平稳和渐进的加速。
#2
1
Quick implementation using followPath:duration:
使用followPath快速实现:duration:
override func didMoveToView(view: SKView) { self.backgroundColor = UIColor.blackColor() let xWidth: CGFloat = CGRectGetMaxX(self.frame) let yHeight: CGFloat = CGRectGetMaxY(self.frame) let ball = SKSpriteNode(color: UIColor.redColor(), size: CGSizeMake(50.0, 50.0)) let offset : CGFloat = ball.size.width / 2 // Moving path let path = CGPathCreateMutable() CGPathMoveToPoint(path, nil, offset, yHeight / 2) CGPathAddLineToPoint(path, nil, xWidth * 2 / 3, yHeight - offset) CGPathAddLineToPoint(path, nil, xWidth - offset, yHeight * 2 / 3) CGPathAddLineToPoint(path, nil, xWidth / 2, offset) CGPathAddLineToPoint(path, nil, offset, yHeight / 2) // Movement let moveByPath = SKAction.followPath(path, asOffset: false, orientToPath: false, duration: 4.0) let moveForever = SKAction.repeatActionForever(moveByPath) ball.runAction(moveForever) self.addChild(ball)}In GameViewController.swift, I changed the default GameScene.unarchiveFromFile method to let scene = GameScene(size: view.bounds.size) for creating the scene's size.
在GameViewController.swift中,我更改了默认的GameScene.unarchiveFromFile方法,让scene = GameScene(size:view.bounds.size)来创建场景的大小。
Preview:
预习:
【文章原创作者:武汉网站制作公司 http://www.1234xp.com/wuhan.html 网络转载请说明出处】