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

Проблема контакта объектов в Box2D.

#0
(Правка: 19:22) 19:17, 17 дек. 2020

В ходе написания кода возникла проблема с приемом мяча игроком. Иными словами, как сделать так, чтобы игрок мог отбивать мяч не всегда, а при нажатии допустим клавиши "Space"? Если в Box2D сделать объект, то при контакте с мячом он будет отбиваться всегда. Возможно ли сделать моего игрока делать объектом не всегда, или какими-то другими способами решить эту проблему?

Вот код функции:

void game_2_players(RenderWindow & window) 
{
  window.setFramerateLimit(60);
  Texture t1, t2, t3, t4;
  t1.loadFromFile("C://Users/1/source/repos/Game Volley/Game Volley/images/court.png");
  t2.loadFromFile("C://Users/1/source/repos/Game Volley/Game Volley/images/ball.png");
  t3.loadFromFile("C://Users/1/source/repos/Game Volley/Game Volley/images/player_1.png");
  t4.loadFromFile("C://Users/1/source/repos/Game Volley/Game Volley/images/player_2.png");
  t1.setSmooth(true);
  t2.setSmooth(true);
  t3.setSmooth(true);
  t4.setSmooth(true);

  Sprite sBackground(t1), sBall(t2), sPlayer_1(t3), sPlayer_2(t4);
  sPlayer_1.setOrigin(110, 145);
  sPlayer_2.setOrigin(110, 145);
  sBall.setOrigin(32, 32);

  /////////box2d///////////
  setWall(960, 840, 2000, 10); //нижняя 
  setWall(960, 830, 95, 350); //центральная
  setWall(0, 0, 70, 2000); //боковая левая
  setWall(1920, 0, 70, 2000); //боковая правая

  b2BodyDef body_def;
  body_def.type = b2_dynamicBody;

  /////players/////////

  //1

  //НЕДОПИСАННЫЙ КОД, ДУМАЛ КАК РЕШИТЬ ПРОБЛЕМУ...

  body_def.position.Set(4, 28);
  b2PolygonShape shape_1;
  shape_1.SetAsBox(1.0f, 1.0f);
  //circle_1.m_radius = 20 / SCALE; 
  //circle_1.m_p.Set(0, 0 / SCALE);

  b2Body* body_1 = World.CreateBody(&body_def);
  b2FixtureDef fixture_def_1;
  fixture_def_1.shape = &shape_1;
  fixture_def_1.density = 1.0f;

  body_1->CreateFixture(&fixture_def_1);
  body_1->SetFixedRotation(true);
  const char* player1[] = { "player1" };
  body_1->SetUserData(player1);

  //2

  body_def.position.Set(60, 28);
  b2CircleShape circle_2;
  circle_2.m_radius = 0 / SCALE;
  //circle_2.m_p.Set(0, 0 / SCALE);
  b2Body *body_2 = World.CreateBody(&body_def);
  body_2->CreateFixture(&circle_2, 5);
  body_2->SetFixedRotation(true);
  const char* player2[] = { "player2" };
  body_2->SetUserData(player2);

  //////ball//////
  body_def.position.Set(5, 1); //7 27
  b2CircleShape circle;
  //circle.m_radius = 32 / SCALE;
  b2Body *ball = World.CreateBody(&body_def);
  b2FixtureDef fdef;
  fdef.shape = &circle;
  fdef.restitution = 0.95;
  fdef.density = 0.2;
  ball->CreateFixture(&fdef);
  const char* ball_name[] = { "ball" };
  ball->SetUserData(ball_name);
  /////////////////////////


  while (window.isOpen())
  {
    Event e;
    while (window.pollEvent(e))
    {
      if (e.type == Event::Closed)
        window.close();
    }

    for (int n = 0; n < 2; n++) // 2 - speed
      World.Step(1 / 60.f, 8, 3);

    
    //player1 

    /////check if player 1 on ground//////
    bool onGround = false;
    b2Vec2 pos = body_1->GetPosition();
    pos.y += 17 / SCALE;
    for (b2Body* it = World.GetBodyList(); it != 0; it = it->GetNext())
      for (b2Fixture *f = it->GetFixtureList(); f != 0; f = f->GetNext())
        if (f->TestPoint(pos))  onGround = true;
    /////////////////////////////

    pos = body_1->GetPosition();
    b2Vec2 vel = body_1->GetLinearVelocity();


    if (Keyboard::isKeyPressed(Keyboard::D))  vel.x = 5;
    if (Keyboard::isKeyPressed(Keyboard::A))   vel.x = -5;
    if (Keyboard::isKeyPressed(Keyboard::W) and onGround)
    {
      if (pos.y*SCALE >= 400) vel.y = -10;
    }
    if (!Keyboard::isKeyPressed(Keyboard::D))
      if (!Keyboard::isKeyPressed(Keyboard::A))
        vel.x = 0;


    body_1->SetLinearVelocity(vel);

    
    //player2 

    /////check if player 2 on ground//////
    bool onGround_2 = false;
    pos = body_2->GetPosition();
    pos.y += 17 / SCALE;
    for (b2Body* it = World.GetBodyList(); it != 0; it = it->GetNext())
      for (b2Fixture *f = it->GetFixtureList(); f != 0; f = f->GetNext())
        if (f->TestPoint(pos))  onGround_2 = true;
    /////////////////////////////

    pos = body_2->GetPosition();
    vel = body_2->GetLinearVelocity();


    if (Keyboard::isKeyPressed(Keyboard::Right))  vel.x = 5;
    if (Keyboard::isKeyPressed(Keyboard::Left))  vel.x = -5;
    if (Keyboard::isKeyPressed(Keyboard::Up) and onGround_2)
    {
      if (pos.y*SCALE >= 400)
      {
        vel.y = -10;
      }
    }
    if (!Keyboard::isKeyPressed(Keyboard::Right))
      if (!Keyboard::isKeyPressed(Keyboard::Left))
        vel.x = 0;

    body_2->SetLinearVelocity(vel);

    //ball max speed
    vel = ball->GetLinearVelocity();
    if (vel.Length() > 15) ball->SetLinearVelocity(15 / vel.Length() * vel);

    //////////Draw///////////////
    window.draw(sBackground);

    for (b2Body* it = World.GetBodyList(); it != 0; it = it->GetNext())
    {
      b2Vec2 pos = it->GetPosition();
      float angle = it->GetAngle();

      if (it->GetUserData() == player1)
      {
        sPlayer_1.setPosition(pos.x*SCALE, pos.y*SCALE);
        sPlayer_1.setRotation(angle*DEG);
        window.draw(sPlayer_1);
      }

      if (it->GetUserData() == player2)
      {
        sPlayer_2.setPosition(pos.x*SCALE, pos.y*SCALE);
        sPlayer_2.setRotation(angle*DEG);
        window.draw(sPlayer_2);
      }

      if (it->GetUserData() == ball_name)
      {
        sBall.setPosition(pos.x*SCALE, pos.y*SCALE);
        sBall.setRotation(angle*DEG);
        window.draw(sBall);
      }
    }
    window.display();
  }
}

#1
19:36, 17 дек. 2020
setCollisionBitmask(0x01)?
#2
(Правка: 22:08) 21:31, 17 дек. 2020

Nurik
> setCollisionBitmask(0x01)?

Лучше это сделать в Collision Callback.

http://www.iforce2d.net/b2dtut/collision-callbacks

Box2DФорумОбщее