【问题标题】:Why does SKShapeNode tear?为什么 SKShapeNode 会撕裂?
【发布时间】:2017-01-23 22:11:35
【问题描述】:

当用户沿着一条线进行跟踪时,SKShapeNode 路径是从线段(来自底层“瓦片”)构建的。实际路径是通过锁定用户之前拖过的行来构建的,并在距离最近的触摸点最近的行上找到最近的点,然后像这样构建路径:

var activatedPointPath: UIBezierPath {
    let activatedPointPath = UIBezierPath()

    // self.state.activatedPoints contains the end point
    // of each full line segment the user has traced through
    if let firstActivatedPoint = self.state.activatedPoints.first {
        activatedPointPath.move(to: firstActivatedPoint)
        for activatedPoint in self.state.activatedPoints {
            activatedPointPath.addLine(to: activatedPoint)
        }
        // self.state.endOfLine contains the last point the user
        // has touched, which may or may not be at the end of a line
        // segment
        if let lastPoint = self.state.endOfLine {
            activatedPointPath.addLine(to: lastPoint)
        }
    }

    return activatedPointPath
}

然后将其分配给 SKShapeNode:

self.lineNode.path = self.activatedPointPath.cgPath

但是,当用户在描线时,之前的线段在被绘制到屏幕时会闪烁,而三角形会丢失,如下所示:

      

上面的图片来自一个简单的 3x3 平铺网格,允许用户追踪一条简单的直线:

这是一个更复杂的例子,行从左下角开始,到右上角结束:

什么可能导致这些伪影?

编辑虽然我找到了解决此问题的方法,但我仍然欢迎任何解释为什么原始代码不起作用而新代码起作用。

【问题讨论】:

  • SKShapeNode 是一个糟糕的实现、半成品、WIP、围绕 CAShapeLayer(我认为)的包装器,它是顽固的、不可变的、不灵活的、无生命的,不值得你花时间。使用拉伸和倾斜的 SKSpriteNode 绘制这些线段。在为它们设置动画时,您也会获得更好的性能。 SKShapeNode 的最初目的是用作物理调试绘图工具,仅用于物理形状……。只有在 iOS 10 中,他们才能以高性能的方式绘制轮廓,前提是它没有被更改并像纹理一样处理。它可能会在 iOS 16 中完成。

标签: ios swift sprite-kit skshapenode


【解决方案1】:

我对这个问题的解决方法是更改​​ activatedPointPath 计算变量以将线段组合在一起,而不是一次性绘制线。

新代码如下所示:

var previousPoint = firstActivatedPoint
for activatedPoint in self.state.activatedPoints {
    let newSegment = UIBezierPath()
    newSegment.move(to: previousPoint)
    newSegment.addLine(to: activatedPoint)

    activatedPointPath.append(newSegment)

    previousPoint = activatedPoint
}
if let lastPoint = self.state.endOfLine {
    let newSegment = UIBezierPath()
    newSegment.move(to: previousPoint)
    newSegment.addLine(to: lastPoint)
    activatedPointPath.append(newSegment)
} else {
    print("No last point")
}

现在可以产生平滑的线条。

【讨论】:

  • ...虽然它有效,但效率极低。最后,我接受了 Confused 的建议,并用一堆 CALayers 将形状渲染为纹理。这具有原始的一次绘制长线的副作用,可以正确渲染。
猜你喜欢
  • 2019-08-20
  • 1970-01-01
  • 2011-04-04
  • 2012-06-15
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
  • 2019-07-20
  • 1970-01-01
相关资源
最近更新 更多