1

I have a class called Textures that use holds some data like this

//Textures.h
#import <Foundation/Foundation.h>

@interface Textures
{
    CCTexture2D *Balloon_RED;
    CCTexture2D *Balloon_POP;
}
@property (nonatomic, retain) CCTexture2D* Balloon_RED;
@property (nonatomic, retain) CCTexture2D* Balloon_POP;

-(void)setTextures;
+(CCTexture2D*) cacheImg: (NSString*) image;
@end

//Textures.m
#import "Textures.h"

@implementation Textures
@synthesize Balloon_RED;
@synthesize Balloon_POP;
-(void)setTextures
{
    Balloon_RED = [Textures cacheImg:@"red.png"];
    Balloon_POP = [Textures cacheImg:@"pop.png"];
}
+(CCTexture2D*)cacheImg: (NSString*)image
{
    return [[CCTextureCache sharedTextureCache] addImage:image];
}
@end

And I use it in my main class like this: (SpriteTextures is of type "Textures" and BalloonSprite is of type "Balloon" which is my subclass of CCSprite)

[SpriteTextures setTextures];
BalloonSprite = [Balloon spriteWithTexture: [SpriteTextures Balloon_RED]];

After the splash screen loads I get an error saying its an invalid texture I'm using:

Assertion failure in -[Balloon initWithTexture:], /Users/Mark/Kobold2D/Kobold2D-1.0.5/__Kobold2D__/libs/cocos2d-iphone/cocos2d/CCSprite.m:192
2012-03-02 20:00:18.011 Game-iOS[1341:1ca03] ERROR: Uncaught exception Invalid texture for sprite
2012-03-02 20:00:18.011 Game-iOS[1341:1ca03] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid texture for sprite'

Additional Info is that I'm using Kobold as you can see in the error log but that shouldn't really make a difference I'm sure I'm probably doing something wrong somewhere.

Any help is appreciated, thanks!

Edit What the resources folder looks like, they are also in folders of the physical drive too. Resources folder

Also, this works just fine (adding the texture2ds to main class)

Texture_RED = [[CCTextureCache sharedTextureCache] addImage:@"red.png"];
Texture_POP = [[CCTextureCache sharedTextureCache] addImage:@"pop.png"];

BalloonSprite = [Balloon spriteWithTexture: Texture_RED];

Or really, overall, is there a better way to organize a lot of sprites (that many need to change texture) for a game with close to 100 different images?

Edit

Main Class (*.h)

#import "Textures.h"

@interface MainClass : CCLayer
{
    Textures *SpriteTextures;
}
-(void)loop;
@property (retain) Textures *SpriteTextures;

Implementation

