以有限的旋转速度触摸旋转精灵 [英] Rotate sprite by touch with a limited rotation speed

查看:146
本文介绍了以有限的旋转速度触摸旋转精灵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正试图让我的spriteNode在手指触摸时旋转。

I'm trying to make my spriteNode rotate over finger touch.

到目前为止,我可以做到,但我想要的是我的节点有一个旋转速度。
所以我计算了角度的长度,然后设置一个不同的旋转时间(如果弧很长,需要时间......)。

So far I can do it, but what I want is that my node have a "rotation speed". So I calculate the length of the angle then set a different timing to rotate with it (if the arc is long, it will take time...).

这是我的代码:

override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
    _isTouched = true
    for touch in touches {
        let location:CGVector = touch.locationInNode(self) - miner.position

        miner.weaponRotation = location.angle() - CGFloat(M_PI_2)
    }
}

var wantedRotation: CGFloat {
    get { return _wantedRotation }
    set(rotation) {
        if rotation > CGFloat(M_PI) || rotation < -CGFloat(M_PI) {
            _wantedRotation = CGFloat(M_PI) + rotation % CGFloat(M_PI)
        }
        else {
            _wantedRotation = rotation
        }

        removeActionForKey("rotation")
        let arc: CGFloat = CGFloat(abs(_wantedRotation - zRotation))
        let shortestArc: CGFloat = min(arc, CGFloat(M_PI * 2.0) - arc)
        runAction(SKAction.rotateToAngle(_wantedRotation, duration: NSTimeInterval(shortestArc / CGFloat(M_PI) * rotationSpeed), shortestUnitArc: true), withKey: "rotation")
    }
}

主要问题是添加几个 SKAction 节点阻止了移动。

The main problem is that adding several SKAction to the node block the movement.

我想知道什么是解决方案?如果可能的话,使用SKAction,因为我想避免在每个帧上进行更新以计算移动(但如果它是唯一的解决方案......)

I would like to know what could be the solution ? If possible by using SKAction, since I would like to avoid doing an update on each frame to calculate the movement (but if it's the only solution...)

回答后的说明

当我收到答案时,我再次阅读了SpriteKit文档,发现这个清晰的注释

As I received answers, I read again the SpriteKit documentation and found this clear note :


何时不应使用行动

虽然行动效率很高,创建和执行它们需要付出代价。如果要在每个动画帧中更改节点的属性,并且需要在每个帧中重新计算这些更改,则最好直接对节点进行更改,而不是使用操作来执行此操作。有关在游戏中可以执行此操作的详细信息,请参阅高级场景处理。

Although actions are efficient, there is a cost to creating and executing them. If you are making changes to a node’s properties in every frame of animation and those changes need to be recomputed in each frame, you are better off making the changes to the node directly and not using actions to do so. For more information on where you might do this in your game, see Advanced Scene Processing.


推荐答案


我有一个炮塔......应该用手指定位,但不要立即花费
,需要时间转。

I have a turret which ... should target the finger position, but not immediately, by taking time to turn.

你无法通过SKActions逃脱这样的事情。你可以尝试,但它会非常混乱和低效。你需要实时运动控制这样的东西,因为你的炮塔的角速度需要根据触摸位置不断变化。

You won't be able to get away with SKActions for something like this. You can try but it will be really messy and inefficient. You need real-time motion control for something like this because the angular velocity of your turret needs to change constantly depending on the touch position.

所以我给你写了一个快速示例项目,展示了如何计算角速度。该项目还处理所有特殊情况,例如防止角度跳过目标旋转。

So I wrote you a quick example project showing how to calculate the angular velocity. The project handles all special cases as well, such as preventing the angle from jumping over your target rotation.

import SpriteKit

class GameScene: SKScene {
    let turret = SKSpriteNode(imageNamed: "Spaceship")
    let rotationSpeed: CGFloat = CGFloat(M_PI) //Speed turret rotates.
    let rotationOffset: CGFloat = -CGFloat(M_PI/2.0) //Controls which side of the sprite faces the touch point. I offset the angle by -90 degrees so that the top of my image faces the touch point.

    private var touchPosition: CGFloat = 0
    private var targetZRotation: CGFloat = 0

    override func didMoveToView(view: SKView) {
        turret.physicsBody = SKPhysicsBody(rectangleOfSize: turret.size)
        turret.physicsBody!.affectedByGravity = false
        turret.position = CGPoint(x: self.size.width/2.0, y: self.size.height/2.0)
        self.addChild(turret)
    }

    override func touchesMoved(touches: NSSet, withEvent event: UIEvent) {
        calculateAngleToTouch(touches.anyObject() as UITouch)
    }

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        calculateAngleToTouch(touches.anyObject() as UITouch)
    }

    func calculateAngleToTouch(touch: UITouch) {
        let position = touch.locationInNode(self)
        let angle = atan2(position.y-turret.position.y, position.x-turret.position.x)

        targetZRotation = angle + rotationOffset
    }

    override func update(currentTime: NSTimeInterval) {
        var angularDisplacement = targetZRotation - turret.zRotation
        if angularDisplacement > CGFloat(M_PI) {
            angularDisplacement = (angularDisplacement - CGFloat(M_PI)*2)
        } else if angularDisplacement < -CGFloat(M_PI) {
            angularDisplacement = (angularDisplacement + CGFloat(M_PI)*2)
        }

        if abs(angularDisplacement) > rotationSpeed*(1.0/60.0) {
            let angularVelocity = angularDisplacement < 0 ? -rotationSpeed : rotationSpeed
            turret.physicsBody!.angularVelocity = angularVelocity
        } else {
            turret.physicsBody!.angularVelocity = 0
            turret.zPosition = targetZRotation
        }

    }


}







这篇关于以有限的旋转速度触摸旋转精灵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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