如何使我的关卡菜单垂直滚动?

时间:2017-03-28 14:40:28

标签: swift swift3 sprite-kit

我有以下级菜单(如下所示)。我想让它垂直滚动,导致总高度是屏幕的两倍(全滚动高度)。我怎样才能做到这一点?

enter image description here

以下是上图的代码:

class LevelMenu: SKScene {


let levelButtonSize = SKSpriteNode(imageNamed: "b1").size
let levelButton1: SKSpriteNode = SKSpriteNode(imageNamed: "b1")

let levelButton2: SKSpriteNode = SKSpriteNode(imageNamed: "b2")
let levelButton3: SKSpriteNode = SKSpriteNode(imageNamed: "b3")
let levelButton4: SKSpriteNode = SKSpriteNode(imageNamed: "b4")
let levelButton5: SKSpriteNode = SKSpriteNode(imageNamed: "b5")
let levelButton6: SKSpriteNode = SKSpriteNode(imageNamed: "b6")
let levelButton7: SKSpriteNode = SKSpriteNode(imageNamed: "b7")
let levelButton8: SKSpriteNode = SKSpriteNode(imageNamed: "b8")

let levelButton9: SKSpriteNode = SKSpriteNode(imageNamed: "b9")
let levelButton10: SKSpriteNode = SKSpriteNode(imageNamed: "b10")
let levelButton11: SKSpriteNode = SKSpriteNode(imageNamed: "b11")
let levelButton12: SKSpriteNode = SKSpriteNode(imageNamed: "b12")

override init(size: CGSize){
    super.init(size: size)
    let bg = SKSpriteNode(imageNamed: "bg")
    backgroundImage.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
    self.addChild(bg)

    let column1PosX = levelButtonSize.width*cDiff
    let column2PosX = levelButtonSize.width*cDiff + levelButtonSize.width*2.0
    let column3PosX = levelButtonSize.width*cDiff + levelButtonSize.width*4.0

    let row1PosY = self.frame.height - levelButtonSize.width*1.5
    let row2PosY = row1PosY - levelButtonSize.height - levelButtonSize.width*rDiff
    let row3PosY = row2PosY - levelButtonSize.height - levelButtonSize.width*rDiff
    let row4PosY = row3PosY - levelButtonSize.height - levelButtonSize.width*rDiff

    levelButton1.position = CGPoint(x: column1PosX, y:  row1PosY)
    levelButton1.zPosition = 10
    self.addChild(levelButton1)


    levelButton2.position = CGPoint(x: column2PosX, y:  row1PosY)
    self.addChild(levelButton2)

    levelButton3.position = CGPoint(x: column3PosX, y:  row1PosY)
    self.addChild(levelButton3)

    levelButton4.position = CGPoint(x: column1PosX, y: row2PosY)
    self.addChild(levelButton4)

    levelButton5.position = CGPoint(x: column2PosX, y: row2PosY)
    self.addChild(levelButton5)

    levelButton6.position = CGPoint(x: column3PosX, y: row2PosY)
    self.addChild(levelButton6)

    levelButton7.position = CGPoint(x: column1PosX, y: row3PosY)
    self.addChild(levelButton7)


    levelButton8.position = CGPoint(x: column2PosX, y: row3PosY)
    self.addChild(levelButton8)


    levelButton9.position = CGPoint(x: column3PosX, y: row3PosY)
    self.addChild(levelButton9)

    levelButton10.position = CGPoint(x: column1PosX, y: row4PosY)
    self.addChild(levelButton10)

    levelButton11.position = CGPoint(x: column2PosX, y: row4PosY)
    self.addChild(levelButton11)

    levelButton12.position = CGPoint(x: column3PosX, y: row4PosY)
    self.addChild(levelButton12)

}

更新

基于Ron Myschuk的解决方案,下面的代码显示了我能够实现的目标,而this link显示了我目前所遇到的问题的.gif,其中屏幕滚动过多的顶部菜单。

class LMScene: SKScene {

let levelButtonSize = SKSpriteNode(imageNamed: "b1").size
let levelButton1: SKSpriteNode = SKSpriteNode(imageNamed: "b1")

let levelButton2: SKSpriteNode = SKSpriteNode(imageNamed: "b2")
let levelButton3: SKSpriteNode = SKSpriteNode(imageNamed: "b3")
let levelButton4: SKSpriteNode = SKSpriteNode(imageNamed: "b4")
let levelButton5: SKSpriteNode = SKSpriteNode(imageNamed: "b5")
let levelButton6: SKSpriteNode = SKSpriteNode(imageNamed: "b6")
let levelButton7: SKSpriteNode = SKSpriteNode(imageNamed: "b7")
let levelButton8: SKSpriteNode = SKSpriteNode(imageNamed: "b8")

let levelButton9: SKSpriteNode = SKSpriteNode(imageNamed: "b9")
let levelButton10: SKSpriteNode = SKSpriteNode(imageNamed: "b10")
let levelButton11: SKSpriteNode = SKSpriteNode(imageNamed: "b11")
let levelButton12: SKSpriteNode = SKSpriteNode(imageNamed: "b12")

let levelButton13: SKSpriteNode = SKSpriteNode(imageNamed: "b13")
let levelButton14: SKSpriteNode = SKSpriteNode(imageNamed: "b14")
let levelButton15: SKSpriteNode = SKSpriteNode(imageNamed: "b15")
let levelButton16: SKSpriteNode = SKSpriteNode(imageNamed: "b16")
let levelButton17: SKSpriteNode = SKSpriteNode(imageNamed: "b17")
let levelButton18: SKSpriteNode = SKSpriteNode(imageNamed: "b18")


private var scrollCell = SKSpriteNode()

private var moveAmtX: CGFloat = 0
private var moveAmtY: CGFloat = 0
private let minimum_detect_distance: CGFloat = 30
private var initialPosition: CGPoint = CGPoint.zero
private var initialTouch: CGPoint = CGPoint.zero
private var resettingSlider = false

override init(size: CGSize){
    super.init(size: size)


    scrollCell = SKSpriteNode(color: .blue, size: CGSize(width: self.size.width, height: 2*self.size.height - self.frame.width*0.24734))
    scrollCell.position = CGPoint(x: 0, y: 0)
    scrollCell.anchorPoint = CGPoint.zero
    scrollCell.zPosition = 0
    self.addChild(scrollCell)

    let backgroundImage = SKSpriteNode(imageNamed: "bg")
    backgroundImage.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
    self.addChild(backgroundImage)

    let column1PosX = levelButtonSize.width/2 + self.frame.width*0.14855
    let column2PosX = 3*levelButtonSize.width/2 + 2*self.frame.width*0.14855
    let column3PosX = 5*levelButtonSize.width/2 + 3*self.frame.width*0.14855


    let row1PosY = self.frame.height - levelButtonSize.height/2 - self.frame.width*0.24734
    let row2PosY = row1PosY - levelButtonSize.height - self.frame.width*0.24734
    let row3PosY = row2PosY - levelButtonSize.height - self.frame.width*0.24734
    let row4PosY = row3PosY - levelButtonSize.height - self.frame.width*0.24734
    let row5PosY = row4PosY - levelButtonSize.height - self.frame.width*0.24734
    let row6PosY = row5PosY - levelButtonSize.height - self.frame.width*0.24734

    levelButton1.position = CGPoint(x: column1PosX, y:  row1PosY)
    levelButton1.zPosition = 10
    scrollCell.addChild(levelButton1)


    levelButton2.position = CGPoint(x: column2PosX, y:  row1PosY)
    levelButton2.zPosition = 10
    scrollCell.addChild(levelButton2)

    levelButton3.position = CGPoint(x: column3PosX, y:  row1PosY)
    levelButton3.zPosition = 10
    scrollCell.addChild(levelButton3)

    levelButton4.position = CGPoint(x: column1PosX, y: row2PosY)
    levelButton4.zPosition = 10
    scrollCell.addChild(levelButton4)

    levelButton5.position = CGPoint(x: column2PosX, y: row2PosY)
    levelButton5.zPosition = 10
    scrollCell.addChild(levelButton5)

    levelButton6.position = CGPoint(x: column3PosX, y: row2PosY)
    levelButton6.zPosition = 10
    scrollCell.addChild(levelButton6)

    levelButton7.position = CGPoint(x: column1PosX, y: row3PosY)
    levelButton7.zPosition = 10
    scrollCell.addChild(levelButton7)


    levelButton8.position = CGPoint(x: column2PosX, y: row3PosY)
    levelButton8.zPosition = 10
    scrollCell.addChild(levelButton8)

    levelButton9.position = CGPoint(x: column3PosX, y: row3PosY)
    levelButton9.zPosition = 10
    scrollCell.addChild(levelButton9)

    levelButton10.position = CGPoint(x: column1PosX, y: row4PosY)
    levelButton10.zPosition = 10
    scrollCell.addChild(levelButton10)

    levelButton11.position = CGPoint(x: column2PosX, y: row4PosY)
    levelButton11.zPosition = 10
    scrollCell.addChild(levelButton11)

    levelButton12.position = CGPoint(x: column3PosX, y: row4PosY)
    levelButton12.zPosition = 10
    scrollCell.addChild(levelButton12)

    levelButton13.position = CGPoint(x: column1PosX, y: row5PosY)
    levelButton13.zPosition = 10
    scrollCell.addChild(levelButton13)

    levelButton14.position = CGPoint(x: column2PosX, y: row5PosY)
    levelButton14.zPosition = 10
    scrollCell.addChild(levelButton14)

    levelButton15.position = CGPoint(x: column3PosX, y: row5PosY)
    levelButton15.zPosition = 10
    scrollCell.addChild(levelButton15)

    levelButton16.position = CGPoint(x: column1PosX, y: row6PosY)
    levelButton16.zPosition = 10
    scrollCell.addChild(levelButton16)

    levelButton17.position = CGPoint(x: column2PosX, y: row6PosY)
    levelButton17.zPosition = 10
    scrollCell.addChild(levelButton17)

    levelButton18.position = CGPoint(x: column3PosX, y: row6PosY)
    levelButton18.zPosition = 10
    scrollCell.addChild(levelButton18)

}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    if let touch = touches.first as UITouch! {

        if let touch = touches.first as UITouch! {

            self.scrollCell.removeAllActions()
            initialTouch = touch.location(in: self.scene!.view)
            moveAmtY = 0
            initialPosition = self.scrollCell.position
        }
    }

}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

