Using SpriteKit inside UIKit - ios

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.

Related

Two scenes at the same time in SpriteKit

I need to have a game scene, and on the bottom a permanent game menu for things like inventory, etc. I thought it would be great to have two scenes: one for the actual game and another for the game menu. How can I do this in SpriteKit? Having two scenes at the same time (and each one having its own nodes and such)
Also, if this is not the best way to implement this, please tell me.
No don't do that. Even if possible it is meaningless.
In a such case I use storyboard. Created menu at top of the screen and give the rest of the screen to SKView. By this way you can control your SKScene easily also you can use UIKit for you menu which is more advanced than SpriteKit ui elements.
Also you can use one scene and create menu nodes with SpriteKit utilities.

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.

Creating a scrollview

Here's my current situation:
I created a CCScene named StoreScene.
Within that scene, I've initialized a CCLayer and just named it Store layer.
Now, I want a scrollable layer that contains content which the user can touch.
To do this, I created another CCLayer named Store Container.
I create an instance of this layer and add it as a child to StoreScene.
In StoreContainer, I've added multiple sprites, each with a unique tag.
The scrolling is done within the StoreScene and touches will move the entire Storecontainer layer up or down.
I have added 4 sprites to my scrolling layer (store container)
Initially,
sprite 1 is located at 0,10
sprite 2 is located at 0,20
sprite 3 is located at 0,30
sprite 4 is located at 0,40
Obviously, as the entire storecontainer layer shifts, the sprite positions shift as well.
However,
when I do this in the TouchesEnded method:
if (CGRectContainsPoint(sprite1.boundingBox, touchpoint)){
NSLog(#"TouchedSprite1");
}
... and so on for each sprite
The touch locations of each sprite remain in the same place!!!
Visually, the sprites are moving up and down nicely.
but their locations when receiving touches stay constant..
is there a reason for this?
Any other way for approaching a scrolling layer?
I've already looked at the UIKit's scrollview and I've looked at CCScrollLayer and both aren't good enough for me.
My way may be simpler but it doesn't work as planned.
Thanks in advance! ^_^
I'm guessing you've implemented touchesEnded in your StoreContainer. In that case the touches' coordinates will be relative to that layer, which explains why their coordinate system is following the layer around the screen. You could implement touchesEnded in the scene instead, or put the StoreContainer instance inside a new and immobile layer whose purpose is only to handle touches.
Alternatively you could keep your current setup and use your answer to this question to get the touch coordinates in the world... :)
Check out CCKit, there is a nice CCScrollLayer implementation included.

UITouch & UIEvents: fighting the framework?

Imagine a view with, say, 4 subviews, next to each other but non overlapping.
Let's call them view#1 ... view#4
All 5 such views are my own UIView subclasses (yes, I've read: Event Handling as well as iOS Event Guide and this SO question and this one, not answered yet)
When the user touches one of them, UIKit "hiTests" it and delivers subsequent events to that view: view#1
Even when the finger goes outside view#1, over say view#3.
Even if this "drag" is now over view#3, view#1 still receives touchesMoved, but view#3 receives nothing.
I want view#3 to start replying to the touches. Maybe with a "touchedEntered" of my own, together with possibly a "touchesExited" on view#1.
How would I go about this?
I can see two approaches.
side step the problem and do all the touch handling in the parent
view whenever I detect a touchesMoved outside of view#1 bounds or,
transfer to the parent view telling it to "redispatch". Not very
clear how such redispatching would work, though.
For solution #2 where I am getting confused is not about the forwarding per se, but how to find the UIVIew I want to forward to. I can obviously loop through the parent subviews until I find one whose bounds/frame contain the touch, but I am wondering if I am missing something, that Apple would have already provided but I cannot relate to this problem.
Any idea?
I have done this, but I used CALayers instead of sub-UIViews. That way, there is no worries about the subviews catching/redispatching events to the parent UIView. You might not be able to do that, but it does simplify things. My solution tended to use CGRectContainsPoint() a lot.
You may want to read Event Handling again, as it comes pretty close to answering your question:
A touch object...is associated with its hit-test view for its
lifetime, even if the touch represented by the object subsequently
moves outside the view.
Given that, if you want to accomplish your goal of having different views react to the user's finger crossing over them, and if you want to do it within the touch-handling mechanism provided by UIView, you should go with your first approach: have the parent view handle the touch. The parent can use -hitTest:withEvent: or -pointInside:withEvent: as it's tracking a touch to determine if the touch is in one of the subviews, and if so can send an appropriate message.

Resources