使用 Swift + SpriteKit 将节点移动到手指 [英] Move a node to finger using Swift + SpriteKit

查看:19
本文介绍了使用 Swift + SpriteKit 将节点移动到手指的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:我已经解决了这个问题,并想出了一个比提供的答案更简单的方法.我的解决方案是让太空船的速度等于它与我手指触摸的距离.为了更快地移动,您可以将此速度乘以一个常数.在这种情况下,我使用了 16.我还摆脱了在 touchesEnd 事件中将 lastTouch 设置为 nil.这样,即使我松开手指,船仍然会停下来.

UPDATE: I have solved the problem, and figured out a more simplified way to do this then the answer provided. My solution was to make the velocity of the SPACESHIP equal the distance it was from my finger touch. For faster movement, you can multiply this velocity by a constant. In this case, I used 16. I also got rid of setting lastTouch to nil in the touchesEnd event. That way, the ship will still stop even when I release my finger.

override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
    if let touch = lastTouch {
        myShip.physicsBody.velocity = CGVector(dx: (lastTouch!.x - myShip.position.x) * 16, dy: 0)
    }

}

=================================

===============================

我有一个 SPACESHIP 节点,其运动限制在 X 轴上.当用户按下并按住屏幕上的某处时,我希望太空船能够移动到手指的 x 坐标,并且在手指松开之前不会停止向手指移动.如果 SPACESHIP 靠近用户手指并且用户手指仍然按下,我希望它逐渐减速并停止.我还希望在太空船改变方向、启动和停止时应用这种平滑的运动.

I have a SPACESHIP node with movement restricted to the X-Axis. When the user PRESSES and HOLDS somewhere on the screen, I want the SPACESHIP to be able to move to the finger's x-coordinate, and not stop moving toward the finger until the finger is RELEASED. If the SPACESHIP is close to the users finger and the users finger is still pressed down, I want it to gradually slow down and stop. I also want this smooth motion to be applied when the SPACESHIP changes direction, starts, and stops.

我正在尝试找出最好的方法.

I am trying to figure out the best way to do this.

到目前为止,我已经创建了节点并且它移动正确,但是有一个问题:如果我在屏幕上按住并按住,船最终会越过我的手指并继续移动.这是因为只有在我移动手指时才会触发改变船方向的逻辑.所以本质上,将我的手指移过船来改变船的方向是可行的,但是如果船越过我静止的手指,它不会改变方向

So far, I have created the node and it moves correctly, but there is a problem: If I press on the screen and hold down, the ship will eventually cross over my finger and keep moving. This is because the logic to change direction of the ship is only triggered if I move my finger. So essentially, moving my finger over the ship to change the ships' direction works, but if the ship crosses over my still finger, it does't change direction

我需要 SPACESHIP 节点来识别它何时越过我静止的手指,并根据它与我手指的距离来改变它的方向或停止.

I need the SPACESHIP node to recognize when it has crossed over my still finger, and either change its direction or stop based on how close it is to my finger.

以下是相关代码:

第 1 部分:当用户按下时,找出触摸的来源并使用速度相应地移动 myShip (SPACESHIP)

Part 1: When the user presses down, find out where the touch is coming from and move myShip (SPACESHIP) accordingly using velocity

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    /* Called when a touch begins */
    let touch = touches.anyObject() as UITouch
    let touchLocation = touch.locationInNode(self)

    if (touchLocation.x < myShip.position.x) {
        myShip.xVelocity = -200
    } else {
        myShip.xVelocity = 200
    }
}

第 2 部分当用户移动他们的手指时,触发一个事件来检查手指现在是否已经移动到船的另一边.如果是这样,改变船的方向.

Part 2 When the user moves their finger, trigger an event that checks to see if the finger has now moved to the other side of the ship. If so, change direction of the ship.

override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {
    let touch = touches.anyObject() as UITouch
    let touchLocation = touch.locationInNode(self)

    //distanceToShip value will eventually be used to figure out when to stop the ship
    let xDist: CGFloat = (touchLocation.x - myShip.position.x)
    let yDist: CGFloat = (touchLocation.y - myShip.position.y)
    let distanceToShip: CGFloat = sqrt((xDist * xDist) + (yDist * yDist))

    if (myShip.position.x < touchLocation.x) && (shipLeft == false) {
        shipLeft = true
        myShip.xVelocity = 200
    }

    if (myShip.position.x > touchLocation.x) && (shipLeft == true) {
        shipLeft = false
        myShip.xVelocity = -200
    }

}

