拖动 SKShapeNode 时遵守其他 SKShapeNode 的边界

问题描述 投票:0回答:1

我需要拖动一个形状节点,避免其他形状,如果它们击中,那么我希望不要跨越边界。因此,如果我有一个天花板,并且我将一个球拖到上面,我希望它击中天花板而不是穿过它。

我有一个“游戏”,我在 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
    }
}

基本上,游戏很简单 - 沿着一条路径拖动并计算需要多长时间以及撞到墙壁的次数。但事实证明,我对实现反射拖动速度以及尊重对象边界的最佳方法缺乏了解,这使得这一目标难以实现,因此非常感谢任何帮助

谢谢!

swift sprite skshapenode
1个回答
0
投票

我能够通过添加检查来解决此问题,以确保建议的移动位置不与形状相交

func intersectsWalls(_ position: CGPoint) -> Bool {
 if bottomShape.contains(position) {
            return true
        }
        if topShape.contains(position) {
            return true
        }
        return false
    }
© www.soinside.com 2019 - 2024. All rights reserved.