-(id) init
{
    if ((self = [super init]))
    {
        self.isTouchEnabled = true;
        [SpriteTextures setTextures];

        BalloonSprite = [Balloon spriteWithTexture: [SpriteTextures Balloon_RED]];
        .......
Mark Lalor
  • 7,820
  • 18
  • 67
  • 106

2 Answers2

1

NSAsserts are a real pain , but when on top of it the message is useless :) ... ok, looking at line 192 in cocos2d (CCSprite), the texture is nil (causing the assert failure). Check to see if you got messages similar to these for your textures when adding them to the sharedTextureCache.

2012-03-02 21:19:43.497 MyGame[55224:12203] cocos2d: CCTexture2D. Can't create Texture. UIImage is nil

2012-03-02 21:19:43.498 MyGame[55224:12203] cocos2d: Couldn't add image:a.png in CCTextureCache

If you did, the textures have not been found. Make certain they are in your resources folder, and also that they are members of the target you are building.

part 2 : just re-reading your code, you would get the same error if SpriteTextures was nil in the statement

[SpriteTextures setTextures];
BalloonSprite = [Balloon spriteWithTexture: [SpriteTextures Balloon_RED]];

That could explain why it works in one place but not the other.

part 3 : you are not initializing nor setting SpritTextures in your class init. Try:

    self.isTouchEnabled = true;
    self.SpriteTextures = [[Textures alloc] init];
    [SpriteTextures setTextures];
YvesLeBorg
  • 9,070
  • 8
  • 35
  • 48
  • Im going to try to edit in a picture of the Resource folder hierarchy in a minute. – Mark Lalor Mar 03 '12 at 02:29
  • Also, what do you mean by "members of the target you are building"? – Mark Lalor Mar 03 '12 at 02:42
  • how did you add the files to the project ? Normally, i drag them from the folder they are onto the Resources folder icon in Xcode. When you do that, Xcode will ask you in 'which target' you want those resources included. For example, in the project 'MyGame' above, I have 2 targets, the game and a lite version. When I add images, i check both targets to make certain they are included in the .app produced by the build process. – YvesLeBorg Mar 03 '12 at 02:45
  • I copied the images folder directly into the projects resources folder then did File->Add Files to "ProjectName" while the resources folder was selected and browsed to the images folder that is now located in the projects resource folder – Mark Lalor Mar 03 '12 at 02:47
  • @Mark : aded part 2 to my answer, that could also explain why you are getting the error in one place but not in the main class. If it works in main, then your resource folder is ok and the textures are members of the target. – YvesLeBorg Mar 03 '12 at 03:12
  • So how come it doesn't work with my other class? Also, is there just any better way to manage a large amount of textures/sprites? – Mark Lalor Mar 03 '12 at 03:15
  • I manage pretty similar to what you are doing (2000+ textures) ... it can get hairy at times. Like you i create sub-groups within Resources, and try to keep things in a semi-ordered manner to i can find myself in that mess. When the art team dumps a large number of updates on me, I tend to copy the files over (with shell) and not use the drag'n drop of Xcode (mostly drag as far as I am concerned :) ). Shell squash is only for texture updates : no new, deleted, or renamed files : for those i go via the Xcode GUI. – YvesLeBorg Mar 03 '12 at 03:26
  • for your other question, did you try to determine if SpriteTextures is nil ? If it is, that is the issue you have to resolve. – YvesLeBorg Mar 03 '12 at 03:27
  • Hmm i set breakpoints and yeah i think your right they look null, but i don't know why. I think it has to do with that i also set breakpoints in the `[SpriteTextures setTextures];` function but it seems like it never actually gets called (it doesn't stop for the breakpoints). – Mark Lalor Mar 03 '12 at 03:55
  • It does not get called because SpriteTextures is nil, thus you are passing a nil to Balloon. To help you more i would need to see where and how you declare and set SpriteTextures. – YvesLeBorg Mar 03 '12 at 04:06
  • Ok i added how spritetextures is 'made' – Mark Lalor Mar 03 '12 at 04:17
  • @Mark - added part 3 to my answer. – YvesLeBorg Mar 03 '12 at 04:29
  • some process is hung up w/ the simulator give me a min to restart – Mark Lalor Mar 03 '12 at 04:34
  • Oh gosh linker error after i restarted, i need to o to bed for the night but ill look into this more tomorrow. Thanks so much for your help – Mark Lalor Mar 03 '12 at 04:41
1

I believe the answer is simpler than you think ..!

Texture_RED = [[CCTextureCache sharedTextureCache] addImage:@"red.png"];
Texture_POP = [[CCTextureCache sharedTextureCache] addImage:@"pop.png"];

The textures are unretained. Try:

self.Texture_RED = [[CCTextureCache sharedTextureCache] addImage:@"red.png"];
self.Texture_POP = [[CCTextureCache sharedTextureCache] addImage:@"pop.png"];

if you need a reason, here is my reasoning:

        if( tex )
            [textures_ setObject: tex forKey:path];
        else
            CCLOG(@"cocos2d: Couldn't add image:%@ in CCTextureCache", path);

        // autorelease prevents possible crash in multithreaded environments
        [tex autorelease];  

The previous code is found in the

CCTextureCache addImage:

Which means, you should retain your textures.

Moreover, even if it was somehow retained elsewhere by CCTextureCache, the cache is purged on receiving a memory warning from the OS, possible causing your game to crash when that happens.

Mazyod
  • 22,319
  • 10
  • 92
  • 157
  • 1
    The cache in CCTextureCache (a singleton) is an NSMutableDictionary keyed on a derivative of the texture's file name. They are retained. Your app needs to manage the cache clearing, and of course a memory warning would be a good opportunity to remove unused textures. If Mark's issue was sending a message to a deallocated object, the program would not get to the Assertion failure. – YvesLeBorg Mar 03 '12 at 10:26
  • Well I'm getting Apple match-o linker error thing so its gone take me some more time to test these things out, sorry. – Mark Lalor Mar 03 '12 at 18:04
  • Tip: I realized in Xcode 4, the Mac-O linkage error appears whenever you have other syntax errors. So make sure you cleared the other errors first. – Mazyod Mar 03 '12 at 19:34