iOS: Animating Multiple UIBezierPaths (One After the Other)? - ios

I have an array of UIBezierPaths, but I'm having trouble doing so.
I've tried calculating the beginTime by doing the following, but all it does is animate the first line, but not the rest of the lines (they just appear without an animation).
pathAnimation.beginTime = n * lineDuration;

pathAnimation.beginTime = n * lineDuration;
Well, that's your problem. That time is in the deep dark past.
You want a time in the future. Start by getting the CACurrentMediaTime() and now add the delay amount to that.

Related

How to implement countdown function like Yahoo's APP News Digest

I can use CAShapeLayer and UIBezierPath to draw the circle, I can also use this property CAShapeLayer.strokeEnd to control the progress. But the fast scrolling of path and time , I do not know how to implement.
Now I think the approach is to calculate the time difference between the two , and then use the time difference to circulation .
For example, The time difference between the two is 1000 seconds , should I have to set strokeEnd and the middle of the Label 1000 cycles ? Or that implement good results it ?
thanks in advance!
Note : StrokeEnd accepts value between 0 - 1
Lets Say,
See in your case circle represents the remaining time it will take to appear new feed. lets say 3PM.
so 3 PM will be your nextFeedTime = 3PM and,
you got this feed at 12PM so feedTime = 12PM.
So now you will have start and end value of feedTime=12PM - nextFeedTime=3PM
So feedTime is 0 for strokeEnd and nextFeedTime is 1 for StrokeEnd.
When you open app you will got currentTime which is initially initialised with feedTime and later it will be replaced all the time with current time stamp.
Lets assume currentTime is 1 PM.
Now we can calculate ratio to animate strockEnd property
strokeEnd = currentTime / nextFeedTime
and animate strokeEnd accordingly. hope this will helps you!

Using shader modifiers to animate texture in SceneKit leads to jittery textures over time

I'm writing a scene in SceneKit for iOS.
I'm trying to apply a texture to an object using a sprite sheet. I iterate through the images in that sheet with this code:
happyMaterial = [SCNMaterial new];
happyMaterial.diffuse.contents = happyImage;
happyMaterial.diffuse.wrapS = SCNWrapModeRepeat;
happyMaterial.diffuse.wrapT = SCNWrapModeRepeat;
happyMaterial.shaderModifiers = #{ SCNShaderModifierEntryPointGeometry : #"_geometry.texcoords[0] = vec2((_geometry.texcoords[0].x+floor(u_time*30.0))/10.0, (_geometry.texcoords[0].y+floor(u_time*30.0/10.0))/7.0);" };
All is good. Except over time, the texture starts to get random jitteriness in it, especially along the x-axis.
Someone mentioned it could be because of "floating-point precision issues," but I'm not sure how to diagnose or fix this.
Also: I'm not sure how to log data from the shader code. Would be awesome to be able to look into variables like "u_time" and see exactly what's going on.
It's definitely a floating point precision issue. you should probably try to do a modulo on (u_time*30.0) so that it loops within a reasonable range.
if you want to iterate over images your texture coordinate must stay the same for a short period of time (1 second for instance).
u_time is similar to CACurrentMediaTime(), it's a time in seconds.
Now let's say you have N textures. Then mod(u_time, N) will increase every second from 0 to N-1 and then go back to 0. If you divide this by N you've got your texture coordinate, and you don't need SCNWrapModeRepeat.
If you want your image to change every 0.04 second (25 times per second), then use mod(25 * u_time, N) / N.

Dispatch and Delay between calls

I'm making a clone for that old game Simon (a.k.a. Genius, in Brazil), the one with the for coloured buttons which the player needs to press following a sequence of colors.
For testing, interface has 4 coloured buttons
I created an array for the button outlets, for easy access:
var buttonArray:[UIButton] = [self.greenButton, self.yellowButton, self.redButton, self.blueButton]
Also, created another array to store the sequence of colors
var colors:[Int] = []
When a game starts it calls a function which adds a random number from 0 to 3 (index on buttonArray), and add this number to the colors array
After adding a new color the color sequence, the app needs to show the sequence for the user, so he can repeat it
For that, it calls the playMoves function, which uses a for loop the run through the colors array and change the alpha from the button, simulating a 'blink'
func playMoves(){
let delay = 0.5 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
for i in self.colors{
self.buttonArray[i].alpha = 0.2
dispatch_after(time, dispatch_get_main_queue(), {
self.buttonArray[i].alpha = 1
})
}
}
It changes the alpha from the button to 0.2 and then, after half a second it returns the alpha to 1. I was using dispatch_after, passing the 0.5 seconds and on the code block it returns the alpha, as you guys can see on the code above.
On the first run, it appears to do it correctly, but when the colors array has 2 or more items, when it runs the loop, although it has a 0.5 sec delay, it blinks all the buttons on the same time.
It's probably some dumb mistake I'm making, but I'm clueless on the moment.
I would appreciate very much all the help!
Thanks!
All of these dispatch_after calls are scheduled at nearly the same time, making them appear to blink at the same time. There are a couple of approaches that would solve this:
You could, for example, adjust the when parameter (the dispatch_time_t parameter) for each button to be offset from the original time (such that delay was, effectively i * 0.5 * Double(NSEC_PER_SEC)).
You could also use key-frame animation, but I'd suggest you first try fixing the delay in your dispatch_after approach first.