    if let touch = touches.first as UITouch! {

        let movingPoint: CGPoint = touch.location(in: self.scene!.view)

        moveAmtY = movingPoint.y - initialTouch.y

        scrollCell.position = CGPoint(x: initialPosition.x, y: initialPosition.y - moveAmtY)
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

    checkForResettingSlider()
    yMoveActions(moveTo: -moveAmtY)
}

func checkForResettingSlider() {

    if resettingSlider { return }

    let scrollDif: CGFloat = (scrollCell.size.height - self.size.height) / 2.0

    if scrollCell.position.y > scrollDif {

        let move: SKAction = SKAction.moveTo(y: scrollDif, duration: 0.3)
        move.timingMode = .easeOut
        scrollCell.run(move, completion: { self.resettingSlider = false })
    }

    if scrollCell.position.y < -scrollDif {

        let move: SKAction = SKAction.moveTo(y: 0 - scrollDif, duration: 0.3)
        move.timingMode = .easeOut
        scrollCell.run(move, completion: { self.resettingSlider = false })
    }
}

func yMoveActions(moveTo: CGFloat) {

    let move: SKAction = SKAction.moveBy(x: 0, y: (moveTo * 1.5), duration: 0.3)
    move.timingMode = .easeOut

    self.scrollCell.run(move, completion: { self.checkForResettingSlider() })
}

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

}

