Adding child SKNode to existing SKNode changes the touch area - ios

I'm create a SKNode to the scene and logging touch events on each individual SKNode. I can add as many as I want and the touches work as expected, if I touch the node and only the visible node do I see the log messages. Now, if I add another SKShapeNode to any of the previous SKNode's the touch area expands to be more of a rectangle and now I see the log message even if I touch outside the origin SKNode.
The first picture shows the original touch area of the SKNode and the second is the new touch area after adding a child SKShapeNode to that SKNode. The SKShapeNode being added is 20x20 so it fits within the 20x100 bar.
The problem is I now get multiple touch events when touching the other bars since they overlap. Is there any way around this?

You appear to be using separate graphics for each angle of your line. Instead try using the same graphic with your line at 0 degrees and then using the zRotation to angle it. I have not tried this myself but I think it will fix your issue.
Alternately try using containsPoint for your touch recognition in the touchesBegan method. You can check if the touch is within any of the nodes and process accordingly.

Related

Preventing a sprite from rotating

I am doing this spritekit game.
I have this object that I want to move up and down when the user touches it. It is an object that has to slide in a rail, up and down or in another case left and right.
So, when the user touches the object I do something like this
CGVector force = CGVectorMake(0.0f, 5000.0f);
[object.physicsBody applyForce:force];
it is a vertical force applied up.
but when the object collide with others it rotates. Is there a way to prevent the object from rotating?
Try object.physicsBody.allowsRotation = NO. This ignores all angular impulses and forces that would make the body rotate.

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.

UIPanGestureRecognizer get translation for each touch point

I have a UIPanGestureRecognizer attached to a parent view, with various CCSprite I want to move around in the parent when panned. Using [gesture locationOfTouch:i inView:recognizer.view] I can get the location of the touch but if I assign that to my subview's center it often makes the subview move unexpectedly since the original touch is probably not in the exact center of the sprite. Really what I want is to get the [gesture translationInView:recognizer.view] for each of the touch locations and use that. It works perfect when you only have 1 panning touch, but more then 1 and there appears no way to get translations for them. Because each touch can be panning in a different directon/speed. The user can use 2 fingers to move two different sprite completely independent of each other. -[UIPanGestureRecognizer translationInView:] doesn't allow me to get the different translations.
How should I do this?
I found a category CCNode-SFGestureRecognizers that adds the ability to attach UIGestureRecognizers to any CCNode. This way I can get around needing multiple translation values.
Now, if you're only interested in pan gesture, why not use cocos touch methods?
In touchBegan: calculate (and save) the location of touch in the subview, in touchMoved:, calculate translation which is just current location less the previous location. Move your subview by that amount.

hacking ios ui responder chain

I'm facing a delicated problem handling touch events. This is problably not a usual stuff to make but i think it is possible. I just don't know how...
I have a Main View (A) and Main View (B) with a lot of subviews 1,2,3,4,5,...
MainView
SubView(A)
1
2
3
SubView(B)
1
2
3
Some of these sub sub views (1,2,4) are scrollviews.
It happens that I want to change between A and B with a two finger pan.
I have tried to attach a UIPanGestureRecognizer to MainView but the scrollviews cancel the touches and it only works sometimes.
I need a consistent method to first capture the touches, detect if it is a two finger pan, and only then decide if it will pass the touches downwards (or upwards... i'm not sure) the responder chain.
I tried to create a top level view to handle that, but I cant make to have the touches being passed through that view.
I have found a lot of people with similar problems but couldn't find a solution to this problem from their solutions.
If any one could give me a light, that would be great as i'm already desperate with this.
You can create a top level view to capture the touches and the coordinates of touches then you can check if the coordinates of touch is inside of the sub views. You can do that using
BOOL CGRectContainsPoint(CGRect rect, CGPoint point)
Method. Rect is a frame of the view, and point is point of touch.
Please not that the frames and touch locations are relative to their super views, therefore you need to convert them to coordinate system of app window.
Or maybe it can be more helpful
Receiving touch events on more then one UIView simultaneously

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.

Resources