Making an incremental counter for scores - cocos2d-iphone

How can I make a counter that will increment (run through) from zero to the score attained within two seconds? I plan to use this for displaying the final score in game over popup. I am not really too sure how to go about this. Please help.

Following is the code you can use to setup your animation (using scheduler) according to given values:
float secs = 2.0f;
float deciSecond = 1 / 10;
newScore = 100;
currentScore = 0;
scoreInDeciSecond = (newScore / secs) * deciSecond;
[self schedule:#selector(counterAnimation) interval:deciSecond];
And this is how your method will handle the animation:
- (void)counterAnimation {
currentScore += scoreInDeciSecond;
if (currentScore >= newScore) {
currentScore = newScore;
[self unschedule:#selector(counterAnimation)];
}
scoreLabel.string = [NSString stringWithFormat:#"%d", currentScore];
}

I personally don't know cocos2d and how it displays text or uses timers, but here is how to do it with pure iOS SDK. If you know cocos2d, it shouldn't be a problem converting it.
- (void)viewDidLoad
{
[super viewDidLoad];
highScoreLabel = [[UILabel alloc] initWithFrame:CGRectMake(100.0, 100.0, 200.0, 75.0)];
[self displayHighScore];
}
-(void)displayHighScore {
highScore = 140;
currentValue = 0;
NSString* currentString = [NSString stringWithFormat:#"%d", currentValue];
[highScoreLabel setText:currentString];
[self.view addSubview:highScoreLabel];
int desiredSeconds = 2; //you said you want to accomplish this in 2 seconds
[NSTimer scheduledTimerWithTimeInterval: (desiredSeconds/highScore) // this allow the updating within the 2 second range
target: self
selector: #selector(updateScore:)
userInfo: nil
repeats: YES];
}
-(void)updateScore:(NSTimer*)timer {
currentValue++;
NSString* currentString = [NSString stringWithFormat:#"%d", currentValue];
[highScoreLabel setText:currentString];
if (currentValue == highScore) {
[timer invalidate]; //stop the timer because it hit the same value as high score
}
}

Related

How do we enumerate and modify positions array of CCsprite inside Update method?

How do we enumerate and alter our object's position (contained in array) for each delta time?
I put some CCsprite objects inside array, then I displayed them in scene, but also I wanted to make them move with modifying update method, I failed on last part.
How do I get around this ?
#implementation GameScene
{
Hunter *_hunter;
Bird *_bird;
NSMutableArray *_arrayOfBirds;
}
-(void)update:(CCTime)delta{
CGSize viewSize = [CCDirector sharedDirector].viewSize;
float birdSpeed = 50;
for (Bird *birds in _arrayOfBirds) {
if (birds.position.x < 0) {
birds.flipX = YES;
}
if (birds.position.x > viewSize.width) {
birds.flipX = NO;
}
float distanceToMove = birdSpeed * delta;
float direction = birds.flipX ? 1 : -1;
float newX = birds.position.x + direction * distanceToMove;
float newY = birds.position.y;
birds.position = ccp(newX, newY);
}
}
-(void)addBird{
CGSize viewSize = [CCDirector sharedDirector].viewSize;
for (int i=0; i < 4; i++) {
_bird = [[Bird alloc]initWithBirdType:(i)];
_bird.position = ccp(viewSize.width * 0.5f + 30 * i , viewSize.height * 0.9f - 15* i);
[self addChild:_bird];
[_arrayOfBirds addObject:_bird];
}
}
You forgot to initialize your array
here (assuming ARC)
-(id) init {
if(self=[super init]) {
_arrayOfBirds = [[NSMutableArray alloc] init];
// the rest
}
return self;
}

Cocos2d-iphone v3 - draw a line and convert it so I could use it for CCSprite

http://i.stack.imgur.com/cjZBq.png
Right I've looked and I can seem to find the answer.
I'm using Cocos2d-iphone V3.
What I want to achieve is the above.
I want to take the devices width or height and and draw two lines.
I want to take the drawn lines and use the for the CCProgress.
Question:
How do I take the drawn lines and convert them to CCSprite?
If you can give me the code it would be great, but if you could give me a link to any tutorial or documentation so I can learn how to do this, that would be even better.
Thank you.
#LearnCocos2d
So i'm doing this now but I get a very weird result;
CGSize winSize = [[CCDirector sharedDirector] viewSize];
_progressWidth = winSize.width *2;
//CGPoint position = ccp(0.3, 0.5);
//CCTime interval = 1.0/60.0;
NSMutableArray * tempProgressFg = [[NSMutableArray alloc] initWithCapacity:[Utilities getRows]+1];
NSMutableArray * tempProgressBg = [[NSMutableArray alloc] initWithCapacity:[Utilities getRows]+1];
CCTexture * bg = [_progressBg texture];
CCTexture * fg = [_progressFg texture];
for (int i = 0; i < [Utilities getRows]; i++)
{
if (i == 0)
{
_progressBg.scaleX = _progressWidth;
_progressFg.scaleX = _progressWidth;
_progressBg.position = ccp(0, i * TILE);
_progressFg.position = ccp(0, i * TILE);
[tempProgressFg addObject:_progressFg];
[tempProgressBg addObject:_progressBg];
}
else
{
CCSprite * tempBg = [CCSprite spriteWithTexture:bg];
CCSprite * tempFg = [CCSprite spriteWithTexture:fg];
tempBg.scaleY = 1;
tempFg.scaleY = 1;
tempBg.scaleX = _progressWidth;
tempFg.scaleX = _progressWidth;
tempBg.position = ccp(0, i * TILE);
tempFg.position = ccp(0, i * TILE);
[self addChild:tempBg];
[self addChild:tempFg];
[tempProgressBg addObject:tempBg];
[tempProgressFg addObject:tempFg];
}
}
The result that i get is in this picture:
http://imgur.com/1dMpiUc,V47d65X
is the _progressBg and Fg;
are the tempBg and Fg (multiples of them);
I want to have them all look like number 1.
Am I doing something wrong? is that the correct way to coppy the bar?

CCRotateBy actions are intermittently jumpy/jerky? Cocos2d

I have a subclass of cpCCSprite, which is just for using chipmunk spaceManager and my class looks like this:
#implementation Helmet
+(id) helmetWithGame:(Game*)game {
return [[[self alloc] helmetInit:game] autorelease];
}
- (id) helmetInit:(Game*)game {
cpShape *helmet_1;
cpShape *helmet_2;
cpShape *helmet_3;
cpShape *reference;
reference = [game.spaceManager addCircleAt:cpvzero mass:STATIC_MASS radius:2];
helmet_1 = [game.spaceManager addCircleToBody:reference->body radius:20 offset:cpv(-5, 2)];
helmet_2 = [game.spaceManager addCircleToBody:reference->body radius:8 offset:cpv(16, -14)];
helmet_3 = [game.spaceManager addCircleToBody:reference->body radius:8 offset:cpv(8, -14)];
reference->group =1;
helmet_1->group =1;
helmet_2->group =1;
helmet_3->group =1;
[self initWithFile:#"Helmet.png"];
[self setBody:reference->body];
self.spaceManager = game.spaceManager;
self.autoFreeShapeAndBody = YES;
gameScreenSize = game.contentSize;
return self;
}
- (void) generateAndShowOn:(Game *)game {
float startX = (float)((arc4random_uniform(101)) + 100);//returns number from 100 to 200 and casts it as a float
float startY;
int endXRange = (game.contentSize.width * .8) - (game.contentSize.width * .5);
float endX = (float)((arc4random_uniform(endXRange)) + (game.contentSize.width * .5));
float endY;
BOOL shouldStartTop;
if ((arc4random_uniform(101)) < 50) {//returns number from 0 to 100 and checks to see if it is less than 50. If it is, than the helmut starts at the top
shouldStartTop = YES;
startY = game.contentSize.height + (self.contentSize.height * .5);
endY = -self.contentSize.height;
}
else {
shouldStartTop = NO;
startY = -(self.contentSize.height * .5);
endY = game.contentSize.height + self.contentSize.height;
}
self.position = ccp(startX, startY);
[game addChild:self];
ccBezierConfig bezier;
bezier.controlPoint_1 = ccp (startX, startY);
bezier.controlPoint_2 = ccp (endX, endY);
bezier.endPosition = ccp (endX, endY);
id rotate =[CCRotateBy actionWithDuration:1.5f angle:360];
id curve = [CCBezierTo actionWithDuration:1.5f bezier:bezier];
id spawn = [CCSpawn actions:rotate, curve, nil];
[self runAction:spawn];
[self schedule:#selector(doneAnimating) interval:1.6];
}
- (void) doneAnimating{
if ([[self delegate]respondsToSelector:#selector(helmetPastBounds:)]) {
[[self delegate]helmetPastBounds:self];
}
}
- (void) dealloc {
CCLOG(#"%s", __PRETTY_FUNCTION__);
[super dealloc];
}
#end
So a new instance of this class is called every second, so that there can be more than one helmet on the screen at a time. Then I have another method that is called just slightly after the acctions have finished to remove the current helmet and deallocate it. But the problem I am having is every so often the actions are jumpy/jerky and that is with the FPS at 60. Do I need to do something different with the actions or what could be causing this?

warnings when using setDelay and addFrameWithFilename

I want to use the following lines of code in my project.
// Create the intro image
CGSize screenSize = [CCDirector sharedDirector].winSize;
CCSprite *introImage = [CCSprite spriteWithFile:#"intro1.png"];
[introImage setPosition:ccp(screenSize.width/2, screenSize.height/2)];
[self addChild:introImage];
// Create the intro animation, and load it from intro1 to intro7.png
CCAnimation *introAnimation = [CCAnimation animation];
[introAnimation setDelay:2.5f];
for (int frameNumber=0; frameNumber < 8; frameNumber++) {
CCLOG(#"Adding image intro%d.png to the introAnimation.",frameNumber);
[introAnimation addFrameWithFilename:
[NSString stringWithFormat:#"intro%d.png",frameNumber]];
I get the warning:
instance method '-setDelay:' not found (return type defaults to 'id')
pointing to the line
[introAnimation setDelay:2.5f];
and a similar warning pointing to the line
[introAnimation addFrameWithFilename: [NSString stringWithFormat:#"intro%d.png",frameNumber]];
Has setDelay and addFrameWithFilename been deprecated? If yes, what should I use in their place. Please help.
hmmm ... not certain these methods exist at all. Here is an example from my code base (cocos2 version 2.0).
+ (CCAnimation *) getAnimationForSoldier:(Soldier *)theSoldier animationType:(mapAnimationTypeE)animationType {
id animation = nil;
NSString *animationName = [SpriteUtils getAnimationNameForSoldier:theSoldier animationType:animationType];
if (!animationName) return nil;
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:[NSString stringWithFormat:#"%#.plist", animationName]];
if ((animation = [[CCAnimationCache sharedAnimationCache] animationByName:animationName])) {
return animation;
} else {
NSUInteger numberOfFrames = 8;
if (animationType == mapAnimationTypeCast || animationType == mapAnimationTypeSkill) numberOfFrames = 20;
NSMutableArray *frames = [NSMutableArray arrayWithCapacity:numberOfFrames];
for (NSUInteger i = 1 ; i <= numberOfFrames ; i++) {
NSString *frName = [SpriteUtils getFrameNameForAnimationNamed:animationName andFrame:i];
CCSpriteFrame *frr = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:frName];
if (frr) {
[frames addObject:frr];
} else {
MPLOGERROR(#"*** No frame named [%#], bailing out.", frName);
return nil;
}
[frames addObject:frr];
}
animation = [CCAnimation animationWithSpriteFrames:frames delay:.06];
[[CCAnimationCache sharedAnimationCache] addAnimation:animation name:animationName];
}
return animation;
}
note : first create your spriteframes array, then create the animation with the array and the desired delay.
The delay is delay between each frame (not the total duration).
If you are using cocos2d version 2.N, the setter for delay is
animation.delayPerUnit = 0.6f;

Block of code running in iPhone simulator and not on iPhone 4? (COCOS2D)

I am using the ccTouchBegan and ccTouchEnded, and for some reason there is a block of code that runs perfectly on iPhone simulator and doesn't run at all on iPhone 4. This is what my methods look like:
-(BOOL)ccTouchBegan:(UITouch*)touch withEvent:(UIEvent *)event {
firstTouch = [self convertTouchToNodeSpace:touch];
if (!self.currentFootball.footballHasEmbarked) {
//arrow.position = ccp(fPos.x, fPos.y);
float newAnc = (120 + (self.currentFootball.contentSize.width * .5f) + (arrow.contentSize.width * .5f)) / arrow.contentSize.width;
arrow.anchorPoint = ccp(-newAnc, .5);//self.currentFootball.position;
arrow.position = self.currentFootball.position;//ccp(fPos.x-120, fPos.y);
arrow.rotation = 180;
arrow.visible = YES;
arrow.scale = 0.5f;
//powerLevel.position = fPos;
powerLevel.position = self.currentFootball.position;
powerLevel.rotation = 180;
powerLevel.percentage = 0;
powerLevel.visible = YES;
outLine.position = self.currentFootball.position;
outLine.rotation = 180;
outLine.visible = YES;
CCProgressFromTo *powerBarGoUp = [CCProgressFromTo actionWithDuration:1.0f from:0.0f to:100.0f];
CCProgressFromTo *powerBarGoDown = [CCProgressFromTo actionWithDuration:1.0f from:100.0f to:0.0f];
id action = [CCRepeatForever actionWithAction:[CCSequence actions:powerBarGoUp, powerBarGoDown, nil]];
[powerLevel runAction:action];
return YES;
}
else {
return NO;
}
}
-(void) ccTouchEnded:(UITouch*)touch withEvent:(UIEvent *)event {
const float max = 100;
CGPoint endTouch = [self convertTouchToNodeSpace:touch];
if (endTouch.x > firstTouch.x) {
endTouch = ccp(firstTouch.x, endTouch.y);
//CCLOG(#"I ran");
}
arrow.visible = NO;
powerLevel.visible = NO;
outLine.visible = NO;
self.currentFootball.footballHasEmbarked = YES;
self.currentFootball.spiraling = YES;
if (self.currentFootball) {
[smgr addBody:self.currentFootball.body];
}
if (CGPointEqualToPoint(endTouch, firstTouch)) {
CCLOG(#" I have run");
float anchorPointDist = ccpLength(endTouch);
float distFactor = distFromFb + anchorPointDist;
projectionAnchorPoint = ccp(firstTouch.x + distFactor,firstTouch.y);
}
CGPoint diff = ccpSub(endTouch, projectionAnchorPoint);
float len = powerLevel.percentage;
CGPoint norm = ccpNormalize(diff);
if (len > max){
len = max;
}
[self.currentFootball applyImpulse:ccpMult(norm, (len * 300))];
pos = self.currentFootball.position.y;
[self schedule:#selector(newFootball)];
}
This is the block of code that will not run on my iPhone.
if (CGPointEqualToPoint(endTouch, firstTouch)) {
CCLOG(#" I have run");
float anchorPointDist = ccpLength(endTouch);
float distFactor = distFromFb + anchorPointDist;
projectionAnchorPoint = ccp(firstTouch.x + distFactor,firstTouch.y);
}
Am I not doing something right?
Print out the values for endTouch and firstTouch. They may vary by a very small amount on device, as it's harder to keep your finger in the same location as opposed to a mouse pointer. If that's the case, you may want to accept end touches within a range of the first touch.
Perhaps there is some slight difference in the points you are comparing, making the result of that comparison always false. Try using this method instead of CGPointEqualToPoint.
BOOL ccpFuzzyEqual(CGPoint a, CGPoint b, float variance);