How to solve the delay problem in animation of sprites? - cocoa-touch

My problem is, I did coding for a sprite. It should change it should change it's image from( 1, 2, 3). It should look like count down time to start a game. 1, 2, 3 are 3 png images. But the images are not displayed in equal intervals of time. I mean time between (1 - 2), (2 - 3) is not same. It is random. Please help me with my problem. Help me if there is better solution than what I am doing.(My animation should be like, before any game starts we see count down 1 then 2 then 3 then GO).
-(id)init
{
if((self = [super init]))
{
[[CCDirector sharedDirector] setAnimationInterval:60.0/60];
[[CCDirector sharedDirector] setDisplayFPS:NO];
CCAnimation* numberAnimation = [CCAnimation animationWithName:#"countDown" delay: 60.0/60];
for( int i=1;i<4;i++)
[numberAnimation addFrameWithFilename: [NSString stringWithFormat:#"number_%02d.png", i]];
id numberAction = [CCAnimate actionWithAnimation: numberAnimation restoreOriginalFrame:NO];
id action2 = [CCFadeOut actionWithDuration:0.5f];
CCSprite *number;
number = [CCSprite spriteWithFile:#"number.png"];
....
}
}

You'll have to update some of the classes used in this article a developer on my team wrote since it was written for Cocos2D 0.8.2 but I think this should do the trick for you...
http://getsetgames.com/2009/08/05/improving-the-performance-of-animating-sprites-in-cocos2d/
From a quick looks like you need to make the following changes...
IntervalAction change to CCIntervalAction
CocosAnimation change to CCAnimation (I think?)
CocosNodeFrames change to CCNodeFrames (I think?)
You'll have to double check the Cocos2D 0.99 release notes. It details all the class names you'll need.

Related

SpriteKit - Using a loop to create multiple sprites. How do I give each sprite a different variable name?

I am using SpriteKit.
The code below basically makes a lattice of dots on the screen. However, I want to call each 'dot' a different name based on its position, so that I can access each dot individually in another method. I'm struggling a little on this, so would really appreciate if someone could point me in the right direction.
#define kRowCount 8
#define kColCount 6
#define kDotGridSpacing CGSizeMake (50,-50)
#import "BBMyScene.h"
#implementation BBMyScene
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
// Background
self.backgroundColor = [SKColor colorWithRed:0.957 green:0.957 blue:0.957 alpha:1]; /*#f4f4f4*/
CGPoint baseOrigin = CGPointMake(35, 385);
for (NSUInteger row = 0; row < kRowCount; ++row) {
CGPoint dotPosition = CGPointMake(baseOrigin.x, row * (kDotGridSpacing.height) + baseOrigin.y);
for (NSUInteger col = 0; col < kColCount; ++col) {
SKSpriteNode *dot = [SKSpriteNode spriteNodeWithImageNamed:#"dot"];
dot.position = dotPosition;
[self addChild:dot];
//6
dotPosition.x += kDotGridSpacing.width;
}
}
}
return self;
}
Here is an image of what appears on screen when I run the above code...
http://cl.ly/image/3q2j3E0p1S1h/Image1.jpg
I simply want to be able to call an individual dot to do something when there is some form of user interaction, and I'm not sure how I would do that without each dot having a different name.
If anyone could help I would really appreciate it.
Thanks,
Ben
- (void)update:(NSTimeInterval)currentTime {
for(SKNode *node in self.children){
if ([node.name containsString:#"sampleNodeName"]) {
[node removeFromParent];
}
}
}
Hope this one helps!
You can set the name property of each node inside the loop.
Then you can access them with self.children[index].
If you want to find a specific node in your children, you have to enumerate through the array.
Update:
To clarify how to search for an item by iterating, here is a helper method:
- (SKNode *)findNodeNamed:(NSString *)nodeName
{
SKNode *nodeToFind = nil;
for(SKNode *node in self.children){
if([node.name isEqualToString:nodeName]){
nodeToFind = node;
break;
}
}];
return nodeToFind;
}

cocos2d Generating multiple of the same sprites with velocity

I'm pretty new to iOS and cocos2d and I'm having a problem trying to create what I want the code to do. Let me give you the rundown first then i'll show what I've got.
What I got so far is a giant sprite in the middle and when that is touched, I want to have say 2000 of a different sprite generate from the center position and like a particle system, shoot off in all directions.
First off, I tried coding implementing the velocity code (written in Objective-c) over to Cocos2d and that didn't work. -code-
-(void)ccTouchBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if(CGRectContainsPoint([[self getChildByTag:1] boundingBox], location))
{
for( int i = 0; i < 100; i++)
{
CCSprite *ballGuySprite = [CCSprite spriteWithFile:#"ball.png"];
[self addChild:ballGuySprite z:7];
ballGuySprite.position = ccp(((s.width + i *10) /2), (s.height + i *10) /2);
}
}
}
What that does is when I touch the first sprite, 100 of the other sprites are on top of each other leading to the top right corner.
The velocity code that I used when as followed and when I try to apply it to the sprite nothing happens. - Velocity code -
-(void) checkCollisionWithScreenEdges
{
if(ballGuysRect.origin.x <= 0)
{
ballVelocity.x = abs(ballVelocity.x);
}
if(ballGuysRect.origin.x >= VIEW_WIDTH - GUY_SIZE)
{
ballVelocity.x = -1 * abs(ballVelocity.x);
}
if(ballGuysRect.origin.y <= 0)
{
ballVelocity.y = abs(ballVelocity.y);
}
if(ballGuysRect.origin.y >= VIEW_HEIGHT - GUY_SIZE)
{
ballVelocity.y = -1 * abs(ballVelocity.y);
}
}
-(void) updateModelWithTime:(CFTimeInterval)timestamp
{
if(lastTime == 0.0)
{
lastTime = timestamp;
}
else
{
timeDelta = timestamp - lastTime;
lastTime = timestamp;
ballGuysRect.origin.x += ballVelocity.x * timeDelta;
ballGuysRect.origin.y += ballVelocity.y * timeDelta;
[self checkCollisionWithScreenEdges];
}
}
When I attach that code to the sprite, nothing happen.
I also tried adding a CCParticleExplosion which did do what I wanted but I still want to add a touch function to each individual sprite that's generated and they tend to just fade away.
So again, I'm still fairly new to this and if anyone could give any advice that would be great.
Thanks for your patients and time to read this.
Your code looks good to me, but you never seem to update the position of your sprites. Somewhere in updateModelWithTime I would expect you to set ballGuySprite.position = ballGuysRect.origin plus half of its height or width, respectively.
Also, I don't see how updateModelWithTime can control 100 different sprites. I see only one instance of ballGuysRect here. You will need a ballGuysRect for each sprite, e.g. an array.
Finally, I'd say that you don't really need ballGuysRect, ballVelocity, and the sprite. Ball could be a subclass of CCSprite, including a velocity vector. Then all you need to do is keep an array of Balls and manage those.
I am not sure what version of cocos2d you are using but a few things look a bit odd.
Your first problem appears to be that you are just using the same sprite over and over again.
Since you want so many different sprites shooting away, I would recommend that you use a CCSpriteBatchNode, as this should simplify things and speed things up.
The following code should help you get that set up and move them offscreen with CCMoveTo:
//in your header file:
CCSpriteBatchNode *batch;
//in your init method
batch = [CCSpriteBatchNode batchNodeWithFile:#"ball.png"];
//Then in your ccTouches method
for( int i = 0; i < 100; i++)
{
CCSprite *ballGuySprite = [CCSprite spriteWithFile:#"ball.png"];
[batch addChild:ballGuySprite z:7 tag:0];
ballGuySprite.position = ccp(where-ever the center image is located);
id actionMove = [CCMoveTo actionWithDuration:actualDuration
position:ccp(random off screen location)];
[ballGuySprite runAction:actionMove];
}
Also usually your update method looks something like the following:
-(void)update:(ccTime)delta{
//check for sprites that have moved off screen and disable them.
}
Hope this helps.

Change LHSprite position from code (levelhelper-XCODE)

I'm trying to move all sprites with the same tag some inches to the right.
I have tried 4 different type of expressions in order to do so, but nothing worked. Here is what i ve done so far...
-(void) moveSprites {
NSArray* spritesWithTag = [lh spritesWithTag: BOXES1]
for (LHSprite* spr in spritesWithTag)
(NSLog (#"name is %#", [spr uniqueName]);
CGPoint newposition = ccpSub (ccp(-50,0), [spr position]);
//generating the new position for the elements
[spr transformPosition: newposition];
//first attemp, should work but for some reason it doesn't work
spr.position = newposition;
//2nd attemp
b2Vec2 newpositionVector (newposition.x, newposition.y);
[spr body]->SetTransform(newpositionVector, 0);
//third try
[spr setPosition:newposition];
//last form
}
When i run the app the method call works fine and all sprites with tag BOXES1 appear in the output tab, but its position hasn't changed at all. Any idea over why is it happening. What did I wrong? Is there any other way to move an sprite or are them prevented from moving in some other form i dont know? Those are static sprites, dont know if this affects... thanks!

Animate UILabel with numbers

I am still learning about UIAnimations, just got into it and I have stumbled upon a problem that I am not sure how to solve. I've seen games where you get a new high score and it adds the new high score to the old high score and they make the numbers animate up or down. It looks very cool and visually appeasing.
Can anyone explain to me how this is done? I apologize if this question is easily solved, like I said I am still trying to learn/perfect animations.
Thanks in advance
I took the code from the post sergio suggested you look at, but took note of Anshu's mention that you wanted a moving up and down animation rather then a fade-in/fade-out animation, so I changed the code to fit what you wanted. Here you go:
// Add transition (must be called after myLabel has been displayed)
CATransition *animation = [CATransition animation];
animation.duration = 1.0; //You can change this to any other duration
animation.type = kCATransitionMoveIn; //I would assume this is what you want because you want to "animate up or down"
animation.subtype = kCATransitionFromTop; //You can change this to kCATransitionFromBottom, kCATransitionFromLeft, or kCATransitionFromRight
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[myLabel.layer addAnimation:animation forKey:#"changeTextTransition"];
// Change the text
myLabel.text = newText;
Hope this helps!
People can correct me if I'm wrong here, but I'm pretty sure you have to code this animation manually. You might be able to find an open source version somewhere online if you look hard enough.
It might be possible to take an image of a UILabel and use sizeWithFont: to determine how wide each character is, then cut the image up into sections based on each digit. Alternatively you could just have multiple UILabels for each digit.
Once you have an array of digit images, you'd have to calculate which digits are going to change during the transition and whether they're going to increase or decrease, then transition to the next digit by pushing it in from the top/bottom (I think there's a built in transition to do this, look around in the Core Animation docs).
You would probably want to determine by how much they increase/decrease and use that to figure out how long the animation will take. That way, if you're going from 5 to 900, the last digit would have to be animating very quickly, the second to last would animate 1/10 as quickly, the third would be 1/100, etc.
This does on ok job, using the reveal function. It would be nice to have some vertical motion, but it's either going to be kCATransitionFromBottom or kCATransitionFromTop - and really we'd need kCATransitionFromBottom | kCATransitionToTop, but that's not a thing. Here's the code:
-(void)countUpLabel:(UILabel *)label fromValue:(int)fromValue toValue:(int)toValue withDelay:(float)delay{
int distance = (int)toValue - (int)fromValue;
int absDistance = abs(distance);
float baseDuration = 1.0f;
float totalDuration = absDistance / 100.0f * baseDuration;
float incrementDuration = totalDuration / (float)absDistance;
int direction = (fromValue < toValue) ? 1 : -1;
//NSString * subtype = (direction == 1) ? kCATransitionFromBottom : kCATransitionFromTop;
for (int n = 0; n < absDistance; n++){
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
CATransition * fade = [CATransition animation];
fade.removedOnCompletion = true;
fade.duration = incrementDuration;
fade.type = kCATransitionReveal;
fade.subtype = kCATransitionMoveIn;
[label.layer addAnimation:fade forKey:#"changeTextTransition"];
int value = fromValue + (n+1) * direction;
label.text = [NSString stringWithFormat:#"%i", value];
});
delay += incrementDuration;
}
}

cocos2d particle effects not appearing

Hi All
Im just having an issue with particle effects not appearing all the time. Im coding using objective c and cocos2d for the iphone.
Below is the code in question.
CCParticleExplosion *emitter;
emitter = [[CCParticleExplosion alloc] initWithTotalParticles:30];
emitter.texture = [[CCTextureCache sharedTextureCache] addImage:#"particle_bubble.png"];
emitter.position = ccp(MidX,MidY);
emitter.life =0.5;
emitter.duration = 0.5;
emitter.speed = 60;
[self addChild:emitter];
emitter.autoRemoveOnFinish = YES;
////////////////////////////////////////////////////
CCParticleMeteor *emitter2;
emitter2 = [[CCParticleMeteor alloc] initWithTotalParticles:150];
emitter2.texture = [[CCTextureCache sharedTextureCache] addImage:#"fire_particle.png"];
emitter2.position = ccp(MidX,MidY);
emitter2.life = 0.5;
emitter2.duration = 2;
emitter2.speed = 60;
id emitMove = [CCMoveTo actionWithDuration:0.5 position:HUD.moonSprite.position ];
[self addChild:emitter2 z:1];
[emitter2 runAction:[CCSequence actions:emitMove, nil]];
emitter2.autoRemoveOnFinish = YES;
This code is within the same function right after each other as shown.
but sometimes the 2nd particle effect is not created and i cant figure out why. the first particle effect is always created no problems so im sure it is getting into the function correctly but sometimes (almost 50%) the 2nd meteor emitter is not displayed. i have tried messing around with z values to make sure it is not hidden behind an other object and it doesnt appear to be the problem. Anyone have any ideas on why this would be happening?
Thanks
G
I suggest using the 71 squared particle designer. http://particledesigner.71squared.com/
Did the trick for me.
Try this:
Define the emitters in a local variable (.h)
Call this before the code above:
if (emitter.parent == self) {
NSLog(#"em1 released");
[emitter release];
}
if (emitter2.parent == self) {
NSLog(#"em2 released");
[emitter2 release];
}
This checks if the emitter is a child and removes it, so you can remove the emitter.autoRemoveOnFinish so your emitter will show every time