Sudeep
Sudeep

Reputation: 806

How do I draw a filled circle using SpriteKit?

I am trying to draw a filled circle in SpriteKit.

I am currently drawing a circle as such.

node.physicsBody = SKPhysicsBody(circleOfRadius: radius)
node.fillColor = color
node.strokeColor = node.fillColor

I need this circle to be filled at a certain level based on a value between 0.0 and 1.0. How can I achieve this effect?

enter image description here

For example, the circle above is filled at a value of 0.5.

Upvotes: 3

Views: 1462

Answers (3)

juniperi
juniperi

Reputation: 3763

One way to achieve this is to use SKCropNode


First you need to create two circle textures, like these;

circlecirclefill


Then create custom SKSpriteNode:

import SpriteKit

class Circle : SKSpriteNode {
    var fillSprite : SKSpriteNode!
    var cropNode : SKCropNode!
    var maskNode : SKSpriteNode!

    override init(texture: SKTexture?, color: UIColor, size: CGSize) {
        super.init(texture: texture, color: color, size: size)

        fillSprite = SKSpriteNode(imageNamed: "bluecircle") 

        maskNode = SKSpriteNode(color: UIColor.blackColor(), size: CGSize(width: self.size.width, height: self.size.height))
        maskNode.position.y -= self.size.height/2

        cropNode = SKCropNode()
        cropNode.addChild(fillSprite)
        cropNode.maskNode = maskNode
        cropNode.zPosition = 1
        self.addChild(cropNode)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setFillAmount(amount: CGFloat) {
        // amount parameter must be float value between 0.0 and 1.0
        let newHeight = amount * (self.size.height*2)
        maskNode.size = CGSize(width: self.size.width, height: newHeight)
    }

}

To use this:

// Image size is 150x150px in this example
let circle = Circle(texture: SKTexture(imageNamed: "whitecircle"), color: UIColor.whiteColor(), size: CGSize(width: 150, height: 150))
circle.setFillAmount(0.4)

and thats it.


Maybe not perfect solution, but something to start with. At least it works.

Upvotes: 2

Aky
Aky

Reputation: 1817

I only have time to give you a partial answer. As Carrl said, you can draw the kind of shape you're looking for using Core Graphics (except I used UIBezierPath which is built on top of it):

UIGraphicsBeginImageContextWithOptions(CGSizeMake(100, 100), false, 0)
UIColor.greenColor().set()
let p = UIBezierPath()
p.moveToPoint(CGPointMake(0, 50))
p.addArcWithCenter(CGPointMake(50, 50), radius: 50, startAngle: 0, endAngle: CGFloat(M_PI), clockwise: true)
p.closePath()
p.fill()
p.removeAllPoints()
p.moveToPoint(CGPointMake(0, 50))
UIColor.greenColor().colorWithAlphaComponent(0.5).set()
p.addArcWithCenter(CGPointMake(50, 50), radius: 50, startAngle: CGFloat(M_PI), endAngle: CGFloat(2 * M_PI), clockwise: true)
p.closePath()
p.fill()
let im1 = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

circle

You still need to figure out how to use this as a texture in an SKSpriteNode, but you should be able to find an answer on this site. (SKShapeNode might be an option, but last time I tried using it in a Swift Playground, I recall it threw an error while trying to fill the shape node's path.)

Upvotes: 1

duan
duan

Reputation: 8855

I recommend you to draw the Image programmatically with the method from CoreGraphics:

UIGraphicsBeginImageContextWithOptions(size, false, 1)
//your code to draw the shape here
let imageYouWant = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

And then use imageYouWant as the image of your SKSpriteNode

Upvotes: 0

Related Questions