Giter VIP home page Giter VIP logo

sktutils's Introduction

Sprite Kit Utils

A collection of Sprite Kit helper classes and functions, written in Swift.

This code was originally written for the book iOS Games by Tutorials, Second Edition, which is published through raywenderlich.com.

iOS Games by Tutorials

SKTUtils requires Xcode 6.1. For the older Objective-C version of SKTUtils, see the objective-c branch.

What can SKTUtils do for you?

It defines handy constants such as π.

It extends CGPoint and CGVector so you can do:

let pt1 = CGPoint(x: 10, y: 20)
let pt2 = CGPoint(x: -5, y: 0)
let pt3 = pt1 + pt2
let pt4 = pt3 * 100
println("Point has length \(pt4.length())")
let pt5 = pt4.normalized()
let dist = pt1.distanceTo(pt2)

It adds handy functions to Int and Float:

let x = 100
let y = x.clamped(10...50)
let z = Int.random(20..30)

let r = 180.degreesToRadians()
let d = π.radiansToDegrees()

It extends various Sprite Kit classes with convenience methods, such as:

let color = SKColor(red: 255, green: 128, blue: 64)
let action = SKAction.afterDelay(2.0, runBlock: { /* your code here */ })

And much more... including SKTEffects, which lets you make your games much more juicy!

Introducting SKTEffects

Sprite Kit has a handy feature named actions that make it really easy to move, rotate and scale your sprites. However, a big downside is the omission of timing functions beyond the standard ease in and ease out. The SKTEffects classes from this package add support for many more easing functions to Sprite Kit.

Note: The iOS 8 version of Sprite Kit includes an SKAction.timingFunction property, but unfortunately it is pretty useless. It's a step in the right direction, but it still won't let you perform the kinds of effects that make games juicy.

It lets you do things like this with just a few lines of code:

The demo app

The only reason SKTEffects exists is because SKAction does not allow arbitrary timing functions, only standard ease-in and ease-out. The SKTEffect subclasses are re-implementations of what SKAction already does but with the addition of custom timing functions. It's a bit of a roundabout way of achieving something that really should have been built into Sprite Kit.

There are currently three SKTEffect subclasses:

  • SKTMoveEffect
  • SKTRotateEffect
  • SKTScaleEffect

You use them like this:

let moveEffect = SKTMoveEffect(node: node, duration: 1.0, startPosition: startPoint, endPosition: endPoint)

moveEffect.timingFunction = SKTTimingFunctionBounceEaseOut

node.runAction(SKAction.actionWithEffect(moveEffect))

First you create the SKTMoveEffect object and pass it the node that it should animate, the duration of the animation in seconds, and the starting and ending position of the node.

Then you (optionally) set the timing function on the effect object. You can use the supplied timing functions -- for example, elastic, bounce, and many others -- or create your own. See SKTTimingFunctions.swift for a complete list.

Finally, you wrap the effect object inside a regular SKAction and run that action on the node.

The process for SKTRotateEffect and SKTScaleEffect is identical, but you specify rotation angles and scale vectors, respectively.

You can combine multiple effects at the same time, e.g. have more than one scale effect going at once on the same node.

Warning about SKTScaleEffect

IMPORTANT: When using SKTScaleEffect, the node that you're scaling must not have a physics body, otherwise the physics body gets scaled as well and collision detection becomes unpredictable (objects may suddenly move through other objects).

To solve this, make a new SKNode, give it the physics body, and add the node that you're scaling as a child node.

Caveats

Currently there is no "relative" version of the effects. You always have to supply an absolute starting and ending position, rotation angle, or scale. Most of the time this is no big deal, but it does mean you cannot put them into repeating actions.

For example, the demo project does the following to rotate a node every second by 45 degrees:

node.runAction(SKAction.repeatActionForever(SKAction.sequence([
  SKAction.waitForDuration(0.75),
  SKAction.runBlock {
    let effect = SKTRotateEffect(node: node, duration: 0.25, startAngle: node.zRotation, endAngle: node.zRotation + π/4)
    
    effect.timingFunction = SKTTimingFunctionBackEaseInOut
    
    node.runAction(SKAction.actionWithEffect(effect))
  }])))

If the effects had a relative version, this could have simply been written as:

let effect = SKTRotateEffect(node: node, duration: 0.25, byAngle: π/4)

effect.timingFunction = SKTTimingFunctionBackEaseInOut

node.runAction(SKAction.repeatActionForever(SKAction.sequence([
  SKAction.waitForDuration(0.75),
  SKAction.actionWithEffect(effect)
  ])))

Not only is this simpler to read, it also saves you from having to create a new effect instance for every repetition. However, this doesn't work in the current version of the library.

