I'm working with Objective-C++.
I'm trying to get the path outline of a text using NSBezierPaths appendBezierPathWithGlyphs. The problem is: the output is rather nonsense :(
What I've written:
String str = Ascii8("test string");
int length = str.getLength();
NSFont* font = [NSFont fontWithDescriptor: [NSFontDescriptor fontDescriptorWithName:#"Times"
size:20]
textTransform: transform];
NSTextStorage *storage = [[NSTextStorage alloc] initWithString:toNSString(str)];
NSLayoutManager *manager = [[NSLayoutManager alloc] init];
NSTextContainer *container = [[NSTextContainer alloc] init];
[storage addLayoutManager:manager];
[manager addTextContainer:container];
NSGlyph* glyphs = new NSGlyph[length+1];
[manager getGlyphs:glyphs range:NSMakeRange(0, length)];
[container release];
[manager release];
[storage release];
NSBezierPath* path = [NSBezierPath bezierPath];
// If I don't do this I get an exception that currentPoint doesn't exist ...
[path moveToPoint: NSMakePoint(0, 0)];
[path appendBezierPathWithGlyphs:glyphs count:length inFont:font];
delete[] glyphs;
// NSBezierPath -> DoublePath
for (NSInteger i=0; i<[path elementCount]; ++i)
{
NSPoint controlPoints[3];
NSBezierPathElement el = [path elementAtIndex:i associatedPoints:controlPoints];
if (el == NSMoveToBezierPathElement)
{
printf("move to (%f,%f)\n", controlPoints[0].x, controlPoints[0].y);
}
else if (el == NSLineToBezierPathElement)
{
printf("line to (%f, %f)\n", controlPoints[0].x, controlPoints[0].y);
}
else if (el == NSCurveToBezierPathElement)
{
printf("cubic to (%f, %f) (%f, %f) (%f, %f)\n",
controlPoints[0].x, controlPoints[0].y,
controlPoints[1].x, controlPoints[1].y,
controlPoints[2].x, controlPoints[2].y);
}
else if (el == NSClosePathBezierPathElement)
{
printf("close\n");
}
}
For example for the letter 't' I get this output:
move to (0.277832, 0.000000)
move to (0.254395, 0.450195)
line to (0.254395, 0.415039)
line to (0.154785, 0.415039)
line to (0.153809, 0.133789)
cubic to (0.153809, 0.109049) (0.155924, 0.090332) (0.160156, 0.077637)
cubic to (0.167969, 0.055176) (0.183268, 0.043945) (0.206055, 0.043945)
cubic to (0.217773, 0.043945) (0.227946, 0.046712) (0.236572, 0.052246)
cubic to (0.245199, 0.057780) (0.255046, 0.066569) (0.266113, 0.078613)
line to (0.278809, 0.067871)
line to (0.268066, 0.053223)
cubic to (0.251139, 0.030436) (0.233236, 0,014323) (0.214355, 0.004883)
cubic to (0.195475, -0.004557) (0.177246, -0.009277) (0.159668, -0.009277)
cubic to (0.121256, -0.009277) (0.095215, 0.007812) (0.081543, 0.041992)
cubic to (0.074056, 0.060547) (0.070312, 0.086263) (0.070312, 0.119141)
line to (0.070312, 0.415039)
line to (0.017090, 0.415039)
cubic to (0.015462, 0.416016) (0.014242, 0.416992) (0.013428, 0.417969)
cubic to (0.012614, 0.418945) (0.012207, 0.420247) (0.012207, 0.421875)
cubic to (0.012207, 0.425130) (0.012939, 0.427653) (0.014404, 0.429443)
cubic to (0.015869, 0.431234) (0.020508, 0.435384) (0.028320, 0.441895)
cubic to (0.050781, 0.460449) (0.066976, 0.475504) (0.076904, 0.487061)
cubic to (0.086833, 0.498617) (0.110189, 0.529134) (0.146973, 0.578613)
cubic to (0.151204, 0.578613) (0.153727, 0.578288) (0.154541, 0.577637)
cubic to (0.155355, 0.576986) (0.155762, 0.574544) (0.155762, 0.570312)
line to (0.155762, 0.450195)
close
This looks really wrong for me!
What do you mean by “looks wrong”? Have you tried rendering the data? It’s valid.
Below is your code modified to output an SVG of the curve data, which appears correct (but upside down because the coordinate convention of SVG is different). Other than that, removing some random C++, and adding transform which is undefined in your extract, the only difference is that it correctly counts the number of glyphs with [manager numberOfGlyphs]. In the test case, this makes no difference, but in general the glyph count isn’t the same as the length of the string.
NSString *str = #"test string";
int length = str.length;
NSAffineTransform *transform = [NSAffineTransform transform];
NSFont* font = [NSFont fontWithDescriptor: [NSFontDescriptor fontDescriptorWithName:#"Times" size:20]
textTransform: transform];
NSTextStorage *storage = [[NSTextStorage alloc] initWithString:str];
NSLayoutManager *manager = [[NSLayoutManager alloc] init];
NSTextContainer *container = [[NSTextContainer alloc] init];
[storage addLayoutManager:manager];
[manager addTextContainer:container];
NSUInteger glyphCount = [manager numberOfGlyphs];
NSGlyph glyphs[glyphCount];
[manager getGlyphs:glyphs range:NSMakeRange(0, glyphCount)];
[container release];
[manager release];
[storage release];
NSBezierPath* path = [NSBezierPath bezierPath];
[path moveToPoint: NSMakePoint(0, 0)]; // If I don't do this I get an exception that currentPoint doesn't exist ...
[path appendBezierPathWithGlyphs:glyphs count:length inFont:font];
printf("<?xml version=\"1.0\" standalone=\"no\"?>\n"
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"
"<svg viewBox=\"-5 -5 10 10\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\">\n"
"\t<desc>Debug dump</desc>\n"
"\t\n<path d=\"");
// NSBezierPath -> DoublePath
for (NSInteger i=0; i<[path elementCount]; ++i)
{
if (i != 0) printf(" ");
NSPoint controlPoints[3];
NSBezierPathElement el = [path elementAtIndex:i associatedPoints:controlPoints];
if (el == NSMoveToBezierPathElement)
{
// printf("move to (%f,%f)\n", controlPoints[0].x, controlPoints[0].y);
printf("M%g %g", controlPoints[0].x, controlPoints[0].y);
}
else if (el == NSLineToBezierPathElement)
{
// printf("line to (%f, %f)\n", controlPoints[0].x, controlPoints[0].y);
printf("L%g %g", controlPoints[0].x, controlPoints[0].y);
}
else if (el == NSCurveToBezierPathElement)
{
// printf("cubic to (%f, %f) (%f, %f) (%f, %f)\n",
printf("C%g %g %g %g %g %g",
controlPoints[0].x, controlPoints[0].y,
controlPoints[1].x, controlPoints[1].y,
controlPoints[2].x, controlPoints[2].y);
}
else if (el == NSClosePathBezierPathElement)
{
// printf("close\n");
printf("Z");
}
}
printf("\"/>\n</svg>\n");
Related
I'm trying to draw an arrowhead-curve using Fibonacci-esque words. I may use method calls instead of building onto a string later on, but for now I want to preserve the string.
// create string. Initially set to "A"
NSMutableString *s1 = [[NSMutableString alloc] init];
[s1 setString:#"A"];
// loop through and replace A and B with the following strings. Toned down iterations to 5 here
for(int i=0; i<5; ++i){
[s1 replaceOccurrencesOfString:#"A"
withString:#"+B-A-B+"
options:NSLiteralSearch
range:NSMakeRange(0, s1.length)];
[s1 replaceOccurrencesOfString:#"B"
withString:#"-A+B+A-"
options:NSLiteralSearch
range:NSMakeRange(0, s1.length)];
}
// set line color, thickness
ccDrawColor4F(0.8, 1.0, 0.76, 1.0);
glLineWidth(1.0f);
float angle = 0;
float travelDist = 1; // distance in pixels the line is drawn. Can be changed to whatever
CGPoint p = CGPointMake(300,100);
for(int i = 0; i < [s1 length]; i++){
if([[NSString stringWithFormat:#"%c",[s1 characterAtIndex:i]] isEqualToString:#"+"]){ // turn right
angle += 60;
}else if([[NSString stringWithFormat:#"%c",[s1 characterAtIndex:i]] isEqualToString:#"-"]){ // turn left
angle -= 60;
}else{ // any other character, draw line
float cosAngle = cosf(CC_DEGREES_TO_RADIANS(angle));
float newDist = travelDist * cosAngle;
float sinAngle = sinf(CC_DEGREES_TO_RADIANS(angle));
float newDist2 = travelDist *sinAngle;
ccDrawLine( ccp(p.x, p.y), ccp(p.x + newDist, p.y + newDist2) );
p = CGPointMake(p.x + newDist, p.y + newDist2);
}
}
I've read up on several sites about arrowhead curves, and the rules they must follow. It seems like I should be doing the right thing, but it doesn't turn out quite right. I get something representing a Sierpinski's triangle, but not a proper arrowhead curve.
You may not have to know Objective-c/Cocos2d to answer this, as I'm probably just doing something logistically incorrect.
I need to create a new temporary string based on the current string, and go through one character at a time, and make the string the temporary one at the end of each iteration:
NSMutableString *s1 = [[NSMutableString alloc] init];
[s1 setString:#"A"];
NSMutableString *sTemp = [[NSMutableString alloc] init];
[sTemp setString:#""];
for(int i=0; i<6; ++i){
for(int j = 0; j < [s1 length]; j++){
unichar character = [s1 characterAtIndex:j];
if(character == 'A'){
[sTemp appendString:#"B-A-B"];
}
else if(character == 'B'){
[sTemp appendString:#"A+B+A"];
}else{
[sTemp appendString:[NSString stringWithFormat:#"%C",character]];
}
}
[s1 setString:sTemp];
[sTemp setString:#""];
}
-(id) init
{
if( (self=[super init])) {
_targets = [[NSMutableArray alloc] init];
temp = [NSArray arrayWithObjects:#"1", #"2", #"3", #"4",nil];
tempArray = [[NSMutableArray alloc] initWithArray:temp];
resultArray = [[NSMutableArray alloc] init];
[self thelogic];
}
return self;
}
-(void)thelogic
{
int i;
int count = 4;
for (i = 0; i < 3; i ++) {
int index = arc4random() % (count - i);
[resultArray addObject:[tempArray objectAtIndex:index]];
CCSprite *target = [CCSprite spriteWithFile:[NSString stringWithFormat:#"%#.png", [tempArray objectAtIndex:index]]];
target.tag = [[NSString stringWithFormat:#"%#",[tempArray objectAtIndex:index]] integerValue];
[self addChild:target];
[_targets addObject:target];
[tempArray removeObjectAtIndex:index];
}
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[_targets removeAllObjects];
[self thelogic];
}
from the up code, I get three different numbers and they make three sprites with different image when enter this scene, and I want to touch the screen, the three old sprites will be removed, and three new sprites will show, but the up code always crashes, so how should I fix it? thanks
It is hard to understand what you are trying to do in your theLogic method, but I would suggest you to replace
int index = arc4random() % (count - i);
with
int index = arc4random() % [tempArray count];
This will fix the crash, but I doubt that your program will work as expected. Indeed, you only populate tempArray in the init method; the first call to theLogic will remove all of its elements, and as far as I see the array is not populated anymore. So, when you make ccTouchesBegan be called and then theLogic, tempArray will be empty.
Sorry if I am missing any points.
I am trying to merge OpenCVCircles and OpenCVSquares for a project. If I open them directly from the Xcode project files (independently) they work fine, but if I move the CVSquares.h and CVSquares.cpp files to the OpenCVCircles project, it starts complaining: "Use of undeclared identifier CVSquares". This happens in CVWrapper.mm (see problematic line towards the end):
#import "CVWrapper.h"
#import "CVCircles.h"
#import "CVSquares.h"
#import "UIImage+OpenCV.h"
//remove 'magic numbers' from original C++ source so we can manipulate them from obj-C
#define TOLERANCE 0.3
#define THRESHOLD 50
#define LEVELS 9
#define ACCURACY 0
#implementation CVWrapper
+ (NSMutableArray*) detectedCirclesInImage:(UIImage*) image
{
double dp = 1;
double minDist = 10;
double param1 = 100;
double param2 = 30;
int min_radius = 1;
int max_radius = 30;
return [[self class] detectedCirclesInImage:image
dp:dp
minDist:minDist
param1:param1
param2:param2
min_radius:min_radius
max_radius:max_radius];
}
+ (NSMutableArray*) detectedCirclesInImage:(UIImage*)image
dp:(CGFloat)dp
minDist:(CGFloat)minDist
param2:(CGFloat)param2
{
double param1 = 100;
int min_radius = 1;
int max_radius = 30;
return [[self class] detectedCirclesInImage:image
dp:dp
minDist:minDist
param1:param1
param2:param2
min_radius:min_radius
max_radius:max_radius];
}
+ (NSMutableArray*) detectedCirclesInImage:(UIImage*)image
dp:(CGFloat)dp
minDist:(CGFloat)minDist
param2:(CGFloat)param2
min_radius:(int)min_radius
max_radius:(int)max_radius
{
double param1 = 100;
return [[self class] detectedCirclesInImage:image
dp:dp
minDist:minDist
param1:param1
param2:param2
min_radius:min_radius
max_radius:max_radius];
}
+ (NSMutableArray*) detectedCirclesInImage:(UIImage*)image
dp:(CGFloat)dp
minDist:(CGFloat)minDist
param1:(CGFloat)param1
param2:(CGFloat)param2
min_radius:(int)min_radius
max_radius:(int)max_radius
{
NSMutableArray *array = [[NSMutableArray alloc] init];
UIImage* modifiedImage = nil;
cv::Mat matImage = [image CVMat];
int num_circles = 0;
matImage = CVCircles::detectedCirclesInImage
(matImage, dp, minDist, param1, param2, min_radius, max_radius, &num_circles);
modifiedImage = [UIImage imageWithCVMat:matImage];
NSLog(#"n circles: %i",num_circles);
[array addObject:modifiedImage];
[array addObject:[NSNumber numberWithInt:num_circles]];
NSLog(#"array: %#, %#",[array objectAtIndex:0],[array objectAtIndex:1]);
return array;
}
+ (UIImage*) detectedSquaresInImage:(UIImage*) image
{
//if we call this method with no parameters,
//we use the defaults from the original c++ project
return [[self class] detectedSquaresInImage:image
tolerance:TOLERANCE
threshold:THRESHOLD
levels:LEVELS
accuracy:ACCURACY];
}
+ (UIImage*) detectedSquaresInImage:(UIImage*) image
tolerance:(CGFloat) tolerance
threshold:(NSInteger)threshold
levels:(NSInteger)levels
accuracy:(NSInteger)accuracy
{
//NSLog (#"detectedSquaresInImage");
UIImage* result = nil;
cv::Mat matImage = [image CVMat];
//ERROR IS ON THIS LINE
matImage = CVSquares::detectedSquaresInImage (matImage, tolerance, threshold, levels, accuracy);
result = [UIImage imageWithCVMat:matImage];
//NSLog (#"detectedSquaresInImage result");
return result;
}
#end
I have the impression that I'm double defining something, missing .mm in some files, or the like but I have been struggling with this for the whole day and I can't make it work (today was my first time with C++). Any help would be much appreciated.
PS: Thanks to foundry (whoever he/she is) for the 2 awesome plug & play projects!
Ended up pasting all the CVSquares.cpp code into the CVCircles.cpp code (as well as the CVSquares.h into the CVCircles.h) and calling:
matImage = CVCircles::detectedSquaresInImage (matImage, tolerance, threshold, levels, accuracy);
Couldn't get it to work otherwise. Hope it helps!
I'm trying to add a Sprite beside the player, but only when the Tile beside the player is NOT a Wall. I know that the Tiled tiles are working properly, as they do their job in this method:
CGPoint p = CGPointMake(tileCoord.x, tileCoord.y - 1);
if ([self isValidTileCoord:p] && ![self isWallAtTileCoord:p]) {
[tmp addObject:[NSValue valueWithCGPoint:p]];
t = YES;
I am checking for Tiled on coordinate with these two methods:
-(BOOL)isProp:(NSString*)prop atTileCoord:(CGPoint)tileCoord forLayer:(CCTMXLayer *)layer {
if (![self isValidTileCoord:tileCoord]) return NO;
int gid = [layer tileGIDAt:tileCoord];
NSDictionary * properties = [_tileMap propertiesForGID:gid];
if (properties == nil) return NO;
return [properties objectForKey:prop] != nil;
}
-(BOOL)isWallAtTileCoord:(CGPoint)tileCoord {
return [self isProp:#"Wall" atTileCoord:tileCoord forLayer:_bgLayer];
}
(Thanks RayWenderlich)
And my code for adding the sprite is
CGPoint tileCoord = ccp(_player.position.x - 24 +60, player.position.y);
CGPoint cTileCoord = [self tileCoordForPosition:tileCoord];
NSLog(#" t: %#, c: %#",
CGPointCreateDictionaryRepresentation(tileCoord),
CGPointCreateDictionaryRepresentation(cTileCoord)
);
if (![self isWallAtTileCoord:cTileCoord])
{
NSLog(#"False");
circle1.position = ccp(_player.position.x - 24 +60, _player.position.y);
[self addChild:circle1];
}
else
{
NSLog(#"True");
}
What I want this to do is to only add the Circle1 sprite to the left of the player when there isn't a Wall tile there. The problem is that this code always detects false, no matter if there is a wall there or not. Do any of you guys understand why it does not detect the walls properly and how I can fix it?
Last year me also observed same problem in retina mode. It worked in non retina but not detected in retina mode.
So finally used custom dictionary to check edge tile. Integer comparison takes less CPU time than string comparison. So replaced it with enum.
Go for this approach only if none other simple way worked.
I used this code to find edge of the tile that set in meta property.
typedef enum GRID_TYPE{
kGrideType_Normal = 4001,
kGrideType_Collidable,
kGrideType_Collectable,
kGrideType_Sea,
kGrideType_Edge,
kGrideType_enemy,
kGrideType_gold,
}GridType;
//Init tilemap and grid type
tileMap.meta = [tileMap layerNamed:PP_TILE_META_LAYER];
[tileMap initTileAnimation];
//Somewhere in code
CGPoint point = [self getTileCoordForPosition:position];
GridType type = [self getTileType:point];
if(type == kGrideType_Edge)
{
//touched edge tile....
}
Functions:
-(GridType)getTileType:(CGPoint)pos
{
// not defined USE_COCOS2D_FOR_TILE_IDENTIFICATION
#ifdef USE_COCOS2D_FOR_TILE_IDENTIFICATION
GridType type = kGrideType_Normal;
CGPoint tileCoord = position;//[self tileCoordForPosition:position];
unsigned int tileGid = [self.meta tileGIDAt:tileCoord];
if (tileGid) {
NSDictionary *properties = [self propertiesForGID:tileGid];
if (properties)
{
NSString *collision = [properties valueForKey:TILE_PROPERTY_COLLIDABLE];
if (collision && [collision caseInsensitiveCompare:#"true"] == NSOrderedSame)
{
type = kGrideType_Collidable ;
}
NSString *collectable = [properties valueForKey:TILE_PROPERTY_COLLECTABLE];
if (collectable && [collectable caseInsensitiveCompare:#"true"] == NSOrderedSame) {
type = kGrideType_Coin ;
}
NSString *collectable = [properties valueForKey:TILE_PROPERTY_CHEST];
if (collectable && [collectable caseInsensitiveCompare:#"true"] == NSOrderedSame) {
type = kGrideType_Chest ;
}
}
}
return type;
#else
int type = [[mTileInfoDict objectForKey:[NSString stringWithFormat:#"TILE(%d,%d)", (int)pos.x,(int)pos.y]] intValue];
GridType gType = kGrideType_Normal;
if(type!=0)
gType = (GridType)type;
return (GridType)gType;
#endif
}
-(void)initTileAnimation
{
mTileInfoDict = [[NSMutableDictionary alloc] init];
//Parse all the tile in map
mBgLayer = [self layerNamed:PP_TILE_MAP_BG_LAYER];
int rowSize = self.mapSize.width ;
int colSize = self.mapSize.height ;
for(int x=0; x<rowSize; x++)
{
for (int y=0; y<colSize; y++)
{
CGPoint tileCord = ccp(x,y) ;
NSString *key = [NSString stringWithFormat:#"TILE(%d,%d)", (int)tileCord.x,(int)tileCord.y];
GridType tileType = kGrideType_Normal;
unsigned int tileGid = [self.meta tileGIDAt:tileCord];
if (tileGid)
{
NSDictionary *properties = [self propertiesForGID:tileGid];
if (properties)
{
/* Check Tile : IS SEA - TILE */
NSString *sea = [properties valueForKey:TILE_PROPERTY_SEA];
if (sea && [sea isEqualToString:#"true"])
{
tileType = kGrideType_Sea;
[mTileInfoDict setObject:[NSNumber numberWithInt:tileType] forKey:key];
continue;
}
/* Check Tile : IS Inky - TILE */
/* Check Tile : IS COLLECTABLE - COIN */
NSString *collectable = [properties valueForKey:TILE_PROPERTY_COLLECTABLE];
if (collectable && [collectable isEqualToString:#"true"])
{
tileType = kGrideType_Collectable;
[mTileInfoDict setObject:[NSNumber numberWithInt:tileType] forKey:key];
PPCoins *coinSprite = [PPCoins spriteWithSpriteFrameName:#"coin_0000.png"];
coinSprite.tag = kTagCoinSprite;
coinSprite.anchorPoint = ccp(0.5f,0.5f);
CCSprite *sprite = [mBgLayer tileAt:tileCord];
coinSprite.position = ccp(sprite.position.x+coinSprite.contentSize.width*0.5f, sprite.position.y+coinSprite.contentSize.height*0.5f) ;
[self addChild:coinSprite z:3 tag:kTagCoinSprite];
[coinSprite runAnimation];
{
coinSprite.key = key;
[mCoinDict setObject:coinSprite forKey:key];
}
continue;
}
/* Check Tile : IS COLLIDABLE - TILE */
NSString *collidable = [properties valueForKey:TILE_PROPERTY_COLLIDABLE];
if (collidable && [collidable isEqualToString:#"true"])
{
tileType = kGrideType_Collidable;
[mTileInfoDict setObject:[NSNumber numberWithInt:tileType] forKey:key];
continue;
}
/* Check Tile : IS Edge - TILE */
NSString *edge = [properties valueForKey:TILE_PROPERTY_EDGE];
if (edge && [edge isEqualToString:#"true"])
{
tileType = kGrideType_Edge;
[mTileInfoDict setObject:[NSNumber numberWithInt:tileType] forKey:key];
continue;
}
NSString *redTargetCoin = [properties valueForKey:TILE_PROPERTY_TARGET_COIN];
if (redTargetCoin && [redTargetCoin isEqualToString:#"true"])
{
tileType = kGrideType_TargetCoins;
[mTileInfoDict setObject:[NSNumber numberWithInt:tileType] forKey:key];
}
}
else
{
[mTileInfoDict setObject:[NSNumber numberWithInt:kGrideType_Normal] forKey:key];
}
}
}
}
}
- (CGPoint)getTileCoordForPosition:(CGPoint)position
{
// CGPoint nodeSpace1 = [self convertToNodeSpace:position];
// float x = floor(nodeSpace1.x / self.tileSize.width);
// float y = floor(self.mapSize.height - (nodeSpace1.y / self.tileSize.height));
//
// if( x >= TILE_IN_ROW)
// x = TILE_IN_ROW - 1;
//
// if( y >= TILE_IN_COL)
// y = TILE_IN_COL - 1;
//
// return ccp(x, y);
int maxTileCol = self.mapSize.height;// (_tileMap.contentSize.height)/TILE_SIZE;
int x = ( (position.x-self.position.x)/TILE_SIZE);
int y = maxTileCol - ( ((position.y)-self.position.y)/TILE_SIZE);
if( x >= TILE_IN_ROW)
x = TILE_IN_ROW - 1;
if( y >= TILE_IN_COL)
y = TILE_IN_COL - 1;
return ccp(x, y);
}
You should check if your tile map has the correct layer settings. I did a mistake with this once, it is easy to forget
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;