swift - 如何防止使用触摸位置处理的 SKShapeNode 超出圆形路径?

标签 swift sprite-kit

我正在使用 SpriteKit for iOS 应用程序和 Swift。

我制作了一个小的 SKShapeNode("ball") 和一个大的圆圈路径("room"),我希望 SKShapeNode 留在圆圈内。

这是我的代码:


import SpriteKit
import GameplayKit

class GameScene: SKScene {

    var isFingerOnBall = false

    var ball: SKShapeNode!
    var room: SKShapeNode!

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        let touchLocation = touch!.location(in: self)

        if let body = physicsWorld.body(at: touchLocation) {
            if body.node!.name == "ball" {
                isFingerOnBall = true
            }
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        let touchLocation = touch!.location(in: self)

        if isFingerOnBall {
            ball.position = touchLocation
        }

    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        isFingerOnBall = false
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {

    }

    override func didMove(to view: SKView) {

        self.physicsWorld.contactDelegate = self
        self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
        self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)

        let radius:CGFloat = 60

        // BALL
        ball = SKShapeNode(circleOfRadius: radius)
        ball.name = "ball"
        ball.fillColor = .red
        ball.strokeColor = .clear
        ball.position = CGPoint(x: 0, y: 150)
        ball.physicsBody = SKPhysicsBody(circleOfRadius: radius)
        ball.physicsBody?.isDynamic = true
        scene?.addChild(ball)

        // ROOM
        room = SKShapeNode(circleOfRadius: radius * 5)
        room.name = "room"
        room.strokeColor = .white
        room.lineWidth = 10
        room.position = CGPoint(x: 0, y: 0)
        room.physicsBody = SKPhysicsBody(edgeLoopFrom: room.path!)
        room.physicsBody?.isDynamic = false
        scene?.addChild(room)

    }

}


我预计房间的 SKPhysicsBody 会限制球超出路径, OK image

但是当我的手指将球拖出圆圈(房间)时,它也熄灭了。 No good image

提前致谢。

最佳答案

有几种方法可以做到这一点,但我能想到的最简单的方法是用这个替换你的 didMove(to view: SKView) 方法:

    override func didMove(to view: SKView) {

    self.physicsWorld.contactDelegate = self
    self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
    self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)

    // BALL
    let ball = SKShapeNode(circleOfRadius: 10)
    ball.fillColor = .yellow
    ball.strokeColor = .yellow
    ball.lineWidth = 5
    ball.physicsBody = SKPhysicsBody(circleOfRadius: 10)
    ball.physicsBody?.isDynamic = true
    ball.physicsBody?.affectedByGravity = true
    ball.physicsBody?.categoryBitMask = 1
    ball.physicsBody?.collisionBitMask = 2
    ball.physicsBody?.contactTestBitMask = 0
    addChild(ball)


    // ROOM
    let room = SKShapeNode(circleOfRadius: 200)
    room.fillColor = .clear
    room.strokeColor = .red
    room.lineWidth = 5
    room.physicsBody = SKPhysicsBody(edgeLoopFrom: room.path!)
    room.physicsBody?.isDynamic = false
    room.physicsBody?.affectedByGravity = false
    room.physicsBody?.categoryBitMask = 2
    room.physicsBody?.collisionBitMask = 0
    room.physicsBody?.contactTestBitMask = 0
    addChild(room)

}

基本上您只需要设置 PhysicsBody CategoryBitMask 和 Collision Bit mask。也不要分配固体物理体,注意使用“edgeFromLoop”来制作房间物理体。

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first
    let touchLocation = touch!.location(in: self)

    if isFingerOnBall {
        let roomRadius: CGFloat = 200
        let hyp = sqrt(touchLocation.x * touchLocation.x + touchLocation.y * touchLocation.y)
        if abs(hyp) > roomRadius {
            ball.position = ball.position
        } else {
            ball.position = touchLocation
        }
    }

}

在这里,您将获得新接触点的斜边,并检查它是否大于房间的半径。如果是,则球的位置保持不变,如果不是,则照常更新球的位置。

希望这对您有所帮助,祝您玩得愉快

关于swift - 如何防止使用触摸位置处理的 SKShapeNode 超出圆形路径?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58681532/

相关文章:

regex - 如何捕获正则表达式模式周围的单词?

json - 创建 JSON 响应

swift - 如何将一个复杂的抽象类移植到swift?

ios - 2 行文本 UIButton

ios - SpriteKit 无限动画之间的空白帧

ios - 如何在 SpriteKit 中创建暂停标签?

ios - 如何全屏显示图像并通过类似于 Apple Photos 的滑动关闭

swift - 更改 ShowPhysics 轮廓颜色

audio - 如何在 WatchOS 3 中播放将在 watch 扬声器上播放的自定义声音

physics - 如何为重力设置不同的值?