Can't change currentPlaybackRate... Any value < 0 make playing little slower than normal speed. I want to change playing speed from 1 to 1/2...1/4 and 1/8. But any changes not working. The Player continues playing with own speed(little slower or normal. Even if I set 0.00001 for currentPlaybackRate the playing speed not change). So, How to make slow motion effect on MPMoviePlayerController.
// Little slower than normal, but same for any value
moviePlayerController.currentPlaybackRate = 0.5;
moviePlayerController.currentPlaybackRate = 0.25;
moviePlayerController.currentPlaybackRate = 0.75;
moviePlayerController.currentPlaybackRate = 0.125;
// Normal
moviePlayerController.currentPlaybackRate = 1;
MPMoviePlayerController is deprecated in iOS 9. You should use AVPlayerViewController instead and use avplayer.Rate property to set the playback rate of the current video.
Related
Sorry for my poor english.
In my work, We made a app which show a high resolution image into a UIScrollVIew. Besides, the user can play a MP3 that animate the position and zoom of UIScrollView from one second with a specific duration showing the detail of image that MP3 is talking about. Currently, the audio play from second 0 to the end sequently. User can´t interactuate with UIScrollView when the MP3 is playing
Now we want that the user can change the current time when is playing, I´m not sure how calculate the position when the user select a second placed in the midst of one animation.
Example:
Second 1: Duration 4; Second 8: Duration 2; Second 20 Duration 10; Second 31 Duration 3;
If the user select the second 24, we would want animate during 6 seconds, but keeping in mind the original position that UIScrollView should have since second 20 to 24 from original animation.
We are using uiview animation (animateWithDuration) with zoomToRect (animated:NO) method from UIScrollView
I´m not sure how calculate those intermediate values.
Thanks.
I do not know, whether I really get you right or wrong. But you can set the animations progress to a progress value that is in relation to the start point and the total duration of the animation. I. e. in your case
float animationStartPoint = 20.0; // Start of the animation
float duration = 10.0; // Its duration
float partialStartPoint = 24.0; // user selected start point
NSAnimation *animation = …;
…
animation.currentProgress = (partialStartPoint-animationStartPoint)/duration;
[animation startAnimation];
I want to make part of video slow down while rest of it are normal speed, just like the slow mode video taken by iOS camera. How to do that? I've search AVFoundation but found nothing.
Thanks!
If you are only talking about creating this effect during playback (and not exporting it), you should be able to do so by just changing the rate property of AVPlayer at specific times. Use addBoundaryTimeObserverForTimes:queue:usingBlock: to get notified when it's time to change the rate.
CMTime interval = CMTimeMake(10, 1);
NSArray *times = #[[NSValue valueWithCMTime:interval]];
_boundaryTimeObserver = [_avPlayer addBoundaryTimeObserverForTimes:times
queue:nil
usingBlock:^{
[_weakPlayer setRate:0.5];
}];
The rate property works as follows:
rate = 0.0; // Stopped
rate = 0.5; // Half speed
rate = 1.0; // Normal speed
For slow motion playback, the AVPlayer property canPlaySlowForward must be set to true.
Remember to remove the time observer when you're finished with it, and make sure to use an unretained reference to self or to the player within the block in order to avoid retain cycles.
I have a problem in pausing a sprite kit game with physics. The game contains a ball which moves in the SpriteScene and has the following parameters:
self.ball.physicsBody.friction = 0;
self.ball.physicsBody.linearDamping = 0;
self.ball.physicsBody.restitution = 1.0f;
self.ball.physicsBody.affectedByGravity = NO;
self.ball.physicsBody.usesPreciseCollisionDetection = YES;
The problem is that when I pause the game, I call these methods:
self.scene.physicsWorld.speed = 0;
self.ball_velocity = self.ball.physicsBody.velocity;
self.ball.physicsBody.velocity = CGVectorMake(0, 0);
self.ball.speed = 0;
self.ball.physicsBody.dynamic = NO;
[self.scene.view setPaused:YES];
and when resume, call these:
self.scene.physicsWorld.speed = 1;
self.ball.physicsBody.velocity = self.ball_velocity;
self.ball.physicsBody.dynamic = YES;
self.ball.speed = 1;
[self.scene.view setPaused:NO];
This stops the ball animation, but when resume, the ball position is changed and it seems if that was moving during the pause duration.
BTW, it works fine on iOS 8 but on iOS 9 it always fails.
Any suggestions ?!!
After chatting, we have come to the conclusion that between iOS8 and iOS9, Apple has done a change that pausing the scene now pauses the update loop. Since the update loop is being paused, the change in time is not being calculated correctly. What is now happening, is the change in time will be the time at unpause - the time at pause, simulating a lag state. The velocity will take the math into effect, and move objects based on this difference in time. To combat this issue, just make a parent node that will house all of your scenes's objects, and pause the parent. This will allow the update to still be called, thus allowing the change in time to stay consistent with the frame rate.
Here's my code:
-(void)play {
animation = [CAKeyframeAnimation animationWithKeyPath: #"contents"];
for (UIImage *image in folder.images) {
[images addObject:(id)image.CGImage];
}
animationArray = [images subarrayWithRange:NSMakeRange(selected, selectedEnd - selected)];
timeBetweenAnimation = 1.0/framesPerSecond;
totalAnimationTime = folder.images.count * timeBetweenAnimation;
animation.duration = totalAnimationTime;
animation.values = animationArray;
animation.delegate = self;
beforeAdd = CACurrentMediaTime();
[displayImage.layer addAnimation:animation forKey:#"contents"];
afterAdd = CACurrentMediaTime();
}
-(void)animationDidStart {
afterStart = CACurrentMediaTime();
}
I am using Core Animation to animate an array of images and I want to get the current image in the animation when I pause the image. I realize that a method of doing this would be to get the image from "animationArray" using timing ratios (played time / total duration time), but I can't capture the begin time. I've tried capturing the begin time, using CACurrentMediaTime(), before and after the call to addAnimation:forKey: and also after animation did start, but it's innaccurate (especially when I have a large array of images). With a larger array of images, the "beforeAdd" and "afterAdd" times are at least a second off. Also, "afterStart" is anywhere between .04 and .08 seconds off independent of the size of my images array.
In the worst case scenario, I could use the "afterStart" begin time. However, if I'm trying to animate 100 images in 1 second, getting the image using this method would be inaccurate by 4 frames. Therefore, I either need a method that doesn't use timing in order to get the current frame of the animation, or I need a way to get a more accurate begin time. Is this possible?
NOTE: I don't want to use UIImageView animation to do this because that animation technique doesn't have smooth transitioning between frames. If there were a way to have smooth transitioning between frames using UIImageView animation I would reconsider, although I'm pretty sure there will still be an issue when calculating the begin time.
Working on a game for iOS, using the sprite-kit framework to build it. The game runs smoothly for about the first minute in a half (maintaining the 60 fps rate), but as the player progresses into the game, the frame rate slowly starts to decrease. With time it even drops as low as 8 fps. I thought this was a result of the added debris and obstacles in the game, so I made an effort to remove a lot of them from the parent after time. This is how the game is set up:
There are 6 NSMutableArrays for the different types of debris that fall in the game. This is the format for each of them:
-(void)spawnDebris6 {
SKSpriteNode * debris6 = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImageNamed:#"debris6.png"] size:CGSizeMake(20, 20)];
debris6.zPosition = 1.0;
SKEmitterNode *debrisTrail = [SKEmitterNode kitty_emitterNamed:#"Dtrail"];
debrisTrail.zPosition = -1.0;
debrisTrail.targetNode = self;
[debris6 addChild:debrisTrail];
debris6.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:25];
debris6.physicsBody.allowsRotation = NO;
debris6.physicsBody.categoryBitMask = CollisionDebris;
//set up a random position for debris
//RandomPosition = arc4random() %248;
//RandomPosition = RandomPosition + 10;
debris6.position = CGPointMake (302, self.size.height + 65);
[_debris6 addObject:debris6];
[self addChild:debris6];
//next Spawn:
[self runAction:[SKAction sequence:#[
[SKAction waitForDuration:deb6Time],
[SKAction performSelector:#selector(spawnDebris6) onTarget:self],
]]];
if (_dead == YES) {
[self removeAllActions];
}
if (debris6.position.y > 568) {
[self removeFromParent];
}
}
Each of the NSMutableArrays appear over time - The first one appears at 0s, 2 # 10s, 3 # 40s, 4 #80s, etc. And when a new one appears I've added code to make former ones appear less frequently and also removed some (to lower the frame rate) yet I still notice a slower frame rate after about 90 seconds.
I don't see why this would be affecting the frame rate as I've minimised the particle birth rate, and life span, and made an effort to delete and slow down spawn rates of the debris over time. Why is the FPS rate slowly depreciating?
If more info is needed please let me know and I'll update this post.
I had a similar problem. It is probably the SKEmitterNodes. Continue to play around with them and lower birth rates and life spans, maybe even range etc. If the problem persists, see if you can take them out. It may not look as good, but sometimes you have to sacrifice looks for functionality. Also I'd recommend maybe having the debris appear at different times and heights, so you still have a full screen, but also a smooth running screen.