第 3 部分当用户从屏幕上松开手指时,我希望飞船停止移动.

Part 3 When the user releases their finger from the screen, I want the ship to stop moving.

override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {
    myShip.xVelocity = 0
}

第 4 部分更新改变船舶位置的事件

Part 4 Update event that changes the Ship's position

    override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
    let rate: CGFloat = 0.5; //Controls rate of motion. 1.0 instantaneous, 0.0 none.
    let relativeVelocity: CGVector = CGVector(dx:myShip.xVelocity - myShip.physicsBody.velocity.dx, dy:0);
    myShip.physicsBody.velocity = CGVector(dx:myShip.physicsBody.velocity.dx + relativeVelocity.dx*rate, dy:0);

感谢阅读,期待回复!

推荐答案

使用 myShip.physicsBody.applyImpluse(vector) 可以省去很多麻烦.它的工作原理就像你在 vector 点的方向上推动了 myShip.如果您将 vector 计算为从您上次触摸位置到 myShip 的 x 距离,那么它将加速、减速、改变方向等,非常接近您的方式重新描述,因为它会在每次 update 上向正确方向推动一点点.

You can save yourself a lot of trouble by using: myShip.physicsBody.applyImpluse(vector). It works by acting as if you gave myShip a push in the direction vector points. If you calculate vector as the x distance from your last touch location to myShip, then it'll accelerate, decelerate, change direction, etc. pretty close to the way you're describing because it'll be giving it little pushes in the right direction on each update.

基本上您存储最后一次触摸位置,然后在您的 update 函数中,计算从 myShip 指向 lastTouch 的 CGVector 并将其作为脉冲应用到你的物理体.

Basically you store the last touch location then, in your update function, you calculate the CGVector pointing from myShip to lastTouch and apply that as an impulse to your physics body.

类似:

var lastTouch: CGPoint? = nil

override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
    let touch = touches.anyObject() as UITouch
    let touchLocation = touch.locationInNode(self)
    lastTouch = touchLocation
}

override func touchesMoved(touches: NSSet!, withEvent event: UIEvent!) {
    let touch = touches.anyObject() as UITouch
    let touchLocation = touch.locationInNode(self)
    lastTouch = touchLocation
}

// Be sure to clear lastTouch when touches end so that the impulses stop being applies
override func touchesEnded(touches: NSSet!, withEvent event: UIEvent!) {
    lastTouch = nil
}

override func update(currentTime: CFTimeInterval) {
    // Only add an impulse if there's a lastTouch stored
    if let touch = lastTouch {
        let impulseVector = CGVector(touch.x - myShip.position.x, 0)
        // If myShip starts moving too fast or too slow, you can multiply impulseVector by a constant or clamp its range
        myShip.physicsBody.applyImpluse(impulseVector)
    }
}

您可能还想使用 myShip.physicsBody 上的 linearDampingangularDamping 值.它们将帮助确定 myShip 加速和减速的速度.

You'll also probably want to play with the linearDamping and angularDamping values on myShip.physicsBody. They'll help determine how fast myShip accelerates and decelerates.

我在我的应用中将 1.0 的值最大化:

I maxed out the values at 1.0 in my app:

myShip.physicsBody.linearDamping = 1.0
myShip.physicsBody.angularDamping = 1.0

如果 myShip 对您来说停止的速度不够快,您还可以尝试在 update 函数中应用一些中断:

If myShip doesn't stop fast enough for you, you can also try applying some breaking in your update function:

override func update(currentTime: CFTimeInterval) {
    // Only add an impulse if there's a lastTouch stored
    if let touch = lastTouch {
        let impulseVector = CGVector(touch.x - myShip.position.x, 0)
        // If myShip starts moving too fast or too slow, you can multiply impulseVector by a constant or clamp its range
        myShip.physicsBody.applyImpluse(impulseVector)
    } else if !myShip.physicsBody.resting {
        // Adjust the -0.5 constant accordingly
        let impulseVector = CGVector(myShip.physicsBody.velocity.dx * -0.5, 0)
        myShip.physicsBody.applyImpulse(impulseVector)
    }
}

这篇关于使用 Swift + SpriteKit 将节点移动到手指的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