恼人的伪bug!

游戏还没做完,不但没有做完,而且还差相当多的东西!

由于之前没有仔细考虑过关卡文件后期的拓展性,以至于很多预想的游戏元素都无法通过关卡文件添加到游戏里面

此数日主要用来对这些问题进行整改

整改之前也狠狠想了一段时间,根据游戏后面的逻辑,还需要加入哪些元素,

怎么在关卡里面为这些元素预留初始化的数据,等等

可以说,游戏看上去虽然简单,但是一步步的走下来,每一个步伐都不那么轻松

希望能认真做好一件事的态度、丰厚的回报以及游戏慢慢展现出来的效果,这些都给我带来了很大的动力!


今天遇到一个bug,有很奇葩的地方,待我贴两段代码看一下就知道奇葩在什么地方了:

片段1:

-(void) tick: (ccTime) dt {

   if(_single.cutCount <_maxCutCount && !_drawing &&_laserSegment) {//在更早的时候消除可能报出的错误,提高程序性能~

       b2Vec2 p1 =_laserSegment.p1;

       b2Vec2 p2 =_laserSegment.p2;

        float segmentLength = sqrt(pow(p2.y - p1.y,2.0f) +pow(p2.x - p1.x,2.0f));

       if(segmentLength >=2.0f) { // 如果划线的长度超过64个像素(retina里面是128个像素)~

            {

                NSLog(@"1");

                RayCastCallbackPrepare prepareCallback;

                _world->RayCast(&prepareCallback, _laserSegment.p1, _laserSegment.p2);

                _world->RayCast(&prepareCallback, _laserSegment.p2, _laserSegment.p1);

                NSLog(@"2");

            }

            NSLog(@"3");

            BOOL isCutValid = [self checkCutValidOrNot:_laserSegment.p1p2:_laserSegment.p2];


片段2:

#import"RayCastCallbackPrepare.h"


/** 相信我,会有的!! */

int fixtureIndexInVector(vector<b2Fixture*> *v,b2Fixture *fixture);

int bodyIndexInVector(vector<b2Body*> *v,b2Body *body);


/** 构造 */

RayCastCallbackPrepare::RayCastCallbackPrepare() {

   NSLog(@"RayCastCallbackPrepare构造开始~");

   _single = [BYSinglegetInstance];

   _validCallbackTimes =0;

   _affectedBodyByLaser =newvector<b2Body*>();

   _affectedBodyByLaserFinal =newvector<b2Body*>();

   _affectedByLaser =newvector<b2Fixture*>();

   _balloonsBeenCutted =newvector<b2Body*>();

    [_singlesetIsPirateExists:NO];

    [_singlesetIsBalloonBeenCutted:NO];

   NSLog(@"RayCastCallbackPrepare构造结束~");

}


/** 

 * 析构

 * 因为回调函数的特殊性,如果不想在每次回调的时候都对单例对象设置一次值的话

 * 唯有在析构方法里面完成最后一次设置(因为回调的次数是难以确定的)

 * 这也就是 GoldMineScene raycast方法调用的那几行必须用小括号包起来的原因!!!

 * 因为要即时析构获得计算出来的结果!!!

 */

RayCastCallbackPrepare::~RayCastCallbackPrepare() {

   NSLog(@"RayCastCallbackPrepare析构开始~");

    [_singlesetReverseDirectionCallbackTimes:_validCallbackTimes];

    [_singlesetAffectedBodyByLaserFinal:_affectedBodyByLaserFinal];

    

   // vector的释放需要谨慎处理~

    for(uint i = 0; i < _affectedBodyByLaser->size(); ++ i) {

        //断绝关系(用不着销毁,销毁由world所维护),避免SOA池出现内存故障~

       _affectedBodyByLaser->at(i) =NULL;

    }

   _affectedBodyByLaser->clear();

   _affectedBodyByLaser =NULL;

    

   // vector的释放需要谨慎处理~

    for(uint i = 0; i < _affectedByLaser->size(); ++ i) {

        _affectedByLaser->at(i) = NULL;

    }

   _affectedByLaser->clear();

   _affectedByLaser =NULL;

    

   // vector的释放需要谨慎处理~

    for(uint i = 0; i < _balloonsBeenCutted->size(); ++ i) {

       _balloonsBeenCutted->at(i) =NULL;

    }

   _balloonsBeenCutted->clear();

   _balloonsBeenCutted =NULL;

   NSLog(@"RayCastCallbackPrepare析构结束~");

}


float32RayCastCallbackPrepare::ReportFixture(b2Fixture* fixture, const b2Vec2& point,constb2Vec2& normal,float32 fraction) {

    NSLog(@"-3");

    b2Body *affectedBody = fixture->GetBody();

    if(affectedBody->GetType() != b2_staticBody) {

        if(affectedBody->m_isCuttable == true) {

            if(fixture->m_isPirate == true) {

                [[BYSinglegetInstance]setIsPirateExists:YES];

            }

            

            //只要累加出所切割 fixture的次数就 ok了,保存在单例里面是为了扩大使用的界限~

            int fixtureIndex = fixtureIndexInVector(_affectedByLaser, fixture);

            if(fixtureIndex == -1) {

                //正方向切割的时候仅仅将受影响的body、切入点保存起来,没有绘制任何圆圈

                _affectedByLaser->push_back(fixture);

            } else {

                _validCallbackTimes += 1;

            }

            

            /**得到所有被切割路径涉及到的 body(目的是为了消除切割之后出现内部黑边)~ */

            int bodyIndex = bodyIndexInVector(_affectedBodyByLaser, affectedBody);

            if(bodyIndex == -1) {

                _affectedBodyByLaser->push_back(affectedBody);

            } else {

               //这才是最后要递交给 _single~

                _affectedBodyByLaserFinal->push_back(affectedBody);

            }

        } else if(affectedBody->m_isBalloon ==true) {

            NSLog(@"-4");

            int bodyIndex = bodyIndexInVector(_balloonsBeenCutted, affectedBody);

            if(bodyIndex == -1) {

                NSLog(@"不存在,添加进去");

                _balloonsBeenCutted->push_back(affectedBody);

            } else {

                NSLog(@"存在,进行处理~");

               //这才是最后要递交给 _single~

                [_singlesetIsBalloonBeenCutted:YES];


                CCSprite *actor = (CCSprite*)affectedBody->GetUserData();

                CGPoint position = actor.position;

                [_single.gameLayerremoveChild:actorcleanup:YES];


                NSLog(@"asf begin!");

                AnimSpriteFactory *asf = [[[AnimSpriteFactoryalloc]init]autorelease];

                CCSprite *animSprite = [asf genAnimSprite:position 

                                                animName:[_single.gCfgobjectForKey:@"balloonAnimName"

                                              startIndex:[[_single.gCfgobjectForKey:@"balloonAnimBegin"]intValue

                                                endIndex:[[_single.gCfgobjectForKey:@"balloonAnimEnd"]intValue]  

                                           repeatForever:NO 

                                                   delay:[[_single.gCfgobjectForKey:@"balloonAnimDelay"]floatValue]];

                NSLog(@"asf finished!");

                affectedBody->SetUserData(animSprite);

                

                _single.gameSceneWorld->DestroyBody(affectedBody);

                

                // 即时播放气球爆炸的音效~

                [[AudioManagergetInstance]musicBalloonExplode];

            }

            NSLog(@"-5");

        }

    }

    return 1.0f;

}


运行之后控制台打印出的部分关键信息为:

2012-01-06 18:19:24.289 GoldMine0.6[818:10a03] 1

2012-01-06 18:19:24.290 GoldMine0.6[818:10a03] RayCastCallbackPrepare构造开始~

2012-01-06 18:19:24.291 GoldMine0.6[818:10a03] RayCastCallbackPrepare构造结束~

2012-01-06 18:19:24.292 GoldMine0.6[818:10a03] -3

2012-01-06 18:19:24.292 GoldMine0.6[818:10a03] -4

2012-01-06 18:19:24.293 GoldMine0.6[818:10a03]不存在,添加进去

2012-01-06 18:19:24.294 GoldMine0.6[818:10a03] -5

2012-01-06 18:19:24.294 GoldMine0.6[818:10a03] -3

2012-01-06 18:19:24.295 GoldMine0.6[818:10a03] -4

2012-01-06 18:19:24.296 GoldMine0.6[818:10a03]存在,进行处理~

2012-01-06 18:19:24.297 GoldMine0.6[818:10a03] asf begin!

2012-01-06 18:19:24.304 GoldMine0.6[818:10a03] RayCastCallbackPrepare析构开始~

2012-01-06 18:19:24.305 GoldMine0.6[818:10a03] RayCastCallbackPrepare析构结束~

2012-01-06 18:19:24.306 GoldMine0.6[818:10a03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

*** First throw call stack:

(0x197d052 0x1b0ed0a 0x196a36e 0x196b220 0x3fb0d 0x15a0d 0x27e31 0x28240 0x2612e 0x6f3a 0x6a26a 0x6a678 0x7c80e 0x7b795 0x92c2db 0x92c1af 0x1951966 0x1951407 0x18b47c0 0x18b3db4 0x18b3ccb 0x2384879 0x238493e 0x9e1a9b 0x295b 0x2905)

terminate called throwing an exceptionsharedlibrary apply-load-rules all

(gdb)


结果表明:

是 AnimSpriteFactory(用于生成带动画的 sprite 对象) 这个对象在调用 genAnimSprite 方法的时候出现了问题,然而,需要注意的是:

在 RayCastCallbackPrepare 对象执行其 ReportFixture 方法的时候,出现了bug,

为什么程序没有在出现 bug 的地方即时中断,

还能执行到 RayCastCallbackPrepare 对象执行析构函数的时候?

这个让我非常不解,难道不是在哪个地方一出现问题就马上终止程序么?

这个问题的答案我没有找到

但是,bug的出现原因我却是找到了!

这是一个典型的伪 bug,说他是伪 bug 就是因为:

app 通常针对不同的设备会使用不同规格的素材图片,

我之前用的是 iTouch4 做的真机测试,那么就是用的高清的那套素材图片~

不过这二日我伙计把设备拿过去了,因此我也就只能用 mac里面的模拟器来进行调试了

mac里面模拟器分辨率是480*320,使用的是普通的那套素材图片

而我之前又偷懒,因此普通的那套素材便没有准备,

这在真机上面没有妨害,但是到了mac的模拟器里面,却是带来了直接的隐患

这次果不其然便中招了

另外一个原因就是我最近又有所懈怠,

好一段时间不写,有些问题如没准备普通素材这件事便给抛到脑后了~


仔细做总结,其实我遇到过很多次控制台打出这样的信息,但是我依然是死猪不怕开水烫,这次,牢牢的记住这两句提示吧:

2012-01-06 18:19:24.306 GoldMine0.6[818:10a03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

*** First throw call stack:

(0x197d052 0x1b0ed0a 0x196a36e 0x196b220 0x3fb0d 0x15a0d 0x27e31 0x28240 0x2612e 0x6f3a 0x6a26a 0x6a678 0x7c80e 0x7b795 0x92c2db 0x92c1af 0x1951966 0x1951407 0x18b47c0 0x18b3db4 0x18b3ccb 0x2384879 0x238493e 0x9e1a9b 0x295b 0x2905)

terminate called throwing an exceptionsharedlibrary apply-load-rules all

(gdb)


一旦出现了这样的提示,

很有可能就是因为与 sprite 动画相关的代码出现了问题,

要第一时间去检查这部分代码!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值