I’m getting some bad access crashes at different places every time. And every time i check all the values are fine. I really don’t know what’s going on. Seems like a memory issue. Any suggestions on a debugging workflow to narrow down bugs like these?
cocos2d-x v2.2 , XCode 5.0.1 , iOS 6.0+
Additional Info: Using Box2D 2.3.0 with bullets enabled on some bodies
void Weapon::shoot(Enemy * target) {
b2Vec2 targetPosition;
if (! target->GetBodyPosition(targetPosition) ) { return; }
Bullet * bullet = Bullet::create();
bullet->setPosition(this->getPosition());
//singleton Gamelayer
GameLayer::sharedGameLayer()->addChild(bullet);
//configures the box2d body in the world
bullet->configureBody();
//shoot at the target position
bullet->shoot(targetPosition);
}
First it loop through and update the position and rotation for the body in my physics world. During the first loop I keep track all enemies within range to engage and shoot in a vector, I also keep track all the bullets that are below the threshold speed to delete them.
Second it loop through all contact listeners and process them.
Third I process all the bodies to be deleted
Fourth I shoot all the targeted enemies
void GameLayer::update(float delta) {
//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/
int velocityIterations = 8;
int 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(delta, velocityIterations, positionIterations);
//prepare a set of to be destory bodies
s_b2Body toDestroy;
//enemy to notify
v_enemy_notify toNotify;
//Iterate over the bodies in the physics world
for (b2Body * b = world->GetBodyList(); b != NULL; b = b->GetNext()) {
//skip ground body
if (b == groundBody) { continue; }
//process bodies with user data
if (b->GetUserData() == NULL) { continue; }
//Synchronize position and rotation with the corresponding body
CCNode * myActor = (CCNode *)b->GetUserData();
if (myActor == NULL) { continue; }
myActor->setPosition( CCPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO) );
myActor->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
//propagate update
EVOEnemy * enemy = dynamic_cast(myActor);
if (enemy) {
enemy->update(delta);
if (enemy->func) { (enemy->*(enemy->func))(); }
//enemy grid point notification
if (enemy->GridPointNotification()) {
m_i_s_block_iter mapIter;
if (being->EnemyNotifible(enemy , mapIter)) {
toNotify.push_back(p_enemy_notify(enemy , mapIter));
}
}
} else {
EVOBullet * bullet = dynamic_cast(myActor);
if (bullet) {
#define BULLET_VELOCITY_THRESHOLD 30.0f
//destroy bullet when its linear velocity is below the threshold
float const velocity = b->GetLinearVelocity().Length();
if (velocity < BULLET_VELOCITY_THRESHOLD) {
toDestroy.insert(b);
}
}
}
}//end iteration over bodies in the world
for (std::vector::iterator pos = contactListener->_contacts.begin(); pos != contactListener->_contacts.end(); ++pos) {
//get the contact object
MyContact contact = *pos;
bool wallContacted = false;
//bodies came into contact with the ground will be deleted
v_b2Fixture_iter groundFixture;
for(groundFixture = groundFixtures.begin(); groundFixture != groundFixtures.end(); groundFixture++) {
if (contact.fixtureA == *groundFixture) {
toDestroy.insert( contact.fixtureB->GetBody() );
wallContacted = true;
break;
} else if (contact.fixtureB == *groundFixture) {
toDestroy.insert( contact.fixtureA->GetBody() );
wallContacted = true;
break;
}
}
if (wallContacted) { continue; }
{//bullet contact detection
//get contacted bodies
b2Body *bodyA = contact.fixtureA->GetBody();
b2Body *bodyB = contact.fixtureB->GetBody();
if (bodyA->GetUserData() == NULL || bodyB->GetUserData() == NULL) {
continue;
}
//get nodes
EVOBodyNode * nodeA = dynamic_cast((CCNode *)bodyA->GetUserData());
EVOBodyNode * nodeB = dynamic_cast((CCNode *)bodyB->GetUserData());
if (nodeA == NULL || nodeB == NULL) {
continue;
}
//Process contact binding
nodeA->ProcessContact(*nodeB , toDestroy);
}
}
DESTROYBODY:
for (s_b2Body_iter iter = toDestroy.begin(); iter != toDestroy.end(); ++iter) {
b2Body * body = *iter;
if (body == NULL) { continue; }
CCNode * node = (CCNode *)body->GetUserData();
world->DestroyBody(body);
(void)body;
if (node != NULL) {
DebugLog("remove node: %x", (unsigned int)node);
this->removeChild(node);
(void)node;
}
}
TONOTIFY:
for (v_enemy_notify_iter iter = toNotify.begin(); iter != toNotify.end(); ++iter) {
being->EnemyNotification((*iter).first, (*iter).second);
}
}