当前位置: 首页 > 面试题库 >

使用Swift + SpriteKit将节点移至手指

高豪
2023-03-14
问题内容

更新:
我已经解决了这个问题,并且找到了一个比提供答案更简单的方法。我的解决方案是使SPACESHIP的速度等于从手指触摸到的距离。为了加快运动速度,可以将该速度乘以一个常数。在这种情况下,我使用了16。我还摆脱了在touchesEnd事件中将lastTouch设置为nil的问题。这样,即使我松开手指,船仍会停下来。

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改变方向,开始和停止时应用这种平滑运动。

我正在尝试找出最佳方法。

到目前为止,我已经创建了节点并且它可以正确移动,但是存在一个问题:如果我按下屏幕并按住不放,船最终将越过我的手指并继续移动。这是因为仅当我移动手指时才会触发更改船方向的逻辑。因此,基本上,将我的手指移到船上以改变船的方向是可行的,但如果船越过我的静止指头,则不会改变方向

我需要SPACESHIP节点来识别它何时越过我的静止手指,并根据其与我手指的接近程度来更改其方向或停止。

以下是相关代码:

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

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部分: 当用户移动手指时,触发一个事件,检查该手指是否现在已移至船的另一侧。如果是这样,请更改船的方向。

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部分: 当用户从屏幕上松开手指时,我希望飞船停止移动。

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

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

    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)。它的工作方式就像您myShip在方向vector点上施加了推力一样。如果您计算的vector是从上次触摸位置到的x距离myShip,则它会加速,减速,改变方向等。与您描述的方式非常接近,因为它只会在正确的方向上进行少量推动每个update

基本上,您存储了最后一次触摸的位置,然后在update函数中计算了CGVectormyShip到的指向,lastTouch并将其作为对物理身体的冲动。

就像是:

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)
    }
}

您可能还想使用linearDamping和的angularDampingmyShip.physicsBody。它们将帮助确定myShip加速和减速的速度。

我最大化了1.0我的应用程序中的值:

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

如果myShip不能足够快地停止,您还可以尝试对update函数进行一些中断:

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)
    }
}


 类似资料:
  • 问题内容: 模拟器显示节点数,即有2个节点。但是为什么呢?由于只有一个var(ball)。有没有一种方法可以创建一个圆而不使它成为两个节点。 问题答案: 这是因为设置了SKShapeNode 。显然,设置或时,它们每个都需要附加的节点和附加的绘制过程。默认情况下,已经设置了strokeColor(一个节点,一个绘制过程),并且由于另外设置了,因此要渲染形状需要两个节点(和两个绘制过程)。 由于明显

  • 问题内容: 我试图弄清楚如何确定一个节点在屏幕上还是屏幕外可见。这仅仅是节点的true / false属性吗?谢谢。(使用swift spritekit) 问题答案: 您可以使用以下命令测试场景中是否有节点: 假设这是一个子类,例如。

  • Swift-SpriteKit-Analog-Stick 虚拟操纵杆 (Swift+Sprite Kit)。

  • 我在馆长2.12.0中使用动物园管理员。 通过使用watcher调用getChildren(我事先不知道完整的节点路径),我成功地监视了新节点,watcher再次提交任务以调用getChildren with watcher。现在我想看节点移除和仅移除。我打电话给守望者。但如果节点由于某种原因不存在,它实际上将是节点创建的观察者,在我的例子中,这是永远不会发生的。因此,我将留下越来越多的“鞭打”观

  • 问题内容: 我正在迅速进行一个项目,并且能够制作精灵。我试图在许多不同的地方制作精灵。作为测试,我将游戏场景中的代码替换为: 我不明白的是,这段代码在左下角产生了一个精灵。正如预期的那样,在y方向上仅显示了一半的精灵,但是x方向似乎完全偏离了。如果我尝试将x值设置为289以下的任何数字,它将不会出现。0,0点真的是289,0还是我缺少什么?我正在为iPhone 6编程,如果有所作为。 谢谢! 问题

  • 问题内容: 如图所示,该图是从y = 0行开始的,这里我想从 y = 50开始绘制一个图,如何在JFreeChart?中指定呢? 这是一些代码: 问题答案: 您可以使用 ValueAxis类的setLowerBound()方法指定Y轴的底部值。 使用您的示例: