Search code examples
swiftsprite-kitplatform

Swift SpriteKit Mario style rotating platform that stays horizontal


I am trying to create a mario style rotating platform that stays horizontal.

enter image description here

What I have done so far is create a simple class for this for testing purposes.

  class PlatformRound: SKNode {

    let platform: Platform

// MARK: - Init
init(barSize: CGSize, color: SKColor, pos: CGPoint) {

    /// Base
    let base = SKShapeNode(circleOfRadius: 6)
    //base.name = Platform.Name.normal
    base.fillColor = SKColor.darkGrayColor()
    base.strokeColor = base.fillColor
    base.position = pos
    let rotatingAction = SKAction.rotateByAngle(CGFloat(-M_PI), duration: 8)
    base.runAction(SKAction.repeatActionForever(rotatingAction))

    /// Bar
    let bar = Platform(size: barSize, color: color, pos: CGPointMake(0, 0 - (barSize.height / 2)), ofType: .Normal) 
    bar.zPosition = -200

    /// Platform that supposed to stay horizontal
    let platformSize = CGSizeMake(40, GameplayConfig.World.platformHeight)
    let platformPos = CGPointMake(0, 0 - (bar.size.height / 2))
    platform = Platform(size: platformSize, color: color, pos: platformPos, ofType: .Normal)

    super.init()

    addChild(base)
    base.addChild(bar)
    bar.addChild(platform)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
   }
}

I am creating a roundBase that I can rotate. I than create a bar that goes down from the base, that is added to the base node. Finally I create the platform that is supposed to stay horizontal at all times. I am using another Platform subclass to create the bar and platform, but they are not relevant to this question.

How can I make the platform stay horizontal. I tried the following which didnt work.

1) In update in my gameScene I constantly update the platform position or zRotation

 platformRound.platform.zRotation = ...

2) Create a zRotation property that gets set once the platform is added and than use that property to constantly update the zRotation.

3) Tried playing around with physicsJoints

Im sure there is a easy way that I am missing. I would appreciate any help.


Solution

  • This should work:

    class GameScene: SKScene{
    
        override func didMoveToView(view: SKView) {
    
            backgroundColor = .blackColor()
    
            let centerSprite = SKSpriteNode(color: .whiteColor(), size: CGSize(width: 10, height: 10))
    
            centerSprite.zPosition = 3
    
            let platform = SKSpriteNode(color: .orangeColor(), size: CGSize(width: 70, height: 20))
            platform.zPosition = 2
            platform.name = "platform"
    
            let container = SKNode()
            container.position = CGPoint(x: frame.midX, y: frame.midY)
    
            container.addChild(centerSprite) //Just for debugging
            container.addChild(platform)
            let radius = 120
    
            let chain = SKSpriteNode(color: .grayColor(), size: CGSize(width: 3, height: radius))
            chain.position = CGPoint(x: 0, y: radius/2)
            container.addChild(chain)
    
    
            platform.position = CGPoint(x: 0, y: radius)
    
            let rotatingAction = SKAction.rotateByAngle(CGFloat(-M_PI), duration: 8)
            container.runAction(SKAction.repeatActionForever(rotatingAction), withKey: "rotating")
    
            addChild(container)
    
        }
    
        override func didEvaluateActions() {
    
            self.enumerateChildNodesWithName("//platform") { node,stop in
    
                if let parent = node.parent{
                    node.zRotation = -parent.zRotation
                }
            }
        }
    }
    

    What I did, is that I have added platform node into container node and applied rotation to that container. Later on, in didEvaluateActions I've adjusted the rotation of platform (to have a negative value of its parent's zRotation). And that's it.

    Here is the result of what I am seeing:

    Rotating Platform

    The adjusting is needed, because otherwise the platform will end-up rotating along with its parent (notice how white, center sprite is being rotated along with container node).