菜鸟教程小白 发表于 2022-12-13 02:34:25

ios - 使用移动触摸旋转 Sprite 节点


                                            <p><p>我是 Swift 和 SpriteKit 的新手,并且正在学习理解游戏“Fish & Trip”中的控制。 sprite 节点始终位于 View 的中心,它会随着您的触摸移动而旋转,无论您在哪里触摸和移动(按住)它都会相应地旋转。 </p>

<p>这里的难点在于它不同于我在图1和图2中提到的Pan Gesture和简单的触摸位置。</p>

<p> <a href="/image/N7W3d.png" rel="noreferrer noopener nofollow"><img src="/image/N7W3d.png" alt="enter image description here"/></a> </p>

<p>对于第一张图片,触摸位置由 atan2f 处理,然后发送到 SKAction.rotate 并完成,我可以让它工作。</p>

<p>对于第二张图片,我可以通过设置 UIPanGestureRecognizer 来获得它并且它可以工作,但是当您将手指围绕初始点 (touchesBegan) 移动时,您只能旋转节点。</p>

<p>我的问题是关于第三张图片,它与 Fish & Trip 游戏相同,您可以触摸屏幕上的任何位置,然后移动(按住)到任何位置,并且节点仍然会随着您的移动而旋转,您不会必须围绕初始点移动手指才能让节点旋转并且旋转平滑准确。 </p>

<p>我的代码如下,它不能很好地工作,并且有些抖动,我的问题是如何以更好的方式实现它?以及如何使旋转平滑? </p>

<p>有没有办法过滤 touchesMoved 函数中的 previousLocation ?我在使用这个属性时总是遇到抖动,我认为它报告得太快了。我使用 UIPanGestureRecoginzer 时没有遇到任何问题,它非常流畅,所以我想我一定是对 previousLocation 做错了。 </p>

<pre><code>func mtoRad(x: CGFloat, y: CGFloat) -&gt; CGFloat {

    let Radian3 = atan2f(Float(y), Float(x))

    return CGFloat(Radian3)
}

func moveplayer(radian: CGFloat){

    let rotateaction = SKAction.rotate(toAngle: radian, duration: 0.1, shortestUnitArc: true)

    thePlayer.run(rotateaction)
}

var touchpoint = CGPoint.zero
var R2 : CGFloat? = 0.0

override func touchesMoved(_ touches: Set&lt;UITouch&gt;, with event: UIEvent?) {

    for t in touches{

      let previousPointOfTouch = t.previousLocation(in: self)

      touchpoint = t.location(in: self)

      if touchpoint.x != previousPointOfTouch.x &amp;&amp; touchpoint.y != previousPointOfTouch.y {

            let delta_y = touchpoint.y - previousPointOfTouch.y
            let delta_x = touchpoint.x - previousPointOfTouch.x

            let R1 = mtoRad(x: delta_x, y: delta_y)

            if R2! != R1 {
                moveplayer(radiant: R1)
            }

            R2 = R1
      }            
    }
}
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>这不是一个答案(但 - 希望稍后发布/编辑它),但您可以通过更改 <code>movePlayer()</code> 的定义使您的代码更加“Swifty”来自:</p>

<pre><code>func moveplayer(radian: CGFloat)
</code></pre>

<p>到</p>

<pre><code>rotatePlayerTo(angle targetAngle: CGFloat) {
   let rotateaction = SKAction.rotate(toAngle: targetAngle, duration: 0.1, shortestUnitArc: true)
   thePlayer.run(rotateaction)
}
</code></pre>

<p>然后,调用它,而不是:</p>

<pre><code>moveplayer(radiant: R1)
</code></pre>

<p>使用</p>

<pre><code>rotatePlayerTo(angle: R1)
</code></pre>

<p>这更易读,因为它描述了你做得更好。</p>

<p>此外,您旋转到新角度的时间恒定为 0.1 秒 - 因此,如果玩家必须进一步旋转,它会旋转得更快。最好保持转速恒定(以弧度/秒计)。我们可以这样做:</p>

<p>添加以下属性:</p>

<pre><code>let playerRotationSpeed = CGFloat((2 *Double.pi) / 2.0) //Radian per second; 2 second for full rotation
</code></pre>

<p>将您的 <code>moveShip</code> 更改为:</p>

<pre><code>func rotatePlayerTo(angle targetAngle: CGFloat) {
    let angleToRotateBy = abs(targetAngle - thePlayer.zRotation)
    let rotationTime = TimeInterval(angleToRotateBy / shipRotationSpeed)
    let rotateAction = SKAction.rotate(toAngle: targetAngle, duration: rotationTime , shortestUnitArc: true)
    thePlayer.run(rotateAction)
}
</code></pre>

<p>这也可能有助于平滑旋转。</p></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 使用移动触摸旋转 Sprite 节点,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/46088188/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/46088188/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 使用移动触摸旋转 Sprite 节点