0

I am trying to use a particle system loading the particles for a texture. Since it's just an exercise, it's fine to me to generate the texture "manually". So in this case I just allocate a buffer of data and fill it with red color (RGBA 32 bit format).

But the problem is that when the program starts running, I just see the black screen and there isn't what I am expecting to see (some red particles moving on).

I explain what I am trying to do in the comments:

if( (self=[super init]))
{
    NSAutoreleasePool* pool=[[NSAutoreleasePool alloc]init];

    uint32_t mask= 255+pow(255, 4); // This is a 32 bit red pixel
    NSUInteger size=256; // The texture is 256x256
    void* buffer= malloc(size*size*4); // Here I hold the data, it will be all red
    for(NSUInteger i=0; i<size; i++)
    {
        for(NSUInteger j=0; j<size; j++)
        {
            memcpy(buffer+j+i*32, &mask, 4);
        }
    }
    NSData* data=[[[NSData alloc]initWithBytesNoCopy: buffer length: size*size*4 freeWhenDone: YES]autorelease];  // I wrap it into NSData to automatically release it later. 
    CCTexture2D* texture=[[[CCTexture2D alloc]initWithData: data.bytes pixelFormat: kCCTexture2DPixelFormat_RGBA8888 pixelsWide: size pixelsHigh: size contentSize: CGSizeMake(size, size)]autorelease];
    CCParticleSystemQuad* system=[[[CCParticleSystemQuad alloc]initWithTotalParticles: 100]autorelease];
    system.texture= texture;  // I set the texture in a way that it should be load to draw particles
    system.position= ccp(200, 200);
    system.startSize= 10;
    system.endSize= 5;
    system.duration= kCCParticleDurationInfinity;
    system.life= 1;
    [self addChild: system]; 

    [pool drain];
}

Using an image

I tried to modify the code in a way that I use an UIImage instead of the manually created texture:

if( (self=[super init]))
{
    // Even with glClearColor() it doesn't work
    //glClearColor(1, 0, 1, 1);
    NSAutoreleasePool* pool=[[NSAutoreleasePool alloc]init];

    NSBundle* bundle=[NSBundle mainBundle];
    NSString* path=[bundle pathForResource: @"fire" ofType: @"png"];
    UIImage* image=[UIImage imageWithContentsOfFile: path];
    CCTexture2D* texture=[[[CCTexture2D alloc]initWithImage: image]autorelease];
    CCParticleSystemQuad* system=[[[CCParticleSystemQuad alloc]initWithTotalParticles: 100]autorelease];
    system.texture= texture;
    system.startSize= 10;
    system.endSize= 10;
    system.life= 1;
    system.duration= kCCParticleDurationInfinity;
    system.position= ccp(200, 200);
    // Even changing the start/end color it doesn't work
    //system.startColor= (ccColor4F){1.0,0.0,0.0,1.0};
    //system.endColor= (ccColor4F){1.0,0.0,0.0,1.0};
    system.emitterMode= kCCParticleModeGravity;
    system.gravity= ccp(200, 200);
    system.speed=1;
    [self addChild: system];

    [pool drain];
}

The image "fire.png" in the app bundle is:

enter image description here

I also set some other properties but it still doesn't work: black screen.

Ramy Al Zuhouri
  • 21,580
  • 26
  • 105
  • 187
  • use memset(buffer, &mask, size*size*4) to fill the buffer with just one color all at once, the for loops and copying 4 bytes each iteration is very ineffective – CodeSmile Mar 09 '13 at 23:41
  • 2
    The NSData is unnecessary, pass buffer to CCTexture2D directly and free(buffer) in the line after that. This is ok because CCTexture2D copies the data from the buffer into an actual texture and buffer is no longer needed. The NSAutoreleasePool here is also completely unnecessary (and the pool is leaking because you don't release it .. consider using ARC). – CodeSmile Mar 09 '13 at 23:44
  • About memset: it takes just the first one byte, but I have a 4 bytes integer, that's why I use a loop. About the pool: should I use release instead of autorelease and drop the autorelease pool? Btw [pool drain] releases the pool. – Ramy Al Zuhouri Mar 10 '13 at 10:10
  • memset sets n integer values, it'll fill the entire buffer just fine. The autorelease pool here has simply nothing or just very, very little to do. It's not like you're creating hundreds of autoreleased objects between the pool's init and drain (didn't know that's an alias for release). – CodeSmile Mar 11 '13 at 01:03
  • The bitmask I need to set here is 255+255^4 . memset() will convert this number to an unsigned char, and it will set every byte with 255 (the casted number). – Ramy Al Zuhouri Mar 11 '13 at 08:18

2 Answers2

2

Couple things come to my mind (besides the code improvements, see my comments):

Change the clear color, just to see if the particle system may be running but only spawning black particles:

glClearColor(1, 0, 1, 1);

The particle system itself may not be properly configured (incomplete data, properties using default values which usually are just 0s). It's possible that the properties you haven't modified cause the particle system to render incorrectly. For example the particle system has startColor and endColor properties. If they are both initialized to a black or transparent color because you haven't set them to a brighter (white) color, it doesn't matter what color your texture has, the particles will be black. I believe this is most likely what's happening here.

Try setting up the particle system with a regular texture from an image file first. If you have confirmed the particle system creates visible, non-black particles you can then switch to using your custom texture.

CodeSmile
  • 64,284
  • 20
  • 132
  • 217
0

I ended up using particles mint to create a particle system, then using the factory method:

CCParticleSystemQuad* system=[[[CCParticleSystemQuad alloc]initWithDictionary: [ParticleFactory makeEffect]]autorelease];
Ramy Al Zuhouri
  • 21,580
  • 26
  • 105
  • 187