Swift: Presenting a Scene over another Scene - ios

I'm having trouble finding this answer. If I have a settings scene that I want to slide down over another scene, how do I do this without removing the original scene. I want to be able to transition the settings scene overtop of the game and when they click "Back" have the settings scene scroll back up and disappear.

Not sure why everyone is talking about view controllers here, but the easiest way to achieve what you want to do does not involve multiple scenes.
In SpriteKit, you can only have 1 scene at a time going.
So what you do, is you have an SKNode that will be used for your settings scene, and an SKNode for your main content.
Place all of your settings nodes into this setting SKNode as you would for the scene.
Place all of your main content into the main SKNode.
Add the main node to your scene for normal game functionality.
Give a high z position to the settings node so that it is on top.
Then when you need to present the settings node, you set its position to the screen height + 1/2 the SKNodes height (unless you change the anchor point).
Pause the main node if needed.
Use an SKAction on the settings node to have it move down to the spot on the screen you need it to go. (SKAction.moveToX(x:y:) should work for you).
Then when you need to leave, just call the reverse of the SKAction and unpause the main node.

Related

Using SpriteKit inside UIKit

I am contemplating a simple app that has four characters that you can drag around on the screen. While dragging they "wiggle" — that's the animation. And they snap to a position if they get close enough to it... like in a puzzle. Without the animation, this is all simple in UIKit.
My first thought is to render each character in its own SKView inside a plain old UIView. I could attach UIGestureRecognizers to each SKView to track tapping and dragging. But I think this implies individual GameScenes for each character/SKView. That seems go go against the grain of SpriteKit.
The alternative is a single GameScene with the four sprites. But I would still need to track & drag them and I don't see how to do that within an all-SpriteKit app.
Is either approach better practice than the other?
You should implement the one that has a single scene and separate sprites for each character. The sprites will be SKSpriteNode instances which are SKNode instances, which descend from UIResponder and can, therefore, respond to touch events.
Look at the documentation for SKNode. It is a wealth of information that applies to sprites as well as to any other kind of node. In particular it says:
All nodes are responder objects that can respond directly to user interaction with the node onscreen…
And then later has a section on "The Hit-Test Order is the Reverse of Drawing Order" etc.

Children of a Scene not releasing fast enough?

