Swift:使相同颜色的半透明重叠线在交叉时不会改变颜色

时间:2016-12-21 08:10:27

标签: swift sprite-kit skshapenode

目前我在屏幕上绘制了两条相同颜色的线,但两者的alpha值都小于1.当这些线相交时,交点与其他线的颜色不同。之前的帖子解决了同一个问题:swift drawing translucent lines, how to make overlapping parts not getting darker?但是,这篇文章没有得到充分的回答。我画出了这样的线条:

    var points = [CGPoint]()

    points = [CGPoint(x: -100, y: 100), CGPoint(x: 100, y: -100)]
    let FirstLine = SKShapeNode(points: &points, count: points.count)
    FirstLine.strokeColor = UIColor.init(red: 0.25, green: 0.62, blue: 0.0, alpha: 0.5)
    FirstLine.lineWidth = 30
    addChild(FirstLine)

    points = [CGPoint(x: 100, y: 100), CGPoint(x: -100, y: -100)]
    let SecondLine = SKShapeNode(points: &points, count: points.count)
    SecondLine.strokeColor = UIColor.init(red: 0.25, green: 0.62, blue: 0.0, alpha: 0.5)
    SecondLine.lineWidth = 30
    addChild(SecondLine)

以下是它的样子:

我明白为什么会发生这种情况,但有没有办法让交叉点看起来一样,所以看起来好多了?

编辑:我决定实施@ Confused的答案。但是,现在的问题是纹理始终以屏幕中间为中心。这是一个例子:

红十字处于正确的位置,因为它将指定的点连接在一起。然而,一旦我将红十字作为纹理,它总是居中于屏幕的中间(绿色十字是红十字作为纹理)。我可以使用任何可以将纹理重新定位到正确位置的代码。注意:此代码不适用于此示例,我需要一个无论红叉如何都能正常工作的代码。位置。

针对同样问题的人的最终编辑

首先,设置如下所示:

var points = [CGPoint]()
let crossParent = SKNode()
addChild(crossParent)

请注意您必须为纹理创建父SKNode,否则屏幕上的所有内容都将成为纹理,而不仅仅是您想要的节点。然后,将该父节点添加到场景中。

之后,创建所需的线条(在本例中为绿叉):

//The first line of the green cross
points = [CGPoint(x: -300, y: 300), CGPoint(x: -100, y: 100)]
let FirstLine = SKShapeNode(points: &points, count: points.count)
FirstLine.strokeColor = UIColor.init(red: 0.25, green: 0.62, blue: 0.0, alpha: 1.0)
FirstLine.lineWidth = 30
crossParent.addChild(FirstLine)

记住 NOT 将您创建的第一行添加到场景中,而不是添加到您在开头创建的父SKNode。另外,为绘制的每一行设置alpha值为1.0。然后添加其他行:

//The second line of the green cross
points = [CGPoint(x: -100, y: 300), CGPoint(x: -300, y: 100)]
let SecondLine = SKShapeNode(points: &points, count: points.count)
SecondLine.strokeColor = UIColor.init(red: 0.25, green: 0.62, blue: 0.0, alpha: 1.0)
SecondLine.lineWidth = 30
FirstLine.addChild(SecondLine)

请注意,您必须将该行添加到第一行,而不是场景。如果您在添加第一行后添加多行,则将其添加到第一行,就像我在此处每次连续一样 你添加的行。

现在,创建如下纹理:

 let tex = view?.texture(from: FirstLine)
 let cross = SKSpriteNode(texture: tex, color: .clear, size: (tex?.size())!)
 cross.alpha = 0.5
 addChild(cross)

完成此操作之后,无论你调用十字架都将是你的纹理,你可以像我在这里所做的那样将alpha值更改为你喜欢的任何颜色并且图像不会有不同的颜色。记得然后将该纹理添加到场景中。

最后,您可能会注意到纹理与最初放置点的位置不在同一位置。你可以把它放回到这样的位置:

cross.position = CGPoint(x: (FirstLine.frame.midX), y: (FirstLine.frame.midY))

希望这有帮助:)感谢@Confused程序的纹理部分:D

4 个答案:

答案 0 :(得分:2)

这是一种技术。它不能解决您的问题,也不会直接回答您的问题。相反,它提供了一种获得所需结果的方法,但没有您实际想要的线条的灵活性和固有性质。

您可以使用任意数量的技术从任何数量的节点绘制的任何内容中创建纹理。

