сделать SKPhysicsBody однонаправленным - PullRequest
3 голосов
/ 01 февраля 2020

У меня есть SKSpriteNode как шар, ему даны все свойства SKPhysicsBody, которые перемещаются во всех направлениях. Теперь я хочу сделать это unidirectional (двигаться только в том направлении, в котором он не двигался раньше, а не go обратно на путь, по которому он двигался) . В настоящее время у меня есть следующие мысли по этой проблеме,

  • сделать fieldBitMask, к пути, который повторяется по нему, и оттолкнуть шар, чтобы не go назад
  • применить какой-то force/ impulses на шаре из touchesBegan/ touchesMoved метода, чтобы не дать ему вернуться
  • что-то, что может быть обработано в update методе
  • спасатель от stackflowoverflow, который кодирует даже в выходные дни:)

Вспомогательные фрагменты кода для лучшего понимания,

//getting current touch position by using UIEvent methods
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else {return}
        let location = touch.location(in: self)
        lastTouchPoint = location
    }
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else {return}
        let location = touch.location(in: self)
        lastTouchPoint = location
    }
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        lastTouchPoint = nil
    }
    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        lastTouchPoint = nil
    }

//ball created
    func createPlayer(){
        player = SKSpriteNode(imageNamed: "player")
        player.position = CGPoint(x: 220, y: 420)
        player.zPosition = 1

    //physics for ball
    player.physicsBody = SKPhysicsBody(circleOfRadius: player.size.width / 2)
    player.physicsBody?.allowsRotation = false
    player.physicsBody?.linearDamping =  0.5


    player.physicsBody?.categoryBitMask = collisionTypes.player.rawValue
    player.physicsBody?.contactTestBitMask = collisionTypes.finish.rawValue
    player.physicsBody?.collisionBitMask = collisionTypes.wall.rawValue

    addChild(player)
}

//unwarp the optional property, calclulate the postion between player touch and current ball position
override func update(_ currentTime: TimeInterval) {
    guard isGameOver == false else { return }
    if let lastTouchPosition = lastTouchPoint {
        //this usually gives a large value (related to screen size of the device) so /100 to normalize it
        let diff = CGPoint(x: lastTouchPosition.x - player.position.x, y: lastTouchPosition.y - player.position.y)
        physicsWorld.gravity = CGVector(dx: diff.x/100, dy: diff.y/100)
    }
}

1 Ответ

0 голосов
/ 06 февраля 2020

Ну, это была комбинация маленьких хаков в touchesBegan/ touchesMoved и update fun c,

Сначала вам нужно выяснить, какое касание произошло, получить его имя (в моем случае я сделал узлы, которые имеет альфа 0, но становится видимым при перемещении по ним, то есть альфа 1). В touchesBegan, touchesMoved следующим образом

                        guard let touch = touches.first else {return}
                        let location = touch.location(in: self)
                        lastTouchPoint = location

                        let positionInScene = touch.location(in: self)
                        let touchedNode = self.atPoint(positionInScene)

                        if let name = touchedNode.name
                        {
                            if name == "vortex"
                            {
                                touching = false
                                self.view!.isUserInteractionEnabled = false
                                print("Touched on the interacted node")
                            }else{
                                self.view!.isUserInteractionEnabled = true
                                touching = true
                            }
                        }
                    }

Второй используйте BOOL touching для отслеживания взаимодействия с пользователем на экране, используя настройки распознавателя крана, как следует

func setupTapDetection() {
        let t = UITapGestureRecognizer(target: self, action: #selector(tapped(_:)))
        view?.addGestureRecognizer(t)
    }

@objc func tapped(_ tap: UITapGestureRecognizer) {
        touching = true
    }

Наконец, в update поставить чеки следующим образом,

        guard isGameOver == false else { return }
        self.view!.isUserInteractionEnabled = true

        if(touching ?? true){
            if let lastTouchPosition = lastTouchPoint {
                //this usually gives a large value (related to screen size of the device) so /100 to normalize it
                let diff = CGPoint(x: lastTouchPosition.x - player.position.x, y: lastTouchPosition.y - player.position.y)
                physicsWorld.gravity = CGVector(dx: diff.x/100, dy: diff.y/100)
            }
        }
    }
...