web-dev-qa-db-fra.com

SKSpriteNode - créer un nœud de coin arrondi?

Existe-t-il un moyen de créer un SKSpriteNode rond? J'essaie de créer un bloc de tuiles likesqaure avec des couleurs remplies SKSpriteNode:

SKSpriteNode *tile = [SKSpriteNode spriteNodeWithColor:[UIColor colorWithRed:0.0/255.0
                                                                           green:128.0/255.0
                                                                            blue:255.0/255.0
                                                                           alpha:1.0] size:CGSizeMake(30, 30)];

Comment puis-je le faire arrondi?

Merci!

28
Haris Hussain

Pour obtenir un nœud de coin arrondi, vous pouvez utiliser deux approches. Chacune d’elles nécessite l’utilisation de SKShapeNode.

La première méthode consiste à utiliser SKShapeNode et à définir son chemin comme un rectangle arrondi, comme ceci:

SKShapeNode* tile = [SKShapeNode node];
[tile setPath:CGPathCreateWithRoundedRect(CGRectMake(-15, -15, 30, 30), 4, 4, nil)];
tile.strokeColor = tile.fillColor = [UIColor colorWithRed:0.0/255.0
                                                    green:128.0/255.0
                                                     blue:255.0/255.0
                                                    alpha:1.0];

L'autre utilise le nœud Sprite, le nœud de recadrage et SKShapeNode avec un rectangle arrondi comme masque de nœuds de recadrage:

SKSpriteNode *tile = [SKSpriteNode spriteNodeWithColor:[UIColor   colorWithRed:0.0/255.0
                                                                           green:128.0/255.0
                                                                            blue:255.0/255.0
                                                                           alpha:1.0] size:CGSizeMake(30, 30)];
SKCropNode* cropNode = [SKCropNode node];
SKShapeNode* mask = [SKShapeNode node];
[mask setPath:CGPathCreateWithRoundedRect(CGRectMake(-15, -15, 30, 30), 4, 4, nil)];
[mask setFillColor:[SKColor whiteColor]];
[cropNode setMaskNode:mask];
[cropNode addChild:tile];

Si vos carreaux sont d'une couleur unie, je vous suggère de choisir la première approche.

46
Dobroćudni Tapir

Dans Swift 3, vous pouvez créer avec:

let tile = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 30, height: 30), cornerRadius: 10)
11
Zoltan Vinkler

J'espère que cela t'aides:

SKSpriteNode *make_rounded_rectangle(UIColor *color, CGSize size, float radius)
{
    UIGraphicsBeginImageContext(size);
    [color setFill];
    CGRect rect = CGRectMake(0, 0, size.width, size.height);
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
    [path fill];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    SKTexture *texture = [SKTexture textureWithImage:image];
    return [SKSpriteNode spriteNodeWithTexture:texture];
}
6
Krzysztof Gabis

C'est vraiment aussi simple que ça .......

class YourSprite: SKSpriteNode {

