How do I make a bounce effect after slide effect in xcode? - ios

I have this code that can slide to left if swiped
[UIView animateWithDuration:1.0 delay:2.0 options:(UIViewAnimationCurveEaseInOut|UIViewAnimationOptionAllowUserInteraction)
animations:^
{
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(faceRight:finished:context:)];
self.bug.center = CGPointMake(75, 200);
}
completion:^(BOOL finished)
{
NSLog(#"Move to left done");
}
];
but I want to add 1 bounce effect, maybe add a code like:
self.bug.center = CGPointMake(78, 200);
but I dont know how to add this code, where should I write this? I'm new to animations. please help :)

-(void)onTimer
{
ball.center = CGPointMake(ball.center.x+pos.x,ball.center.y+pos.y);
if(ball.center.x > 320 || ball.center.x < 0)
pos.x = -pos.x;
if(ball.center.y > 460 || ball.center.y < 0)
pos.y = -pos.y;
}
-(your method)
{
pos = CGPointMake(14.0,7.0);
[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(onTimer) userInfo:nil repeats:YES];
}

You should use the block based animation methods, it says in the documentation that using blocks is the recommended way. Also, in iOS 7, UIView has a new +method that will do just that. Or you can use the UIkit Dynamics system.

Related

Sticking image to another image