Have a couple of child nodes in a scene, and do a quick transition to a new scene.
In the new scene, didMove(to view: ….) is used to add the children from the previous scene to this next scene.
SceneKit crashes when doing this quickly, seemingly because the children of the old scene haven’t yet been released.
If I add a slight delay before adding the children to the second scene, it’s fine… it seems SpriteKit isn’t releasing the child fast enough for the scene transition.
the above is the most important thing to understand with regard the purpose for this question. I (wrongly) assumed SpriteKit would make sure all nodes attached to a scene were released before attempting to add them to a subsequent scene. It doesn't do this. But it does release them, it just takes a little time. Is this one frame? One second? Dunno...
My scene transition time is 0.25 seconds
Also tried using willMove(to view: ….) in the original scene to manually remove the children. This also doesn’t work, seemingly same behaviour: not fast enough.
Also tried assuming the child still has a relationship to its parent, so tried moving to its new parent, the new scene, with move(toParent:…) this also crashes. So maybe the children are already flagged as about to be released, I suppose.
Is this known about, and if so, how is it dealt with?
You can't present a scene and have willMove function at the same time in the same frame (SK loop)--your next scene's viewDidLoad will be called before the previous scene is destroyed. You have to remove all of the nodes before calling presentScene:
I suggest making a global variable of some sort to access your SKView; with that you can have control over your scenes from anywhere:
currentScene.removeAllChildren()
gView!.presentScene(nextScene)
“Is this a known about, and if so, how is it dealt with?"
Yes, this is a known issue of the SceneKit and IOS design and operational paradigms. It is considered that a scene must always be present and upon the screen. Can't have time without a scene onscreen.
As a result, for a brief time during transitions, both scenes are loaded, and active.
There are three ways to do deal with this problem:
Remove all content from the old scene prior to executing the transition so it can be instantly loaded by the new scene in didMove(to view...
or
Wait for completion of the transition before loading any content from the old scene into the new scene so there's no ownership conflicts of children.
or
KnightOfDragon’s first suggestion to use .copy() so there’s not the same instances being fought over by the scenes.

Overlay scenes/regions

I am working on my first spritekit app and had a quick question on how to handle something I had in mind. I am working on a prototype of a board game I had in mind and wanted to do some brainstorming in an iOS Map.
The main scene is a world map that the user can pan around. I have this working at the moment. My next step is to create some overlay that would appear with a bunch of actions/cards available for the user to activate.
Do you guys have any tips on how to set this up? Would this overlay be another scene? I don't think that is correct since the SKView can only present 1 scene at a time. In addition, I currently have a UIPanGestureRecognizer, I would want this to stop working in the region my overlay is in.
Any help is appreciated!
You can create an SKNode and add your actions/cards to that node. You can then add the node to your world map node (so it pans appropriately) as an overlay. You should set the zPosition of the overlay node to a value larger than your world map's zPosition so it appears over the map.

Sprite Kit: Game menu prefrences. Using a separate scene for the menu, an offscreen node or UIView

Just wanted your opinions on this. I am leaning towards UIView to hold my main menu and such, and just displaying it over the SKView when appropriate. Or I can have an offscreen node with the menu, or I can make a whole new SKScene to transition to.
Do you have any other alternatives or advice on the topic?
If we want to be specific about the scope of the game. It will be something along the lines of an infinite runner. So the menu would be pretty simple (Start, leaderboard... etc)
I'm also developing a SpriteKit game and also needed to display a menu with options and a settings menu, in my case, I found it better to use UiView to present most of the settings of the game as well as a tutorial view because it is a UipageViewController (to present images for how the game works) but here is the downside of either option:
If you choose to use views for menus and pause the game then the rootController must present it and any buttons, labels, images, etc must be presented and then removed, otherwise they will still sit on top of content. This works but animating stuff is difficult, unlike with another Skcene where elements like buttons can bounce, move, etc
The downside of using Skscene is that simple Ui-elements, like those I mentioned before, are now difficult to work with. For example instead of having a button you now have a node and you must therefore work with the touches methods: began, moving, and ending to make the node behave as a touch-up-inside button. Same with labels, and everything will have to be done programmatically whereas if you want to use views, you could make them in he storyboard and instantiate them as needed.
Conclusion: In my game I only chose to use Skscene for the game itself, (i.e playing) and used the views for pause, settings, about, tutorial. Hope this gives you some idea!
I initially started out with all these non-gameplay scenes as UIViews/UIViewControllers, but later on switched to having everything as an SKScene except for the welcome scene viewcontroller.
It doesn't seem very difficult having the options/settings/high scores type of screens under the SKScene option. You really only need to use one method to detect the UITouch:
touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
This works great with sklabels. You could easily load a spritekitnode behind the sklabel and get the same full effects of the UIButton with this combination. You can of course all all touch methods, but touchesBegan almost mimics the expected behavior.
With these views under an SKScene, you also get access to the update: method where you can get more creative in how you display animations and events.

Building a tower defense game. How do I add a circular menu with tower choices on tile Node in SpriteKit?

I'm building a tower defence game using SpriteKit and I'm relatively new to this.
My map basically consists of tile Nodes that are touchable. Once a user touches the node, I can place a tower on that node (I have this part working so far). What I want to do moving forward, is instead of directly placing a tower, I'd like a circular menu to pop up around the tile Node to let the user pick the tower that they wish to place in this tile node.If the user clicks anywhere other than the circular menu, the menu should disappear.
So something like this:
http://imgur.com/QvCsM8Q
I'm wondering what the best way to do this is. I have two possible solutions but they seem hacky:
1) Creating a custom UIView consisting of the menu and 4 buttons and then adding it to my scene (but then how do I detect button presses in this menu from the scence?)
2) Extending a SKShapeNode to create a circle and adding in 4 SpriteNodes around the circle, then verifying if a touch location corresponds to one of the 4 SpriteNode locations.
Any suggestions/code examples of how best to approach this?
I would suggest you create a separate class for your tile nodes (which inherit SKSpriteNode) and add the functionality within that.
For the approach for the menu, I think something along the lines of point (2) would be better. By subclassing the tile node, you can make the tile detect the selection by itself.
Expand the tile using SKShapeNode or a SKSpriteNode with a circular image using animation.
Place the four buttons on the expanded part.
Implement the touch for the selection within the tile node class.
For closing the menu, a tap on the scene can trigger a NSNotification for which the tileNode could become a listener on expansion.

Resources