Skip to main content
2 of 4
Clarified the movement of the aerolites
Alex CB
  • 386
  • 2
  • 14

X axis intersection with inverted Y axis coordinates

I'm making a visual clue for the player to know where (and more or less when) an asteroid is going to enter the screen. For this I'm using a triangle pointing at the incoming object and color interpolation from green (far) to red (near).

My working thoughts are this:

  1. Determine from which part of the screen the aerolite will enter (top, left, ...) by calculating tha angle of the spawn point of the aerolite and the center of the screen with atan2.
  2. Asign a entering direction so the pointing arrow can stay close to the border that the aerolite will enter.
  3. Calculate the entering point using slope Y intersect formula b = y - mx and X intersect x = -b / m.
  4. Calculate, with the linear velocity of the aerolite, the time it will take to arrive to the entering point, so I can interpolate the colors.

So far so good for the aerolites that come from left or right directions, but I get wrong results from the ones that come from top or bottom. Here's the code:

// project a point from the position and the delta_v. Useful for working with lines / segments
const b2Vec2 point_b {aerolite_pos + delta_v};
float slope{}, distance{};
b2Vec2 intersect_point {};
// arrow: calculate the angle of attack respect to the screen's center
const auto theta {atan2Normalized(aerolite_pos.y - screen_center.y, aerolite_pos.x - screen_center.x)};
// asign an incoming direction so we can position the arrow
if (theta >= b2_pi / 6.f && theta < 5.f * b2_pi / 6.f) {
  // TOP
  aerolite->arrow_->incoming_direction_ = Direction::Top;
  slope = (point_b.y - aerolite_pos.y) / (point_b.x - aerolite_pos.x);
  const auto y_intersect = aerolite_pos.y - (slope * aerolite_pos.x);
  intersect_point.Set(-y_intersect / slope, b2_screen_size_.y);

} else if (theta >= 5.f * b2_pi / 6.f && theta < 7.f * b2_pi / 6.f) {
  // LEFT
  aerolite->arrow_->incoming_direction_ = Direction::Left;
  slope = (point_b.y - aerolite_pos.y) / (point_b.x - aerolite_pos.x);
  intersect_point.Set(0.f, aerolite_pos.y - (slope * aerolite_pos.x));

} else if (theta >= 7.f * b2_pi / 6.f && theta < 11.f * b2_pi / 6.f) {
  // BOTTOM
  aerolite->arrow_->incoming_direction_ = Direction::Bottom;
  slope = (point_b.y - aerolite_pos.y) / (point_b.x - aerolite_pos.x);
  const auto y_intersect = aerolite_pos.y - (slope * aerolite_pos.x);
  intersect_point.Set(-y_intersect / slope , 0.f);

} else {
  // RIGHT
  aerolite->arrow_->incoming_direction_ = Direction::Right;
  slope = (point_b.y - aerolite_pos.y) / (point_b.x - aerolite_pos.x + b2_screen_size_.x);
  intersect_point.Set(b2_screen_size_.x, aerolite_pos.y - (slope * (aerolite_pos.x + b2_screen_size_.x)));
}
// distance from spawn point to intersect point
distance = b2Distance(aerolite_pos, intersect_point);
// calculate the time for the aerolite to enter the screen
aerolite->arrow_->time_to_enter_ = distance / delta_v.Length();

I've tried changing the sign, inverting formulae, googling, ... but nothing.

How can I calculate the intersection points taking into account that the Y-axis is inverted?

Edit: the aerolites always go to the center of the screen, no matter where they spawn.

Alex CB
  • 386
  • 2
  • 14