Skip to content

Instantly share code, notes, and snippets.

@talentless
Created November 2, 2011 14:02
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save talentless/1333705 to your computer and use it in GitHub Desktop.
Save talentless/1333705 to your computer and use it in GitHub Desktop.
A Score Label for Cocos2d
#import "TGScoreLabel.h"
-(void) setupPercentComplete {
TGScoreLabel * myScoreLabel = [TGScoreLabel scoreLabelWithFormatString:@"%d%%!" score:0 dimensions:CGSizeMake(380, 45) alignment:UITextAlignmentRight fontName:@"TacoGraveyard" fontSize:36];
myScoreLabel.position = myScoreLabelPosition;
[self addChild:myScoreLabel];
[myScore rollToScore: percentComplete];
}
-(void) rollToScore:(int)newScore {
self.score = newScore;
if (!updating_) {
updating_ = TRUE;
[self schedule:@selector(update_:) interval:interval_];
}
}
#import <Foundation/Foundation.h>
#import "cocos2d.h"
@interface TGScoreLabel : CCLabelTTF {
double curScore_; // the current score value of the label
BOOL updating_; // if we currently have an update running
double interval_; // how long we wait between updates
int score; // the target score
NSString * formatString; // the string that we format
int pointsPerSecond; // how fast we update
}
@property int score;
@property (nonatomic, retain) NSString * formatString;
@property int pointsPerSecond;
// give me that object!
+(id) scoreLabelWithFormatString:(NSString*)formatString score:(int)score dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size;
// start rolling up
-(void) rollToScore:(int)newScore;
// internal stuff
-(void) update_;
-(void) setup_:(int)score formatString:(NSString *)formatString;
@end
#import "TGScoreLabel.h"
@implementation TGScoreLabel
@synthesize score, formatString, pointsPerSecond;
+(id) scoreLabelWithFormatString:(NSString*)formatString score:(int)score dimensions:(CGSize)dimensions alignment:(CCTextAlignment)alignment fontName:(NSString*)name fontSize:(CGFloat)size {
TGScoreLabel * l;
if ( (l=[[[super alloc] initWithString:[NSString stringWithFormat:formatString, score] dimensions:dimensions alignment:alignment fontName:name fontSize:size] autorelease]) ) {
[l setup_:score formatString:formatString];
}
return l;
}
-(void) setup_:(int)score formatString:(NSString*)formatString {
self.score = score;
self.formatString = formatString;
self.pointsPerSecond = 30;
curScore_ = score;
interval_ = 0.05;
updating_ = FALSE;
}
-(void) rollToScore:(int)newScore {
self.score = newScore;
if (!updating_) {
updating_ = TRUE;
[self schedule:@selector(update_:) interval:interval_];
}
}
-(void) update_:(ccTime)dt {
int direction = 1; // the score can roll in either direction
if (self.score < curScore_) {
direction = -1;
}
double pointChange = self.pointsPerSecond * direction * dt;
curScore_ += pointChange;
// don't let it overrun the target
if (direction == -1 && curScore_ < self.score) {
curScore_ = self.score;
} else if (direction == 1 && curScore_ > self.score) {
curScore_ = self.score;
}
// update the string
// this is as costly as creating a new label
// we should be using cclabelatlas
[self setString:[NSString stringWithFormat:self.formatString, (int)curScore_]];
// if we are at the score then stop updating
if (self.score == curScore_) {
[self unschedule:@selector(update_:)];
updating_ = FALSE;
}
}
-(void) dealloc {
if (updating_) {
[self unschedule:@selector(update_:)];
}
[self.formatString release];
[super dealloc];
}
@end
-(void) update_:(ccTime)dt {
int direction = 1; // the score can roll in either direction
if (self.score < curScore_) {
direction = -1;
}
double pointChange = self.pointsPerSecond * direction * dt;
curScore_ += pointChange;
// don't let it overrun the target
if (direction == -1 && curScore_ < self.score) {
curScore_ = self.score;
} else if (direction == 1 && curScore_ > self.score) {
curScore_ = self.score;
}
// update the string
// this is as costly as creating a new label
// we should be using cclabelatlas
[self setString:[NSString stringWithFormat:self.formatString, (int)curScore_]];
// if we are at the score then stop updating
if (self.score == curScore_) {
[self unschedule:@selector(update_:)];
updating_ = FALSE;
return;
}
}
@tanapon
Copy link

tanapon commented Mar 14, 2012

Very nice!! If you have a way to do with with easing equations it would be awesome!

I'm not good with easing animation math, but I was actually able to produce a running number animation with easing by animating an invisible sprite with CCEaseExponentialOut from any value to any value. Then I update the number in an update method to the invisible sprite position.

Check out my free app Adamo Calculator in the statistics page to see it in action. http://itunes.apple.com/us/app/adamo-calculator/id493913129?ls=1&mt=8
Just in case you're interested. It's a very dirty trick but works beautifully.

@talentless
Copy link
Author

I've been meaning to create a CCLabelBMFont version of this class. Maybe, I'll take a look at the easing math at the same time and wrap it all up into a blog post.

@tanapon
Copy link

tanapon commented Mar 15, 2012

Awesome! Looking forward to it! I really need to learn easing math by example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment