FML!!真是搓了,难怪好朋友说我想出来的都是写蛋疼的玩意儿,唉~

这是我之前的写法:

-(void) tick: (ccTime) dt
{
	//It is recommended that a fixed time step is used with Box2D for stability
	//of the simulation, however, we are using a variable time step here.
	//You need to make an informed choice, the following URL is useful
	//http://gafferongames.com/game-physics/fix-your-timestep/
	
	int32 velocityIterations = 8;
	int32 positionIterations = 1;
	
	// Instruct the world to perform a single step of simulation. It is
	// generally best to keep the time step and iterations fixed.
	_world->Step(dt, velocityIterations, positionIterations);
	
	//Iterate over the bodies in the physics world
//	for (b2Body* b = _world->GetBodyList(); b; b = b->GetNext())
//	{
//		if (b->GetUserData() != NULL) {
//			//Synchronize the AtlasSprites position and rotation with the corresponding body
//			CCSprite *myActor = (CCSprite*)b->GetUserData();
//			myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
//			myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
//		}	
//	}
	b2Body *node = _world->GetBodyList();
	while(node) {
		b2Body *b = node;
		if(b->GetUserData() != NULL) {
			//Synchronize the AtlasSprites position and rotation with the corresponding body
			// 根据 box2d 对物理世界的现实模拟得到的结果同步更新 精灵的位置以及旋转角度~
			CCSprite *myActor = (CCSprite*)b->GetUserData();
			CGPoint currentPosition = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO );
			
			if([self isPositionOutOfBounds:currentPosition] == NO) {
				// 如果没有越界的话,实时更新~
				myActor.position = currentPosition;
				myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
				node = node->GetNext();
			} else {
				// 1.在一个物体摧毁之前一切都很顺利。
				// 一旦一个物体摧毁了,它的 next 指针就变得非法,所以 b2Body::GetNext()就会返回垃圾。
				// 解决方法是在摧毁之前拷贝 next 指针。
				node = node->GetNext();
				
				// 2.在销毁body之前先把 myActor 释放掉~
				[myActor removeFromParentAndCleanup:YES];
				
				// 3.b2Fixture, b2PolygonShape 将在 DestructionListener 类的监听下自动被销毁(如果其所依附的 b2Body 被销毁了的话)~
				_world->DestroyBody(b);
				b = NULL;
			}
		} else {
			node = node->GetNext();
		}
	}
	
	// 将b2Body类型的成员变量被销毁之后的 BYShape 对象请出 _shapes 数组并调用其 dealloc 方法释放内存~
	NSMutableArray *itemsToKeep = [NSMutableArray arrayWithCapacity:[_shapes count]];
	for (id object in _shapes) {
		// 这里有问题,b2Body 被 destroy 掉之后内存返回 SOA 池,所以 getBody 所指向的那块内存依然不会为 NULL,麻烦了~
		if ( [(BYShape*)object getSprite] == NULL ) {
			NSLog(@"被清理");
			// 做内存清理工作
			[(BYShape*)object dealloc]; 
		} else {
			[itemsToKeep addObject:object];
		}
	} 
	[_shapes setArray:itemsToKeep];
}

为什么要这么搓呢??直接遍历 _shapes NSMutableArray 对象不是很好,为什么一定要挤在一起呢?!!

不过一些小知识点还是值得记录下来的:

1。遍历(不管是Iteroter还是for循环)的过程中不能从 NSMutableArray中删除Items,这在Java里面也是一样的,Java中会报出一个什么Concurrency...错误

2。iteroter的话可以才用备份指针的方法对item进行安全的删除,如以上代码所书

3。集中遍历容器的方案:for(id object in _shapes), for(int i = 0; i < [_shapes count]; ++i), Iteroter...

4。代码尾部那段删除其中符合特定条件条目的方案应该算是比较优秀,高效的,少了removeItem,复制啊什么的东西

5。还有BAD_EXEC_ACCESS的问题,如果试图去访问已经释放掉的对象的成员变量,为报出此种错误。另外,将objc字符串不小心写成c风格字符串也可能报出该错。

6。objective-c 的 try-catch-finally 写法:

NSString* test = [NSStringstringWithString:@"ss"];

@try {

[testcharacterAtIndex:6];

}

@catch (NSException * e) {

NSLog(@"Exception: %@", e);

}

