SpriteKit follow partial path - ios

I've used CGPath to create a race track by stroking the path and offsets of it to draw the road and lines. My hope was that I could use this CGPath in SpriteKit so that I could make a car sprite follow the track. I can get a sprite to follow the entire path from start to finish using SKAction.followPath (screenshot added at bottom of post.)
However, my issue is I sometimes want a car sprite to move from the start to the half-way point (or 25% or some fraction of the path.)
I don't see a way of doing with with an SKAction so I was looking into a way of taking a CGPath and splitting it to whatever fraction of the path I needed but I've yet to find anything that seems to do that. I'm reasonably hopeful it can be done since in a CAShapeLayer you can set strokeStart and strokeEnd to specify where you want the path stroked from percent start to percent end so it looks like something like this has already been implemented.
Is there any way of either getting SpriteKit to set the start and end point of followPath or modifying a CGPath so that it returns a subpath?
car race screenshot

Related

Animating line graph with circular points

I have stumbled upon an interesting problem and I am not sure how to solve it. I have a line graph on which data points are marked with circular dots. At the moment I am creating one CAShapeLayer for the line itself and also CAShapeLayer for each dot.
The line is being animated with the strokeEnd animation key path. And it is working. However, the slightly negative effect is that once I open the graph I see all the data points already drawn and then a line is being animated through them.
Ideally I would like to change this behaviour in such a way that at the beginning nothing is shown and as the line gets animated data points are being drawn once the line passes through them.
I was thinking about this problem for some time now and I cannot find an elegant way of solving it. It seems to me that there should be a fairly easy way of achieving what I want. Maybe I should create a compounded path (but then how do I specify that a line needs to be stroked whereas dots need to be filled?).
Could anyone please guide me in the right direction?
There are lots of ways to handle this.
Assuming that the X increments of your graph are constant, and you're using linear timing, you could simply divide the total animation time by the number of data-points, and calculate the times when you need to add points to the graph when the line progresses to that X position. Simply add dot shape layers to the parent view's layer at the appropriate time intervals.
You could also change your drawing method to add new line segments to your graph path one at a time, on a timer, and add dot shapes at the same time. That would give you a step-by-step animation rather than a smooth line drawing.

Moving a node around a path incrementally without using SKAction followPath

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.

How do I make an SKNode follow an SKShapeNode in Sprite Kit?

I have a line, lets say a rounded rect, drawn on screen (SKShapeNode drawn from a CGPath). Now I want a node to follow that rounded rect, either clockwise or counter clockwise. I've done this with SKAction's followPath:asOffset:orientToPath:duration: method, which works fine if the node starts at the path's origin.
The thing is, the node can be placed anywhere on the rounded rect, and when I press and hold a button I want it to start following the rect from the point it's currently located. When I release the button the node stops where it is. Right now if I stop the node and start it again it follows a new rounded rect starting at the nodes point.
Is there an easy way of achieving this?
It seems that you may make use of newly introduced SKConstraint class (https://developer.apple.com/library/prerelease/ios/documentation/SpriteKit/Reference/SKConstraint_Ref/).
For a quick introduction take a look at session 606 from WWDC2014: "What's new in SpriteKit".
It's really quick and simple way to adjust position/rotation/distance of the sprite in relation to another sprite.
What you exactly need is
+ (instancetype)orientToNode:(SKNode *)node
offset:(SKRange *)radians
This is a difficult problem. I can think of two solutions:
Each time you press and hold, construct a new CGPath for the node to follow which starts at the point your node is currently stopped.
Keep a reference to the SKAction object that you're running. When you stop pressing on the screen, instead of stopping the action, set it's speed property to 0.0. This will effectively pause the animation. When you press down again, set the speed back to 1.0.

Efficient animation of time-variant drawing using CAKeyFrameAnimation

My current goal is to animate the drawing of a picture in my iOS app so that a user could see something like http://www.youtube.com/watch?v=xlDmk5WdaHk happening on their screen.
The acceleration of my drawings vary with time so I've built my animation using CAKeyFrameAnimation and keyTimes. At the moment, I only have one Bezier path which specifies all the points of my drawing, I add the path to my CAShapeLayer object, and then pass the path off to my animation object when I start my animation.
My problem: the completed drawing immediately appears on the screen, and my pen cursor then moves along the picture according to my keyTimes values, instead of having the stroke color filling in tandem with my pen cursor movement on the screen to produce the same effect as the video.
I noticed this SO question, where the recommended solution was to produce a separate path for every point in the animation: How to Animate CoreGraphics Drawing of Shape Using CAKeyframeAnimation
Given that I have 100-300 individual points, is there a more efficient method of producing a time-variant drawing, than creating an array of a couple hundred paths (with a couple hundred values in each path) with the paths in this form:
path0 = point0...point0...point0...point0...
path1 = point0...point1...point1...point1...
path2 = point0...point1...point2...point2...
path3 = point0...point1...point2...point3...
Then taking that array of paths, passing it into myAnimation.values and animating values with my keyTimes? Or is that really the best way to go about this?
Thanks in advance
There certainly is a more efficient way if your points are on a bezier path. CAShapeLayer has two little properties called strokeStart and strokeEnd. If you initially set strokeEnd to zero then your path will not show. At 1.0 it will show completely. Increasing the values from zero to one will trace your curve accordingly. This is an animatable property so synchronize its value with the key times of your other animation and your drawing will appear as the "pen" is moving.

How to reverse the point order of a CGPath

I want to draw a Circle with Letter punched out of it. to do this, I need to stroke the circle clockwise and the letter counterclockwise.
That is all good and well, but when I get the letter path using Core Text I can't figure out how to essentially reverse the path. NOT MIRROR or ROTATE or anything...that is straightforward enough. I want the point stroke order to be counterclockwise.
it is actually hilariously difficult. I've had entirely too many visual 'off by one' errors.
About all I can think of is to call CGPathApply on the path and save information about all of the points, and then redraw the path in the opposite direction. Remember to call CGPathCloseSubpath when you're done.
iOS 6 introduced -bezierPathByReversingPath
It had some issues at first but it seems to be the answer to this question.

Resources