Okay, I'm befuddled yet again.
I've basically used Ernesto's magic code from start to finish, with only a few changes to keep the warning and error demons at bay inside of XCode.
Here's the original ERNESTO code, as a refresher:
//1) Load the image:
UIImage *collisionImage = [UIImage imageNamed:@"levelmask.png"];
//2) Get the image size:
int width = (int)collisionImage.size.width;
int height = (int)collisionImage.size.height;
//3) Allocate our array for quick lookups and clear it:
unsigned char *collisionMap = (unsigned char *)malloc( width *
height );
memset( collisionMap, 0, width * height );
//4) Get access to the raw bits of the image
CFDataRef imageData = CGDataProviderCopyData( CGImageGetDataProvider
( collisionImage.CGImage ) );
const UInt32 *pixels = (const UInt32*)CFDataGetBytePtr( imageData );
//5) Build our collision map:
for( j = 0; j < (width * height); j++ )
if ( pixels[j] & 0xff000000 ) collisionMap[j] |= 1;
//6) Release what we no longer need:
CFRelease( imageData );
//Now, whenever you need to see if you hit something, you call a routine
//that does:
-(int)collisionForPoint:(CGPoint)point
{
int x = (int)point.x;
int y = (int)point.y;
// TODO: check for boundaries here
return collisionMap[(y*width)+x];
}
I first tried putting the first 6 steps just inside the init of my game's action layer itself. I decided to do this so that we get the data on hand just the once (at init) and don't waste ALL our processing crunches on making and releasing the bloody thing on every update. Then I put the last method further down in the same layer (PAST the init).
It's the last little method that screws me up.
If I place the map maker INSIDE the init, I can't call back to it from the collisionForPoint method, because it tells me that collisionMap (and width) is undeclared.
My fix for this was to make the mapping code its own method, which I then declared an instance of in the @interface of the header, so that I could create the instance in my init and call back to it from my collisionForPoint method.
The problem with this is that I assumed that the maker method would be of the same type that the collisionMap it returns was created: an unsigned char. So my method looked like this:
-(unsigned char) makeCollisionMap
{
UIImage *collisionImage = [UIImage imageNamed:@"bgColl2.png"];
int width = (int)collisionImage.size.width;
int height = (int)collisionImage.size.height;
unsigned char *collisionMap = (unsigned char *)malloc(width * height);
memset(collisionMap, 0, width * height);
CFDataRef imageData = CGDataProviderCopyData(CGImageGetDataProvider(collisionImage.CGImage));
const UInt32 *pixels = (const UInt32*)CFDataGetBytePtr(imageData);
for (int j = 0; j < (width * height); j++)
{
if ( pixels[j] & 0xff000000 ) collisionMap[j] |= 1;
}
CFRelease(imageData);
return collisionMap;
}
I initialize this as colly in my init:
colly = [self makeCollisionMap];
Then of course call it from the other method:
-(int) collisionForPoint:(CGPoint)point
{
int a = (int)point.x;
int b = (int)point.y;
int mapValue = colly[(b * 1024)+a];
NSLog(@"val: %i", mapValue);
return mapValue;
}
As you can see, I just gave it the constant of my map width (1024) rather than a variable, and then use the NSLog to double check my returned value. And the NSLog gives me a whole crazy range of numbers back from my little array of supposedly 1s and 0s, depending on the player position that I pass into it!
I believe this is because of the way the first method is returning the (unsigned char).
I am getting a warning from Xcode saying:
warning: assignment makes pointer from integer without a cast
at my init.
I assume this is what is ruining my data. I NSLogged my collisionMap as it's being made, and I DID get back my 1s and 0s, so the data INSIDE my collisionMap is good, but it seems to be getting screwed up as I pull it back out of the instance I had to create.
Is anyone still awake after all that? Good! Because I'm ready to kill this silly iMac.
I am open to suggestions/criticism.