您可以通过将所有绘图元素附加到您有权访问的SKView空间中的单个节点,然后将绘制对象的“父”节点渲染为纹理来执行此操作(最简单的方法)。

这有什么帮助?

我很高兴你问:

您可以在100%的不透明度级别绘制所有内容,并将其渲染为纹理,然后将图形纹理放在您喜欢的位置,并将其不透明度降低到您喜欢的任何百分比,并获得均匀的效果结果。没有亮点,彼此重叠。

这是完成上述所有操作的代码:

   var points = [CGPoint]()

   points = [CGPoint(x: -100, y: 100), CGPoint(x: 100, y: -100)]
   let FirstLine = SKShapeNode(points: &points, count: points.count)
   FirstLine.strokeColor = UIColor.init(red: 0.25, green: 0.62, blue: 0.0, alpha: 1)
   FirstLine.lineWidth = 30
//      ^^ Note the FirstLine is not added to the Scene

   points = [CGPoint(x: 100, y: 100), CGPoint(x: -100, y: -100)]
   let SecondLine = SKShapeNode(points: &points, count: points.count)
   SecondLine.strokeColor = UIColor.init(red: 0.25, green: 0.62, blue: 0.0, alpha: 1)
   SecondLine.lineWidth = 30
   FirstLine.addChild(SecondLine)
// ^^ Note SecondLine being added to FirstLine, and that they both have alpha of 1

// Now the magic: use the view of the SKScene to render FirstLine and its child (SecondLine)
// They are rendered into a texture, named, imaginatively, "tex"

   let tex = view.texture(from: FirstLine)
   let cross = SKSpriteNode(texture: tex, color: .clear, size: (tex?.size())!)
       cross.alpha = 0.5

// ^^ The alpha of the above sprite is set to your original desire of 0.5
// And then added to the scene, with the desired result.
   addChild(cross)

这是结果:

enter image description here

答案 1 :(得分:1)

NO!不幸的是,我认为是答案。

有以下混合模式,其中没有一个提供您正在寻找的结果:

case alpha // Blends the source and destination colors by multiplying the source alpha value.

case add // Blends the source and destination colors by adding them up.

case subtract // Blends the source and destination colors by subtracting the source from the destination.

case multiply // Blends the source and destination colors by multiplying them.

case multiplyX2 // Blends the source and destination colors by multiplying them and doubling the result.

case screen // Blends the source and destination colors by multiplying one minus the source with the destination and adding the source.

case replace // Replaces the destination with the source (ignores alpha).

唯一可行的选项是自定义着色器,以某种方式确定它是否重叠。但我没有任何关键,甚至可以开始制作类似的东西,或者甚至是可能的。

答案 2 :(得分:1)

  1. 使笔触颜色完全不透明。
  2. 将您的路径节点添加到SKEffectNode
  3. 将效果节点的alpha设置为所需的值。
  4. 将效果节点放入主场景。
  5. 执行此操作时,您还可以将所有行放在一个形状节点中:

    let path = CGMutablePath()
    path.move(   to: CGPoint(x: -100, y:  100))
    path.addLine(to: CGPoint(x:  100, y: -100))
    path.move(   to: CGPoint(x:  100, y:  100))
    path.addLine(to: CGPoint(x: -100, y: -100))
    
    let shape = SKShapeNode(path: path)
    shape.strokeColor = UIColor(red: 0.25, green: 0.62, blue: 0.0, alpha: 1)
    shape.lineWidth = 30
    
    let effect = SKEffectNode()
    effect.addChild(shape)
    effect.alpha = 0.5
    addChild(effect)
    

答案 3 :(得分:1)

问题是你在颜色级别进行alpha混合,在节点级别进行alpha混合

var points = [CGPoint]()
var cross = SKEffectNode()
points = [CGPoint(x: -100, y: 100), CGPoint(x: 100, y: -100)]
let FirstLine = SKShapeNode(points: &points, count: points.count)
FirstLine.strokeColor = UIColor.init(red: 0.25, green: 0.62, blue: 0.0, alpha: 1)
FirstLine.lineWidth = 30
cross.addChild(FirstLine)

points = [CGPoint(x: 100, y: 100), CGPoint(x: -100, y: -100)]
let SecondLine = SKShapeNode(points: &points, count: points.count)
SecondLine.strokeColor = UIColor.init(red: 0.25, green: 0.62, blue: 0.0, alpha: 1)
SecondLine.lineWidth = 30
cross.addChild(SecondLine)
cross.alpha = 0.5
addChild(cross)