【问题标题】:How to add dictionary values to images using SpriteKit?如何使用 SpriteKit 向图像添加字典值?
【发布时间】:2017-07-21 09:10:52
【问题描述】:

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

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

(( 编辑2:现在从字典键值对的角度考虑它,而不是单独的值。摆脱了在将值分配给卡片时找到键的问题。现在玩标记卡片用SKLabelNode。需要翻牌,加值,比较key。))

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

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

我想让每张卡片翻转以显示字典键/值中的一个单词 value

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

另外,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]]

所以SKLabelNode 在touchDown 上?我会试试看。还需要翻转卡片,所以图像上没有文字。最后将按下的卡片的键与 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)

编辑 4:成功翻转卡片。在节点上使用 .contains 并运行 SKAction 序列。我将如何为卡创建三个状态?元组听起来是个有趣的主意。未翻转、翻转、翻转-突出显示。它加载所有卡片(完成),我想取消翻转卡片(完成),然后再次点击它以突出显示它(帮助?)。在第二次这样做时,它会突出显示自己和最热门的猜测词。然后将两个字符串连接到底部的标签中,并激活“下一步”按钮(尚未构建)。成功匹配 key[value] == A[B] 然后 Score += 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
        }

【问题讨论】:

    标签: swift3 sprite-kit


    【解决方案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]
    

    【讨论】:

    • 我想我将使用 SwiftyJSON 将问题编辑为 JSON 文件,以便获得 .arrayValue 。元组也可能有助于像数组对一样跟踪顺序。
    • 对不起,这对我不起作用,因为 cardTopLeft 的附加属性用于设置位置、图像等
    • ????一旦你有了节点,你就可以修改他的适当性。 cardTopLeft.node.position = .....
    • 谢谢,我不知道。我再看看。我对这一切都不熟悉
    【解决方案2】:

    所有 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 作为替代方案。

    你可以做的是在卡片上创建SKLabelNodes,并将其标记为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
        }
    

    您可能希望为标签命名,这样您就不必使用 children[0],但我将让您自己决定如何查找节点。

    【讨论】:

    • 感谢您的评论。这很有趣,我将使用它来看看它是如何为每组 4 张卡片动态地应用于节点的。
    • 您的帖子对我很有帮助,我意识到我需要在每张卡上放置键和值对,然后只显示值。这样我就不需要像 userData 这样的数据结构了。我也将尝试使用 SKLabelNode。感谢您的帖子,它帮助我确定了前进的方向。
    • 您希望保持数据的模块化和包含性。通过仅执行未附加到节点的键值对,您将面临数据被破坏且不再存在的风险,这可能会使您的应用程序崩溃。这有点像拥有一个ID。当然你可以把它交给你妈妈拿着,但是当你妈妈丢失或毁坏它时会发生什么。或者当其他人需要查看您的身份证件时会发生什么,您会打电话给您的妈妈并告诉她把它带给您吗?最好随身携带身份证。
    • 这就是我们有钥匙链的原因。所以 cardKeys 会替我保管钥匙。然后我可以根据切片索引导出值并将其用于节点标签。晚饭后我试试;)
    • 什么意思?
    猜你喜欢
    • 2016-11-11
    • 2019-05-02
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 2015-02-24
    • 2015-08-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多