【问题标题】:How can I set UIGestureRecognizer's Speed as the velocity for my Physicsbody in SpriteKit?如何在 SpriteKit 中将 UIGestureRecognizer 的速度设置为我的 Physicsbody 的速度?
【发布时间】:2017-11-13 07:00:23
【问题描述】:

我计算了 UIGestureRecognizer 的速度,我想用它作为 SpriteKit 中 Physicsbody 的速度。

我怎么能这样做,因为速度是在触摸开始和触摸结束方法中计算的,而我的 Physicsbody 被包裹在 swipeUp 和 swipeDown 等函数中,这些函数无法访问 Speed 变量?

这是我的代码:

class GameScene: SKScene, SKPhysicsContactDelegate, SKViewDelegate, UIGestureRecognizerDelegate, UIViewControllerTransitioningDelegate {

    var Kite = SKSpriteNode(imageNamed: "ASC_8025_large.jpg")




@objc let minusButton = SKSpriteNode(imageNamed: "minus.jpg")
@objc let plusButton = SKSpriteNode(imageNamed: "plus.png")

//override init(Kite: SKSpriteNode) {

















//For long Long press gesture to work
let longPressGestureRecPlus = UILongPressGestureRecognizer()

let longPressGestureRecMinus = UILongPressGestureRecognizer(target: self, action: #selector(longPressed(press:)))





//First we declare all of our Gestures...

//swipes

let swipeRightRec = UISwipeGestureRecognizer()
let swipeLeftRec = UISwipeGestureRecognizer()
let swipeUpRec = UISwipeGestureRecognizer()
let swipeDownRec = UISwipeGestureRecognizer()

//rotate

let rotateRec = UIRotationGestureRecognizer()

//taps

let tapRec = UITapGestureRecognizer()
let tapRec2 = UITapGestureRecognizer()








override func didMove(to view: SKView) {

    // Get label node from scene and store it for use later




































    Kite.size = CGSize(width: 40.0, height: 40.0)
    Kite.position = CGPoint(x: frame.midX, y: frame.midY)

    plusButton.size =  CGSize(width: 30.0, height: 30.0)
    plusButton.position = CGPoint(x: frame.midX, y: frame.minY + 20.0)

    plusButton.name = "plusButton"
    //plusButton.isUserInteractionEnabled = true

    addChild(Kite)
    addChild(plusButton)


    swipeRightRec.addTarget(self, action: #selector(GameScene.swipedRight) )
    swipeRightRec.direction = .right
    self.view!.addGestureRecognizer(swipeRightRec)

    swipeLeftRec.addTarget(self, action: #selector(GameScene.swipedLeft) )
    swipeLeftRec.direction = .left
    self.view!.addGestureRecognizer(swipeLeftRec)


    swipeUpRec.addTarget(self, action: #selector(GameScene.swipedUp) )
    swipeUpRec.direction = .up
    self.view!.addGestureRecognizer(swipeUpRec)

    swipeDownRec.addTarget(self, action: #selector(GameScene.swipedDown) )
    swipeDownRec.direction = .down
    self.view!.addGestureRecognizer(swipeDownRec)

    //notice the function this calls has (_:) after it because we are passing in info about the gesture itself (the sender)

    rotateRec.addTarget(self, action: #selector (GameScene.rotatedView (_:) ))
    self.view!.addGestureRecognizer(rotateRec)


    // again notice (_:), we'll need this to find out where the tap occurred.

    tapRec.addTarget(self, action:#selector(GameScene.tappedView(_:) ))
    tapRec.numberOfTouchesRequired = 1
    tapRec.numberOfTapsRequired = 1
    self.view!.addGestureRecognizer(tapRec)


    tapRec2.addTarget(self, action:#selector(GameScene.tappedView2(_:) ))
    tapRec2.numberOfTouchesRequired = 1
    tapRec2.numberOfTapsRequired = 2  //2 taps instead of 1 this time
    self.view!.addGestureRecognizer(tapRec2)


   longPressGestureRecPlus.addTarget(self, action: #selector(longPressed(press:)))
   longPressGestureRecPlus.minimumPressDuration = 2.0
   self.view?.addGestureRecognizer(longPressGestureRecPlus)

}

//the functions that get called when swiping...

@objc func swipedRight() {


    print("Right")

    Kite.physicsBody?.velocity = CGVector(dx: 60, dy: 60)

    //Tilts the Kite towards Right

    let tiltRight = SKAction.rotate(toAngle: -1.00, duration: 0.1)

    Kite.run(tiltRight)



}



@objc func swipedLeft() {


    Kite.physicsBody?.velocity = CGVector(dx: -60, dy: 60)

     //Tilts the Kite towards Right

    let tiltLeft = SKAction.rotate(toAngle: 1.00, duration: 0.1)

    Kite.run(tiltLeft)

    print("Left")
}





@objc func swipedUp() {

   Kite.physicsBody?.velocity = CGVector(dx: 60, dy: 60)

    //Straightens the Kite



    let straightens = SKAction.rotate(toAngle: 0.00, duration: 0.1)

    Kite.run(straightens)





    print("Up")
}

@objc func swipedDown() {

   Kite.physicsBody?.velocity = CGVector(dx: 0, dy: -60)


    print("Down")
}



// what gets called when there's a single tap...

//notice the sender is a parameter. This is why we added (_:) that part to the selector earlier

@objc func tappedView(_ sender:UITapGestureRecognizer) {

    let point:CGPoint = sender.location(in: self.view)








    print("Single tap")

    print(point)

}

// what gets called when there's a double tap...

//notice the sender is a parameter. This is why we added (_:) that part to the selector earlier

@objc func tappedView2(_ sender:UITapGestureRecognizer) {

    let point:CGPoint = sender.location(in: self.view)



    print("Double tap")

    print(point)

}

//what gets called when there's a rotation gesture
//notice the sender is a parameter. This is why we added (_:) that part to the selector earlier

@objc func rotatedView(_ sender:UIRotationGestureRecognizer) {

    if (sender.state == .began) {

        print("rotation began")

    }
    if (sender.state == .changed) {

        print("rotation changed")

        //you could easily make any sprite's rotation equal this amount like so...
        //thePlayer.zRotation = -sender.rotation

        //convert rotation to degrees...
        let rotateAmount = Measurement(value: Double(sender.rotation), unit: UnitAngle.radians).converted(to: .degrees).value

        print("\(rotateAmount) degreess" )



    }
    if (sender.state == .ended) {

        print("rotation ended")


    }


}

func removeAllGestures(){

    //if you need to remove all gesture recognizers with Swift you can do this....

    for gesture in (self.view?.gestureRecognizers)! {

        self.view?.removeGestureRecognizer(gesture)
    }

    //this is good to do before a SKScene transitions to another SKScene.


}
func removeAGesture()
{

    //To remove a single gesture you can use...

    self.view?.removeGestureRecognizer(swipeUpRec)
}


//Fix the gesture recognizing the plusButton

@objc func longPressed(press: UILongPressGestureRecognizer) {

    if press.state == .began {
        isUserInteractionEnabled = true



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



        plusButton.name = "plusButton"
       Kite.physicsBody?.velocity = CGVector(dx: 0, dy: 60.0*3)


        print("Pressed on the screen")


        if let name = touchedNode.name {

            if name == "plusButton" {

                print("LONG TAPPED")



            }

        }
    }


}


var start: CGPoint?
var startTime: TimeInterval?


 var taps = 0

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    print("Began")

    Kite.physicsBody = SKPhysicsBody(rectangleOf: Kite.size)

    Kite.physicsBody?.affectedByGravity = false

    //Kite.physicsBody?.velocity = CGVector(dx: 0, dy: 0)

    Kite.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 5))

    plusButton.name = "plusButton"
    plusButton.isUserInteractionEnabled = false


    //We figure how to interact with BUTTON in Spritekit
    let touch = touches.first
    let positionInScene = touch!.location(in: self)
    let touchedNode = self.atPoint(positionInScene)



    if let name = touchedNode.name {
        if name == "plusButton" {


            taps +=  1


            Kite.size = CGSize(width: 200, height: 200)

            print("tapped")
            print("Taps", taps)

    }
    }



    for touch in touches {
        let location:CGPoint = touch.location(in: self.view!)
        start = location
        startTime = touch.timestamp


    }










}




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



        //Calculating Speed of the Gestures
        for touch in touches {
            let location:CGPoint = touch.location(in: self.view!)
            var dx:CGFloat = location.x - start!.x;
            var dy:CGFloat = location.y - start!.y;
            var magnitude:CGFloat = sqrt(dx*dx+dy*dy)

            //Calculate Time
            var dt:CGFloat = CGFloat(touch.timestamp - startTime!)
            //Speed = Distance / Time
            var speed:CGFloat = magnitude / dt

            var speedX:CGFloat = dx/dt
            var speedY:CGFloat = dy/dt

            print("SpeedY", speedX)
            print("SpeedY", speedY)


            }





}

【问题讨论】:

    标签: ios iphone swift sprite-kit game-physics


    【解决方案1】:

    所以从像 dx 和 dy 这样的向量计算速度是

    let speed = sqrtf(Float(pow(dx!, 2) + pow(dy!, 2)))
    

    因此,如果要将速度作为速度应用于对象,则至少需要一个方向。

    let newDx = 0 // means in no x direction
    
    // next you can change the formula to your new dy to match the given speed
    
    let newDy = sqrtf(pow(speed, 2) - Float(pow(newDx, 2)))
    
    yourNode.physicsBody?.velocity = CGVector(dx: newDx, dy: CGFloat(newDy))
    

    【讨论】:

    • 这听起来像是一个解决方案,但我已经尝试过了。问题是我必须在 Swipe up 或 Swipe 函数中调用 Speed 变量。但是我无法访问那些函数中的 Speed 变量,因为 Speed 变量嵌套在 Touches Canceled 方法中!
    • 物理体就是风筝? Kite.physicsBody?.velocity 在 touchCanceld 函数中是不可能的?
    • 这对我的解决方案不起作用,因为我使用向上滑动和向下滑动功能来移动风筝,而这些功能在 TouchCancelled 方法中不起作用!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-12
    • 2014-04-07
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    相关资源
    最近更新 更多