How to make an SKNode continue in the same direction after finishing following a path - objective-c

In my project I have an SKNode following a CGPathRef made with touchesMoved. What I want to have happen is once it reaches the end of the CGPathRef, it follows in the same direction that it ended in. I am using the SKAction followPath and tried to implement this by adding a line from the last point on the path (touchesEnded) all the way to the end of the scene using some previous points and a unit vector however this was not only complicated but also very inconsistent. Is there another method I can use to make it just continue on its path after it finishes the CGPath? Thanks!

I suggest storing your node's CGVector (dx, dy) which represents the direction of movement for your node. For example, if the last moving vector was 15,15 that translates to your node having moved up and to the right. You can use this value to continue moving. If the values are too low or too high, you can add a min/max filter.

Related

How do I control animation timing along a NSBezier path?

In Apple's docs about CAKeyframeAnimation they say:
"For most types of animations, you specify the keyframe values using
the values and keyTimes properties. During the animation, Core
Animation generates intermediate values by interpolating between the
values you provide. When animating a value that is a coordinate point,
such as the layer’s position, you can specify a path for that point to
follow instead of individual values. The pacing of the animation is
controlled by the timing information you provide."
What I want to do is to make an animation of an image along the path above while controlling the timing. More specific, the path starts at (0,0) and goes to (100,0) during 1 sec, then follows a half-circle path to point (300,0) during 3 sec, and the goes to point (400,0) during 1 sec.
I have already definied this path as a NSBezier path and I can make the animation, but I don't know how to control the timing of the different parts of the path. From Apple's docs it seems that this should be possible, but how?
Get reference from here Controlling Animation Timing
There is a simple solution. The only thing you have to choose are the points on your path that you want to use for time control. In my case I have 4 points p0=(0,0), p1=(100,0), p2 =(200,0), and p3 =(300,0). I then use
animation.values = #[[NSValue valueWithPoint:p0],
[NSValue valueWithPoint:p1],
[NSValue valueWithPoint:p2],
[NSValue valueWithPoint:p3]];
animation.keyTimes = #[#0.0, #0.2, #0.8, #1.0];
The fact that we are using a half circle (or any other complicated) path DOES NOT have any influence (as long as it doesn't cross itself). You just choose some points on the path, use them to define animation.values, and then choose (relative) times for those points and use them to define animation.keyTimes. That's all, really.

Following a CGPath with SKAction without starting from beginning of CGPath

I have an SKShape node that represents an ellipse. A player is placed on the current point of a Bezier Path that is based on the ellipse's CGPath:
I have two actions that the player node can perform. The player can either follow the path clockwise or counterclockwise.
rotateCounterClockwiseAction = SKAction.followPath(counterClockwisePath.CGPath, asOffset: false, orientToPath: true, duration: 1)
rotateClockwiseAction = SKAction.followPath(clockwisePath.CGPath, asOffset: false, orientToPath: true, duration: 1)
When I start one of the actions as:
player.runAction(SKAction.repeatActionForever(rotateClockwiseAction), withKey: "ClockwiseRotation")
The player moves along the appropriate path and direction. When I stop one of the actions:
player.removeActionForKey("ClockwiseRotation")
The player stops on the path where it was last moved to. I want to be able to start either of the actions from the player's current point, and follow the same path, but right now, if I start either one of the actions again (after an action has already been started and stopped) the player jumps to the same starting point as seen in the picture and follows the path from there. How can I get the player to follow the path from the point that it is already at?
You can achieve this easily by using the speed property of SKNode.
Instead of removing and recreating the action, you can pause and resume it by adjusting the speed value. This will cause your bezier path animation to resume from its current position.
// Set the player node's speed to 0.0 causing all actions to be paused.
[playerNode setSpeed:0.0];
...
// Then when you're ready to resume set the player node's speed back to 1.0.
// This will cause the action to continue from its current position.
[playerNode setSpeed:1.0];

physicsBody rotation limitation

I've got the following node set as follow.
box.physicsBody.allowsRotation = YES;
No mater what force applies to this box, I want it to never fall down or rotate more than a certain angle, just like a tree or a spring that might bend all the way down but has a tendency to go back to it's initial angle or position.
Is there a any trick or method to that?
I was thinking maybe joining an invisible un-rotatable physics body under the box and use a joint spring method for that which I have no Idea how that works!
Or, maybe there be a trick to play with the pivot. Any idea?
In the update: method you will have to continuously check the desired node's properties. In your case it is going to be the zRotation property of your node.
Add this code in your update: method:
if(yourNode.zRotation > 0.5)
yourNode.zRotation = 0.5;
if(yourNode.zRotation < -0.5)
yourNode.zRotation = -0.5;
Change the 0.5 value to your desired value or replace it with a static const float.

Touch a sprite without boundingBox

So i'm trying to move multiple sprites on the screen at the same time. The problem is that if the 2 sprites are close to each other the position becomes the same (so the bounding box is the same) and i can't seem to pull them apart.
I'm using the "standard" CGRectContainsPoint(sprite1.boundingBox,location).
What i need is to get the sprite on top regardless of boundingBox. Any ideas?
One way would be to start assigning explicit z values to sprites you add, using CCNode's -(void) addChild: (CCNode*)node z:(NSInteger)z method.
Then, when you get multiple sprites back from your bounding test, only move the one with largest z value.
hah..i fixed in the easiest way possible :\
if (CGRectContainsPoint (sprite1.boundingBox,location)){
sprite1.position=location;
}else if (CGRectContainsPoint (sprite2.boundingBox,location)){
sprite2.position=location;
}
the way this behaves is that if the bounding boxes are the same..it only takes one..not the 2nd one

Projectile hit coordinates at the apex of its path

I have a projectile that I would like to pass through specific coordinates at the apex of its path. I have been using a superb equation that giogadi outlined here, by plugging in the velocity values it produces into chipmunk's cpBodyApplyImpulse function.
The equation has one drawback that I haven't been able to figure out. It only works when the coordinates that I want to hit have a y value higher than the cannon (where my projectile starts). This means that I can't shoot at a downward angle.
Can anybody help me find a suitable equation that works no matter where the target is in relation to the cannon?
As pointed out above, there isn't any way to make the apex be lower than the height of the cannon (without making gravity work backwards). However, it is possible to make the projectile pass through a point below the cannon; the equations are all here. The equation you need to solve is:
angle = arctan((v^2 [+-]sqrt(v^4 - g*(x^2+2*y*v^2)))/g*x)
where you choose a velocity and plug in the x and y positions of the target - assuming the cannon is at (0,0). The [+-] thing means that you can choose either root. If the argument to the square root function is negative (an imaginary root) you need a larger velocity. So, if you are "in range" you have two possible angles for any particular velocity (other than in the maximum range 45 degree case where the two roots should give the same answer).
I suspect one trajectory will tend to 'look' much more sensible than the other, but that's something to play around with once you have something working. You may want to stick with the apex grazing code for the cases where the target is above the cannon.