@finally {

NSLog(@"finally");

}


下面将贴出我修改过之后的该方法,太蛋疼了,方向一错,工作量就大大增加,而且还让人产生一股在挣扎中优雅的盲目自得感觉。。。~。~

-(void) tick: (ccTime) dt {	
	int32 velocityIterations = 8;
	int32 positionIterations = 1;
	
	_world->Step(dt, velocityIterations, positionIterations);
	
	//Iterate over the bodies in the physics world
	for (b2Body* b = _world->GetBodyList(); b; b = b->GetNext())
	{
		if (b->GetUserData() != NULL) {
			//Synchronize the AtlasSprites position and rotation with the corresponding body
			// 根据 box2d 对物理世界的现实模拟得到的结果同步更新 精灵的位置以及旋转角度~
			CCSprite *myActor = (CCSprite*)b->GetUserData();
			myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
			myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
		}
	}
	
	// 将b2Body类型的成员变量被销毁之后的 BYShape 对象请出 _shapes 数组并调用其 dealloc 方法释放内存~
	NSMutableArray *itemsToKeep = [NSMutableArray arrayWithCapacity:[_shapes count]];
	for (id object in _shapes) {
		BYShape *shape = (BYShape*)object;
		b2Body *b = [shape getBody];
		
		CGPoint currentPosition = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO );
		
		if([self isPositionOutOfBounds:currentPosition] == YES) {
			// 如果已经越界的话,就将其 dealloc 掉并且不再放入保存列表当中~
			[shape dealloc];
		} else {
			[itemsToKeep addObject:object];
		}
	}
	[_shapes setArray:itemsToKeep];
}

至此,是直接从_shapes里面拿了,但是一潮未平一潮又起,结果又遇到 EXC_BAD_ACCESS错误了,而且仅此提示以外,别无其他信息,迷茫了~

我推测原因可能是因为对 _shapes 容器的不安全操作引起的,不过没办法了,不想再去多理会这个事情。

其实出于项目需要,并不需要在触摸屏幕的时候新建出一大堆的形状对象,我只不过是看不惯这只拦路虎,一心想把他干掉

不过现在看来是没办法了,娘的,且容他再活几日吧,等哥哥技术上来了一并将它收拾之~

so,现在的情形清晰明了:

1。如果要持续往屏幕中添加形状的话,用刚开始那种方案,弊端就是 BYShape的数组引用会越来越多,虽然起所指向的对象中的成员对象都被架空干掉了,但我还是觉着这么写他妈的太别扭。

2。如果不需要持续往屏幕中点击添加形状的话,那么就直接用第二种方案吧,这种情况下不会报出 EXC_BAD_ACCESS 的错误。。

不过我还是不死心,这个问题一定得解决了~

老版得cleanEdition:

-(void) tick: (ccTime) dt {
    int32 velocityIterations = 8;  
    int32 positionIterations = 1;  

    _world->Step(dt, velocityIterations, positionIterations);  
	
    b2Body *node = _world->GetBodyList();  
    while(node) {  
        b2Body *b = node;  
        if(b->GetUserData() != NULL) {  
            //Synchronize(同步) the AtlasSprites position and rotation with the corresponding(相应的) body
            // 根据 box2d 对物理世界的现实模拟得到的结果同步更新 精灵的位置以及旋转角度~  
            CCSprite *myActor = (CCSprite*)b->GetUserData();  
            CGPoint position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO );  
			
            if([self isPositionOutOfBounds:position] == NO) {  
                // 如果没有越界的话,实时更新~  
                myActor.position = position;  
                myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());  
                node = node->GetNext();  
            } else {  
                // 1.在1个物体摧毁之前一切都很顺利。1旦1个物体摧毁了,它的next指针就变得非法,所以 b2Body::GetNext()就会返回垃圾。  
                // 解决方法是在摧毁之前拷贝 next 指针。
                node = node->GetNext();
				
                // 2.在销毁body之前先把 myActor 释放掉~
                [myActor removeFromParentAndCleanup:YES];
				
                // 3.b2Fixture, b2PolygonShape 将在 DestructionListener 类的监听下自动被销毁(如果其所依附的 b2Body 被销毁了的话)~  
                _world->DestroyBody(b);
                b = NULL;  
            }  
        } else {  
            node = node->GetNext();  
        }  
    } 
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值