为满足游戏逻辑,需要将加入sprite与b2Body相分离!也就是要做出植物大战僵尸中那种“僵尸保龄球”最上面那栏“滚动条”的效果
这里我的想法是先将sprite先加入,然后拖拽到y坐标达到一定下限的时候,给该sprite对象添加 b2Body 骨架 ,让 牛顿来作导演
原来的代码被我改的面目全非了,而且对于xcode这种ide,以及objective-c语言的特性,不能像在eclipse中对java项目那样方便的进行重构
报错的错误也是不疼不痒,所以说当爆出莫名其妙的错误的时候,找bug在哪里往往就是一件非常蛋疼的事情
本次由于我修改了很多原文件,因此急需确定错误是出在哪里,因此我采用“暴力调试大法”,没办法,对xcode 调试功能掌握的不熟练~。~
这次遇到的还是哪个什么 EXC_BAD_ACCESS 错误,这个错误恶心我很久了,但是我始终是未曾放弃!!这不,这次我又找到了元凶!!
此次有几点收获:
一。对于在栈上分配的内存,比如说
_circleShape.m_radius = verticesBak.x/2/PTM_RATIO;
_fixtureDef.shape = &_circleShape;
_fixtureDef.density = BOX_DENSITY;
_fixtureDef.friction = BOX_FRICTION;
_fixtureDef.restitution = BOX_RESTITUTION;
这里的 _fixtureDef 是成员变量,这个成员变量是分配在栈上的
而在box2d里面,在使用 _fixtureDef 来创建 b2Body 上的附着物的时候,采用的是复制使用的方式
也就是说,这里的 _fixtureDef 是可以被重复配置使用的,并不会对多个采用该定义创建的附着物产生交叉影响
其实这里也是迫不得已,因为 _fixtureDef 使用完之后已经不再有存在的价值了,完全每必要再占用内存空间
但是我却不知到该如何去释放保存再栈上的成员变量。。。
刚开始我再使用晚之后还采用了 _fixtureDef = NULL 的写法,结果编译时即报出错误说不可以这样
想想也是,他又不是指针,你怎么可以赋予其1个NULL值表示不再引用分配在堆上的对象呢?
还有 if(_fixtureDef == NULL) 的这种写法,也是不成立的,与上同理!!
二。第二个问题就时对局部变量取地址的问题
这次的错误也是源于此,本来我还以为是因为项目中修改到的地方太多出现了疏漏才造成的错误~
b2CircleShape shape;
shape.m_radius = verticesBak.x/2/PTM_RATIO;
_fixtureDef.shape = &shape;
_fixtureDef.density = BOX_DENSITY;
_fixtureDef.friction = BOX_FRICTION;
_fixtureDef.restitution = BOX_RESTITUTION;
以上是我之前的写法,_fixtureDef 是定义在栈上的成员变量
这个成员变量对该方法中的局部变量 shape 有取地址 的操作!!注意,这里问题就来了
等到跳出这个方法的时候,保存在成员变量 _fixtureDef 中的 shape 数据已经不复存在了
因为一跳出这对大括号,shape 变量的存活周期就结束了,就被系统回收了
之后再从这块儿已经被回收的地方取东西的话肯定是会报出错误的,对于这类错误
XCode经常就是以 EXC_BAD_ACCESS 来提示开发者的~
解决方法也很简单,把 shape 由方法中的局部变量提升为类的成员变量即可~
3。不得不提的是某些类的设计实在是深谋远虑
如同Cocos2d中的CCSprite 类,以及 box2d中的 b2Body 类,都包含了一个 (void*) 类型的 userData 字段
个人感觉这对解决某些需要自 成员变量 提取 所属对象 的时候,还是非常方便的,否则又得继承什么什么得了,省了不少事儿~
// 加载 TMX 地图~
-(void) loadTmxTiledMap {
NSLog(@"暴利调试大法启动");
_gameMap = [CCTMXTiledMap tiledMapWithTMXFile:[NSString stringWithFormat:@"level_%@.tmx", @"demo"]];
[self addChild:_gameMap];
// Element Group 中的 Table 类表示的是地图中的拦路方块儿~
CCTMXLayer *ground = [_gameMap layerNamed:@"Ground"];
for (int x = 0; x < GAME_WIDTH; x ++) {
for (int y = 0; y < GAME_HEIGH; y ++) {
int tileGID = [ground tileGIDAt:CGPointMake(x, y)];
if (tileGID) {
NSDictionary *properties = [_gameMap propertiesForGID:tileGID];
if (properties) {
NSString *collision = [properties valueForKey:@"collidable"];
if (collision && [collision compare:@"hori"] == NSOrderedSame) {
[[Table alloc] init:_world type:1
x:[ground tileAt:CGPointMake(x, y)].position.x/PTM_RATIO
y:[ground tileAt:CGPointMake(x, y)].position.y/PTM_RATIO];
} else if (collision && [collision compare:@"left"] == NSOrderedSame) {
[[Table alloc] init:_world type:2
x:[ground tileAt:CGPointMake(x, y)].position.x/PTM_RATIO
y:[ground tileAt:CGPointMake(x, y)].position.y/PTM_RATIO];
} else if (collision && [collision compare:@"right"] == NSOrderedSame) {
[[Table alloc] init:_world type:3
x:[ground tileAt:CGPointMake(x, y)].position.x/PTM_RATIO
y:[ground tileAt:CGPointMake(x, y)].position.y/PTM_RATIO];
} else if (collision && [collision compare:@"full"] == NSOrderedSame) {
[[Table alloc] init:_world type:4
x:[ground tileAt:CGPointMake(x, y)].position.x/PTM_RATIO
y:[ground tileAt:CGPointMake(x, y)].position.y/PTM_RATIO];
}
}
}
}
}
NSLog(@"分叉口");
// 读取对象层中配置的数据(将所有形状均保存至1个统一的数组 _shapes,便于在越界的时候做清除遍历)~
CCTMXObjectGroup *objects = [_gameMap objectGroupNamed:@"Objects"];
NSAssert(objects != nil, @"'Objects' object group not found");
for( NSMutableDictionary *child in [objects objects] ) {
CGPoint p = CGPointMake([[child valueForKey:@"x"] intValue], [[child valueForKey:@"y"] intValue]);
CGSize sz = CGSizeMake([[child valueForKey:@"w"] intValue], [[child valueForKey:@"h"] intValue]);
float rotateDegree = [[child valueForKey:@"r"] floatValue];
if( [[child valueForKey:@"name"] isEqual: @"Triangle"] ) { // 三角形~
NSLog(@"三角形开始");
BYTriangle *triangle = [[BYTriangle alloc] init:_world
size:sz
rotate:rotateDegree
textureImgName:@"darkWoodenTexture.png"];
[triangle addSprite2b2World:p];
[_triangles addObject:triangle];
[_shapes addObject:triangle];
// 将精灵加入到层当中~
[self addChild: [triangle getSprite] z:4];
NSLog(@"三角形结束");
} else if ( [[child valueForKey:@"name"] isEqual:@"Rectangle"] ) { // 矩形~
// NSLog(@"矩形开始");
// BYRectangle *rectangle = [[BYRectangle alloc] init:_world
// size:sz
// rotate:rotateDegree
// insideColor:(ccColor4F){0, 0.0f, 0, 0.3f}
// outsideColor:(ccColor4F){1.0f, 1.0f, 1.0f, 0.7f}
// textureImgName:@"redWoodFloor.png"
// noiseImgName:@"paperNoise_compact512.png"];
// [rectangle addSprite2b2World:p];
// [_rectangles addObject:rectangle];
// [_shapes addObject:rectangle];
// [self addChild:[rectangle getSprite] z:4];
// NSLog(@"矩形结束");
} else if ( [[child valueForKey:@"name"] isEqual:@"Trapezium"] ) { // 梯形~
NSLog(@"梯形开始");
BYTrapezium *trapezium = [[BYTrapezium alloc] init:_world
size:sz
rotate:rotateDegree
insideColor:(ccColor4F){0, 0.0f, 0, 0.3f}
outsideColor:(ccColor4F){1.0f, 1.0f, 1.0f, 0.7f}
textureImgName:@"colorMixed_compact256.png"];
[trapezium addSprite2b2World:p];
[_trapeziums addObject:trapezium];
[_shapes addObject:trapezium];
[self addChild:[trapezium getSprite] z:4];
NSLog(@"梯形结束");
} else if ( [[child valueForKey:@"name"] isEqual:@"Pentagon"] ) { // 五边形~
NSLog(@"五边形开始");
BYPentagon *pentagon = [[BYPentagon alloc] init:_world
size:sz
rotate:rotateDegree];
[pentagon addSprite2b2World:p];
[_pentagons addObject:pentagon];
[_shapes addObject:pentagon];
[self addChild:[pentagon getSprite] z:4];
NSLog(@"五边形结束");
} else if ( [[child valueForKey:@"name"] isEqual:@"Sexangle"] ) { // 六边形~
NSLog(@"六边形开始");
BYSexangle *sexangle = [[BYSexangle alloc] init:_world
size:sz
rotate:rotateDegree
insideColor:(ccColor4F){0, 0.0f, 0, 0.3f}
outsideColor:(ccColor4F){1.0f, 1.0f, 1.0f, 0.7f}
textureImgName:@"greenStoneTexture.png"];
[sexangle addSprite2b2World:p];
[_sexangles addObject:sexangle];
[_shapes addObject:sexangle];
[self addChild:[sexangle getSprite] z:4];
NSLog(@"六边形结束");
} else if ( [[child valueForKey:@"name"] isEqual:@"Circle"] ) { // 圆~
NSLog(@"圆形开始");
BYCircle *circle = [[BYCircle alloc] init:_world
size:sz
rotate:rotateDegree];
NSLog(@"初始化无物!!");
[circle addSprite2b2World:p];
[_circles addObject:circle];
[_shapes addObject:circle];
[self addChild:[circle getSprite] z:4];
NSLog(@"圆形结束");
}
}
NSLog(@"暴利调试大法结束");
}