예제 #1
0
void PhysicalObj::SetXY(const Point2d &position)
{
  CheckOverlapping();

  // Don't use METER_PER_PIXEL here: bad truncation occurs
  if (IsOutsideWorldXY(Point2i(position.x, position.y)) && can_be_ghost) {
    SetPhysXY(position / PIXEL_PER_METER);
    Ghost();
    SignalOutOfMap();
  } else {
    SetPhysXY(position / PIXEL_PER_METER);
    if (FootsInVacuum())
      StartMoving();
  }
}
예제 #2
0
PhysicalObj* PhysicalObj::CollidedObjectXY(const Point2i & position) const
{
  if (IsOutsideWorldXY(position))
    return NULL;

  Rectanglei rect(position.x + m_test_left, position.y + m_test_top,
                 m_width - m_test_right - m_test_left, m_height - m_test_bottom - m_test_top);

  if (m_collides_with_characters) {
    FOR_ALL_LIVING_CHARACTERS(team,character) {
      // We check both objet if one overlapses the other
      if (&(*character) != this && !IsOverlapping(&(*character)) &&
          !character->IsOverlapping(this) && character->Intersect(rect)) {
        return (PhysicalObj*) &(*character);
      } else if (IsOverlapping(&(*character)) != character->IsOverlapping(this)) {
        //printf("Check 0\n");
      }
    }
  }

  if (m_collides_with_objects) {
    if (m_is_character) {
      FOR_EACH_OBJECT(it) {
        PhysicalObj * object=*it;
        // We check both objet if one overlapses the other
        if (object->m_collides_with_characters) {
          if (object != this && !IsOverlapping(object) && !object->IsOverlapping(this) &&
              object->m_collides_with_objects && object->Intersect(rect)) {
            return object;
          } else if (IsOverlapping(object) != object->IsOverlapping(this)) {
            //printf("Check1\n");
          }
        }
      }
    } else {
      FOR_EACH_OBJECT(it) {
        PhysicalObj * object=*it;
        // We check both objet if one overlapses the other
        if (object != this && !IsOverlapping(object) && !object->IsOverlapping(this) &&
            object->m_collides_with_objects && object->Intersect(rect)) {
          return object;
        } else if (IsOverlapping(object) != object->IsOverlapping(this)) {
          //printf("Check2\n");
        }
      }
    }
  }
예제 #3
0
bool PhysicalObj::IsInVacuumXY(const Point2i &position, bool check_object) const
{
  if (IsOutsideWorldXY(position))
    return GetWorld().IsOpen();

  if (check_object && !m_go_through_objects && CollidedObjectXY(position))
    return false;

  int width = m_width - m_test_right - m_test_left;
  int height = m_height -m_test_bottom - m_test_top;
  width  =  !width ? 1 : width;
  height = !height ? 1 : height;
  Rectanglei rect(position.x + m_test_left, position.y + m_test_top,
                  width, height);

  return GetWorld().RectIsInVacuum(rect);
}
예제 #4
0
파일: bullet.cpp 프로젝트: yeKcim/warmux
void BulletParticle::Refresh()
{
  if(IsOutsideWorldXY(GetPosition())) {
    m_left_time_to_live = 0;
    return;
  }
  int current_time = Time::GetInstance()->Read();
  UpdatePosition();
  image->Update();
  if(start_to_fade > 0) {
    m_left_time_to_live = start_to_fade + BULLET_PARTICLE_FADE_TIME - current_time;
    m_left_time_to_live = (m_left_time_to_live > 0 ? m_left_time_to_live : 0);
    image->SetAlpha(ONE - ((Double)(current_time - start_to_fade)) / BULLET_PARTICLE_FADE_TIME);
  } else {
    // FIXME this is still a ugly hack
    image->SetRotation_rad((Time::GetInstance()->Read()/4) % 3 /* 3 is arbitrary */ );
  }
}
예제 #5
0
// Move to a point with collision test
collision_t PhysicalObj::NotifyMove(Point2d oldPos, Point2d newPos)
{
  if (IsGhost())
    return NO_COLLISION;

  Point2d contactPos;
  Double contactAngle;
  Point2d pos, offset;
  PhysicalObj* collided_obj = NULL;

  collision_t collision = NO_COLLISION;

  // Convert meters to pixels.
  oldPos *= PIXEL_PER_METER;
  newPos *= PIXEL_PER_METER;

  // Compute distance between old and new position.
  Double lg = oldPos.SquareDistance(newPos);

  MSG_DEBUG("physic.move", "%s moves (%s, %s) -> (%s, %s), square distance: %s",
            GetName().c_str(),
            Double2str(oldPos.x).c_str(), Double2str(oldPos.y).c_str(),
            Double2str(newPos.x).c_str(), Double2str(newPos.y).c_str(),
            Double2str(lg).c_str());

  if (!lg.IsNotZero())
    return NO_COLLISION;

  // Compute increments to move the object step by step from the old
  // to the new position.
  lg = sqrt(lg);
  offset = (newPos - oldPos) / lg;

  // First iteration position.
  pos = oldPos + offset;

  if (!m_collides_with_ground || IsInWater()) {
    MSG_DEBUG("physic.move", "%s moves (%s, %s) -> (%s, %s), collides ground:%d, water:%d",
              GetName().c_str(),
              Double2str(oldPos.x).c_str(), Double2str(oldPos.y).c_str(),
              Double2str(newPos.x).c_str(), Double2str(newPos.y).c_str(),
              m_collides_with_ground, IsInWater());

    SetXY(newPos);
    return NO_COLLISION;
  }

  do {
    Point2i tmpPos(uround(pos.x), uround(pos.y));

    // Check if we exit the GetWorld(). If so, we stop moving and return.
    if (IsOutsideWorldXY(tmpPos)) {

      if (!GetWorld().IsOpen()) {
        tmpPos.x = InRange_Long(tmpPos.x, 0, GetWorld().GetWidth() - GetWidth() - 1);
        tmpPos.y = InRange_Long(tmpPos.y, 0, GetWorld().GetHeight() - GetHeight() - 1);
        MSG_DEBUG("physic.state", "%s - DeplaceTestCollision touche un bord : %d, %d",
                  GetName().c_str(), tmpPos.x, tmpPos.y);
        collision = COLLISION_ON_GROUND;
        break;
      }

      SetXY(pos);

      MSG_DEBUG("physic.move", "%s moves (%f, %f) -> (%f, %f) : OUTSIDE WORLD",
                GetName().c_str(), oldPos.x.tofloat(), oldPos.y.tofloat(),
                newPos.x.tofloat(), newPos.y.tofloat());
      return NO_COLLISION;
    }

    // Test if we collide...
    collided_obj = CollidedObjectXY(tmpPos);
    if (collided_obj) {
      if (!m_go_through_objects || m_last_collided_object != collided_obj) {
        MSG_DEBUG("physic.state", "%s collide on %s", GetName().c_str(), collided_obj->GetName().c_str());

        if (m_go_through_objects) {
          SignalObjectCollision(GetSpeed(), collided_obj, collided_obj->GetSpeed());
          collision = NO_COLLISION;
        } else {
          collision = COLLISION_ON_OBJECT;
        }
        m_last_collided_object = collided_obj;
      } else {
        collided_obj = NULL;
        collision = NO_COLLISION;
      }
    } else if (!IsInVacuumXY(tmpPos, false)) {
      collision = COLLISION_ON_GROUND;
      m_last_collided_object = NULL;
    }

    if (collision != NO_COLLISION) {
      // Nothing more to do!
      MSG_DEBUG("physic.state", "%s - Collision at %d,%d : on %s",
                GetName().c_str(), tmpPos.x, tmpPos.y,
                collision == COLLISION_ON_GROUND ? "ground" : "an object");

      // Set the object position to the current position.
      SetXY(Point2d(pos.x - offset.x, pos.y - offset.y));
      break;
    }

    // Next motion step
    pos += offset;
    lg -= ONE;
  } while (ZERO < lg);

  Point2d speed_before_collision = GetSpeed();
  Point2d speed_collided_obj;
  if (collided_obj) {
    speed_collided_obj = collided_obj->GetSpeed();
  }

  ContactPointAngleOnGround(pos, contactPos, contactAngle);

  Collide(collision, collided_obj, pos);

  // ===================================
  // it's time to signal object(s) about collision!
  // WARNING: the following calls can send Action(s) over the network (cf bug #11232)
  // Be sure to keep it isolated here
  // ===================================
  ActiveTeam().AccessWeapon().NotifyMove(!!collision);
  switch (collision) {
  case NO_COLLISION:
    // Nothing more to do!
    break;
  case COLLISION_ON_GROUND:
    SignalGroundCollision(speed_before_collision, contactAngle);
    break;
  case COLLISION_ON_OBJECT:
    SignalObjectCollision(speed_before_collision, collided_obj, speed_collided_obj);
    collided_obj->SignalObjectCollision(speed_collided_obj, this, speed_before_collision);
    break;
  }
  // ===================================

  return collision;
}