Setting SKSpriteNode position by using invisible UIView in Storyboard - ios

I just recently started on iOS Spritekit. Most tutorials and StackOverflow topics mentioned that I can't use Storyboard for arranging SKSpriteNode so I've been struggling on layout my views, especially I also have some other components like UILabels.
I hack this by placing invisible UIViews (and do autolayout on them with other components), and pass the values into the SKScene which will place SpriteNode based on the value--after converting the coordinate systems, etc.
Would there be potential issues on this approach? It works for simple cases but it is obviously a hack... :P
Or if there are better way of layout SpriteNode? I am going through RayWenderlich tutorials, but so far many of them seems to be hardcoded positions?

Well, it's certainly more work than needs to be done so there could be performance issues. As an alternative (and the correct way) to do this is use the scene editor in Xcode.
Create a new SpriteKit Scene File and add your nodes to it. Create a new Swift file of class SKScene and set the custom class for the scene file.
Then all you have to do to get those nodes into your class (like IBOutlet) is the following...
override func didMove(to: view){
let shipNode = self.childNode(withName: "shipNodeName") as! SKSpriteNode
}

Related

Accessing SKView methods from an SKNode

In SpriteKit development, how is one supposed to get access to the SKView?
For example; lets say I create a custom SKNode class called Player for use throughout my game:
class Player: SKNode {
/*...*/
}
In this class, if I wanted to generate a SKSpriteNode from an SKShapeNode (in order to improve performance) I need to use the SKView.texture() method. But I don't have access to the SKView that my Player is residing in unless I pass the view to the Player from whoever is instantiating it.
Is there any way to get the current view that an SKNode is attached, so that I'm not having to pass references to the view around my application? Is this just an anomaly of the framework? What is the preferred way of dealing with this problem?
I'm using the Swift language.
Update
Ron Myschuk's answer is correct and I've accepted it as it is probably most useful to the community. However my use-case for wanting to access the view from within a node was in order to use the texture method to create an SKSpriteNode from an SKShapeNode.
Here's a description of the method I wanted to gain access to:
Renders a portion of a node’s contents and returns the rendered image as a SpriteKit texture.
https://developer.apple.com/documentation/spritekit/skview/1519994-texture
This method seems useful outside of the view. For example, when initialising/populating SKNode's that have not yet been added to the display tree.
My solution to this specific problem was simply to create an SKView on the fly and use it for the purposes of my needs, allowing it to be garbage collected by the engine.
let view = SKView()
let texture = view.texture(from: someSkShapeNode)
let sprite = SKSprite(texture: texture)
// we don't need view anymore
Hope this helps someone.
providing that you've added an instance of player to your scene and providing that you are not doing his in the initializer of Player you could use the .scene property
self.scene?.view
You can build a SKTexture from UIImageor CGImage and you can create images from every complex path/drawing you want (see SKTexture from path for example or Drawing and Creating images).

How to design an SKNode in a graphical designer and reuse it in code?

Because of the fact that SpriteKit does not support custom drawing on SKNodes, I have to create a custom sprite node and add other nodes to it.
When I am adding other nodes to the parent node, the coordinate system of the parent view is really confusing me. I always have to try a lot of times to get the node to the place where I want it to be. Sometimes I can't even see the node added.
I think this is very annoying. I think SpriteKit must provide some way to let me "design" a custom node in a graphical way. I want something like the SKScene designer. But instead of designing a scene, I can design a node. After that, I can reuse the designed node in code, just like I can reuse table view cells that are already designed in IB.
Is there something like that in Xcode?
The coordinate system is really easy to understand, when you place a node inside another node, the coordinates become relative to parent, not the scene.
Since SKScenes are SKNodes, you can use the sks file to design your nodes on a per node basis and load an sks for every node you need, or you can create several nodes inside 1 SKScene file, and just extract them from the sks during your loading phase.

Can't reference Xcode GameScene.sks with swift

I am a beginer and starting my first swift game. It seems like the GameScene.sks interface would be extrememly easy to position my labels and nodes for each level, but I am having trouble figuring out how to reference the nodes with swift.
For example I dragged over a label to act as a timer, but I dont know how to update the label text with code.
I was thinking something like:
func timerDidFire(){
countDown--
SKLabelNode.name("countDownTimerLabel").text = countDown
}
You need to use the childNodeWithName method on SKNode. For example:
func timerDidFire() {
let label = childNodeWithName("countDownTimerLabel") as! SKLabelNode
label.text = --countDown
// I believe this is an appropriate case for force unwrapping since you're going to
// want to know if your scene doesn't contain your label node.
}
Since you're going to be accessing the SKLabelNode often, and it takes time to search through the node tree (not very much but something to bear in mind), it may be a good idea to keep a reference to the label. For example, in your SKScene subclass:
lazy var labelNode: SKLabelNode = self.childNodeWithName("countDownTimerLabel") as! SKLabelNode
On a related note, if you're looking for multiple nodes there's the
enumerateChildNodesWithName(_:usingBlock:), also on SKNode.
Finally, for more information have a look at Apple's WWDC 2014 talk: Best Practices for Building SpriteKit Games where they cover both the methods I mentioned.

xcode 4 drawing rectangles

i'm very new to xcode. i've googled this and even serched here and i didn't find exactly what i was looking for. i really wanna get this. especially since it's the most basic thing there is.
so, i have the .h and .m files
i want to DRAG a uiview into the .xib file, i don't want it to be as big as the screen, so i resize it.
now i want to draw a bunch of rectangles INSIDE this view object.
how do i go about doing this?
your help would be greatly appreciated!
So you add a generic UIView then create a subclass of UIView and do your drawing inside the drawRect method.
Then change the class of the UIView to your subclass name in the inspector.
Be sure to #include your header in the app delegate.
That's the basic thing.
For more sophistication, you're going to want to learn to use UIViewController subclasses as well. These are used all over ios.

UIView Responsabilities (Object-Oriented Programming)

I am just starting out with iOS app development and it's been a great experience so far. Apple documentation is great, but there are some questions I have that are not as technical and only someone with experience might be able to answer.
I have a bunch of UIViewController which handle the "dynamic skinning" of the custom UIViews that they control. This leads to a controller with big chunks of code which seems a bit unpractical to me.
So the question is: Following the MVC pattern, should I give the responsibility of setting a UIFont, UIColor, etc to the view itself? Or should I create "micro" controllers that handle this task using some kind of input?
Thanks for the response.
Creating UIView subclasses that handle the layout works. Override layoutSubviews in the UIView subclass to do the positioning layout (setting frames etc). I find the init method to be a good place to set fonts, colors etc.
Now the UIViewController has relatively little code related to the custom UIView. The viewController just needs to position an instance of the custom UIView and perhaps set a few properties (like a textLabel's text).

Resources