More precisse shape or mask for a SKSpriteNode object - ios

I'm bulding a simple application using SpriteKit for iOS 7 / 8 but I'm having some issues with my sprites when I try to touch and launch some events from one of two nodes that are too close to each other.
When I try to touch one of them, I end up touching the upper layer one square mask, and if I change the [self addChaild:] order it happens the same but with the other one.
I want to know if I can create a more precisse mask for my nodes so this won happen when I try to touch them. I know I can create a physics world and a physics body for each of them to control Collision Detection but I don't know if this is the right approach.
BTW... I'm using the methods touchesBegan:withEvent: and touchesEnded:withEvent: for touching events detection.
PD: if you need any more info about my implementation please let me know.

Related

Detecting touch inside bounding box (alpha mask) of Sprite using SpriteKit

I am starting to learn Swift2 to develop on iOS using SpriteKit and I cannot seem to detect if I touched a visible part of my Sprite.
I can find which node was touched like this:
let touchedNode = self.nodeAtPoint(location)
But this detect the touch on the sprite. I would like to detect the touch on the "not transparent" part of the sprite only.
I tried creating a PhysicsBody with an alpha mask bounding box and testing if the bounding box of the node I selected contains the location of the touch like this:
sprite.physicsBody = SKPhysicsBody.init(texture: sprite.texture!, size: sprite.size)
sprite.physicsBody?.affectedByGravity = false
if (touchedNode.containsPoint(location)){
But it didn't help. If I click in a transparent part of my sprite, the event still triggers.
The documentation says "A new physics body is created that includes all of the texels in the texture that have a nonzero alpha value.", so shouldn't it work?
Thanks for your time.
PS: I also tried to be more generous on my alpha threshold, but this also did not work (in case my transparency wasn't perfect).
UPDATE:
To add a little more details, I am building a level editor. This means that I will create many nodes, depending on what the user chooses, and I need to be able to select/move/rotate/etc those nodes. I am actually using SKSpriteNodes as my PNG pictures are automatically added in xcassette that way. I decided to use the PhysicsBody's Alpha Mask bounding box, as this value is shown in the Scene Editor (Xcode) when you select a node, and when selected, the Alpha Mask highlights exactly the part of my Sprite that I want to be able to detect a touch inside.
If I am using the wrong ideas/techniques, please tell me. This is possible as I am only starting to use Swift and SpriteKit.
UPDATE 2
I queried the physicsWord (as recommended) to get the right physicsBody and got the name of the attached node like this:
let body = self.physicsWorld.bodyAtPoint(location)
print(body?.node?.name)
But this is still printing the name of the node even if I touch outside the bounding box, which makes no sense to me.
Thank you anyway for your help.
The SKPhysicsBody doesn't define the bounds of the SKNode. You can do the hit check by querying the SKPhysicsWorld of your scene by calling bodyAtPoint on it. That will return the SKPhysicsBody you are interested in.
I was having the same problem. You actually can't perform the touch on the alpha mask of a Sprite Node and it says it right in the Apple documentation. You have to use a Composite Box. I used a shape Node and changed the "line width" to 0 so essentially the composite box is invisible. Make sure that the Z axis is higher for the composite box and then run the touch event through the composite box shape node instead of the original node.

How to drag gameObject using touch(unity2d)

I searched this on the internet but I still haven't found the answer I wanted.
So, I have a 2d tiled game and each tiles position is a multiple of 1.25 for example 7.5, 3.75. There is going to be a player walking on top it and i want to control the player by dragging it and if you release the touch it would be perfectly on a tile instead of in between the tiles. Right now, I can't even figure out how to drag the gameObject with touch. Can anyone help me and explain to me how to do that?
You need to have a collider on every object you plan to move. Then create a class whose sole purpose is to fire a Raycast. Detect when a touch happens. Then fire the Raycast.
RaycastHit hit;
if(Physics.Raycast(ray, out hit, 100))
Debug.DrawLine(ray.origin, hit.point);
You will notice that you have what you hit; with that you can send a message to that particular object.
hit.collider.SendMessage("move");
Inside the object that you hit, you now have to use the coordinates of the touch position to update the transform.position.

How would I build pool-cues / simplified pinball-style plungers with SpriteKit?

I'm working on a game in which the user should be able to trigger 'rods' that come out from the edge of the screen to displace elements on screen (balls). These projectiles roughly resemble pool-cues. Or perhaps pinball plungers, except that they start from the 'loaded' position (mostly offscreen), and when triggered, they eject out, then quickly retreat.
I'm unclear how I should build these with Sprite Kit.
The game uses the PhysicsEngine, and the onscreen balls should be effected both by gravity AND they should be displaced when they collide with the rods. However the rods should neither be effected by gravity, not displaced when they collide with the balls -- they should simply retreat regardless of whether they've made contact with the balls.
I realize I can set the affectedByGravity property for the rods. However because they will still displace slightly when they collide with the balls. How can I 'fix' or 'peg' them in place? Do I need to use an SKPhysicsSlidingJoint? If so, has anyone encountered any examples online? Is there a simpler way to do this?
A related physics engine, Box2D distinguishes static, kinematic, and dynamic bodies.
Kinematic bodies can move and will collide with other objects, but they are themselves not affected by dynamic bodies or forces like gravity. Thus, consider setting rod.dynamic = NO; but animate it with actions. See also here in the reference for SKPhysicsBody.

how to extract more touch points from UIResponder?

When I touch a UIView with the base of my finger tip, and get the touch point using touches anyObject, I get a single touch point, even though the base of my finger tip has an area that touches a lot many points. Is there a way to get all those points? If there is no such way, how are simple paint apps implemented in ios?
You are getting the only point / touch. Each touch is related to a single finger. This is controlled by iOS.
'Simple' drawing / painting apps use the path traced by the touch points together with the current line drawing width and texture to create lines or bezier paths.
If you're trying to create a drawing app with some form of pressure sensitivity then you'd need to integrate with a 3rd party stylus (like this one)

Detecting collision with two or more shapes with Chipmunk

I wonder if anyone can suggest the best approach to detect collision between multiple shapes.
I am using Chipmunk on an iPad with iOS 4.2 and Cocos2D 1.0 - I basically have a cpShape travelling around the iPad screen - there are two segment cpShape's (arranged in a V-shape) and I'd like to know when my travelling shape is touching BOTH the segment shapes (ie the corresponding sprite is sitting comfortably inside the V).
Any ideas? I have set up my callback with cpSpaceAddCollisionHandler but I don't seem to have a list of all of the shapes the current colliding shape is touching. Is that possible or do I have to code and store the information manually?
Thanks
i think your going to have to store some data in your sprite object.
There are callbacks in chipmunk for when 2 objects first touch, and then they part.
Begin: Two shapes just started touching for the first time this step. Return true from the callback to process the collision normally or false to cause Chipmunk to ignore the collision entirely. If you return false, the pre-solve and post-solve callbacks will never be run, but you will still recieve a separate event when the shapes stop overlapping.
Separate: Two shapes have just stopped touching for the first time this step.
You could make your object that is to 'sit within the V' have a 2 bool's one for each side of the V, make it true when they 'begin' and false when they separate.
If they are both true, and the object isSleeping (stop moving) (i come from a box2d background, not sure the chipmunk equivalent is).
Hope that helps.

Resources