Posts

Showing posts from August, 2015

Memoization in Swift 2

The WWDC 2014 talk "Advanced Swift" (https://developer.apple.com/videos/wwdc/2014/#404 ) included a sample 'memoization function' which could speed up performance of certain functions by storing function results in a dictionary. Here's my implementation of it: func memoize<Input: Hashable, Output>(function: Input  -> Output ) -> ( Input  -> Output ) {     var lookupTable = [ Input : Output ]()     return {input in         if lookupTable[input] == nil {lookupTable[input] = function(input)}         return lookupTable[input]!     } } This implementation is very similar to the first implementation of memoization presented in the Advanced Swift talk. However, that first implementation had an issue with creating recursive functions: let factorialMemoized = memoize {n in return n < 2 ? 1 : factorialMemoized(n- 1 )*n} //Error: Variable used within its own initial value when using 'Take One' implementation of m

How to add a folder to Launchpad

Image
I'm not sure if I'll actually use this, but I think it's pretty neat. I use Launchpad a lot to open applications because it works well with trackpad gestures. One way to add folders to Launchpad is by creating applications within Automator that open folders. 1. Open Automator and create a new Application 2. Click the Variables tab and the Locations submenu (the one with the Finder icon), and drag the Path variable to the 'Drag actions or files here.' 3. Double-click 'Path' in the Variable menu (beneath the workflow) and set the path to the folder you want to add to Launchpad. 4. Go back to Actions, choose Files and Folders, and drag 'Open Finder Items' to below the 'Get Specified Variable' action. 5. Save the application in the Applications folder in your user folder, with the same name as the folder it opens. 6. At this point, the app shows up, but it has an automator robot as its icon. Since it opens a folder, it ought

Operator precedence in Swift

The SKActions to move all take a duration argument. To ensure that the rate of the move remains the same even if the distance is different, the duration must be computed: SKAction . moveBy (myVector, duration: NSTimeInterval ( sqrt (myVector. dx *myVector. dx + myVector. dy *myVector. dy )/ 1_000 )) That's an awful lot of code to write for such a simple operation! To alleviate this, I extended CGVector to include a 'magnitude' variable: extension CGVector {     static func from(start: CGPoint , to end: CGPoint ) -> CGVector {         return CGVector (dx: end. x -start. x , dy: end. y -start. y )     }     var magnitude: CGFloat {         return sqrt ( dx ^ 2 + dy ^ 2 )     } } The constant-rate move action could then be created much more simply: SKAction . moveBy (myVector, duration:  NSTimeInterval ( myVector.magnitude / 1_000 )) All seemed to be going well, but I soon noticed a bug in the magnitude: CGVector (dx: 0 , dy: 200

Finding bottlenecks with Time Profiler

After watching a WWDC talk on using time profiler, and noticing low framerate in my game, I decided to try using it to find out what I could optimize. To my surprise, I had a bottleneck that the profiler found very quickly. The culprit was this computed variable: var playerSprite: PlayerSprite ? {         return self [ "PlayerSprite" ][ 0 ] as ? PlayerSprite     } It was called twice every frame in the update method: override   func  update(currentTime:  NSTimeInterval ) {                   guard   didInitialize   else  { return }                   camera !. position  =  playerSprite !. position                   for  child  in   self . children  {             (child  as ?  OverworldSpriteNode )?. updateWithDeltaTime ( 1 / 60 )         }                   k  = ( k  +  1 ) %  7_200                   if   playerSprite ?. position . isInRect ( bounds ) ==  false  {             playerSprite?.gameOver() //not counting this one because the