iosswiftsprite-kitswift3skspritenode

How can I modify the size of SpriteKit nodes in Swift?


In my app, for one screen, I am setting the size and centering the background of a SpriteKit node. For example, I'm setting the size of the background subview as follows:

backgroundNode.size = self.frame.size  

While this is working on the iPhone 6 Plus, the smaller screen/lower resolution of the iPhone 5 means the default size of the other nodes makes is too large to fit within their scene.

How can I force other nodes conform to the size of the background node? I wanted to divide each subview's size by the background subview's size, but math operations can't be done directly on the size property.


Solution

  • SpriteKit scenes (SKScene) contain nodes, nodes (SKNode), which have size and position properties (of type CGSize and CGPoint, respectively).

    UIKit UIView.frame and bounds properties are a CGRect structs comprised of the same CGSize and CGPoint type structs.

    So it really helps to understand how to work with CGRect, CGSize and CGPoint.

    Be aware, CGRect, CGSize and CGPoint as structs, in Swift, are always passed by value to functions, not by references as classes are, so you can't modify fields inside the structs passed into a function, and have them propagate back to the caller's copy of the struct without taking extra steps.

    Because size and position properties are compound types, you can't use them like scalars in simple in math and logic operations; as they contain multiple properties.

    For example:

    If want to divide size, you have to access width and height properties of the CGSize struct individually.

    You can assign the size in one operation (i.e. single constructor):

    node.size = CGSize(
       width:  node.size.width  / backgroundNode.size.width,
       height: node.size.height / backgroundNode.size.height)
    

    Or you could do it discretely:

    node.size.width  = node.size.width  / backgroundNode.size.width
    node.size.height = node.size.height / backgroundNode.size.height
    

    When dealing with CGRect fields, sometimes it's useful to deal with it as a single entity. For example,

     view.frame = CGRect(x: 0, y: 0, width: 10, height: 10)
    

    Others sometimes it's more practical to set size and origin properties separately:

     view.frame.origin = CGPoint (x: 0, y: 0)
     view.frame.size   = CGSize  (width: 10, height: 10)
    

    or even:

     view.frame.origin.x     = 0
     view.frame.origin.y     = 0
     view.frame.size.width   = 10
     view.frame.size.height  = 10
    

    It's also worth knowing about the "zero" static property of each of the struct, as convenient crisp shorthand equivalents:

     CGRect .zero   ...    CGRect  (x: 0, y: 0, width: 0, height: 0)
     CGPoint.zero   ...    CGPoint (x: 0, y: 0)
     CGSize .zero   ...    CGSize  (width: 0, height: 0)
    
    If you do a lot of adjusting of size and position, to reduce code bloat, you might consider borrowing or developing convenient Swift extensions to `CGRect, CGSize and CGPoint` to simplify applying delta values to sizes or origins.