DEV Community

Cover image for SpriteKit Adventures pt2
emin
emin

Posted on

SpriteKit Adventures pt2

SKCropNode and sizing, SpriteKit Adventures pt2

In the first post I found a nice way to add my fuelGauge in the upper left section of the screen. Now let's try to animate that fuel so it reflects our consumption.

Spritekit adventure image

History

If you are interested in how we got here, go here to check out the First Post. If you are however up to speed, let's get to it!

Our journey begins!

Like I mentioned in the description, my idea is to add the SKCropNode so I can "animate" fuel consumption by moving it up and down. I found this post by Paul Hudson which explains it really well.

So, I will place a base gauge first, then on top if that, an SKCropNode which will crop the fuel amount.

// MARK: Fuel Gauge Base (this is basically the gauge without the bright green fuel texture)-------------------------------
let fuelGaugeBase = SKSpriteNode()
fuelGaugeBase.size = CGSize(width: fuelGaugeHeight/23, height: fuelGaugeHeight)
fuelGaugeBase.position = CGPoint(x: 16, y: playableArea.maxY - fuelGaugeHeight/1.5)
fuelGaugeBase.texture = SKTexture(imageNamed: "fuelGaugeBase")
addChild(fuelGaugeBase)
// ------------------------------------------------------------------------------------

// MARK: Fuel Gauge -------------------------------
fuelGauge = SKSpriteNode()
// We are using 0's here since its positioned in regards to the parent, or SKCropNode
fuelGauge.position = CGPoint(x: 0, y: 0)
fuelGauge.texture = SKTexture(imageNamed: "fuelGauge")
fuelGauge.size = CGSize(width: 5, height: fuelGaugeHeight * 0.97)
// ------------------------------------------------------------------------------------

// MARK: Crop Node -------------------------------
let cropNode = SKCropNode()
cropNode.position = CGPoint(x: 16, y: playableArea.maxY - fuelGaugeHeight/1.5)
cropNode.maskNode = SKSpriteNode(imageNamed: "fuelGaugeMask")
cropNode.addChild(fuelGauge)
cropNode.zPosition = 1
addChild(cropNode)
// ------------------------------------------------------------------------------------
Enter fullscreen mode Exit fullscreen mode

Spritekit adventure image


So far so good, positioning seems to be ok and the sizes are great.

Next, I want to move the fuelGauge up and down, therefore masking the fuel amount. I think I can do that by moving the base SKSpriteNode which is a child of the SKCropNode

All I need to do is change the Y position of the node. -100 should give us an ok result.

//...
fuelGauge.position = CGPoint(x: 0, y: -100)
//...
Enter fullscreen mode Exit fullscreen mode

Spritekit adventure image


F*k me...that is not looking good at all. It does mask the gauge, but the size of the mask is not at all close the the size of the *fuelGauge node we added. It just picks up the size of the sprite which we defined here:

cropNode.maskNode = SKSpriteNode(imageNamed: "fuelGauge")
Enter fullscreen mode Exit fullscreen mode

Time to look around and see if I can make that SKCropNode size the same as the fuelGauge. I do have other options I can use here, but I REALLY want to crop it. Because reasons.


The Solution ๐Ÿ†

I haven't found anyone with similar issues so that only meant that I am the issue ๐Ÿ˜ I took a short break over the weekend (๐Ÿป๐Ÿป๐Ÿป) and believe it or not, five minutes after I sat down and looked at the code again, and it hit me!

It was actually quite obvious, it just never occurred to me to try NOT using a sprite for the mask at all.

Our .maskNode is picking up the sprite size and it doesn't care that we changed all our sizes depending on the playable area. All it needs to know is the SIZE we are using now!

Let's give this one a go โฌ‡๏ธ

//...
cropNode.maskNode = SKSpriteNode(color: .green, size: CGSize(width: fuelGauge.size.width, height: fuelGauge.size.height * 0.97))
//...
Enter fullscreen mode Exit fullscreen mode

Spritekit adventure image

Now THAT'S WHAT I AM TALKIN' 'BOUT! ๐Ÿคœ๐Ÿ’ฅ๐Ÿค›


Let's Polish this up ๐Ÿ‡ต๐Ÿ‡ฑ

Now that size works, let's animate the usage of the fuel by moving the sprite inside the mask upwards. Just as an extra "thing" I will make the Lander consume more fuel while both thrusters are engaged.

First, we will declare a globalVariable to hold the Y position of the sprite.

var fuelConsumption : CGFloat = 0
.
.
.
fuelGauge.position = CGPoint(x: 0, y: fuelConsumption)
Enter fullscreen mode Exit fullscreen mode

And place out consumption logic inside a newly created updateFuel() method:

func updateFuel() {

    // Determine consumption
    switch touchCount {
    case 1:
        fuelConsumption += 0.3
    case 2:
        fuelConsumption += 0.45
    default:
        fuelConsumption -= (isTouching && fuelConsumption > 0) ? 0.8 : 0.0
    }

    // Update sprite position
    fuelGauge.position.y = fuelConsumption
}
Enter fullscreen mode Exit fullscreen mode

Which of course we will then add to the very beginning of our default update() method

override func update(_ currentTime: TimeInterval) {

    updateFuel()
    .
    .
    .
Enter fullscreen mode Exit fullscreen mode

Done'zo Washington!

Spritekit adventure image

And here is the final product (for now) Our Lander can now spend fuel as well as re-fuel.
Not sure how much this would cost IRL but hey, that's the drivers problem, now mine ๐Ÿ˜‰.
Also, as a kind of a dumb joke I made the fuel consumption move UP since...we are in SPACE ๐Ÿ›ฐ.

This has been an experiment post, and I am really interested if you liked it...or not!

I would really appreciate if you let me know on Twitter.
Even if you just send me a message "It sucks dude", it would mean the world to me ๐ŸŒŽ.

No hard feelings, I appreciate honesty more than you can imagine.

Top comments (0)