У меня есть аркадная игра для iPhone, которая построена на Cocos2d-iPhone и работает нормально, за исключением того, что она случайно вылетает без видимой причины после непредсказуемого количества игр. Иногда вы можете играть на нескольких уровнях без проблем, а на других он вылетает через несколько секунд. В XCode есть несколько общих строк, которые обычно обозначаются как EXC_BAD_ACCESS, что указывает на наличие памяти, но все объекты автоматически высвобождаются с дополнительным сохранением, и сбои очень противоречивы. Одна вещь, которая кажется подходящей, состоит в том, что по мере того, как происходит больше, вероятность аварийного отказа возрастает, что снова наводит на мысль о некоторой проблеме с памятью, но затем не выдается предупреждение памяти приложения.
Некоторые примеры строк сбоя:
if(gameGlobals.gameState == GAME_STATE_PAUSED) {...}
if(![hearts isKindOfClass:[CCSprite class]]) {...}
но обе эти строки имеют глобальные объекты, которые целую вечность до краха.
Итак, мой вопрос на самом деле, как мне отследить проблему и есть ли вероятные виновники?
Спасибо.
UPDATE
Я занимался детективной работой, и у меня, по крайней мере, есть последовательность. Я думаю, что происходит две вещи:
1) то, что математика, используемая для обнаружения идеального столкновения пикселей с объектом с удалением данных пикселей, готовит процессор.
2) У меня есть несколько зомби-спрайтов, и в противном случае они выпускаются без моего понимания.
Когда я добавляю спрайт пули, я использую:
CCSprite *bullet = [CCSprite spriteWithFile:@"bullet.png"];
bullet.tag = BULLET_TAG_GOODY;
bullet.position = ccp(player.position.x,50);
[self addChild:bullet];
[bullet runAction:[CCSequence actions:
[CCMoveTo actionWithDuration:2 position:ccp(player.position.x,320)],
[CCCallFuncN actionWithTarget:self selector:@selector(bulletMoveFinished:)],
nil]];
[bullets addObject:bullet];
А потом я перебираю массив пуль. В данный момент происходит сбой, сообщая, что я пытаюсь получить доступ к освобожденному экземпляру.
Итак, 1) как мне это настроить, чтобы мои спрайты не выпускались? Это хорошая идея, чтобы удалить авто-релиз из CCSprite?
2) Каков наилучший способ обнаружения пуль, сталкивающихся с базой в стиле космических захватчиков, наносящих удар по спрайту при его выстреле?
В настоящее время:
if([self overlapBases: bullet.position.x :bullet.position.y :true]) {...}
-(bool)overlapBases :(GLfloat)x :(GLfloat)y :(bool)up {
// NSLog(@"overlapping - %f,%f",x,y);
if(y > 20 && y < 100) {
int bn = -1;
if(x > 28 && x < 118) {
bn = 0;
}
if(x>140 && x<230 ) {
bn = 1;
}
if(x>254 && x<343 ) {
bn = 2;
}
if(x>365 && x<453 ) {
bn = 3;
}
if(bn> -1) {
NSLog(@"overlapping - %f,%f",x,y);
// for (int ix = 0; ix < NUM_BASES; ix++) {
if (overLap(x, 2, aspeaker[bn].position.x, BASE_WIDTH * aspeaker[bn].scale)) {
if (overLap(y, 4, aspeaker[bn].position.y, BASE_HEIGHT * aspeaker[bn].scale)) {
NSLog(@"ix: %i, x: %f, y: %f",bn,x,y);
return [self fineCollision:bn :x :y :up];
}
}
}
}
return false;
}
-(bool)fineCollision :(GLuint)baseNum :(GLfloat)x :(GLfloat)y :(bool)up {
//convert bullet x and y passed in to this base coords
//check if solid
//if so, remove bits in gfx and array, return true
//else return false;
GLfloat bullx = (x - aspeaker[baseNum].position.x + BASE_WIDTH) / 2.0;
GLfloat bully = (y - aspeaker[baseNum].position.y + BASE_HEIGHT) / 2.0;
GLint testx = (GLint)bullx;
if ((testx < 0) | (testx >= BASE_WIDTH)) {
return false;
}
GLuint testy;
bool hit = false;
for (int iy = -2; iy < 2; iy++) {
testy = (GLint)(bully - iy);
if ((testy >= 0) & (testy < BASE_HEIGHT)) {
if (baseShape[baseNum][15 - testy][testx] > 0) {
if(showrm == YES) {
CCSprite *maskSprite = [CCSprite spriteWithFile:@"bullet-mask.png"];
[maskSprite setBlendFunc: (ccBlendFunc) {GL_ZERO, GL_ONE_MINUS_SRC_ALPHA}];
maskSprite.position = ccp( x , y-(40+22-5) );
NSLog(@"sprite: %f",maskSprite.position.x);
NSLog(@"render mask: %f",rm.frameInterval);
[rm addSpriteMask:maskSprite];
[rm drawCurrent];
}
[self remove:testx :testy :baseNum :up];
GLuint seed = rand()%64;
if (seed & 1) {
[self remove:testx - 1:testy - 1 :baseNum :up];
}
if (seed & 2) {
[self remove:testx - 1:testy :baseNum :up];
}
if (seed & 4) {
[self remove:testx - 1:testy + 1:baseNum :up];
}
if (seed & 8) {
[self remove:testx + 1:testy - 1:baseNum :up];
}
if (seed & 16) {
[self remove:testx + 1:testy :baseNum :up];
}
if (seed & 32) {
[self remove:testx + 1:testy + 1:baseNum :up];
}
hit = true;
}
}
}
return hit;
}
- (void)remove:(GLint)offX :(GLint)offY :(GLuint)baseNum :(bool)up {
if ((offX < 0) | (offX >= BASE_WIDTH)) {
return;
}
if ((offY < 0) | (offY >= BASE_HEIGHT)) {
return;
}
baseShape[baseNum][15 - offY][offX] = 0;
}
bool overLap(GLfloat x1, GLfloat w1, GLfloat x2, GLfloat w2) {
GLfloat left1, left2;
GLfloat right1, right2;
GLfloat halfWidth1 = w1 * 0.5f;
GLfloat halfWidth2 = w2 * 0.5f;
left1 = x1 - halfWidth1;
left2 = x2 - halfWidth2;
right1 = x1 + halfWidth1;
right2 = x2 + halfWidth2;
if (left1 > right2) {
return false;
}
if (right1 < left2) {
return false;
}
return true;
}
Для обнаружения и визуализации маски используйте множество спрайтов и режим их наложения для истощения.
Спасибо.
ОБНОВЛЕНИЕ СНОВА :)) 1034 *
Хорошо, я нашел несколько зомби!
Address Category Event Type RefCt Timestamp Size Responsible Library Responsible Caller
0 0x13a00e90 CCSprite Malloc 1 00:32.974.212 432 SpacedInvaders +[CCSprite spriteWithFile:]
1 0x13a00e90 CCSprite Autorelease <null> 00:32.974.235 0 SpacedInvaders +[CCSprite spriteWithFile:]
2 0x13a00e90 CCSprite Retain 2 00:32.974.546 0 SpacedInvaders -[CCArray insertObject:atIndex:]
3 0x13a00e90 CCSprite Retain 3 00:32.974.629 0 SpacedInvaders -[CCActionManager addAction:target:paused:]
4 0x13a00e90 CCSprite Retain 4 00:32.974.634 0 SpacedInvaders -[CCArray addObject:]
5 0x13a00e90 CCSprite Release 3 00:32.986.279 0 QuartzCore CA::Display::DisplayLink::dispatch(unsigned long long, unsigned long long)
6 0x13a00e90 CCSprite Release 2 00:33.074.889 0 SpacedInvaders -[CCArray removeObject:]
7 0x13a00e90 CCSprite Release 1 00:33.074.915 0 SpacedInvaders -[CCActionManager deleteHashElement:]
8 0x13a00e90 CCSprite Release 0 00:33.074.918 0 SpacedInvaders -[CCArray removeObject:]
9 0x13a00e90 CCSprite Zombie -1 00:33.074.939 0 SpacedInvaders -[GameLayer update:]
Так что здесь происходит? Я вижу, что количество удержаний слишком низкое, но как мне этого избежать. Я предполагаю, что делаю что-то тупое между прочим.
Спасибо.