如何使用SpriteKit为图像添加字典值?

时间:2017-07-21 09:10:53

标签: swift3 sprite-kit

((编辑4:成功使卡片翻转。在节点上使用.contains并运行SKAction序列。我如何为卡片创建三种状态?元组听起来像一个有趣的主意。未翻转,翻转,翻转突出显示它加载了所有卡片(完成),我想要解开卡片(完成),然后再次点击它以突出显示它。第二次这样做时,它突出显示自己和顶部猜测词。然后两个字符串在底部的标签中连接,并激活了一个Next按钮(尚未构建)。成功匹配键[value] == A [B]然后得分+ = 1.越来越近了!))

((编辑3:使用拆分键和值更新didMove。现在可以将标题作为第一个键,我可以将第一个值放在左上角的卡上作为测试。进展。现在我只需要要么在触摸时将卡空白,要么找到翻转它的方法。如何完成触摸代码?触摸开始?))

((编辑2:现在从词典键值对的角度考虑它而不是单独的值。当值被分配给卡时,摆脱找到键的问题。现在玩标签卡使用SKLabelNode。需要翻卡,增值,比较密钥。))

((编辑:我在GameScene.swift中创建了所有代码的元素。该文件现在包含在这篇文章中。还更新了问题文本并删除了其他一些文本。)

我是SpriteKit和Swift 3的新手。有几百万个扬声器,没有很多世界语软件,所以我想为自己制作一个游戏来学习1000个世界语单词。 (未显示!)

enter image description here

我想让每张卡片翻转,以便从字典键/值中显示字样。

然后查看该单词是否与所选值的wordGuess标签匹配。

JSON也可能更好地将1000个单词分解为模块化部分,但我会在另一个时间跨越该桥。

// Code updated to EDIT 4
//  
//

import SpriteKit


class GameScene: SKScene {

    let guessLabel = SKLabelNode(fontNamed: "HelveticaNeue-UltraLight")
    let anotherLabel = SKLabelNode(fontNamed: "HelveticaNeue-UltraLight")

    var cardTopLeftLabel = SKLabelNode(fontNamed: "Arial-BoldMT")
    let cardTopLeft = SKSpriteNode(imageNamed: "Redcard")

    var cardTopRightLabel = SKLabelNode(fontNamed: "Arial-BoldMT")
    let cardTopRight = SKSpriteNode(imageNamed: "Redcard")

    var cardBottomLeftLabel = SKLabelNode(fontNamed: "Arial-BoldMT")
    let cardBottomLeft = SKSpriteNode(imageNamed: "Redcard")

    var cardBottomRightLabel = SKLabelNode(fontNamed: "Arial-BoldMT")
    let cardBottomRight = SKSpriteNode(imageNamed: "Redcard")

    var cardsDictionary: [String:String] = [
        "tree": "arbo",
        "forest": "arbaro",
        "spider": "araneo",
        "water": "akvo",
        "watermelon": "akvomelono",
        "school": "lerno",
        "year": "jaro",
        "grasshopper": "akrido",
        "lawn": "gazono",
        "friend": "amiko",
        "people": "homoj",
        "city": "urbo",
        "mayor": "urbestro",
        "movie": "filmo",
        "Monday": "lundo",
        "dog": "hundo"
    ]





    // not used yet
    func randomSequenceGenerator(min: Int, max: Int) -> () -> Int {
        var numbers: [Int] = []
        return {
            if numbers.count == 0 {
                numbers = Array(min ... max)
            }

            let index = Int(arc4random_uniform(UInt32(numbers.count)))
            return numbers.remove(at: index)
        }
    }



    func addLabel(spriteNode:SKSpriteNode, labelNode: SKLabelNode, cardValue: String, cardName: String) {
        labelNode.zPosition = 1
        labelNode.text = cardValue
        labelNode.name = cardName //"cardTopRightLabel"
        labelNode.fontSize = 40
        labelNode.fontColor = .black
        labelNode.position = CGPoint.init(x: cardTopLeft.size.width/4, y: 0.5)
        labelNode.isHidden = true
        spriteNode.addChild(labelNode)
    }


    override func didMove(to view: SKView) {

        if let words = self.userData?.value(forKey: "words")
        {
            print("word information contains \(words)")
        }

        // get all the card keys
        var cardKeys:[String] = []
        for (k,_) in cardsDictionary {
            cardKeys.append(k)
        }
        print("all keys are \(cardKeys)")

        // slice for four card keys
        var fourCardKeys = cardKeys[0...3]
        print("four keys are \(fourCardKeys)")

        // get keys for display
        var firstCardKey = fourCardKeys[0]
        var secondCardKey = fourCardKeys[1]
        var thirdCardKey = fourCardKeys[2]
        var fourthCardKey = fourCardKeys[3]
//        print("Card Keys are \(firstCardKey), \(secondCardKey), \(thirdCardKey), \(fourthCardKey)")

        // get the card values
        var cardsValue:[String] = []
        for (_,v) in cardsDictionary {
            cardsValue.append(v)
        }
        print(cardsValue)

        // slice for card values
        let fourCardValues = cardsValue[0...3]
        print(fourCardValues)

        // get values for display
        let firstCardValue  = fourCardValues[0]
        let secondCardValue = fourCardValues[1]
        let thirdCardValue = fourCardValues[2]
        let fourthCardValue = fourCardValues[3]
        print("Card Values are  \(firstCardValue), \(secondCardValue), \(thirdCardValue), \(fourthCardValue)")


        // put first card key into label
        guessLabel.zPosition = 1
        guessLabel.text = firstCardKey //cardKeys[0]
        guessLabel.name = "guessLabel"
        guessLabel.fontSize = 144;
        guessLabel.fontColor = .black
        //anotherLabel.position = CGPoint(x:frame.midX, y:frame.midY - 100.0)
        guessLabel.position = CGPoint(x:-2, y:233)
        addChild(guessLabel)


        anotherLabel.zPosition = 0
        anotherLabel.text = "Guess key here, values in cards"
        anotherLabel.name = "anotherLabel"
        anotherLabel.fontSize = 45;
        anotherLabel.fontColor = .blue
        //anotherLabel.position = CGPoint(x:frame.midX, y:frame.midY - 100.0)
        anotherLabel.position = CGPoint(x:-2, y:203)
        addChild(anotherLabel)


        ////////////////
        // top left card
        cardTopLeft.zPosition = 0
        cardTopLeft.size = CGSize(width: 300.0, height: 300.0)
        cardTopLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        cardTopLeft.position = CGPoint(x:-229, y:-57)
        addChild(cardTopLeft)

        addLabel(spriteNode: cardTopLeft,
                 labelNode: cardTopLeftLabel,
                 cardValue: firstCardValue,
                 cardName: "cardTopLeftLabel")


        /////////////////
        // top right card
        cardTopRight.zPosition = 1
        cardTopRight.size = CGSize(width: 300.0, height: 300.0)
        cardTopRight.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        cardTopRight.position = CGPoint(x:132, y:-57)
        addChild(cardTopRight)

        addLabel(spriteNode: cardTopRight,
                 labelNode: cardTopRightLabel,
                 cardValue: secondCardValue,
                 cardName: "cardTopRightLabel")

        ///////////////////
        // bottom left card
        cardBottomLeft.zPosition = 1
        cardBottomLeft.size = CGSize(width: 300.0, height: 300.0)
        cardBottomLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        cardBottomLeft.position = CGPoint(x:-225, y:-365)
        addChild(cardBottomLeft)

        addLabel(spriteNode: cardBottomLeft,
                 labelNode: cardBottomLeftLabel,
                 cardValue: thirdCardValue,
                 cardName: "cardBottomLeftLabel")

        ////////////////////
        // bottom right card
        cardBottomRight.zPosition = 1
        cardBottomRight.size = CGSize(width: 300.0, height: 300.0)
        cardBottomRight.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        cardBottomRight.position = CGPoint(x:132, y:-365)
        addChild(cardBottomRight)

        addLabel(spriteNode: cardBottomRight,
                 labelNode: cardBottomRightLabel,
                 cardValue: fourthCardValue,
                 cardName: "cardBottomRightLabel")

    }


    func touchDown(atPoint pos : CGPoint)
    {

    }

    func touchMoved(toPoint pos : CGPoint) {

    }

    func touchUp(atPoint pos : CGPoint) {


    }

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


        guard let touch = touches.first else {
            return
        }

        let touchLocation = touch.location(in: self)
        let touchedNode = self.atPoint(touchLocation)


        func flipCard (node: SKNode, label: SKLabelNode)
        {
            label.isHidden = true

            node.run(SKAction.sequence(
                [SKAction.scaleX(to: 0, duration: 0.2),
                 SKAction.scale(to: 1, duration: 0.0),
                 SKAction.setTexture(SKTexture(imageNamed: "Redcard-blank"))
                                 ]
            ))
            label.isHidden = false
        }

        func flipCardPause (node: SKNode, interval: Double)
        {
            node.run(SKAction.wait(forDuration: interval))
            print("paused for \(interval) seconds")
        }

        func flipCardBack (node: SKNode, label: SKLabelNode)
        {
            label.isHidden = true

            node.run(SKAction.sequence(
                [SKAction.scaleX(to: 1, duration: 0.2),
                 SKAction.setTexture(SKTexture(imageNamed: "Redcard"))
                 // SKAction.scale(to: 1, duration: 0.2)


                ]
            ))
        }


        if cardTopLeft.contains(touchLocation)
        {
            flipCard(node: cardTopLeft, label: cardTopLeftLabel)
            //flipCardPause(node: cardTopLeft, interval: 3)
            //flipCardBack(node: cardTopLeft, label: cardTopLeftLabel)
        }

        if cardTopRight.contains(touchLocation)
        {
            flipCard(node: cardTopRight, label: cardTopRightLabel)

        }

        if cardBottomLeft.contains(touchLocation)
        {
            flipCard(node: cardBottomLeft, label: cardBottomLeftLabel)
        }

        if cardBottomRight.contains(touchLocation)
        {
            flipCard(node: cardBottomRight, label: cardBottomRightLabel)
        }

        for t in touches { self.touchDown(atPoint: t.location(in: self)) }

    }

如何为卡片分配字典值?。编辑2:不使用值!我将从字典键的角度来做,每个卡都有一个键值对,然后只显示值。

// get all the card keys
var cardKeys:[String] = []
for (k,_) in cardsDictionary {
    cardKeys.append(k)
}

// slice for only four cards
var fourCardKeys = cardKeys[0...3]

// get 1st value for display
cardsDictionary[fourCardKeys[0]]

TouchDown上的SKLabelNode?我会试试看。还需要翻卡,这样字就不在图像上。最后将按下的卡的键与wordGuess键文本进行比较。越来越近了

编辑3:使用拆分键和值更新didMove。现在可以将标题作为第一把钥匙,我可以将左上角的第一个值作为测试。进展。现在我只需要在touchDown上清空卡片或找到翻转它的方法。

    cardTopLeft.zPosition = 0
    cardTopLeft.size = CGSize(width: 300.0, height: 300.0)
    cardTopLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    cardTopLeft.position = CGPoint(x:-229, y:-57)
    addChild(cardTopLeft)

    cardTopLeftLabel.zPosition = 1
    cardTopLeftLabel.text = fourCardValues[0]
    cardTopLeftLabel.name = "cardTopLeftLabel"
    cardTopLeftLabel.fontSize = 40
    cardTopLeftLabel.fontColor = .black
    cardTopLeftLabel.position = CGPoint.init(x: cardTopLeft.size.width/4, y: 0.5)
    cardTopLeft.addChild(cardTopLeftLabel)

enter image description here

编辑4:成功翻卡。在节点上使用.contains并运行SKAction序列。我如何为卡创建三种状态?元组听起来很有趣。 Unflipped,Flipped,Flipped-Highlighted。它加载所有卡片(完成),我想解开卡片(完成),然后再次点击它以突出显示它(帮助?)。在第二次这样做时,它会突出显示自己和最顶级的猜测词。然后将两个字符串连接在底部的标签中,并激活一个Next按钮(尚未构建)。成功匹配键[value] == A [B]然后得分+ = 1.越来越近了!它真的类似于一个匹配的游戏,但我正在添加一层额外的卡片翻转。

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

        guard let touch = touches.first else {
            return
        }

        let touchLocation = touch.location(in: self)
        let touchedNode = self.atPoint(touchLocation)


        func flipCard (node: SKNode, label: SKLabelNode)
        {
            label.isHidden = true

            node.run(SKAction.sequence(
                [SKAction.scaleX(to: 0, duration: 0.2),
                 SKAction.scale(to: 1, duration: 0.0),
                 SKAction.setTexture(SKTexture(imageNamed: "Redcard-blank"))
                                 ]
            ))
            label.isHidden = false
        }

enter image description here

2 个答案:

答案 0 :(得分:1)

所有SKNode都有一个可以写成名为userData的词典。它是一个可选的NSMutableDictionary,因此您将不得不创建它:

    cardTopLeft.zPosition = 1
    cardTopLeft.size = CGSize(width: 300.0, height: 300.0)
    cardTopLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    cardTopLeft.position = CGPoint(x:-229, y:-57)
    cardTopLeft.userData = ["word":"tree","value","arbo"]
    addChild(cardTopLeft)

使用:

    let word = cardTopLeft.userData["word"]
    let value = cardTopLeft.userData["value"]

为了更好地理解您的问题,我会使用SKLabelNode作为替代方案。

您可以执行的操作是使用您要附加的字词为卡片创建SKLabelNode,并将其标记为isHidden = true。当您准备好显示该单词时,您只需标记isHidden = false

    let value = SKLabelNode("arbo")
    value.isHidden = false      

    cardTopLeft.zPosition = 1
    cardTopLeft.size = CGSize(width: 300.0, height: 300.0)
    cardTopLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    cardTopLeft.position = CGPoint(x:-229, y:-57)
    cardTopLeft.addChild(value)
    addChild(cardTopLeft)


    //to reveal it
    if let label = cardTopLeft.children[0] as? SKLabelNode
    { 
        label.isHidden = false
    }

    //to use it
    if let label = cardTopLeft.children[0] as? SKLabelNode
    { 
        let value = label.text
        //compare value to dictionary of answers
    }

您可能希望为标签指定一个名称,这样您就不必使用子[0]了,但我会留下您希望找到的节点。

答案 1 :(得分:1)

就个人而言,我不想使用userData,我认为这不是一个可读的代码。

我有兴趣创建一个自定义的SKNode,如:

class Card: SKSpriteNode {
    var value....
    var dictionary
    etc
} 

另一种解决方案,你可以创建一个元组:

var cardsDictionary: [String:String] = [
        "vegetable":"legomo",
        "plant":"vegetalo",
        "actually":"efektive",
        "currently":"aktuale"
    ]
let cardTopLeft = (node:SKNode, value:Int, type:[String:String])

cardTopLeft.node = SKSpriteNode(imageNamed: "Redcard")
cardTopLeft.value = 1
cardTopLeft.type = cardsDictionary[0]