Effects keep state (unlike SKActions), so you should not reuse the same effect instance in multiple actions.

If you use a lot of effects over a long period of time, you may run into memory fragmentation problems, because you need to allocate a new object for every effect. Currently, effects cannot be reset, so it's tricky to put them into an object pool and reuse them.

Because actions keep state, you cannot put them into an action after a delay if the node also moves in the mean time. In other words, doing the following may or may not work:

let effect = SKTMoveEffect()

let action = SKAction.sequence([
  SKAction.waitForDuration(5.0),
  SKAction.actionWithEffect(effect)
  ])

If the node has moved during the delay, either through another SKAction, physics, or the app changing the node's position property, then the effect will start in the wrong place.

Let's get SKTEffects included in Sprite Kit!

If you think custom timing functions are an important feature to have built into Sprite Kit, then go to bugreport.apple.com and duplicate this feature request. The more they receive, the better!

The demo app

The Examples/Effects folder contains a little demo project that shows how to do animations with more interesting timing functions. This app uses physics to move the balls and detect collisions.

It has the following special effects:

  • The objects appear with an animation when the game starts
  • Screen shake on collisions
  • Screen rotate on collisions, for extra shaky goodness!
  • Screen zoom on collisions
  • Color glitch (flashing background color)
  • Ball scales up on collisions
  • Ball smoothly rotates in the direction it is flying
  • "Jelly" effect on the obstacles on collisions
  • And more...

Most of these effects are cumulative; i.e. if there are several collisions in quick succession, then the screen shake movement is the sum of these hits.

All the fun happens in MyScene.swift. There are several let statements at the top that let you turn effects on or off.

Tap the screen to add a random impulse to the balls.

Playground

The Examples/Playground folder contains an Xcode workspace with a Playground. To use this,

  1. Open SKTUtils.xcworkspace in Xcode.
  2. Press Command+B to build the SKTUtils module -- this is important!
  3. Open MyPlayground.playground and start messing around.
  4. Press Option+Command+Enter to open the Assistant Editor so you can see the output.

Have fun playing with SKTUtils!

Unit tests

The Examples/Tests folder contains an Xcode project with unit tests for SKTUtils. Press Command+U to run the tests.

sktutils's People

Contributors

hollance avatar icanzilb avatar rwenderlich avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sktutils's Issues

CocoaPods support

It'd be really nice to be able to use SKTUtils without copying the whole project manually and keeping that up to date.

Demo: Balls don't always collide with screen borders

It feels like this might be a SpriteKit issue of some sort but when I run the demo app on iOS10 iPhone 6s Simulator the balls sometimes just wonder off the screen.

Does anyone want to have a look at this and send a PR if they find a fix?

Support for SKAction.speed ?

I'm changing the SKAction.speed property on some of my SKMoveEffect actions, but nothing is happening. Is there some additional passthru functionality I need to implement in your SKAction extension?

Could not found file xxx.caf

When I play a background music named xxx.caf, it shows that file cannot be found, playSoundEffect method didn't works too. Why? Because the file size is bigger? Any help will be great appreciated!

Naming conflicts (due to public extensions)

I know this may be not the right place for this. So I'm sorry for posting this here, but don't know were else I should put this.

In a pod I'm using, there is a CGFloat+Extensions.swift which I think comes from somewhere here (at least from RW, as it has your Razeware header comment in it).
My problem is that, because those extensions are public, I get naming conflicts e.g. when using them in multiple modules (pods, or even my own).
So I was just wondering, why you declared them public, and don't just stick to the internal default? This is really annoying :-/ Or am I seeing this wrong?
Anyway as these Extensions are just copied around, there is probably no way to stop this ;-)

RubyMotion version

Hi !

This is not an issue. I didn't know where else to contact you to tell you that I've translated SKTUtils and the demo to RubyMotion. Let me know if you're interested in adding a RM branch. SKTUtils are awesome, thanks a lot.

Best,

Bruno.

The Swift version of SKTUtils gives many compilation errors on OS X

For some reason, the compiler on OS X is more strict about its types. On iOS this works fine:

extension CGPoint {
  init(angle: Float) {
    return self.init(x: cosf(angle), y: sinf(angle))
  }

But on OS X it needs to be written as:

extension CGPoint {
  init(angle: Float) {
    return self.init(x: CGFloat(cosf(CFloat(angle))), y: CGFloat(sinf(CFloat(angle))))
  }

Maybe this is a different build setting, maybe it's a compiler feature/bug. Let's wait until we get a new beta.

Maybe we should also use CGFloat in the API instead of Swift's own Float.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.