First of all, thanks for great tutorials, they've been very helpful.
Following those i started creating a test for player character class, which would consist of main fixture, and 3 sensors for now: 1 for ground checking, and 2 sensors to the left and to the right. The idea is, to gather all enemies that are in one of those sensors in the vector, and then depending on the direction of the player, attack all those to the right or to the left.
Atm attacking works, but the problem is, regardless of direction of the player enemies in any of those 2 sensors are affected at the same time. After doing some checking i found out, that when there is a contact, pointers to enemies are pushed in both vectors ( enemiesInRangeRight and enemiesInRangeLeft) and i have no idea why.
Here's some code( sorry for some stupid variable names:
Code: Select all
//Hero
std::vector<Enemy*> enemiesInRangeLeft;
std::vector<Enemy*> enemiesInRangeRight;
void enemy_in_range_left(Enemy *enemy){ enemiesInRangeLeft.push_back(enemy);}
void enemy_left_range_left(Enemy* enemy) {enemiesInRangeLeft.erase( std::find(enemiesInRangeLeft.begin(), enemiesInRangeLeft.end(), enemy ) );}
void enemy_in_range_right(Enemy *enemy){ enemiesInRangeRight.push_back(enemy);}
void enemy_left_range_right(Enemy* enemy) {enemiesInRangeRight.erase( std::find(enemiesInRangeRight.begin(), enemiesInRangeRight.end(), enemy ) );}
void attack(){
if ( this->direction == left)
{
for ( int i = 0 ; i <enemiesInRangeLeft.size(); i++)
enemiesInRangeLeft[i]->m_body->ApplyLinearImpulse( b2Vec2(0,50), enemiesInRangeLeft[i]->m_body->GetWorldCenter() );
}
else if ( this->direction == right)
{
for ( int i = 0 ; i <enemiesInRangeRight.size(); i++)
enemiesInRangeRight[i]->m_body->ApplyLinearImpulse( b2Vec2(0,50), enemiesInRangeRight[i]->m_body->GetWorldCenter() );
}
}
// Contact Listener
class MyContactListener : public b2ContactListener
{
void BeginContact(b2Contact* contact) {
Hero* hero;
Enemy* enemy;
if ( enemy_checker_right(contact, hero, enemy) )
hero->enemy_in_range_right(enemy );
if ( enemy_checker_left(contact, hero, enemy) )
hero->enemy_in_range_left(enemy );
if (ground_checker(contact,hero))
hero->start_contact();
}
void EndContact(b2Contact* contact) {
Hero* hero;
Enemy* enemy;
if ( enemy_checker_left(contact, hero, enemy) )
hero->enemy_left_range_left( enemy);
if ( enemy_checker_right(contact, hero, enemy) )
hero->enemy_left_range_right( enemy);
if (ground_checker(contact,hero))
hero->end_contact();
}
};
// Helpers
bool enemy_checker_left(b2Contact* contact, Hero*& hero, Enemy*& enemy)
{
b2Fixture* fixtureA = contact->GetFixtureA();
b2Fixture* fixtureB = contact->GetFixtureB();
bool sensorA = fixtureA->IsSensor();
bool sensorB = fixtureB->IsSensor();
if ( ! (sensorA ^ sensorB) )
return false;
if (( fixtureA->GetFilterData().categoryBits == GROUND) || (fixtureB->GetFilterData().categoryBits == GROUND ))
return false;
Entity* entityA = static_cast<Entity*>( fixtureA->GetBody()->GetUserData() );
Entity* entityB = static_cast<Entity*>( fixtureB->GetBody()->GetUserData() );
if ( sensorA ) {
if((fixtureA->GetFilterData().categoryBits == HERO_SENSOR_LEFT) || (entityB->getEntityType() == ENEMY))
// if((entityA->getEntityType() == HERO_SENSOR_LEFT) || (entityB->getEntityType() == ENEMY))
{
hero = static_cast<Hero*> (entityA);
enemy = static_cast<Enemy*> (entityB);
return true;
}
}
else if (sensorB){
if((fixtureB->GetFilterData().categoryBits == HERO_SENSOR_LEFT) || (entityA->getEntityType() == ENEMY))
{
hero = static_cast<Hero*> (entityB);
enemy = static_cast<Enemy*> (entityA);
return true;
}
}
}
bool enemy_checker_right(b2Contact* contact, Hero*& hero, Enemy*& enemy)
{
b2Fixture* fixtureA = contact->GetFixtureA();
b2Fixture* fixtureB = contact->GetFixtureB();
bool sensorA = fixtureA->IsSensor();
bool sensorB = fixtureB->IsSensor();
if ( ! (sensorA ^ sensorB) )
return false;
if (( fixtureA->GetFilterData().categoryBits == GROUND) || (fixtureB->GetFilterData().categoryBits == GROUND ))
return false;
Entity* entityA = static_cast<Entity*>( fixtureA->GetBody()->GetUserData() );
Entity* entityB = static_cast<Entity*>( fixtureB->GetBody()->GetUserData() );
if ( sensorA ) {
if((fixtureA->GetFilterData().categoryBits == HERO_SENSOR_RIGHT) || (entityB->getEntityType() == ENEMY))
//if((entityA->getEntityType() == HERO_SENSOR_RIGHT) || (entityB->getEntityType() == ENEMY))
{
hero = static_cast<Hero*> (entityA);
enemy = static_cast<Enemy*> (entityB);
return true;
}
}
else if (sensorB){
if((fixtureB->GetFilterData().categoryBits == HERO_SENSOR_RIGHT) || (entityA->getEntityType() == ENEMY))
{
hero = static_cast<Hero*> (entityB);
enemy = static_cast<Enemy*> (entityA);
return true;
}
}
}
I tried polling by filter type, or purely by bodyuserdata as you can see. i'm sure it's some kind of stupid oversight on my part.
Any help would be appreciated.