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

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

问题描述

更新:我已经解决了该问题,并找到了一个比提供答案更简单的方法.我的解决方案是使SPACESHIP的速度等于从我的手指触摸到的距离.为了更快地移动,可以将该速度乘以一个常数.在这种情况下,我使用了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轴.当用户在屏幕上的某个位置按下并按住时,我希望SPACESHIP能够移动到手指的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);

感谢您的阅读,并期待您的回复!

Thanks for reading, and looking forward to a response!

推荐答案

您可以使用以下代码为自己省很多麻烦: 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 上的 linearDamping angularDamping 值.它们将帮助确定 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天全站免登陆