Why does this image keep moving down (objective-c)? - ios

I'm using UIKit to create a simple game. In my game, I want the ball to completely stop moving if its upMovement is less than -4.
So it appears to freeze in mid air.
What I have is the following:
if (upMovement < -4) {
upMovement = 0;
ball.center = CGPointMake(ball.center.x, ball.center.y);
ball.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"fallingball.png"], nil];
[ball setAnimationRepeatCount:0];
ball.animationDuration = 1;
[ball startAnimating];
}
I thought by adding upMovement = 0; and ball.center = CGPointMake(ball.center.x, ball.center.y) it would freeze the ball as soon as the upMovement < -4 ? but instead it, just makes it move really slow.
Any reasons as to why?

If your ball view is animating because of an UIView animation block or similar, then
[ball.layer removeAllAnimations];
should remove that animation and freeze it in place.
If you're animating it in place by repeatedly changing its frame then you would just have to stop doing that.

Related

Stop Sprite Animation in cocos2d

This is the code to show sprite sheet animation if something happens in the game, animation works perfect but it is not stopping after the animation frames sequence complete, i had done so many things to stop the animation, but nothing is giving me solution, here is my code
if(m_bEffectChangeColor){
`
m_gamecoinffect = [CCSprite spriteWithSpriteFrameName:#"powerup0001"];
[self addChild:m_gamecoinffect z:3];
CCAnimate *coineffect = [CCAnimate actionWithSpriteSequence:#"powerup%04d" numFrames:30 delay:0.1f restoreOriginalFrame:NO];
[m_gamecoinffect runAction:[CCRepeatForever actionWithAction:coineffect]];
m_gamecoinffect.position = ptEffectPos;
CCCallBlock *block = [CCCallBlock actionWithBlock:^{
//[m_gamecoinffect stopAllActions];
[self removeChild:m_gamecoinffect cleanup:YES];
}];
CCDelayTime *time = [CCDelayTime actionWithDuration:1];
[m_gamecoinffect runAction:[CCSequence actions:time, block, nil]];
`
Above code i tried to add timer and everything i know, but nothing is working,,, i would like to stop animation and remove those sprite from the layer.
Thanks in advance.
The animation does not stop because the CCRepeatForever is the action which animates forever means continuously. Change below line:
[m_gamecoinffect runAction:[CCRepeatForever actionWithAction:coineffect]];
With
[m_gamecoinffect runAction:coineffect];

Changing SpriteKit Game Background At A Certain Score

I'm having a little trouble implementing a background change when the player hits a certain score.
I'm using the if(self.score>=10) line to tell my game to change the background but it doesn't seem to be working. I have no errors with this line but no results either.
What I have:
#implementation Scene{
SKScrollingNode * floor;
SKScrollingNode * back;
SKLabelNode * scoreLabel;
}
- (void) createBackground
{
back = [SKScrollingNode scrollingNodeWithImageNamed:#"back" inContainerWidth:WIDTH(self)];
if(self.score>=10){
back = [SKScrollingNode scrollingNodeWithImageNamed:#"image2" inContainerWidth:WIDTH(self)];
[back setAnchorPoint:CGPointZero];
[back setPhysicsBody:[SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame]];
back.physicsBody.categoryBitMask = backBitMask;
back.physicsBody.contactTestBitMask = birdBitMask;
[self addChild:back];
}
there are certain points you have to keep in your mind i think your both background contains physics body
1)may be and the time of transition they first background colliding with second background and they preventing each other to swap
change your collisionBitMask for both background ->prevent them for colliding
for eg
bg.physicsBody.categoryBitMask=bg1;
bg.physicsBody.collisionBitMask=0;
bg.physicsBody.contactTestBitMask=bg2;
bg.physicsBody.categoryBitMask=bg2;
bg.physicsBody.collisionBitMask=0;
bg.physicsBody.contactTestBitMask=bg1;
or use skaction to swap backgrounds
The way i would do this would be to create a brand new SKScene entirely with a new background.
Or if you want them to scroll to the next background. I would create two backgrounds.
Ex.
//this syntax is wrong (dont remember)
//initializing
SKSpriteNode *bg1 = [SKSpritenode spritenodefromImage:#"bg1"];
SKSpriteNode *bg1 = [SKSpritenode spritenodefromImage:#"bg1"];
bg1.position = CGPointMake(self.size.width/2, self.size.height/2);
bg2.position = CGPointMake(self.size.width/2 + bg1.size.width, self.size.height/2);
//////////////////////////////
//then when you want to scroll them
-(void)scrollBackgrounds
{
bg1.position = CGPointMake(bg1.position.x - 5, self.size.height/2);
bg2.position = CGPointMake(bg2.position.x -5 , self.size.height/2);
}

Complex animation of objects' images using Core Animation

I got 5 objects with their images. I add them to array and shuffle them.
// Adding Things to Things Strip
[thingStrip removeAllObjects];
for (Thing *i in myThings) {
[self addThing:[i icon]];
}
// Randomizing Things' order in the Things Strip
for (int x = 0; x<thingStrip.count; x++) {
int randInt = (arc4random() % (thingStrip.count - x)) + x;
[thingStrip exchangeObjectAtIndex:x withObjectAtIndex:randInt];
}
// Adding Things' Images
for (int i=0; i<thingStrip.count; i++) {
UIImage *thingImage = thingStrip[i];
Then I add them to UIImage and create CALayers with them.
All I need is:
Make them move from right to left continuously without any gaps.
Scale them smoothly from 80x53 at right position to 120x80 at left position
Make opacity from 0.5 at right position to 1.0 at left position.
Each iteration lasts 0.5 seconds.
Whole animation lasts 5 seconds or stop on screen touch.
After animation is stopped I need left object proceed to the left end of the screen.
After animation is stopped I need to know which object image stopped at left end of the screen to use its' object data later.
For now I can do moving animation, but my solution is not so good.
// Adding Things' Images
for (int i=0; i<thingStrip.count; i++) {
UIImage *thingImage = thingStrip[i];
//for (int j = 0; j < 10; j++)
//{
CALayer *thingFrame = [CALayer layer];
thingFrame.bounds = CGRectMake(0.0, 0.0, 80.0, 53.0);
thingFrame.position = CGPointMake(i*thingFrame.frame.size.width, 515.0);
//thingFrame.position = CGPointMake(i*thingFrame.frame.size.width + j * thingStrip.count * thingFrame.frame.size.width, 515.0);
thingFrame.contents = (id)thingImage.CGImage;
[thingFrame setAnchorPoint:CGPointMake(0.0, 0.0)];
[self.view.layer addSublayer:thingFrame];
CGFloat currentPosition = [[thingFrame valueForKeyPath:#"position.x"] floatValue];
CGFloat newPosition = currentPosition - thingStrip.count * thingFrame.frame.size.width;
CABasicAnimation *thingMoveAnimation = [CABasicAnimation animationWithKeyPath:#"position.x"];
thingMoveAnimation.duration = 0.5f;
thingMoveAnimation.repeatDuration = 5.0f;
thingMoveAnimation.delegate = self;
thingMoveAnimation.fromValue = #(currentPosition);
thingMoveAnimation.toValue = #(newPosition);
thingMoveAnimation.fillMode = kCAFillModeForwards;
[thingFrame addAnimation:thingMoveAnimation forKey:#"position.x"];
//}
}
This code works only if I use for loop with 'j' (commented one) which adds 5 of each image. Only then I get smooth moving animation without any gaps. I guess it's not right solution. When I use only one for loop, I get animation of 5 images moving left again and again, but not continuously one after another.
I don't have working solution for scaling and opacity animation and I don't know how to end it by touching the screen and get needed image data.
I was trying to find similar solution for a while but found nothing.
I'm looking for help with working code.
Thanks in advance.

How to change CAEmitterLayer position without emitting particles in between?

I want to display sparkles for the short period when a user touches the screen (placed at the touch position).
The problem is when I change CAEmitterLayer's emitterPosition it acts as if it is trying to animate this position from old value to new one during about 0.5s period, instead of changing it instantly.
For example the emitter position is set to (0,0) by default, so when I try to touch at the center of the screen for the first time, it emits a line of sparkles from (0,0) to current position, instead of emitting sparkles form the center.
To stop sparkles, I set layer's birthRate to 0 after a short delay, then on touch I change emitterPosition and turn birthRate back to 1.
The only solution I could find is to have 0.5s delay between moving the position and turning birthRate on.
- (void)initSparkles {
layer = [CAEmitterLayer layer];
layer.birthRate = 0;
[sparkleView.layer addSublayer:layer];
}
- (void)showSparkles:(CGPoint)position {
layer.emitterPosition = position;
CAEmitterCell *sparkle = [CAEmitterCell emitterCell];
sparkle.props = ...;
layer.emitterCells = [NSArray arrayWithObjects:sparkle, nil];
layer.birthRate = 1.0;
[self performSelector:#selector(stopSparkles) withObject:nil afterDelay:0.05 ];
}
- (void)stopSparkles {
layer.birthRate = 0.0;
}

iOS Animation 2D game

I'm making an application, for the iPhone, which is a 2D game.
I have done all the spritesheets, but now i need to animate some of them particulary :
My game is a game where your hero should avoid some obstacles. The borders should move to give the impression that the game is more difficult by increasing the speed (so the hero looks like going faster and faster). I have my image of the border, but really don't know how to animate it dynamically, and when the end of the image is coming, put the top of the image to come after it.
Note : I know how to make a translation, to animate an image but here i need to animate it faster and faster, so to change dynamically the speed of the animation.
Thanks for your help !
Code or a UIImageView :
nuages_bas2 = [[UIImageView alloc] initWithFrame:CGRectMake(-100, 0, 160, 1000)];
UIImage * ImageNuages = [UIImage imageNamed:#"Menu_nuage.png"];
nuages_bas2.image = ImageNuages;
nuages_bas2.alpha = 0.0f;
[menu_principale addSubview:nuages_bas2];
[nuages_bas2 release];
Code for one of the animations :
- (void)AnimationNuagesBas2
{
nuages_bas2.alpha = 1.0f;
CABasicAnimation * nuagesbas2 = [CABasicAnimation animationWithKeyPath:#"transform.translation.y"];
nuagesbas2.fromValue = [NSNumber numberWithFloat:480.0f];
nuagesbas2.toValue = [NSNumber numberWithFloat:-960.0f];
nuagesbas2.duration = 35.0f;
nuagesbas2.repeatCount = 10;
[nuages_bas2.layer addAnimation:nuagesbas2 forKey:#"nuagesbas2"];
}
First things first, if you're making a game, you probably should not be using UIKit unless it's something very simple. You should have a look at libraries like cocos2d
As for this question, you may want to look at CAKeyframeAnimation. I'll attempt to sketch out some code that will do something like this, but you'll probably want to modify it(Also, I don't have the means to test it).
Note, what follows below is a hack that consists of creating a keyframe animation where the object goes back and forth each time with a smaller duration.
- (void)AnimationNuagesBas2
{
nuages_bas2.alpha = 1.0f;
CAKeyframeAnimation * nuagesbas2 = [CAKeyframeAnimation animationWithKeyPath:#"transform.translation.y"];
float from = [NSNumber numberWithFloat:480];
float to = [NSNumber numberWithFloat:-960];
int repeatCount = 10;
float duration = 6;
float durationDecrease = 0.5;
float t = 0;
NSMutableArray * values = [NSMutableArray array];
NSMutableArray * times = [NSMutableArray array];
[values addObject:from];
[times addObject:[NSNumber numberWithFloat:0]];
for (int i = 0; i < repeatCount; i++){
t += duration/2;
[values addObject:to];
[times addObject:[NSNumber numberWithFloat:t]];
t += duration/2;
[values addObject:from];
[times addObject:[NSNumber numberWithFloat:t]];
duration -= durationDecrease;
}
[nuages_bas2.layer addAnimation:nuagesbas2 forKey:#"nuagesbas2"];
}
Another approach would be to set yourself as the delegate to the CABasicAnimation and set it with a repeatCount of 0. Then, every time it's done, you re-initiate it with a smaller duration.

Resources