【问题标题】:How to create realistic spinning wheel in SpriteKit如何在 SpriteKit 中创建逼真的旋转轮
【发布时间】:2017-12-16 22:02:05
【问题描述】:

我正在尝试通过SKAction 创建一个旋转的幸运轮动作。我有一个用作轮子的SKNode,这个SKNode 是一个分成四个四分之一的圆圈(每个四分之一有不同的颜色)。我还设置了一个 SKAction(重复 10 次),它围绕固定点(节点的中心)旋转 SKNode。问题是动作运行良好,但它突然停止并且没有减速 - 就像一个真正的轮子。我真的不知道如何设置这个动画,我的意思是在动作停止之前减慢旋转速度。 到目前为止,这是我的代码:

class GameScene: SKScene {

let colors = [SKColor.yellow, SKColor.red, SKColor.blue, SKColor.purple]


override func didMove(to view: SKView) {
    createWheel()

    let sq = CGRect(x: size.width/2, y: size.height/2, width: 300, height: 300)
    let sqx = SKShapeNode(rect: sq)
    sqx.lineWidth = 2
    sqx.fillColor = .clear
    sqx.setScale(1.0)
    addChild(sqx)
    }

func createWheel() {
    let path = UIBezierPath()
    path.move(to: CGPoint(x: 0, y: 0))
    path.addLine(to: CGPoint(x: 0, y: -200))
    path.addArc(withCenter: CGPoint.zero,radius: 200,startAngle: CGFloat(0.0), endAngle: CGFloat(3.0 * Double.pi / 2),clockwise: false)
    path.addLine(to: CGPoint(x: 200, y: 0))

    let obstacle = obstacleByDuplicatingPath(path, clockwise: true)
    obstacle.position = CGPoint(x: size.width/2, y: size.height/2)
    addChild(obstacle)

    let rotateAction = SKAction.rotate(byAngle: CGFloat((3.0 * CGFloat(Double.pi / 2)) - 90), duration: 0.5)
    //obstacle.run(SKAction.repeatForever(rotateAction))
    obstacle.run(SKAction.repeat(rotateAction, count: 10))


}

func obstacleByDuplicatingPath(_ path: UIBezierPath, clockwise: Bool) -> SKNode {
    let container = SKNode()

    var rotationFactor = CGFloat(Double.pi / 2)
    if !clockwise {
        rotationFactor *= -1
    }

    for i in 0...3 {
        let section = SKShapeNode(path: path.cgPath)
        section.fillColor = colors[i]
        section.strokeColor = colors[i]
        section.zRotation = rotationFactor * CGFloat(i);

        let origin = CGPoint(x: 0.0, y: 0.0)
        switch i {
        case 0:
            section.position = CGPoint(x: (origin.x + 10), y: (origin.y - 10))
        case 1:
            section.position = CGPoint(x: (origin.x + 10), y: (origin.y + 10))
        case 2:
            section.position = CGPoint(x: (origin.x - 10), y: (origin.y + 10))
        case 3:
            section.position = CGPoint(x: (origin.x - 10), y: (origin.y - 10))
        default:
            print("bolbol")

        }

        container.addChild(section)
    }
    return container
}

}

编辑: 我正在考虑它并尝试通过 SKAction 来实现,我设置了另一个动作,但这次我将它们的持续时间设置为长。首先它运行一个持续时间为 0.5 的动作,然后是 2 并在 4 结束时运行。我看起来很不错,但仍然不像我想要的那样平滑。 这是我的代码:

        let rotateAction = SKAction.rotate(byAngle: CGFloat(2.0 * CGFloat(M_PI)), duration: 0.5)
    let rotateAction2 = SKAction.rotate(byAngle: CGFloat(2.0 * CGFloat(M_PI)), duration: 2)
    let rotateAction3 = SKAction.rotate(byAngle: CGFloat(2.0 * CGFloat(M_PI)), duration: 4)
    let wait = SKAction.wait(forDuration: 5)
    let g1 = SKAction.repeat(rotateAction, count: 10)
    let group = SKAction.group([wait, g1, rotateAction2, rotateAction3])

