9

SpriteKit のメタボール エフェクトに取り組んでいます。バッファーの色範囲を圧縮するシェーダーを備えた SKEffectNode があります。このエフェクト ノードには、その子として 100 数の SKSpriteNode があります。エフェクトは数秒間うまく機能しますが、突然、数フレームの間にすべてのスプライトノードが画面から消え、ノード数が 100 奇数から 2 に減少します (残りの 2 つはエフェクトノードだと思います)。それ自体、およびボールを保持するコンテナを形成するエッジ チェーン?)

ボール スプライト ノードをシーンのルート ノードに直接追加すると、これは発生しません。数秒後に積極的にカリングされるように見えるのは、エフェクトノードの子になったときだけです。

興味深いことに (これは、フレーム レートが非常に低い場合にシミュレーターで確認できます)、SpriteNode は、現在画面に表示されている垂直方向 (画面の上部から下部) でカリングされるようです。

ビューのshowsPhysicsプロパティが true に設定されている場合、SKSpriteNode の物理ボディがまだ画面上にあり、転がっていることがわかります。しかし、それらの視覚的表現は消失し、ビューのノード数は枯渇しています。ドキュメントによると、showsNodeCount「シーンに表示される物理体を示しています」。そのため、ノードが表示されなくなったため、ノード数が減少しました。

これを引き起こしている可能性のあるもの、またはデバッグに使用できるツールを知っている人はいますか?

標準の SpriteKit iOS Swift 2.2 Xcode 7 テンプレートでは、GameScene ファイルを次のように置き換えます。

import SpriteKit

class GameScene: SKScene {

    override func didMoveToView(view: SKView) {
        // create walls to contain balls
        let box = SKPhysicsBody(edgeLoopFromRect: CGRect(x: 0, y: 0, width: 800, height: 800))
        let boxNode = SKNode()
        boxNode.physicsBody = box
        addChild(boxNode)

        let radius: CGFloat = 5

        let texture = createMetaballTexture(radius)

        let centre = CGPoint(x: frame.size.width / 2, y: frame.size.height / 2)
        let rows = 12
        let columns = 10

        let metaballs = SKEffectNode()
        let shaderString = [
            "void main()",
            "{",
            "vec4 c = texture2D(u_texture, v_tex_coord);",
            "gl_FragColor = smoothstep(0.3, 0.6, c); ",
            "}"].joinWithSeparator("\n")
        let map = SKShader(source: shaderString)

        metaballs.shader = map
        for i in 0...(rows * columns) {
            let ball = SKSpriteNode(texture: texture)
            let body = SKPhysicsBody(circleOfRadius: radius)
            body.friction = 0.1
            body.restitution = 0.8
            ball.physicsBody = body
            ball.position = CGPoint(x: centre.x + CGFloat(i % columns) * radius, y: centre.y + CGFloat(i / rows) * radius)
            ball.blendMode = .Add

            metaballs.addChild(ball) // change this to "addChild(ball)", and the nodes don't get culled

        }

        addChild(metaballs)
        physicsWorld.speed = 0.2
        backgroundColor = SKColor.darkGrayColor()

    }

    func createMetaballTexture(radius: CGFloat) -> SKTexture {
        let metaballScale: CGFloat = 8
        let ellipseOrigin = (metaballScale / 2) - 1.5
        UIGraphicsBeginImageContext(CGSize(width: radius * metaballScale, height: radius * metaballScale))
        let context = UIGraphicsGetCurrentContext()
        SKColor.whiteColor().setFill()

        CGContextFillEllipseInRect(context, CGRect(x: radius * ellipseOrigin, y: radius * ellipseOrigin, width: radius * 3, height: radius * 3))

        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return SKTexture(CGImage: blur(image!))
    }

}

func blur(image: UIImage) -> CGImage {
    let gaussianBlurFilter = CIFilter(name: "CIGaussianBlur")
    let inputImage = CIImage(CGImage: image.CGImage!)
    gaussianBlurFilter?.setValue(inputImage, forKey:kCIInputImageKey)
    gaussianBlurFilter?.setValue(5, forKey: kCIInputRadiusKey)
    let outputImage = gaussianBlurFilter?.outputImage
    let context = CIContext(options: nil)
    return context.createCGImage(outputImage!, fromRect: inputImage.extent)
}
4

0 に答える 0