I have icons that are children of node "shelf", which is a child of "self"(the scene). I also have decorations that are children of node "vehicle", which is also a child of "self".
When an icon is dragged off of the shelf and onto the vehicle, the icon node is removed and a decoration node is spawned in its place, which is made a child of "vehicle" instead of "shelf". This is a problem: when the decoration node is spawned, it jumps far away in the scene because the coordinate systems of "shelf" and "vehicle" are incongruous.
How can I convert the new decoration node from its position in the "shelf" node to its new position in "vehicle" so that it doesn't jump?
(I can post code if you need it, but it will be very long and messy.)
Assuming you're using Sprite Kit, you can use the SKNode method convertPoint:toNode: to convert points between coordinate systems.
So for instance, as soon as dragging ends on top of the vehicleNode:
CGPoint iconPos = iconNode.position; // this is position on shelf node
iconPos = [shelfNode convertPoint:iconPos toNode:vehicleNode];
// ... remove iconNode from shelfNode
// ... make new decorationNode
decorationNode.position = iconPos; // this is now position on vehicle node
// ... add decorationNode to vehicleNode
Related
I create game with spriteKit in Xcode. I need to create carousel and move 4 nodes around one pillar.
carousel
How can I move some bind nodes? It`s necessary to change zPosition when node approaches the pillar and when node comes out from behind the pillar. How it can be implemented?
To group your nodes together, just create a new SKNode, add it to the scene, and anything that needs to be grouped to this, just call move(toParent:) on the nodes that need to be moved.
let groupedNode = SKNode()
self.addChild(groupedNode)
node1.move(toParent:groupedNode)
As for zPosition, it is relative to the parent, so if your pillar is at 2, and your group is at 1, to make your individual nodes above the pillar, you need to make the node 2. This will make the node zPosition really 3 (node + group) placing it above the pillar.
I have a problem in my game and i am trying to find out what it is and it is about the position of a SKSpriteNode and i made a SKLabelNode to display the position so i could see what is going wrong. I did:
testlable.text = "\(leftObstacle.position)"
testlable.zPosition = 50
testlable.fontSize = 60
It displays the position of (00,00) when it is in the top left corner or outside of the screen not ever the right position and it isn't ever at (00,00) so what should i do to make it display the right position?
The position parameter is the position of a node relative to its parent node - so if leftObstacle is a child of another node in the scene that would explain why it always looks like it is at 0,0. In this case report the position of its parent (or its grand-parent etc.) to get what you need.
I created a rope based off this tutorial, except my rope has one ball attached on each end of the rope.
High Level: This is how they create the rope.
create an array of SKNodes
append each rope segment (node) to the array
add each node to the screen
join each node together to form a rope
(Then I add a ball on each end of the rope)
In my program I move the ball around and basically swing the rope around kind of like a stretchy pendulum.
Here's my issue: If I swing the rope around very hard, the rope stretches too much! How can I decrease the amount the rope stretches? I don't see a method to decrease the elasticity of the body.
If there is any other information that will be useful please let me know! Thanks in advance
You can try these two methods. The first method is to increase the property frictionTorque of SKPhysicsJointPin class.
The range of values is from 0.0 to 1.0. The default value is 0.0. If a
value greater than the default is specified, friction is applied to
reduce the object’s angular velocity around the pin.
An example for the tutorial you followed, before adding a joint to the scene, modify frictionTorque:
for i in 1...length {
let nodeA = ropeSegments[i - 1]
let nodeB = ropeSegments[i]
let joint = SKPhysicsJointPin.jointWithBodyA(nodeA.physicsBody!, bodyB: nodeB.physicsBody!,
anchor: CGPointMake(CGRectGetMidX(nodeA.frame), CGRectGetMinY(nodeA.frame)))
joint.frictionTorque = 0.5 // Add this line
scene.physicsWorld.addJoint(joint)
}
The second method is to limit the swing angle of the pin joint. After enabling shouldEnableLimits, adjust lowerAngleLimit and upperAngleLimit in radians.
Read more about SKPhysicsJointPin Class Reference for Determining the Characteristics of the Pin Joint.
Within a UISrollView, I have several programmatically-added subviews representing nodes in a tree:
Each node's frame includes the node itself plus the line connecting it to its parent. (I did this to facilitate animation of the line with the node.) In the picture below, the frame is drawn for one of the nodes:
When the user taps on one of the nodes, two child nodes are "born". I'd like to animate this by having the child nodes descend down from behind the parent node. My basic animation code is:
- (void)descendFromParent
{
// Do nothing if this is root node
if (!self.parent)
return;
// Move node to parent location
self.frame = CGRectMake(self.frame.origin.x + self.parent.nodeFrame.origin.x - self.nodeFrame.origin.x,
self.frame.origin.y + self.parent.nodeFrame.origin.y - self.nodeFrame.origin.y,
self.frame.size.width, self.frame.size.height);
// Animate the move back to original location
[UIView animateWithDuration:1.0
delay:0.0
options:0
animations:^{
self.frame = self.trueFrame;
}
completion:nil];
}
(nodeFrame is a frame containing just the circular part of the view.)
The problem of course is that as the child node is descending, it (especially the line) is visible on top of and above the parent node:
I've tried a lot of different ways to make this work -- using CGContextClip, etc. -- but none of them work, mainly because drawRect: isn't called during the animation.
How can I make this work?
I think your problem is not how to arrange the views in the correct view hierarchy, but the following:
After you have arranged the child disks behind the parent disk, you want them to slide down, and while they are sliding, the edge that connects their centers should have first zero length (when all 3 disks are at the same place), and should then be extended until it reaches its final length in the end.
If this is the case, one possible solution would be:
Lets call the initial x,y center coordinate of one disk (0,0), and the final coordinate (X,Y). Using the usual animation code, it is easy to move the child center to (X,Y) in time t.
Now assume you have an additional image view that shows the edge along the diagonal. In the end position, the center of the "edge view" is at (X/2,Y/2), and its size is (X,Y). If this view is placed behind all others, it will connect the two disks at their final position.
The animation consists now of 1) changing the center property from the initial position (0,0) to (X/2,Y/2), and 2) changing the scale of the view (using its transform property) from zero to the final size, also in time t.
This should do it.
You may want to look at the UIView methods
-insertSubview:belowSubview:
-insertSubview:atIndex:
-sendSubviewToBack:
In your case, you can either send the two subviews to the background with -sendSubviewToBack: after you have added them. Or you can just add them with -insertSubview:atIndex: and provide 0 as the index.
You can specific an index for a subview, try inserting the nodes you want to animate at index 0 and have the blue nodes at a higher index.
I've been looking at Figure 7-3 in this sprite kit documentation: https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Actions/Actions.html but it has left me pretty confused. They seem to give the same name to multiple things e.g., camera/character.
I am in the default SKScene, MyScene class. In initWithSize, I create a SKNode *myWorld, just like the documentation suggests. I then have a series of methods that add my background images to myWorld. Scrolling that works just fine, but what I want to do is stop the vertical scrolling when the bottom of the images in myWorld reach the bottom of the scene. For the life of me, I cannot figure out how to refer to the bottom of myWorld. For the bottom of the scene, I simply do
CGPoint sceneFarBottomSide = CGPointMake(0, -self.size.height/2);
where self.anhorPoint is set to [0.5, 0.5].
How do I refer to the bottom of myWorld?
The edge of myWorld is whatever you set it to be. In other words, myWorld is a node which isn't itself a view or a sprite. It's simply an object that contains sprite or shape children (for example, SKSpriteNodes or SKShapeNodes). When you are adding your sprites to myWorld, keep track of their position. Then use their position to define the "size" of myWorld. You can use this size information along with myWorld.position to know when the (bottom) edge of myWorld is coming up.
It ended up being extraordinarily easy to resolve. Thanks Andrey for pointing me to that Apple documentation on the Adventure game, that's what really tipped me off and cleared up some of my understanding. Here's the few lines of code to get the behavior I desired:
// Move world
if (monkeyPosition.y > 0 && monkeyPosition.x > 0) {
[myWorld setPosition:CGPointMake(-monkeyPosition.x, -monkeyPosition.y)];
} else if (monkeyPosition.y > 0 && monkeyPosition.x < 0) {
[myWorld setPosition:CGPointMake(0, -monkeyPosition.y)];
}