你怎么看?有没有更好的办法??

编辑 2: 继续@Ali Beadle 的回答,我试图通过物理体来做,现在的问题是当我在屏幕上拖动手指时,SKShapeNode(形状)继续旋转并且永不停止。你能发现什么问题吗?

class GameScene: SKScene {
var start: CGPoint?
var end:CGPoint?
var startTime: TimeInterval?
let shape = SKShapeNode.init(rectOf: CGSize(width: 150, height: 150))

override func didMove(to view: SKView) {

    self.physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
    let sceneBody = SKPhysicsBody.init(edgeLoopFrom: self.frame)
    sceneBody.friction = 0
    self.physicsBody = sceneBody


    shape.fillColor = SKColor.red
    shape.position = CGPoint(x: self.size.width/2, y: self.size.height/2)
    shape.physicsBody = SKPhysicsBody.init(rectangleOf: CGSize(width: 50, height: 50))
    shape.physicsBody?.affectedByGravity = false
    shape.physicsBody?.isDynamic = true
    addChild(shape)
}


override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else {return}
    self.start = touch.location(in: self)
    self.startTime = touch.timestamp
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else {return}
    self.end = touch.location(in: self)
    var dx = ((self.end?.x)! - (self.start?.x)!)
    var dy = ((self.end?.y)! - (self.start?.y)!)

    let magnitude:CGFloat = sqrt(dx*dx+dy*dy)
    if(magnitude >= 25){
        let dt:CGFloat = CGFloat(touch.timestamp - self.startTime!)
        if dt > 0.1 {
            let speed = magnitude / dt
            dx = dx / magnitude
            dy = dy / magnitude
            print("dx: \(dx), dy: \(dy), speed: \(speed) ")

        }
    }
    let touchPosition = touch.location(in: self)
    if touchPosition.x < (self.frame.width / 2) {
        self.shape.physicsBody?.angularVelocity = 10
        self.shape.physicsBody?.applyAngularImpulse(-180)
    } else {
        self.shape.physicsBody?.angularVelocity = 10
        self.shape.physicsBody?.applyAngularImpulse(180)
    }
}}

【问题讨论】:

    标签: swift sprite-kit skaction sknode


    【解决方案1】:

    我在 Spritekit 中创建了一个开源奖纺轮,它使用物理来实现逼真的运动和挡板控制。它还允许用户拖动轮子旋转或通过推动轮子的中心产生随机旋转。

    https://github.com/hsilived/SpinWheel

    【讨论】:

    • 上帝保佑你
    【解决方案2】:

    您可以使用 SpriteKit 的内置物理模拟添加这样的逼真运动。这将允许你给你的轮子一个质量和摩擦力,然后用力来旋转它。然后它会现实地放慢速度。

    概要参见 Apple 文档中的 Simulating Physics

    要在游戏中使用物理,您需要:

    • 将物理实体附加到节点树中的节点并配置它们的物理属性。见SKPhysicsBody
    • 定义场景物理模拟的全局特征,例如重力。见SKPhysicsWorld
    • 在需要支持您的游戏玩法时,设置场景中物理实体的速度或对其施加力或脉冲。 ...

    最适合你的轮子的方法大概是把轮子pinned放到场景中,然后用applyAngularImpulse旋转。

    【讨论】:

    • 你能看到我的新编辑吗,我使用了 skphysicsbody 但我遇到了一个新问题...@Ali Beadle
    • @omerc a 不要同时使用角速度和角脉冲 - 快速推动它的冲动,或者让它不断旋转的速度。此外,为了让 SO 答案对其他人有用,最好单独提出新问题,而不是编辑旧问题。
    • 我只是删除了角速度,但它没有改变任何东西。你能解释一下吗? @阿里比德尔
    • 可能您需要调整冲量值、质量和摩擦力 - 可能此时,在零摩擦、默认质量和 180 冲量的大推动下,您只是太用力了。
    • 如何更改脉冲值?当我将其设置为 10 时,它并没有改变任何东西。 @阿里比德尔
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    • 1970-01-01
    相关资源
    最近更新 更多