我正在开发一个多层次的游戏。如果我从级别1或级别2开始,初始级别运行正常无关紧要。在代码中,根据用户的分数加载下一级别。我正在使用游戏状态管理器来解除初始级别并加载下一级别。在IOS 4.2中,此代码运行时没有错误。但是,在IOS 4.3.3中,当在下一级的Rendder方法中调用glClear(GL_COLOR_BUFFER_BIT)行时,我得到一个EXC_BAD_ACCESS错误。
其他帖子建议我在我的Render方法结尾处放置glBindBuffer(GL_ARRAY_BUFFER,0)和glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0),但是我得到了相同的EXC_BAD_ACCESS错误。我确信我访问了不良内存,但需要使用什么OpenGL来加载我的新级别w / o错误?
两个级别的渲染方法相同:
//clear anything left over from the last frame, and set background color.
glClearColor(0xff/256.0f, 0x66/256.0f, 0x00/256.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
[tileWorld draw];
[super renderEndgame];
//you get a nice boring white screen if you forget to swap buffers.
[self swapBuffers];
我有一个处理OpenGL设置的GLTexture类:
#import <OpenGLES/ES1/glext.h>
#import "GLTexture.h"
//CONSTANTS:
#define kMaxTextureSize 1024
//CLASS IMPLEMENTATIONS:
@implementation GLTexture
@synthesize contentSize=_size, pixelFormat=_format, pixelsWide=_width, pixelsHigh=_height, name=_name, maxS=_maxS, maxT=_maxT;
@dynamic width, height;
- (float) width {
return self.contentSize.width;
}
- (float) height {
return self.contentSize.height;
}
- (id) initWithData:(const void*)data pixelFormat:(GLTexturePixelFormat)pixelFormat pixelsWide:(NSUInteger)width pixelsHigh:(NSUInteger)height contentSize:(CGSize)size
{
GLint saveName;
if((self = [super init])) {
glGenTextures(1, &_name); //get a new texture id. _name increases as more textures are loaded
glGetIntegerv(GL_TEXTURE_BINDING_2D, &saveName); //generally, saveName==1. gets existing bound texture, so we can restore it after load.
glBindTexture(GL_TEXTURE_2D, _name); //start working with our new texture id
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//associate pixel data with the texture id.
switch(pixelFormat) {
case kGLTexturePixelFormat_RGBA8888:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
break;
case kGLTexturePixelFormat_RGB565:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);
break;
case kGLTexturePixelFormat_A8:
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@""];
}
glBindTexture(GL_TEXTURE_2D, saveName); //restore the previous texture binding.
//NSLog(@"name %d, savename %d", _name, saveName);
_size = size;
_width = width;
_height = height;
_format = pixelFormat;
_maxS = size.width / (float)width;
_maxT = size.height / (float)height;
}
return self;
}
- (void) dealloc
{
if(_name)
glDeleteTextures(1, &_name);
[super dealloc];
}
- (NSString*) description
{
return [NSString stringWithFormat:@"<%@ = %08X | Name = %i | Dimensions = %ix%i | Coordinates = (%.2f, %.2f)>", [self class], self, _name, _width, _height, _maxS, _maxT];
}
@end
@implementation GLTexture (Image)
- (id) initWithImage:(UIImage *)uiImage
{
NSUInteger width,
height,
i;
CGContextRef context = nil;
void* data = nil;;
CGColorSpaceRef colorSpace;
void* tempData;
unsigned int* inPixel32;
unsigned short* outPixel16;
BOOL hasAlpha;
CGImageAlphaInfo info;
CGAffineTransform transform;
CGSize imageSize;
GLTexturePixelFormat pixelFormat;
CGImageRef image;
UIImageOrientation orientation;
BOOL sizeToFit = NO;
image = [uiImage CGImage];
orientation = [uiImage imageOrientation];
if(image == NULL) {
[self release];
NSLog(@"Image is Null");
return nil;
}
info = CGImageGetAlphaInfo(image);
hasAlpha = ((info == kCGImageAlphaPremultipliedLast) || (info == kCGImageAlphaPremultipliedFirst) || (info == kCGImageAlphaLast) || (info == kCGImageAlphaFirst) ? YES : NO);
if(CGImageGetColorSpace(image)) {
if(hasAlpha)
pixelFormat = kGLTexturePixelFormat_RGBA8888;
else
pixelFormat = kGLTexturePixelFormat_RGB565;
} else //NOTE: No colorspace means a mask image
pixelFormat = kGLTexturePixelFormat_A8;
imageSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));
transform = CGAffineTransformIdentity;
width = imageSize.width;
if((width != 1) && (width & (width - 1))) {
i = 1;
while((sizeToFit ? 2 * i : i) < width)
i *= 2;
width = i;
}
height = imageSize.height;
if((height != 1) && (height & (height - 1))) {
i = 1;
while((sizeToFit ? 2 * i : i) < height)
i *= 2;
height = i;
}
while((width > kMaxTextureSize) || (height > kMaxTextureSize)) {
width /= 2;
height /= 2;
transform = CGAffineTransformScale(transform, 0.5, 0.5);
imageSize.width *= 0.5;
imageSize.height *= 0.5;
}
switch(pixelFormat) {
case kGLTexturePixelFormat_RGBA8888:
colorSpace = CGColorSpaceCreateDeviceRGB();
data = malloc(height * width * 4);
context = CGBitmapContextCreate(data, width, height, 8, 4 * width, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
break;
case kGLTexturePixelFormat_RGB565:
colorSpace = CGColorSpaceCreateDeviceRGB();
data = malloc(height * width * 4);
context = CGBitmapContextCreate(data, width, height, 8, 4 * width, colorSpace, kCGImageAlphaNoneSkipLast | kCGBitmapByteOrder32Big);
CGColorSpaceRelease(colorSpace);
break;
case kGLTexturePixelFormat_A8:
data = malloc(height * width);
context = CGBitmapContextCreate(data, width, height, 8, width, NULL, kCGImageAlphaOnly);
break;
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid pixel format"];
}
CGContextClearRect(context, CGRectMake(0, 0, width, height));
CGContextTranslateCTM(context, 0, height - imageSize.height);
if(!CGAffineTransformIsIdentity(transform))
CGContextConcatCTM(context, transform);
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);
//Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRGGGGGGBBBBB"
if(pixelFormat == kGLTexturePixelFormat_RGB565) {
tempData = malloc(height * width * 2);
inPixel32 = (unsigned int*)data;
outPixel16 = (unsigned short*)tempData;
for(i = 0; i < width * height; ++i, ++inPixel32)
*outPixel16++ = ((((*inPixel32 >> 0) & 0xFF) >> 3) << 11) | ((((*inPixel32 >> 8) & 0xFF) >> 2) << 5) | ((((*inPixel32 >> 16) & 0xFF) >> 3) << 0);
free(data);
data = tempData;
}
self = [self initWithData:data pixelFormat:pixelFormat pixelsWide:width pixelsHigh:height contentSize:imageSize];
CGContextRelease(context);
free(data);
return self;
}
@end
@implementation GLTexture (Drawing)
- (void) drawAtPoint:(CGPoint)point
{
GLfloat coordinates[] = { 0, _maxT,
_maxS, _maxT,
0, 0,
_maxS, 0 };
GLfloat width = (GLfloat)_width * _maxS,
height = (GLfloat)_height * _maxT;
GLfloat vertices[] = { -width / 2.0f + point.x, -height / 2.0f + point.y, 0.0,
width / 2.0f + point.x, -height / 2.0f + point.y, 0.0,
-width / 2.0f + point.x, height / 2.0f + point.y, 0.0,
width / 2.0f + point.x, height / 2.0f + point.y, 0.0 };
glBindTexture(GL_TEXTURE_2D, _name);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
- (void) drawAtPoint:(CGPoint)point withRotation:(CGFloat)rotation withScale:(CGFloat)scale
{
GLfloat coordinates[] = { 0, _maxT,
_maxS, _maxT,
0, 0,
_maxS, 0 };
GLfloat width = (GLfloat)_width * _maxS,
height = (GLfloat)_height * _maxT;
GLfloat vertices[] = {
-width / 2.0f, -height / 2.0f, 0.0,
width / 2.0f, -height / 2.0f, 0.0,
-width / 2.0f, height / 2.0f, 0.0,
width / 2.0f, height / 2.0f, 0.0
};
glBindTexture(GL_TEXTURE_2D, _name);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glPushMatrix();
glTranslatef(point.x, point.y, 0);
glRotatef(rotation, 0, 0, 1); //in degrees, about screen origin.
glScalef(scale, scale, scale);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glPopMatrix();
}
//note that if you clip too near to a drastic color change in the source texture, the color may bleed through on
//the edges due to anti-aliasing.
//draws align bottom-left, like opengl coordinates.
- (void) drawInRect:(CGRect)dest withClip:(CGRect)src withRotation:(CGFloat)rotation {
GLfloat
gx0 = src.origin.x/_width, gx1 = (src.origin.x+src.size.width)/_width,
gy0 = src.origin.y/_height, gy1 = (src.origin.y+src.size.height)/_height;
GLfloat coordinates[] = {
gx0, gy1,
gx1, gy1,
gx0, gy0,
gx1, gy0
};
GLfloat vertices[] = {
-dest.size.width/2, -dest.size.height/2, 0.0,
dest.size.width/2, -dest.size.height/2, 0.0,
-dest.size.width/2, dest.size.height/2, 0.0,
dest.size.width/2, dest.size.height/2, 0.0
};
glBindTexture(GL_TEXTURE_2D, _name);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glPushMatrix();
glTranslatef(dest.origin.x+dest.size.width/2, dest.origin.y+dest.size.height/2, 0);
glRotatef(rotation, 0, 0, 1); //in degrees, about screen origin.
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glPopMatrix();
}
- (void) drawInRect:(CGRect)rect
{
GLfloat coordinates[] = { 0, _maxT,
_maxS, _maxT,
0, 0,
_maxS, 0 };
GLfloat vertices[] = { rect.origin.x, rect.origin.y, 0.0,
rect.origin.x + rect.size.width, rect.origin.y, 0.0,
rect.origin.x, rect.origin.y + rect.size.height, 0.0,
rect.origin.x + rect.size.width, rect.origin.y + rect.size.height, 0.0 };
glBindTexture(GL_TEXTURE_2D, _name);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
- (void) drawInVertices:(GLfloat*) vertices {
GLfloat coordinates[] = { 0, _maxT,
_maxS, _maxT,
0, 0,
_maxS, 0 };
glBindTexture(GL_TEXTURE_2D, _name);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glTexCoordPointer(2, GL_FLOAT, 0, coordinates);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
@end