swift SKCropNode的宽度是否限制在5000以下?

gfttwv5a  于 2023-01-04  发布在  Swift
关注(0)|答案(1)|浏览(141)

我尝试使用宽度至少为5000像素的SKCropNode,但是如果maskNode属性width大于4100,就会发生奇怪的事情--前100 - 200个左右的像素不会被裁剪,裁剪范围大约只有4100个像素。
我用的是Mac Mini M1、文图拉13.0.1和Xcode 14.1(14B47b)
下面是工作代码:

import SwiftUI
import SpriteKit

struct ContentView: View {
    
    @State var spriteView : SpriteView!
    
    var body: some View {
        ScrollView(.horizontal, showsIndicators: true) {
            ZStack {
                if spriteView != nil {
                    spriteView
                }
                VStack {
                    Image(systemName: "globe")
                        .imageScale(.large)
                        .foregroundColor(.accentColor)
                    Text("Hello, world!")
                }
            }
            .padding()
            .onAppear {
                spriteView = .init(scene: myScene)
            }
            .frame(minWidth: 1000, minHeight: 500)
        }
    }
    
    var myScene : SKScene {
        let r = SKScene.init(size: .init(width: 2000, height: 500))
        r.backgroundColor = .yellow
        
        let maskRect = SKShapeNode.init(rect: .init(x: 0, y: 100, width: 5000, height: 300))
//        let maskRect = SKShapeNode.init(rect: .init(x: 0, y: 100, width: 4096+2, height: 300))
        maskRect.fillColor = .white
        maskRect.lineWidth = 0
        
        let redRect = SKShapeNode.init(rect: .init(origin: .zero, size: .init(width: 5000, height: 500)))
        redRect.fillColor = .red
        redRect.lineWidth = 0
        
        let path = CGMutablePath.init()
        path.move(to: .zero)
        path.addLine(to: .init(x: 1000, y: 500))

        let blueLine = SKShapeNode.init(path: path)
        blueLine.strokeColor = .blue
        blueLine.lineWidth = 12

        redRect.addChild(blueLine)
        
        let cropNode = SKCropNode.init()
        
        cropNode.maskNode = SKNode.init()
        cropNode.maskNode?.addChild(maskRect)
        cropNode.addChild(redRect)
        
        let blackRect = SKShapeNode.init(rect: .init(origin: .init(x: 0, y: 100), size: .init(width: 5000, height: 300)))
        blackRect.fillColor = .black
        blackRect.lineWidth = 0
        r.addChild(blackRect)
        r.addChild(cropNode)
        
        return r
    }
}

得到的结果是

如果我将宽度更改为4096,我会得到正确的结果,但左侧没有黑色矩形,即let maskRect = SKShapeNode.init(rect: .init(x: 0, y: 100, width: 4096, height: 300))

编辑:
按照建议使用SKSpriteNode对我来说产生了相同的结果:

let maskRect = SKSpriteNode.init(color: .black, size: .init(width: 5000, height: 300))
        maskRect.position.x = 0 + maskRect.size.width/2
        maskRect.position.y = 100 + maskRect.size.height/2
m0rkklqb

m0rkklqb1#

这似乎是SKShapeNode的问题。
解决方案:使用SKSpriteNode代替--对于你的遮罩和场景中的任何其他大元素。这里是一个插图(交换红色和绿色节点来查看小故障):

import SwiftUI
import SpriteKit

struct GameSceneCrop: View {
    @State private var scene = CropScene()
    
    var body: some View {
        SpriteView(scene: scene)
    }
}

class CropScene: SKScene {
    let skCameraNode = SKCameraNode()
    var WIDTH:CGFloat = 5000
    var HEIGHT:CGFloat = 1000
    let container = SKNode()

    override func didMove(to view: SKView) {
        scaleMode = .aspectFill // Set the scale mode to scale to fit the window
        backgroundColor = .yellow
        anchorPoint = CGPoint(x: 0.5, y: 0.5)

        //set up camera node
        camera = skCameraNode
        addChild(skCameraNode)
        skCameraNode.setScale( 10000 )
        
        addChild(container)
        rebuild()
    }
    
    func rebuild() {
        container.removeAllChildren()
        
        //a green SKSpriteNode
        let green = SKSpriteNode(color: .green, size: CGSize(width: WIDTH, height: HEIGHT))
        
        //a red SKShapeNode
        let red = SKShapeNode(rectOf: CGSize(width: WIDTH, height: HEIGHT))
        red.fillColor = .red
        
        //crop node
        let mask = SKSpriteNode(color: .black, size: red.frame.size) //using SKSpriteNode here instead of SKShapeNode
        let crop_node = SKCropNode()
        crop_node.maskNode = mask
        crop_node.addChild(green) //<--- replace green SKSpriteNode with red SKShapeNode to see clipping glitch
        container.addChild(crop_node)

        //draw outline around red block
        let reference_frame = SKShapeNode(rect: red.frame.insetBy(dx: -50, dy: -50))
        reference_frame.strokeColor = .black
        reference_frame.lineWidth = 50
        container.addChild(reference_frame)
    }
    
    override func update(_ currentTime: TimeInterval) {
        let x = 0.65 + (sin(currentTime*2) + 1) / 4
        WIDTH = 5000 * x
        rebuild()
    }
}

相关问题