Войти
Box2DФорумОбщее

Проблема контакта двух тел.

#0
(Правка: 29 дек. 2020, 14:05) 19:03, 27 дек. 2020

Добрый день. Пишу код игры про волейбол. Решил реализовать прием мяча в прыжке ( то есть удар) и прием стоя. Имею почти два одинаковых условия этих событий. Проблема в том, что когда мой персонаж на земле (onGround == true), контакт между двумя телами (персонажем и мячом) не обнаруживается, а когда персонаж в прыжке (onGround == false) - все отлично выполняется, контакт находится. Буду благодарен, если кто разъяснит в чем проблема, или укажет на возможные её причины. Заранее спасибо!

Проверка персонажа на нахождение на земле:

onGround = false;
    position = body_1->GetPosition();
    position.y += 161 / SCALE;
    for (b2Body* it = World.GetBodyList(); it != 0; it = it->GetNext())
      for (b2Fixture *f = it->GetFixtureList(); f != 0; f = f->GetNext())
        if (f->TestPoint(position))  onGround = true;

Проверка на контакт двух тел:

is_contact = false;
    for (b2Contact* contact = World.GetContactList(); contact; contact = contact->GetNext())
    {
      if ((contact->GetFixtureA()->GetBody() == body_1 && contact->GetFixtureB()->GetBody() == ball)
        || (contact->GetFixtureA()->GetBody() == ball && contact->GetFixtureB()->GetBody() == body_1))
      {
        is_contact = true;
        break;
      }
    }

Условие приема мяча на земле:

if (Keyboard::isKeyPressed(Keyboard::Q) and onGround)
    {
      //std::cout << "удар на земле " << onGround;
      for (b2Fixture* fix = ball->GetFixtureList(); fix; fix = fix->GetNext())
      {
        b2Filter filter = fix->GetFilterData();

        filter.categoryBits = 0x0008;
        filter.maskBits = 0x0002 | 0x0004;
        fix->SetFilterData(filter);
      }
      std::cout << "Контакт: " << is_contact << std::endl;
      if (is_contact)
      {
        ball->SetLinearVelocity(b2Vec2(20, -20));
      }
    }
else {
      for (b2Fixture* fix = ball->GetFixtureList(); fix; fix = fix->GetNext())
      {
        b2Filter filter = fix->GetFilterData();

        filter.categoryBits = 0x0008;
        filter.maskBits = 0x0002;
        fix->SetFilterData(filter);
      }
    }

Условие приема мяча в прыжке (в воздухе):

if (Keyboard::isKeyPressed(Keyboard::Q) and !onGround)
    {
      //std::cout << "удар на воздухе " << onGround;
      for (b2Fixture* fix = ball->GetFixtureList(); fix; fix = fix->GetNext())
      {
        b2Filter filter = fix->GetFilterData();

        filter.categoryBits = 0x0008;
        filter.maskBits = 0x0002 | 0x0004;
        fix->SetFilterData(filter);
      }
      //std::cout << "Контакт: " << is_contact << std::endl;
      if (is_contact)
      {
        float S = 35 - ball->GetPosition().Length();
        float h = 250 / SCALE;
        float t = h / 9.81;
        ball->SetLinearVelocity(b2Vec2((S / t), t));
      }
    }
else {
      for (b2Fixture* fix = ball->GetFixtureList(); fix; fix = fix->GetNext())
      {
        b2Filter filter = fix->GetFilterData();

        filter.categoryBits = 0x0008;
        filter.maskBits = 0x0002;
        fix->SetFilterData(filter);
      }
    }

#1
12:12, 28 дек. 2020

я заранее извиняюсь. мне кажется Ваш код в принципе не верен. не в отношении написания, а в отношении концепции работы с боксом. все что нужно, для того, чтобы было взаимодействие двух тел -это фильтр, который позволяет это сделать (либо его отсутствие). Судя по проблеме, в коде есть зависимость от ground/!ground хотя боксу абсолютно наплевать на пользовательские флаги. ему надо тело и фикстуру

#2
18:07, 29 дек. 2020

Проблема решена, спасибо за помощь!

Box2DФорумОбщее