I currently have some code which creates a UIImageView at a random location which is animated towards the bottom of the screen. When that object collides with another object which is controlled by the user, the collision is detected. However, I do not know how to then make the random image stay on top of of the user controlled image after the collision so that the random image moves together with the user controlled one. This is the code that I have so far:
-(void)spawnMechanism{
timeSinceLastSpawn++;
if(timeSinceLastSpawn >= 3)
{
if( arc4random() % 10 < 7 ){
UIImageView *spawnGood;
spawnGood=[[UIImageView alloc]initWithFrame:CGRectMake(arc4random() % 700, -100, 70,70)];
UIImage *image;
image=[UIImage imageNamed:#"friendly-01"];
[spawnGood setImage:image];
[self.view addSubview:spawnGood];
NSLog(#"spawnGood spawned");
[UIView animateWithDuration:2.0
delay: 0.0
options: UIViewAnimationOptionCurveLinear
animations:^{
CGRect frame1 =[spawnGood frame];
frame1.origin.y =frame1.origin.y+950;
[spawnGood setFrame:frame1];
}
completion:^(BOOL finished){
if(CGRectIntersectsRect(userToken.frame, spawnGood.frame)){
NSLog(#"Good Collision");
}else{
[UIView animateWithDuration:2.0 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
CGRect frame1 =[spawnGood frame];
frame1.origin.y =frame1.origin.y+950;
[spawnGood setFrame:frame1];
}
completion:nil];
};
}
];}
}
}
To control the user image, I have this code:
- (IBAction)right {
/*[UIView animateWithDuration:0.10f
animations:^{
_userToken.frame = CGRectMake(_userToken.frame.origin.x + 80, _userToken.frame.origin.y, _userToken.frame.size.width, _userToken.frame.size.height);
}];
}*/
if(goRight==nil){
goRight=[NSTimer scheduledTimerWithTimeInterval:rate
target:self
selector:#selector(goRight)
userInfo:nil
repeats:YES];
}
[self myDetectCollisionsOnRight];
}
- (IBAction)left{
/*[UIView animateWithDuration:0.10f
animations:^{
_userToken.frame = CGRectMake(_userToken.frame.origin.x - 80, _userToken.frame.origin.y, _userToken.frame.size.width, _userToken.frame.size.height);
}];
}*/
if(goLeft==nil){
goLeft=[NSTimer scheduledTimerWithTimeInterval:rate
target:self
selector:#selector(goLeft)
userInfo:nil
repeats:YES];
}
[self myDetectCollisions];
}
-(IBAction)stopLeft{
[goLeft invalidate];
goLeft=nil;
}
-(IBAction)stopRight{
[goRight invalidate];
goRight=nil;
}
-(void)goLeft{
userToken.center =CGPointMake(userToken.center.x -25, userToken.center.y);
[self myDetectCollisions];
}
-(void)goRight{
userToken.center =CGPointMake(userToken.center.x +25, userToken.center.y);
[self myDetectCollisionsOnRight];
}
Is anyone able to suggest a solution to this?
Try using -addSubview:. I think if it is added to userToken and then userToken is moved, spawnGood will move with it because it is a subview.
if(CGRectIntersectsRect(userToken.frame, spawnGood.frame)){
NSLog(#"Good Collision");
[spawnGood removeFromSuperView]
[userToken addSubview: spawnGood];
//Position the subview where the collision took place here
}

Why are these UIImages glitching when they reload on the screen?:

In my code, after the frog jumps on the lily pad, the lilypad fades out slowly, (making it look like they are submerged) and then after they pass the bottom of the screen, they reload on the top of the screen. The code is as follows:
if (CGRectIntersectsRect(FrogSquare.frame, lilypadTS.frame) && (upMovement <= -1) && (swim == YES) && (startingice.hidden == NO)){
[self bounce];
[self iceblockfall];
if (lilypadused == NO) {
addedScore = 1;
lilypadused = YES;
}
//hide pad
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:4];
[startingice setAlpha:0];
[UIView commitAnimations];
[self performSelector:#selector(hidePad) withObject:self afterDelay:4.0];
}
That part works fine, the lily pad does what its supposed to do. The following is where I get this weird glitch:
if (lilypad.center.y > 610) {
RandomPosition = arc4random() %248;
RandomPosition = RandomPosition + 36;
lilypad.center = CGPointMake(RandomPosition, -22);
lilypadused = NO;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0];
[lilypad setAlpha:1];
[UIView commitAnimations];
[self performSelector:#selector(showlilypad) withObject:self afterDelay:0];
} else if ((lilypad.center.y > 610) && (lilypad.hidden == YES)) {
RandomPosition = arc4random() %248;
RandomPosition = RandomPosition + 36;
lilypad.center = CGPointMake(RandomPosition, -22);
lilypadused = NO;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0];
[lilypad setAlpha:1];
[UIView commitAnimations];
[self performSelector:#selector(showlilypad) withObject:self afterDelay:0];
}
What happens is for some reason, the lilypads will reload at the top of the screen like they're supposed to, but then as the user is jumping on lilypads below the ones at the top. If thats confusing -- Screen Dimensions 320 x 568, lilypad1 reloads at the top of the screen point = -22, then slowly falls down, so say point is 10 after falling for a bit, say the player jumps on lilypad2 that HAS NOT been hidden and gone past 610 (to reload at the top), it makes lilypad1 hide instantly, why is this??
The amount of code you've provided really isn't enough to diagnose your problem. You are likely (definitely) referencing the incorrect lilypad which is causing the errant behavior. You should probably take a close look at the architecture of your app to make sure you are properly managing the list of lilypads in the best way.
Also, whenever you use delays - note that those delays are approximate, not exact. It is possible that you are in a race condition, where the hide has yet to occur but you're already showing it again at the top, then the hide triggers later.
Lastly, if afterDelay is 0 you might as well just call the showlilypad method directly - no need to really delay for 0 seconds.
Good luck!

UIView animation on completion not working properly

I have a problem using a slider to trigger a series of animations, here's the code:
-(void)slideAlpha:(id)sender{
self.bigPhotoViewA.alpha = self.alphaSlider.value;
if (self.alphaSlider.value == 1){
[UIView animateWithDuration:1
animations:^{
self.alphaSlider.alpha = 0;
} completion:nil
];
[self performSelector:#selector(nextPhotoAnimation) withObject:self afterDelay:5.0 ];
}
}
-(void) nextPhotoAnimation{
self.alphaSlider.value = 0;
[UIView animateWithDuration:2
animations:^{
self.bigPhotoViewA.alpha = 0.0;
self.bigPhotoView.alpha = 0.0;
self.smallPhotoView.center = CGPointMake(startX, startY);
}
completion:^(BOOL finished) {
NSLog(#"Animation ended");
self.smallPhotoView.image = ((UIImage *)[smallImagesArray objectAtIndex:imageCount]);
}
];
}
So, when the slider reaches a value of 1, nextPhotoAnimation is launched after a delay. So far so good. The problem comes inside nextPhotoAnimation. The animations block runs ok, but the completion block runs several times every time nextPhotoAnimation is called. I get the NSLog from 6 to 9 times displayed when nextPhotoAnimation starts, and then I get it again at the right time, after 2 seconds.
I've tried to replicate the problem with simpler code and the animation/completion flow works just fine.
Try this in nextPhotoAnimation,
-(void) nextPhotoAnimation{
self.alphaSlider.value = 0;
[UIView animateWithDuration:2
animations:^{
self.bigPhotoViewA.alpha = 0.0;
self.bigPhotoView.alpha = 0.0;
self.smallPhotoView.center = CGPointMake(startX, startY);
}
completion:^(BOOL finished) {
if (finished) {
NSLog(#"Animation ended");
self.smallPhotoView.image = ((UIImage *)[smallImagesArray objectAtIndex:imageCount]);
}
}
];
}
neither you are using
[UIView beginAnimations:nil context:nil];
nor
[UIView commitAnimations];
Best way is to create a UIView and then use the protocols.call your methods using [self YOURMETHOD]; in the View.
:-)

How to stop this sequence?

i am animating a frame, through this code, which is easily understandable in code, now i am trying to stop this sequence after 20 time means in completion parentheses i need to call that function for 20 times only: how can i do that?
-(void)conveyComplete:(UIView*)v
{
[self convey:v delay:0];
}
-(void)convey:(UIView*)v delay:(int)nDelay
{
[UIView animateWithDuration:.5
delay:nDelay
options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
animations: ^
{
CGRect rPos = v.frame;
NSLog(#"x:%f y:%f vFrame:%f vFrame:%f" , rPos.origin.x,rPos.origin.y,v.frame.origin.x,v.frame.origin.y);
rPos.origin.x -= 5;
rPos.origin.y -=100;
v.frame = rPos;
}
completion: ^(BOOL finished)
{
[self conveyComplete:v];
NSLog(#"I:%i, F:%i",i,f);
}];
}
As your function does only animation, one possible solution is not to call function 20 times, but instead set repeat count of animation with setAnimationRepeatCount: method.
It'll looks something similar to this:
[UIView UIView animateWithDuration:.5
delay:nDelay
options:(UIViewAnimationOptionRepeat | ...)
animations: ^{
// Do your animation stuff
[UIView setAnimationRepeatCount:20];
}
completion:NULL];
But one other aspect that is worth regarding is whether you need to repeat animation 20 times at all. All you do is just stepwise shifting of you view frame. Why not to animate this at once by setting appropriate offsets and animation duration?
i have made a global integer:
int i=1;
-(void)conveyComplete:(UIView*)v{
[self convey:v delay:0];
}
-(void)convey:(UIView*)v delay:(int)nDelay{
[UIView animateWithDuration:.5
delay:nDelay
options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionAllowUserInteraction)
animations: ^
{
CGRect rPos = v.frame;
i+=1;// then increase +1 every time it runs
NSLog(#"x:%f y:%f vFrame:%f vFrame:%f" , rPos.origin.x,rPos.origin.y,v.frame.origin.x,v.frame.origin.y);
rPos.origin.x -= 5;
rPos.origin.y -=100;
v.frame = rPos;
}
completion: ^(BOOL finished)
{
if(i<20){
[self conveyComplete:v];
}
NSLog(#"I:%i, F:%i",i,f);
}];
}

animating in 3 steps one after the other ios

I have 3 cards. at first all cards move to the right, then after 1 sec card2 would appear on the left side of the view, and then after some more second card2 moves to the right. I implemented this using the following code. when the view loads I have the following code,
counter = 0;
timer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(performAnimationToRight) userInfo:nil repeats:YES];
here is the implementation of the performAnimationToRightMethod
-(void)performAnimationToRight
{
if (counter == 0) {
CGAffineTransform transformToLeft = CGAffineTransformMakeTranslation(388,0);
[UIView beginAnimations:#"Move1" context:nil];
[UIView setAnimationDuration:2];
card0.transform = transformToLeft;
card1.transform = transformToLeft;
card2.transform = transformToLeft;
[UIView commitAnimations];
}else if(counter == 50){
card2.frame = CGRectMake(-300,card2.frame.origin.y, card2.frame.size.width, card2.frame.size.height);
}else if(counter == 200){
timer = nil;
counter = 0;
CGAffineTransform transformToLeft = CGAffineTransformMakeTranslation(-300,0);
[UIView beginAnimations:#"Move2" context:nil];
[UIView setAnimationDuration:2];
card2.transform = transformToLeft;
[UIView commitAnimations];
}
counter++;
}
the problem is that on the last action card2 instead of moving to the right moves to the left, and that's wether or not I use,
CGAffineTransform transformToLeft = CGAffineTransformMakeTranslation(-300,0);
or
CGAffineTransform transformToLeft = CGAffineTransformMakeTranslation(+300,0);
Two comments:
First, you are moving your card2 to the left at counter == 50 by setting it's frame origin to be (probably) left of your starting position.
Second, this would be easier to implement using a CAKeyframeAnimation. You wouldn't have to manage your NSTimer and the counter mechanism.

Resources