我需要拖动一个形状节点,避免其他形状,如果它们击中,那么我希望不要跨越边界。因此,如果我有一个天花板,并且我将一个球拖到上面,我希望它击中天花板而不是穿过它。
我有一个“游戏”,我在 A 地板和天花板 (
SKShapeNode
) 形状节点之间创建一条路径。然后我有一个圆形的“球”SKShapeNode
来代表玩家。
地板和天花板是由相当复杂的
UIBezierPath
创建的
两堵墙分别是顶部和底部,并通过移动 x 位置来进行动画处理。
func update(_ currentTime: TimeInterval)
方法。
在墙壁和球上设置了碰撞检测和接触测试,这些在大多数情况下都运行良好。然而,在尝试了两种球拖动方法之后,我遇到了一些问题
改变位置 使用
.position
属性更新 TouchMoved 函数中的球运动
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let translation = CGVector(dx: location.x - previousLocation.x, dy: location.y - previousLocation.y)
var newPosition = ball.position
newPosition.x += translation.dx
newPosition.y += translation.dy
ball.position = newPosition
}
这在大多数情况下效果很好,拖动会随着手指的移动而变化。缓慢拖动时,它会尊重地板和天花板的边界 但是 - 如果我快速拖动,球将直接穿过天花板或地板
应用冲动 对球施加冲量
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first, let location = touchLocation else { return }
let newLocation = touch.location(in: self)
let scalingFactor: CGFloat = 0.1
let touchMovement = CGVector(dx: newLocation.x - location.x, dy: newLocation.y - location.y)
touchForce = CGVector(dx: touchMovement.dx * scalingFactor, dy: touchMovement.dy * scalingFactor)
touchLocation = newLocation
ball.physicsBody?.applyImpulse(touchForce!)
}
这尊重边界,但具有缓入/缓出效果,这不是这种体验所需的运动应用。它也不能真正代表发生的拖动量。
理想情况下我需要介于这两种方法之间的东西
附加代码供参考
吸顶/落地式物体
class Wall: SKShapeNode {
init(size: CGSize) {
super.init()
let bottomPath = UIBezierPath()
bottomPath.move(to: CGPoint(x: 0, y: -19.99))
bottomPath.addLine(to: CGPoint(x: 5723.5, y: -19.99))
bottomPath.addLine(to: CGPoint(x: 5723.5, y: 35.51))
bottomPath.addLine(to: CGPoint(x: 4915.5, y: 35.51))
bottomPath.addCurve(to: CGPoint(x: 4892.87, y: 44.88), controlPoint1: CGPoint(x: 4907.01, y: 35.51), controlPoint2: CGPoint(x: 4898.87, y: 38.88))
/// many more paths
bottomPath.close()
self.path = bottomPath.cgPath
strokeColor = UIColor.green
fillColor = UIColor.clear
lineWidth = 5
lineCap = .round
lineJoin = .round
zPosition = 0
name = "bottom"
physicsBody = SKPhysicsBody(edgeLoopFrom: self.path!)
physicsBody?.isDynamic = false
physicsBody?.affectedByGravity = false
physicsBody?.categoryBitMask = 1
physicsBody?.contactTestBitMask = 2
physicsBody?.collisionBitMask = 1
physicsBody?.restitution = 0
physicsBody?.usesPreciseCollisionDetection = true
physicsBody?.density = 100
physicsBody?.mass = 100
}
球
class Ball: SKShapeNode {
convenience init(radius: CGFloat) {
self.init(circleOfRadius: radius)
fillColor = .red
zPosition = 0
physicsBody = SKPhysicsBody(circleOfRadius: radius)
physicsBody?.affectedByGravity = false
physicsBody?.categoryBitMask = 2
physicsBody?.contactTestBitMask = 1
physicsBody?.collisionBitMask = 1
physicsBody?.restitution = 1
physicsBody?.usesPreciseCollisionDetection = true
}
}
基本上,游戏很简单 - 沿着一条路径拖动并计算需要多长时间以及撞到墙壁的次数。但事实证明,我对实现反射拖动速度以及尊重对象边界的最佳方法缺乏了解,这使得这一目标难以实现,因此非常感谢任何帮助
谢谢!
我能够通过添加检查来解决此问题,以确保建议的移动位置不与形状相交
func intersectsWalls(_ position: CGPoint) -> Bool {
if bottomShape.contains(position) {
return true
}
if topShape.contains(position) {
return true
}
return false
}