How to move image with low values?

The problem is simple: I want to move (and later, be able to rotate) an image. For example, every time i press the right arrow on my keyboard, i want the image to move 0.12 pixels to the right, and every time i press the left arrow key, i want the image to move 0.12 pixels to the left.
Now, I have multiple solutions for this:
1) simply add the incremental value, i.e.:
image.x += 0.12;
this is of course assuming that we're going to the right.
2) i multiplicate the value of a single increment by the times i already went into this particular direction + 1, like this:
var result:Number = 0.12 * (numberOfTimesWentRight+1);
image.x = result;
Both of these approaches work but produce similiar, yet subtly different, results. If we add some kind of button component that simply resets the x and y coordinates of the image, you will see that with the first approach the numbers don't add up correctly.
it goes from .12, .24, .359999, .475 etc.
But with the second approach it works well. (It's pretty obvious as to why though, it seems like += operations with Numbers are not really precise).
Why not use the second approach then? Well, i want to rotate the image as well. This will work for the first attempt, but after that the image will jump around. Why? In the second approach we never took the original position of the image in account. So if the origin-point shifts a bit down or up because you rotated your image, and THEN you try to move the image again: it will move to the same position as if you hadn't rotated before.
Alright, to make this short:
How can i reliably move, scale and rotate images for 1/10 of a pixel?
Short answer: I don't know! You're fighting with floating point math!
Luckily, I have a workaround, if you don't mind.
You store the location (x and y) of the image in a separate variable... at a larger scale. Such as 100x. So 123.45 becomes 12345, and you then divide by 100 to set the attribute that flash uses to display.
Yes, there are limits to number sizes too, but if you're willing to accept some error rate, and the fact that you'll be limited to, I dunno, a million pixels in each direction, you can fit it in a regular int. The only rounding error you will encounter will be a single rounding error when you divide by 100 (or the factor you used). So instead of the compound rounding error which you described (0.12 * 4 = 0.475), you should see things like 0.47999999. Which doesn't matter because it's, well, so small.
To expand on #Pimgd answer a bit, you're probably hitting a floating point error (multiple +='s will exaggerate the error more than one *='s) - Numbers in Flash are 53-bit precision.
There's also another thing to keep in mind, which is probably playing a bigger role with such small movement values; Flash positions all objects using twips, which is roughly about 1/20th of a pixel, or 0.05, so all values are rounded to this. When you say image.x += 0.12, it's actually the equivalent of image.x += 0.10, hence which the different becomes apparent; you're losing 0.02 of a pixel with every move.
You should be able to get around it by moving to another scale, as #Pimgd says, or just storing your position separately - i.e. work from a property _x rather than image.x so you're not losing that precision everytime:
this._x += 0.12;
image.x = this._x;

What equation do endless running games use to set the player's speed?

I'm making an endless running game (e.g. canabalt, temple run, Jetpack Joyride) and I'm trying to get the "feel" of it right. So far, I'm using the following equation to set the speed:
speed = (time+500)*(.05+(time/300))
Any tips for how to make the increase feel just right, other than trial and error?
Well, I did something similar in one of my games but I did not increase speed constantly, I increased it once every minute or once the player reaches a certain amount of points. Like so:
- (void)setTravelTimeTo:(NSNumber*)targetTime
{
if (maxTravelTime > targetTime.floatValue)
{
maxTravelTime -= 0.1f;
[self performSelector:#selector(setTravelTimeTo:) withObject:targetTime afterDelay:2];
}
}
Where maxTravelTime is the time or in your case speed. Just modify it to suit your needs. The travel time in this case was the time a moving platform needed to get across the whole screen.
Hope it helps.
Generally you are going to accumulate the speed and position as you go. So something like
a = <some function of current speed (drag), player actions, and terrain>
v = v + a*deltaTime
x = x + v*deltaTime
DeltaTime is just the time since the last computation - possibly the last frame. An implication of this is that v should be at most linear with time (not quadratic as in your formula). Position is at most quadratic. The computation for "a" should ensure that as v approaches some maximum speed (possibly level dependent), "a" goes to zero.

Resources