    func yourSetupFunction() {

          texture = SKTexture( image: UIImage(named: "cat")!.circleMasked! )

Il n'y a rien de plus.

Vous avez vraiment ne pouvez pas utiliser SKShapeNode.

C'est aussi simple que cela. Utiliser SKShapeNode est un succès fou, ce n’est pas la bonne solution, c’est inutilement difficile, et le but de SKShapeNode n’a aucun rapport avec ce problème.

 enter image description here

Regarde tous les minous!

Le code pour circleMasked est simple:

(De toute façon, tous les projets traitant d’images en auront besoin.)

extension UIImage {

    var isPortrait:  Bool    { return size.height > size.width }
    var isLandscape: Bool    { return size.width > size.height }
    var breadth:     CGFloat { return min(size.width, size.height) }
    var breadthSize: CGSize  { return CGSize(width: breadth, height: breadth) }
    var breadthRect: CGRect  { return CGRect(Origin: .zero, size: breadthSize) }

    var circleMasked: UIImage? {

        UIGraphicsBeginImageContextWithOptions(breadthSize, false, scale)
        defer { UIGraphicsEndImageContext() }

        guard let cgImage = cgImage?.cropping(to: CGRect(Origin:
            CGPoint(
                x: isLandscape ? floor((size.width - size.height) / 2) : 0,
                y: isPortrait  ? floor((size.height - size.width) / 2) : 0),
            size: breadthSize))
        else { return nil }

        UIBezierPath(ovalIn: breadthRect).addClip()
        UIImage(cgImage: cgImage, scale: 1, orientation: imageOrientation)
            .draw(in: breadthRect)
        return UIGraphicsGetImageFromCurrentImageContext()
    }

// classic 'circleMasked' stackoverflow fragment
// courtesy Leo Dabius /a/29047372/294884
}

C'est tout ce qu'on peut en dire.

3
Fattie

Ceci est fortement inspiré de la réponse acceptée, mais il utilise un moyen plus lisible de créer la variable SKShapeNode et corrige également la ligne de pixel gênante autour du rognage. Cela semble être un détail mineur, mais cela peut coûter quelques minutes à quelqu'un.

CGFloat cornerRadius = 15;
SKCropNode *cropNode = [SKCropNode node];
SKShapeNode *maskNode = [SKShapeNode shapeNodeWithRectOfSize:scoreNode.size cornerRadius:cornerRadius];
[maskNode setLineWidth:0.0];
[maskNode setFillColor:[UIColor whiteColor]];
[cropNode setMaskNode:maskNode];
[cropNode addChild:scoreNode];
3

Swift 4:

Une bonne solution pourrait être créée avant que vous ne deviez ajouter votre Sprite à son parent. Je vous ai présenté une petite extension qui pourrait être corrigée à votre guise:

extension SKSpriteNode {
    func addTo(parent:SKNode?, withRadius:CGFloat) {
        guard parent != nil else { return }
        guard  withRadius>0.0 else {
            parent!.addChild(self)
            return
        }
        let radiusShape = SKShapeNode.init(rect: CGRect.init(Origin: CGPoint.zero, size: size), cornerRadius: withRadius)
        radiusShape.position = CGPoint.zero
        radiusShape.lineWidth = 2.0
        radiusShape.fillColor = UIColor.red
        radiusShape.strokeColor = UIColor.red
        radiusShape.zPosition = 2
        radiusShape.position = CGPoint.zero
        let cropNode = SKCropNode()
        cropNode.position = self.position
        cropNode.zPosition = 3
        cropNode.addChild(self)
        cropNode.maskNode = radiusShape
        parent!.addChild(cropNode)
    }
}

Usage:

let rootNode = SKSpriteNode(color: .white, size: self.size)
rootNode.alpha = 1.0
rootNode.anchorPoint = CGPoint.zero
rootNode.position = CGPoint.zero
rootNode.zPosition = 1
rootNode.name = "rootNode"
rootNode.addTo(parent: self, withRadius: 40.0)
2

Voici un extrait de Swift 3 basé sur la deuxième solution de la réponse acceptée.

func createPlayerRoundedNode(){
    let tile = SKSpriteNode(color: .white, size: CGSize(width: 30, height: 30))
    tile.zPosition = 3
    tile.name = "tile node"
    let cropNode = SKCropNode()
    cropNode.zPosition = 2
    cropNode.name = "crop node"
    let mask = SKShapeNode(rect: CGRect(x: 0, y: 0, width: 30, height: 30), cornerRadius: 10)
    mask.fillColor = SKColor.darkGray
    mask.zPosition = 2
    mask.name = "mask node"
    cropNode.maskNode = mask
    self.addChild(cropNode)
    cropNode.addChild(tile)
}
0
JP Aquino

de la référence de classe:

"Un SKSpriteNode est un nœud qui dessine une image texturée, un carré coloré ou une image texturée mélangée à une couleur."

Il semble que le moyen le plus simple consiste à dessiner un bloc avec des angles arrondis, puis à utiliser l'une des méthodes de classe suivantes:

  • spriteNodeWithImageNamed:
  • spriteNodeWithTexture:
  • spriteNodeWithTexture: taille:
0
Thorsten