1 个答案:

答案 0 :(得分:1)

以下是我用来垂直滚动的一些代码,我已根据您的菜单进行了调整。它并不完全符合您的所有物品,但它会让您在某个地方开始。它会告诉你如何自己解决这个问题。

  编辑:我已经更新了使用这些资金的代码。仍然以相同的方式声明您的按钮,但调用我的createMenu函数来实际创建菜单。它是循环的,因此如果您更改菜单项的数量,它会自动调整。你唯一需要注意的是;如果添加或删除按钮,则相应地更改createMenu顶部的数组。同时将填充变量调整为项目之间所需的垂直空间

func createMenu() {

    let buttons = [levelButton1, levelButton2, levelButton3, levelButton4, levelButton5, levelButton6, levelButton7, levelButton8, levelButton9, levelButton10, levelButton11, levelButton12, levelButton13, levelButton14, levelButton15, levelButton16, levelButton17, levelButton18]
    let padding: CGFloat = 400

    let numberOfRows = CGFloat(buttons.count / 3)

    scrollCell = SKSpriteNode(color: .blue, size: CGSize(width: 1024, height: levelButtonSize.height * numberOfRows + padding * numberOfRows))
    scrollCell.position = CGPoint(x: 0 - self.size.width / 4, y: 0 - (scrollCell.size.height - self.size.height / 2))
    scrollCell.anchorPoint = CGPoint.zero
    scrollCell.zPosition = 0
    self.addChild(scrollCell)

//        let backgroundImage = SKSpriteNode(imageNamed: "bg")
//        backgroundImage.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
//        self.addChild(backgroundImage)

    let column1PosX = scrollCell.size.width / 3 / 2
    let column2PosX = scrollCell.size.width / 2
    let column3PosX = scrollCell.size.width / 3 / 2 + scrollCell.size.width / 3 * 2
    var colCount = 0
    var rowCount = 0

    for button in buttons {

        var posX: CGFloat = column2PosX
        if colCount == 0 {
            posX =  column1PosX
        }
        else if colCount == 2 {
            posX =  column3PosX
            colCount = -1
        }

        let indexOffset = CGFloat(rowCount) * (levelButtonSize.height + padding)
        let posY = scrollCell.size.height - levelButtonSize.height / 2 - (indexOffset + padding / 2)
        button.position = CGPoint(x: posX, y: posY)
        button.setScale(0.5)
        button.zPosition = 10
        scrollCell.addChild(button)

        if colCount == -1 {
            rowCount += 1
        }
        colCount += 1
    }
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    if let touch = touches.first as UITouch! {

        self.scrollCell.removeAllActions()
        initialTouch = touch.location(in: self.scene!.view)
        moveAmtY = 0
        initialPosition = self.scrollCell.position
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

    if let touch = touches.first as UITouch! {

        let movingPoint: CGPoint = touch.location(in: self.scene!.view)

        moveAmtY = movingPoint.y - initialTouch.y

        scrollCell.position = CGPoint(x: initialPosition.x, y: initialPosition.y - moveAmtY)
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

    checkForResettingSlider()
    yMoveActions(moveTo: -moveAmtY)
}

func checkForResettingSlider() {

    let topPos: CGFloat = scrollCell.size.height - self.size.height / 2
    let bottomPos = 0 - (self.size.height / 2)

    if scrollCell.position.y > bottomPos {

        let move = SKAction.moveTo(y: bottomPos, duration: 0.3)
        move.timingMode = .easeOut
        scrollCell.run(move)
    }

    if scrollCell.position.y < -topPos {

        let move = SKAction.moveTo(y: -topPos, duration: 0.3)
        move.timingMode = .easeOut
        scrollCell.run(move)
    }
}

func yMoveActions(moveTo: CGFloat) {

    let move = SKAction.moveBy(x: 0, y: (moveTo * 1.5), duration: 0.3)
    move.timingMode = .easeOut

    self.scrollCell.run(move, completion: { self.checkForResettingSlider() })
}