如何使用自定义设计显示数字字符串?

时间:2016-09-30 04:45:39

标签: ios swift sprite-kit

我不想使用SKLabelNode因为我想要像渐变填充,阴影和自定义字体这样的特效,所以我创建了10个png图像,每个数字一个,我把它们添加为图像地图集。然后,在设置要显示的数字时,我为每个数字创建一个新的SKSpriteNode,其中包含来自地图集的数字纹理,并将其添加到没有纹理的父SKSpriteNode。我遇到的问题是我正在尝试将锚点设置为添加的所有节点的中间位置,但是在设置锚点时,它只设置相对于其自身帧的锚点,这不是添加子节点时更新。

我已经做了更多的工作,我不能让精灵集中。这是SKNode的子类,我正在这样做:Gist。当我创建此节点的实例时,将位置设置为0,0,设置currentValue,并将节点添加到游戏场景中,它看起来像this。它下面的框是SKShapeNode,其中包含数字节点的累积帧的帧和与数字节点相同的位置。游戏场景中的黑点是0,0。

有更好的方法吗?或者我该怎么做才能解决我的问题?

1 个答案:

答案 0 :(得分:2)

这是非常基本的UI内容,无论是游戏还是其他应用程序。 “说起来容易做起来难”更多的是一种心态。当谈到构建游戏的复杂性时,这就是简单的事情。

无论如何,关键是你需要知道如何获得你的数字宽度。对于任何文本,此问题都是相同的。因此,如果您了解如何执行此操作,您实际上可以制作自己的自定义字体。

下面是一些“代码”。它不会编译,我没有填写方法。其原因是多方面的。首先,您将通过实践学习获得更多好处。另外,我不知道你是如何做你的东西的,输入一个不属于我的项目的所有细节是很乏味的。

为此,我正在创建一个虚构的课程NumberLabel。这是一个组合SKNode /“自定义字体”类。实际上,我会将两者分开。但就目前而言,这是为了简单起见(尽管非常混乱作为副产品,我不会在单一类中构建它)。

class NumberLabel {
    // Root for all digits. This is also the "center"
    var root:SKNode = SKNode()

    private var underlyingValue:UInt = 0

    // These will hold each digit, for example 1234 will be [1, 2, 3, 4]
    private var digits: Array<UInt>

    var value: UInt {
        get {
           return underlyingValue
        }

        set {
            // There is no optimization checks (ie. if underlyingValue != newValue, you can do that later WHEN you get this working properly)
            underlyingValue = newValue

            // Release old nodes

            // You will build your other nodes here
            buildDigits()

            let width = getWidth()
            let x = -width / 2
            let y = ??? // Determine what your y should be based on your anchoring policy for sprites

            // I now know that -width/2
            for (digit in digits) {
                // This is all pseudo code
                var digitNode = createDigitNodeForDigit(digit, x, y)

                // You need to determine any trailing spacing, this would be also accounted for in getWidth
                x += getWidthOfDigit(digit)

                root.addChild(digitNode)
            }
        }
    }
    // Initialization omitted

    // Build the digits array
    // For laziness this uses underlyingValue. Safer would be to take it as an argument, but this is just example code
    private func buildDigits() {
        // Populate array based on the number value
        // For example 1234 will be the array [1, 2, 3, 4]
    }

    // Get's width of underlyingValue (use float if you want)
    // For laziness of writing this, it assumes BOTH underlyingValue and digits are properly assigned
    public func getWidth() -> UInt {
        // Get the width of the number
        // Traverse your digits array, determine the width based on number, and insert any kerning (if appropropiate)
    }

    // Use float if you want
    public func getHeight() -> UInt {
        // Return height. While width may not be uniform, for digits, there should be uniform height
    }
}

所以一些关键的要点:

  • 我没有从SKNode派生。你可以自由地这样做。我从来没有从SKNode那里得到像这样的课程。对于这些案例,我使用“has a”与“is a”方法。如果你想要子类,它不会改变太多。

  • getWidth是你的朋友。您正在构建的任何字体系统都需要将其作为角石。您可以通过它进行渲染,也可以在UI中进行放置。

  • 有些假设你知道你的宽度或者会得出它们。你需要它们

  • 假设您知道如何从数字到个别数字。您将使用此来填充digits

  • 这一切都是一个快速的例子,所以我的界面很草率。他们没有参数,而更清晰的界面

  • createDigitNodeForDigit是获取数字值(0-9)并创建SKSpriteNode或“数字节点”对象的方法

  • getWidthOfDigit是获取该数字宽度的方法。大概你可以只查询纹理的宽度。由您决定如何处理数字间距

  • 取决于您
  • 请注意,我们只在设置值时执行此操作。因此,每一帧都不会导致解构和构造节点。

我在这里回答了类似的问题:Add custom "number" images to SKLabelNode in as a Score in SpriteKit with Swift

所以也许还有一些其他信息供你吸收。