This week’s game development journey was all about learning how to add simple effects to a SpriteKit game. I used a combination of SKPhysics and SKActions to create these simple effects. I also spent a bit of time working on game balance, but that’s a discussion for another time.

A Very Simple SpritKit Effect

In my searches throughout the week, I found a simple animation that Apple used in their documentation. Rather than trying to reinvent the wheel, I decided to implement this working solution into ZER0ED.

let shockWaveAction: SKAction = {
let growAndFadeAction = SKAction.group([SKAction.scale(to: 50, duration: 0.5),
                                                SKAction.fadeOut(withDuration: 0.5)])
        
let sequence = SKAction.sequence([growAndFadeAction,                                      SKAction.removeFromParent()])      
return sequence
}()

By changing the stroke color, fill color, and size I’ve been able to reuse this simple SpriteKit effect three times. I might even be able to find other uses for it in the future – who knows!

This effect is implemented when a charge is being consumed when points are being distributed and to indicate a game-ending event.

SKPhysicsWorld – Playing With Physics

If you know anything about ZER0ED you probably are wondering what on earth am I doing working with physics? I had this same thought when I started implementing SpriteKit’s physics engine into the game, but this serves two purposes.

  1. Gave me the opportunity to learn some of the basics of SKPhysics.
  2. Allowed me to add some pretty interesting effects into the game.

This isn’t the first time I’ve worked with the SpriteKit physics engine. However, I have come a long way in my ability and understanding of Swift since the last time.

In previous builds of ZER0ED, I had resource charges falling to infinity. I’d then remove them from the scene after they reached a significantly low enough y-value to ensure they’d be off the screen. This felt kind of boring though. To make this more exciting the solution was to have the charge label pull the falling charges towards it. Once they reached the label they would collide and explode.

The first step was to give the charge counter to label a center of gravity. To do this I created a radialGravityField SKFieldNode and added it as a child to the resource counter label.

let chargeLabelGravityCenter = SKFieldNode.radialGravityField()
chargeLabelGravityCenter.falloff = 2
chargeLabelGravityCenter.strength = 15
chargeLabelGravityCenter.categoryBitMask = 00000001
chargeLabelGravityCenter.isEnabled = true
        resourceChargesLabel.addChild(chargeLabelGravityCenter)

The next step was to modify the physics bodies of the charges so that they would interact with this SKFieldNode.

zPosition = -2
physicsBody = SKPhysicsBody(circleOfRadius: self.size.width / 2)
physicsBody?.affectedByGravity = true
physicsBody?.fieldBitMask = 00000001
physicsBody?.categoryBitMask = 00000010
physicsBody?.collisionBitMask = 00000100
physicsBody?.contactTestBitMask = 00000100
physicsBody?.mass = 5
physicsBody?.isDynamic = true

Charges given a name associated with their charge upon creation. I also apply impulses and some torque to give a bit of movement as the charge falls.

let charge = ChargedParticle(color: .red, size: CGSize(width: 30, height: 30))
charge.position = spawnLocation
charge.name = "chargeNeg"
addChild(charge)
            
charge.physicsBody?.applyImpulse(CGVector(dx: randomImpulseX(), dy: randomImpulseY()))
charge.physicsBody?.applyTorque(CGFloat(30.0))
charge.physicsBody?.applyAngularImpulse(CGFloat(45))

Upon collision, I trigger the shockwave animation I mentioned earlier. Then I determine whether or not this is a positive or negative charge (based on the name). Once I know the charge’s state I can either subtract or add from the available resource charges and apply the correct color to the stroke of the shockwave.

if nodeA.name == "chargeNeg" || nodeA.name == "chargePos" {
               
   let shockwave = SKShapeNode(circleOfRadius: 10)      
   shockwave.position = contact.contactPoint
       if nodeA.name == "chargeNeg" {
             resourceCharges -= 1
             shockwave.strokeColor = .red
       } else if nodeA.name == "chargePos" {
              resourceCharges += 1
              shockwave.strokeColor = .green
       }     
shockwave.zPosition = -2
addChild(shockwave)
shockwave.run(shockWaveAction)
nodeA.removeFromParent()
}

I use a very similar approach to the animation used for allocating points. A different SKFieldNode is created and a similar code is used to create the points SKSpriteNodes. The largest difference here is that the BitMasks are different to ensure the two gravity systems don’t interact with each other.

Signaling Game Over

One of the largest areas of ZER0ED prior to this build was that losing felt, uneventful. That changes this week with a new game over animation.

Using the shockwave effect mentioned above I was able to create little exposition centered at the cause of game over. For example, if the reason a player loses when a Target goes negative that Target will be the center of the explosion. However, if the loss is due to running out of charges, the charge label will center the explosion.

In addition to being a nice effect, it also serves a purpose. This animation creates a slight delay before the Game Over scene is presented to the player. Prior to this, the Game Over screen would appear so quickly that it was difficult to understand why and how game over had occurred.

Join the Beta Test

ZER0ED is available for you to try in beta form through the TestFlight app. I appreciate any feedback, suggestions, or comments that you might have during your playthroughs. Follow me on twitter to get an invite link

Categories:

Tags:

Comments are closed