I'm developing a SpriteKit game using Swift and Xcode 6.3. I want a sprite node to follow along a defined path. I also want the position of the node following the defined path to be relative to the, in this case y coordinate change, of the other node.
The pink one is the one I move with my finger. Its "path" is from the origin to the horizontal pink line. If I drag it up 20% of its path I want the other two to move 20% in the same time. If I drag it back it will make the others go backwards on their path as well. The black dots represent this.
I'm sorry for not posting any code. I read about following a path in SpriteKit but nothing of what i found would have helped here. Thanks for your help.
Related
I was trying to achieve the following functionality and wanted to ask for some help:
There are n barrels on the screen.
Randomly, a monster will pop up out of the barrel, and then go back down. I got this working, but I want to make a revision where sometimes instead of going up/down, a monster will jump out of the barrel along an arc, and land somewhere on the ground nearby. After some time, he will jump back and follow the path in reverse back into the barrel.
My original code workedby simply created a barrel i.e. addChild(barrel) to the scene, added a cropping node over it i.e. addChild(croppingNode) where croppingNode's position is over the barrel, and then add the monster to the cropping node as a child (croppingNode.addchild(monster))
This worked perfectly - the monsters come up, and then slide back down and the node hides their lower half so they appear to have went back inside the barrel.
My revision was to have a monster randomly jump out of the barrel on an angle and land on the ground, but the problem is because the monster is added to the cropping node, it is clipped if I try to move it outside the bounds of a cropping node.
If I add the monster outside of the cropping node, I believe he will no longer be cropped, correct?
What would be a way to achieve something like this? Use a larger cropping node image that is larger than the barrel and accounts for his arc onto the ground?
Thanks!
I have noticed that the centerOnNode: method as shown,
- (void)centerOnNode:(SKNode *)node {
cameraOffset = [node.scene convertPoint:node.position fromNode:node.parent];
node.parent.position = CGPointMake(node.parent.position.x - cameraOffset.x, node.parent.position.y - cameraOffset.y);
}
greatly impacts the relative positioning of child nodes. As soon as this method runs, the child nodes do in fact seem to be impacted. The following image show the logic of NO movement then with moving left and slightly down:
I drew a light blue box to estimate the physics body that it seems the paths are referencing instead of the updated frame. The lines and circles that you see represent 2 methods I am using for pathfinding.
The line with the dots are just ray tests that I am doing to see if a ray along the green line intersects the square physics body.
The single point you see at the top corner is from using GameplayKit to construct a path that avoids the black square as an obstacle.
I am struggling to figure out how to avoid the camera repositioning from effecting the positioning of the children in the scene.
FYI: I have tested the pathfinding with moving the character but NOT the camera and it works perfectly (shown below)
Clearly the camera offset is the issue. If anyone can tell me what to do to keep the camera movement and the precision of the pathfinding I would greatly appreciate it.
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.
I am making a basic app that pushes shapes across the screen and detects collision with Sprite Kit. My first attempt was using moveTo on the nodes. The issue I had was with collision, the objects would rotate around each other instead of bounce.
Therefore I found I need to use applyForce OR applyImpulse.
In this situation I have a circle for example that is position off screen at its start of life. We then determine a target exit point, and want to 'flick'/'push' the node in that direction.
I cannot figure out how to applyImpulse towards the target end position I have as a CGPoint. I need to get this to a CGVector but I am not sure what needs to be done. I had a look around and found some Ray tuts but they just show applyForce or moveTo. I am not sure how to calculate this.
I found a site that explains 2D physics well.
http://www.rodedev.com/tutorials/gamephysics/
With this I worked out what the angle needed to be and have a speed that I can control and it works well.
You can move an object by changing manually the x and y position so you can reach your end point. In the update function you change yourObject.position.x and yourObject.position.y if I have understood correctly your question. If not please be more explicit. Hope that helps.
I want to have a path that my node can travel around on demand.
For example, I want to have a circle in the middle of the screen and when i tap the left side of the screen, my SKSpriteNode will move in a counter-clockwise direction on the circle (and the same if i tap the right side of the screen).
From what I've researched, I can create the circular path using SKShapeNode, CGPathRef, or even UIBezierPath. Creating the path isn't the issue. In all the instances I've seen researching this topic, most people just use [SKAction followPath:path duration:1.0] and this makes the node go around the the circular path ENTIRELY in 1.0 seconds. I want to be able to tap left/right and only move incremental amount of space per tap. (If anyone's played Super Hexagon, think of the fluid circular motion of that game)
*Note: I only use a circular path as an example so I don't particularly need specific pointers on how to move around a circle per se, but more of ANY path of any shape.
You can create any kind path shape you want using CGPath. This gives you the ability to create only the path for which you need to move your node. To use your circle example, create a 90 degree arc path and your node will move 4 separate times to complete a full circle.
If you do not want to use a path, you can also use the SKAction moveBy x,y,duration command. Tie a couple of those together and use them in a block sequence and you have yourself a generic path function.