如何在 SKSpriteNodes 中切割随机孔 [英] How to cut random holes in SKSpriteNodes

查看:19
本文介绍了如何在 SKSpriteNodes 中切割随机孔的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

除了这里提出的问题:

如果您想要完全 reversed 孔,(负图像),您可以使用 SKCropNodehole.blendMode,例如:

替换这部分代码:

//-- 结束删除让holeTxt = SKView().texture(来自:cheeseCropNode,裁剪:sprite.frame)让孔 = SKSpriteNode.init(纹理:holeTxt)hole.position = CGPoint(x:-(self.frame.maxX)+(100*CGFloat(counter)),y:150)孔名 = 节点名self.addChild(洞)孔.附加(孔)计数器 += 1

这部分:

//-- 结束删除让holeTxt = SKView().texture(来自:cheeseCropNode,裁剪:sprite.frame)让孔 = SKSpriteNode.init(纹理:holeTxt)hole.position = CGPoint(x:-(self.frame.maxX)+(100*CGFloat(counter)),y:150)孔名 = 节点名让negativeCropHole = SKCropNode()让阴影 = SKShapeNode.init(矩形:hole.frame)shadow.fillColor = (node as!SKShapeNode).fillColorshadow.strokeColor = SKColor.clear孔.blendMode = .subtract负作物洞.addChild(阴影)负CropHole.maskNode = 阴影负作物洞.addChild(洞)负作物孔名称 = 孔名称self.addChild(negativeCropHole)holes.append(negativeCropHole)计数器 += 1

结果(另一个例子):

希望这些示例和此代码可以帮助您实现目标,我使用矩形制作蒙版,但您可以根据需要创建 CGPath.

Aside from the fact that the question asked here : Draw a hole in a rectangle with SpriteKit? has not satisfactorily been answered in its own right, the most significant difference between the two is that this question requires an absence of workarounds and specifically asks about reversing the functionality of SKCropNodes.

The primary concerns in this question cannot be addressed by the type of hacky ways the above question could be answered due to the randomness of the holes, the number of holes, and the variation in objects to which the holes are to be applied.

Hence the Swiss Cheese example:

Imagine a bunch of randomly sized rectangular SKSpriteNodes filled with various shades of cheese-like colours.

How to make Swiss Cheese out of each by cutting random circles out of each slice of cheese?

If SKCropNodes are the circles, they only leave circular pieces of cheese rather than cutting holes out of the pieces of cheese. Is there a way to invert the behaviour of SKCropNodes so they cut holes instead?

解决方案

In my total honesty, I'm not really sure to understand deeply what do you want to achieve, but I can try to answer to this question:

..cutting random circles out of each slice of cheese?

In this project I've try to re-build a typical rectangle (the piece of cheese) with random holes, then I've extract these holes and collect them to an array.

import SpriteKit
class GameScene: SKScene {
    struct Cheese
    {
        static let color1 = SKColor(red: 255/255, green: 241/255, blue: 173/255, alpha: 1)
        static let color2 = SKColor(red: 255/255, green: 212/255, blue: 0/255, alpha: 1)
        static let color3 = SKColor(red: 204/255, green: 170/255, blue: 0/255, alpha: 1)
        static let color4 = SKColor(red: 140/255, green: 116/255, blue: 0/255, alpha: 1)
    }
    let cheeseColor = [Cheese.color1,Cheese.color2,Cheese.color3,Cheese.color4]
    override func didMove(to view: SKView) {        
        let totHoles = randomNumber(range:4...8)
        let color = randomNumber(range:0...3)
        let cheeseCropNode = makeCheese(size: CGSize(width:400,height:200),color: cheeseColor[color], totHoles:totHoles)
        cheeseCropNode.position = CGPoint(x:0,y:-50)
        addChild(cheeseCropNode)
        // Start to collect and show holes
        var holes = [SKNode]()
        var counter = 1
        let _ = cheeseCropNode.enumerateChildNodes(withName: "//hole*", using:{ node, stop in
            // node is the hole
            let pos = self.convert(node.position, from: cheeseCropNode)
            let sprite = SKSpriteNode.init(color: .red, size: node.frame.size)
            sprite.position = pos

            //Remove these shapes, it's just to debug
            let shape = SKShapeNode.init(rect: sprite.frame)
            shape.strokeColor = .red
            self.addChild(shape)
            // -- end to remove

            let holeTxt = SKView().texture(from: cheeseCropNode, crop: sprite.frame)
            let hole = SKSpriteNode.init(texture: holeTxt)
            hole.position = CGPoint(x:-(self.frame.maxX)+(100*CGFloat(counter)),y:150)
            hole.name = node.name
            self.addChild(hole)
            holes.append(hole)
            counter += 1
        })
    }

    func randomNumber(range: ClosedRange<Int> = 1...6) -> Int {
        let min = range.lowerBound
        let max = range.upperBound
        return Int(arc4random_uniform(UInt32(1 + max - min))) + min
    }
    func randomCGFloat(min: CGFloat, max: CGFloat) -> CGFloat {
        return (CGFloat(arc4random()) / CGFloat(UINT32_MAX)) * (max - min) + min
    }
    func makeCheese(size:CGSize , color:SKColor, totHoles:Int)->SKCropNode {
        let cropNode = SKCropNode()
        let cheese = SKSpriteNode.init(color: color, size: size)
        for i in 0..<totHoles {
            let radius = randomCGFloat(min:20.0, max:50.0)
            let circle = SKShapeNode(circleOfRadius: radius)
            circle.position = CGPoint(x:randomCGFloat(min:-size.width/2, max:size.width/2),y:randomCGFloat(min:-size.height/2, max:size.height/2))
            circle.fillColor = color
            circle.blendMode = .subtract
            circle.name = "hole(i)"
            cheese.addChild(circle)
        }
        cropNode.addChild(cheese)
        cropNode.maskNode = cheese
        return cropNode
    }
}

Result:

P.S. Don't pay attention to red rectangles, it's just to show you the holes:

If you want the exactly reversed hole, (the negative image), you could use SKCropNode with the hole.blendMode, for example:

Substitute this part of the code:

// -- end to remove

                let holeTxt = SKView().texture(from: cheeseCropNode, crop: sprite.frame)
                let hole = SKSpriteNode.init(texture: holeTxt)
                hole.position = CGPoint(x:-(self.frame.maxX)+(100*CGFloat(counter)),y:150)
                hole.name = node.name
                self.addChild(hole)
                holes.append(hole)
                counter += 1

with this part:

// -- end to remove

            let holeTxt = SKView().texture(from: cheeseCropNode, crop: sprite.frame)
            let hole = SKSpriteNode.init(texture: holeTxt)
            hole.position = CGPoint(x:-(self.frame.maxX)+(100*CGFloat(counter)),y:150)
            hole.name = node.name

            let negativeCropHole = SKCropNode()
            let shadow = SKShapeNode.init(rect: hole.frame)
            shadow.fillColor = (node as! SKShapeNode).fillColor
            shadow.strokeColor = SKColor.clear
            hole.blendMode = .subtract
            negativeCropHole.addChild(shadow)
            negativeCropHole.maskNode = shadow
            negativeCropHole.addChild(hole)
            negativeCropHole.name = hole.name
            self.addChild(negativeCropHole)
            holes.append(negativeCropHole)
            counter += 1

Result (another example):

Hope these example and this code help you to obtain your objectives, I've used rectangles to make masks but your could create CGPaths if you need.

这篇关于如何在 SKSpriteNodes 中切割随机孔的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