Exemplo n.º 1
0
triangle_t triangle_new3(point_t a, point_t b, point_t c, material_t material) {
  triangle_t triangle;
  triangle.points[0] = a; triangle.points[1] = b; triangle.points[2] = c;
  triangle.material = material;
  triangle.normal = vec_normalize(vec_cross(point_direction(a, b), point_direction(a, c)));
  return triangle;
}
Exemplo n.º 2
0
color_t getAntialiasedPixel(float x, float y, intersect_t *intersect, float antialiasLevel) {
  float antialiasLevelSquared = antialiasLevel * antialiasLevel;
  float precalculatedOffsetPart = 1.0 / (2.0 * antialiasLevel);
  point_t pos;
  vec_t rayDirection;
  ray_t ray;
  color_t color;
  float avgR = 0, avgG = 0, avgB = 0;
  for (int j = 0; j < antialiasLevel; j++) {
    for (int i = 0; i < antialiasLevel; i++) {
      float xOff = i / antialiasLevel + precalculatedOffsetPart;
      float yOff = j / antialiasLevel + precalculatedOffsetPart;
      float xPos = (x + xOff) * 2 / width - 1;
      float yPos = -((y + yOff) * 2 / height - 1);
      pos = point_new(xPos, yPos, -2);
      rayDirection = vec_normalize(point_direction(cameraPos, pos));
      ray = ray_new(cameraPos, rayDirection);
      color = shootRay(ray, intersect, 0);
      avgR += (float)color.r / (float)antialiasLevelSquared;
      avgG += (float)color.g / (float)antialiasLevelSquared;
      avgB += (float)color.b / (float)antialiasLevelSquared;
    }
  }

  return rgb((char)avgR, (char)avgG, (char)avgB);
}
Exemplo n.º 3
0
color_t getPixel(float x, float y, intersect_t *intersect) {
  intersect->t = -1;
  x = (x + 0.5) * 2 / width - 1;
  y = -((y + 0.5) * 2 / height - 1);
  point_t pixelPos = point_new(x, y, -2);
  vec_t rayDirection = vec_normalize(point_direction(cameraPos, pixelPos));
  ray_t ray = ray_new(cameraPos, rayDirection);
  return shootRay(ray, intersect, 0);
}
void move_towards_point (const double point_x, const double point_y, const double newspeed) {
    enigma::object_planar* const inst = ((enigma::object_planar*)enigma::instance_event_iterator->inst);
    inst->direction = point_direction ( inst->x,inst->y, (point_x), (point_y) );
    inst->speed = (newspeed);
}
Exemplo n.º 5
0
bool move_bounce_object(int object, bool adv, bool solid_only)
{
    enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator->inst);
    if (inst1->sprite_index == -1 && (inst1->mask_index == -1))
        return -4;

    if (collide_inst_inst(object, solid_only, true, inst1->x, inst1->y) == NULL &&
        collide_inst_inst(object, solid_only, true, inst1->x + inst1->hspeed, inst1->y + inst1->vspeed) == NULL) {
        return false;
    }

    if (collide_inst_inst(object, solid_only, true, inst1->x, inst1->y) != NULL) {
        // Return the instance to its previous position.
        inst1->x = inst1->xprevious;
        inst1->y = inst1->yprevious;
    }

    const double angle = inst1->direction, radang = angle*(M_PI/180.0), DBL_EPSILON = 0.00001;
    double sin_angle = sin(radang), cos_angle = cos(radang), pc_corner, pc_dist, max_dist = 1000000;
    int side_type = 0;
    const int quad = int(2*radang/M_PI);
    const bbox_rect_t &box = inst1->$bbox_relative();
    const double x1 = inst1->x, y1 = inst1->y,
                 xscale1 = inst1->image_xscale, yscale1 = inst1->image_yscale,
                 ia1 = inst1->image_angle;
    int left1, top1, right1, bottom1;

    get_border(&left1, &right1, &top1, &bottom1, box.left, box.top, box.right, box.bottom, x1, y1, xscale1, yscale1, ia1);

    for (enigma::iterator it = enigma::fetch_inst_iter_by_int(object); it; ++it)
    {
        const enigma::object_collisions* inst2 = (enigma::object_collisions*)*it;
        if (inst2->id == inst1->id || (solid_only && !inst2->solid))
            continue;
        if (inst2->sprite_index == -1 && (inst2->mask_index == -1))
            continue;
        const bbox_rect_t &box2 = inst2->$bbox_relative();
        const double x2 = inst2->x, y2 = inst2->y,
                     xscale2 = inst2->image_xscale, yscale2 = inst2->image_yscale,
                     ia2 = inst2->image_angle;
        int left2, top2, right2, bottom2;

        get_border(&left2, &right2, &top2, &bottom2, box2.left, box2.top, box2.right, box2.bottom, x2, y2, xscale2, yscale2, ia2);

        if (right2 >= left1 && bottom2 >= top1 && left2 <= right1 && top2 <= bottom1)
            return false;

        switch (quad)
        {
            case 0:
                if ((left2 > right1 || top1 > bottom2) &&
                direction_difference(point_direction(right1, bottom1, left2, top2),angle) >= 0  &&
                direction_difference(point_direction(left1, top1, right2, bottom2),angle) <= 0)
                {
                    pc_corner = direction_difference(point_direction(right1, top1, left2, bottom2),angle);
                    if (fabs(pc_corner) < DBL_EPSILON)
                    {
                        pc_dist = (left2 - right1)/cos_angle;
                        if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 4;
                        }
                    }
                    else if (pc_corner > 0)
                    {
                        pc_dist = (top1 - bottom2)/sin_angle;
                        if (fabs(pc_dist - max_dist) < DBL_EPSILON)
                        {
                            if (side_type == 2)
                                side_type = 3;
                            else if (side_type != 3)
                                side_type = 1;
                        }
                        else if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 1;
                        }
                    }
                    else
                    {
                        pc_dist = (left2 - right1)/cos_angle;
                        if (fabs(pc_dist - max_dist) < DBL_EPSILON)
                        {
                            if (side_type == 1)
                                side_type = 3;
                            else if (side_type != 3)
                                side_type = 2;
                        }
                        else if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 2;
                        }
                    }
                }
            break;
            case 1:
                if ((left1 > right2 || top1 > bottom2) &&
                direction_difference(point_direction(left1, bottom1, right2, top2),angle) <= 0  &&
                direction_difference(point_direction(right1, top1, left2, bottom2),angle) >= 0)
                {
                    pc_corner = direction_difference(point_direction(left1, top1, right2, bottom2),angle);

                    if (fabs(pc_corner) < DBL_EPSILON)
                    {
                        pc_dist = (left2 - right1)/cos_angle;
                        if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 4;
                        }
                    }
                    else if (pc_corner > 0)
                    {
                        pc_dist = (right2 - left1)/cos_angle;
                        if (fabs(pc_dist - max_dist) < DBL_EPSILON)
                        {
                            if (side_type == 1)
                                side_type = 3;
                            else if (side_type != 3)
                                side_type = 2;
                        }
                        else if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 2;
                        }
                    }
                    else
                    {
                        pc_dist = (top1 - bottom2)/sin_angle;
                        if (fabs(pc_dist - max_dist) < DBL_EPSILON)
                        {
                            if (side_type == 2)
                                side_type = 3;
                            else if (side_type != 3)
                                side_type = 1;
                        }
                        else if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 1;
                        }
                    }
                }
            break;
            case 2:
                if ((left1 > right2 || top2 > bottom1) &&
                direction_difference(point_direction(right1, bottom1, left2, top2),angle) <= 0  &&
                direction_difference(point_direction(left1, top1, right2, bottom2),angle) >= 0)
                {
                    pc_corner = direction_difference(point_direction(left1, bottom1, right2, top2),angle);
                    if (fabs(pc_corner) < DBL_EPSILON)
                    {
                        pc_dist = (right2 - left1)/cos_angle;
                        if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 4;
                        }
                    }
                    else if (pc_corner > 0)
                    {
                        pc_dist = (bottom1 - top2)/sin_angle;
                        if (fabs(pc_dist - max_dist) < DBL_EPSILON)
                        {
                            if (side_type == 2)
                                side_type = 3;
                            else if (side_type != 3)
                                side_type = 1;
                        }
                        else if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 1;
                        }
                    }
                    else
                    {
                        pc_dist = (right2 - left1)/cos_angle;
                        if (fabs(pc_dist - max_dist) < DBL_EPSILON)
                        {
                            if (side_type == 1)
                                side_type = 3;
                            else if (side_type != 3)
                                side_type = 2;
                        }
                        else if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 2;
                        }
                    }
                }
            break;
            case 3:
                if ((left2 > right1 || top2 > bottom1) &&
                direction_difference(point_direction(right1, top1, left2, bottom2),angle) <= 0  &&
                direction_difference(point_direction(left1, bottom1, right2, top2),angle) >= 0)
                {
                    pc_corner = direction_difference(point_direction(right1, bottom1, left2, top2),angle);
                    if (fabs(pc_corner) < DBL_EPSILON)
                    {
                        pc_dist = (bottom1 - top2)/sin_angle;
                        if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 4;
                        }
                    }
                    else if (pc_corner > 0)
                    {
                        pc_dist = (left2 - right1)/cos_angle;
                        if (fabs(pc_dist - max_dist) < DBL_EPSILON)
                        {
                            if (side_type == 1)
                                side_type = 3;
                            else if (side_type != 3)
                                side_type = 2;
                        }
                        else if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 2;
                        }
                    }
                    else
                    {
                        pc_dist = (bottom1 - top2)/sin_angle;
                        if (fabs(pc_dist - max_dist) < DBL_EPSILON)
                        {
                            if (side_type == 2)
                                side_type = 3;
                            else if (side_type != 3)
                                side_type = 1;
                        }
                        else if (pc_dist < max_dist)
                        {
                            max_dist = pc_dist;
                            side_type = 1;
                        }
                    }
                }
            break;
        }
    }

    switch (side_type)
    {
        case 0:  //no side hit
            return false;
        case 1:  //horizontal side hit
            inst1->vspeed *= -1;
        break;
        case 2:  //vertical side hit
            inst1->hspeed *= -1;
        break;
        case 3: case 4:  //corner or both horizontal and vertical side hit
            inst1->hspeed *= -1;
            inst1->vspeed *= -1;
        break;
    }
    return true;
}
Exemplo n.º 6
0
double move_outside_object(int object, double angle, double max_dist, bool solid_only)
{
    enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator->inst);
    if (inst1->sprite_index == -1 && (inst1->mask_index == -1))
        return -4;
    const double DMIN = 0.000001, DMAX = 1000000;
    const double contact_distance = DMIN;
    if (max_dist <= 0)
    {
        max_dist = DMAX;
    }
    double dist = 0;
    angle = fmod(angle, 360.0);
    double radang = angle*(M_PI/180.0);
    const double sin_angle = sin(radang), cos_angle = cos(radang);
    const int quad = int(angle/90.0);
    const double    xscale1 = inst1->image_xscale, yscale1 = inst1->image_yscale,
                     ia1 = inst1->image_angle;

    const double x_start = inst1->x, y_start = inst1->y;

    bool had_collision = true;

    while (had_collision) // If there was no collision in the last iteration, we have moved outside the object.
    {
        had_collision = false;
        for (enigma::iterator it = enigma::fetch_inst_iter_by_int(object); it; ++it)
        {
            const bbox_rect_t &box = inst1->$bbox_relative();
            const double x1 = inst1->x, y1 = inst1->y;
            int left1, top1, right1, bottom1;

            get_border(&left1, &right1, &top1, &bottom1, box.left, box.top, box.right, box.bottom, x1, y1, xscale1, yscale1, ia1);

            const enigma::object_collisions* inst2 = (enigma::object_collisions*)*it;
            if (inst2->id == inst1->id || (solid_only && !inst2->solid))
                continue;
            if (inst2->sprite_index == -1 && (inst2->mask_index == -1))
                continue;
            const bbox_rect_t &box2 = inst2->$bbox_relative();
            const double x2 = inst2->x, y2 = inst2->y,
                         xscale2 = inst2->image_xscale, yscale2 = inst2->image_yscale,
                         ia2 = inst2->image_angle;
            int left2, top2, right2, bottom2;

            get_border(&left2, &right2, &top2, &bottom2, box2.left, box2.top, box2.right, box2.bottom, x2, y2, xscale2, yscale2, ia2);

            if (!(right2 >= left1 && bottom2 >= top1 && left2 <= right1 && top2 <= bottom1))
                continue;

            had_collision = true;

            // Move at least one step every time there is a collision.
            const double min_dist = dist + 1;

            switch (quad)
            {
                case 0:
                    if (direction_difference(point_direction(left1, bottom1, right2, top2),angle) < 0)
                    {
                        dist += ((bottom1) - (top2))/sin_angle;
                    }
                    else
                    {
                        dist += ((right2) - (left1))/cos_angle;
                    }
                break;
                case 1:
                    if (direction_difference(point_direction(right1, bottom1, left2, top2),angle) < 0)
                    {
                        dist += ((left2) - (right1))/cos_angle;
                    }
                    else
                    {
                        dist += ((bottom1) - (top2))/sin_angle;
                    }
                break;
                case 2:
                if (direction_difference(point_direction(right1, top1, left2, bottom2),angle) < 0)
                {
                    dist += ((top1) - (bottom2))/sin_angle;
                }
                else
                {
                    dist += ((left2) - (right1))/cos_angle;
                }
                break;
                case 3:
                    if (direction_difference(point_direction(left1, top1, right2, bottom2),angle) < 0)
                    {
                        dist += ((right2) - (left1))/cos_angle;
                    }
                    else
                    {
                        dist += ((top1) - (bottom2))/sin_angle;
                    }
                break;
            }
            dist = max(min(dist, max_dist), min_dist);
            inst1->x = x_start + cos_angle*dist;
            inst1->y = y_start - sin_angle*dist;

            for (int i = 0; i < 1; i++) // Move a single step on if the moving was not precise.
            {
                if (collide_inst_inst(inst2->id, solid_only, true, inst1->x, inst1->y) == NULL) {
                    break;
                }
                dist += 1;
                inst1->x = x_start + cos_angle*dist;
                inst1->y = y_start - sin_angle*dist;
            }
        }
    }

    return dist;
}
Exemplo n.º 7
0
double move_contact_object(int object, double angle, double max_dist, bool solid_only)
{
    enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator->inst);
    if (inst1->sprite_index == -1 && (inst1->mask_index == -1))
        return -4;
    const double DMIN = 1, DMAX = 1000000;
    const double contact_distance = DMIN;
    double sin_angle, cos_angle;
    if (max_dist <= 0)
    {
        max_dist = DMAX;
    }
    angle = fmod(fmod(angle, 360) + 360, 360);
    if (angle == 90)
    {
        sin_angle = 1; cos_angle = 0;
    }
    else if (angle == 180)
    {
        sin_angle = 0; cos_angle = -1;
    }
    else if (angle == 270)
    {
        sin_angle = -1; cos_angle = 0;
    }
    else
    {
        const double radang = angle*(M_PI/180.0);
        sin_angle = sin(radang), cos_angle = cos(radang);
    }
    const int quad = int(angle/90.0);

    const bbox_rect_t &box = inst1->$bbox_relative();
    const double x1 = inst1->x, y1 = inst1->y,
                 xscale1 = inst1->image_xscale, yscale1 = inst1->image_yscale,
                 ia1 = inst1->image_angle;
    int left1, top1, right1, bottom1;

    get_border(&left1, &right1, &top1, &bottom1, box.left, box.top, box.right, box.bottom, x1, y1, xscale1, yscale1, ia1);

    for (enigma::iterator it = enigma::fetch_inst_iter_by_int(object); it; ++it)
    {
        const enigma::object_collisions* inst2 = (enigma::object_collisions*)*it;
        if (inst2->sprite_index == -1 && (inst2->mask_index == -1))
            continue;
        if (inst2->id == inst1->id || (solid_only && !inst2->solid))
            continue;
        const bbox_rect_t &box2 = inst2->$bbox_relative();
        const double x2 = inst2->x, y2 = inst2->y,
                     xscale2 = inst2->image_xscale, yscale2 = inst2->image_yscale,
                     ia2 = inst2->image_angle;
        int left2, top2, right2, bottom2;

        get_border(&left2, &right2, &top2, &bottom2, box2.left, box2.top, box2.right, box2.bottom, x2, y2, xscale2, yscale2, ia2);

        if (right2 >= left1 && bottom2 >= top1 && left2 <= right1 && top2 <= bottom1)
        {
            return 0;
        }

        switch (quad)
        {
            case 0:
                if ((left2 > right1 || top1 > bottom2) &&
                direction_difference(point_direction(right1, bottom1, left2, top2),angle) >= 0  &&
                direction_difference(point_direction(left1, top1, right2, bottom2),angle) <= 0)
                {
                    if (direction_difference(point_direction(right1, top1, left2, bottom2),angle) > 0)
                    {
                        max_dist = min(max_dist, (top1 - bottom2 - contact_distance)/sin_angle);
                    }
                    else
                    {
                        max_dist = min(max_dist, (left2 - right1 - contact_distance)/cos_angle);
                    }
                }
            break;
            case 1:
                if ((left1 > right2 || top1 > bottom2) &&
                direction_difference(point_direction(left1, bottom1, right2, top2),angle) <= 0  &&
                direction_difference(point_direction(right1, top1, left2, bottom2),angle) >= 0)
                {
                    if (direction_difference(point_direction(left1, top1, right2, bottom2),angle) > 0)
                    {
                        max_dist = min(max_dist, (right2 - left1 + contact_distance)/cos_angle);
                    }
                    else
                    {
                        max_dist = min(max_dist, (top1 - bottom2 - contact_distance)/sin_angle);
                    }
                }
            break;
            case 2:
                if ((left1 > right2 || top2 > bottom1) &&
                direction_difference(point_direction(right1, bottom1, left2, top2),angle) <= 0  &&
                direction_difference(point_direction(left1, top1, right2, bottom2),angle) >= 0)
                {
                    if (direction_difference(point_direction(left1, bottom1, right2, top2),angle) > 0)
                    {
                        max_dist = min(max_dist, (bottom1 - top2 + contact_distance)/sin_angle);
                    }
                    else
                    {
                        max_dist = min(max_dist, (right2 - left1 + contact_distance)/cos_angle);
                    }
                }
            break;
            case 3:
                if ((left2 > right1 || top2 > bottom1) &&
                direction_difference(point_direction(right1, top1, left2, bottom2),angle) <= 0  &&
                direction_difference(point_direction(left1, bottom1, right2, top2),angle) >= 0)
                {
                    if (direction_difference(point_direction(right1, bottom1, left2, top2),angle) > 0)
                    {
                        max_dist = min(max_dist, (left2 - right1 - contact_distance)/cos_angle);
                    }
                    else
                    {
                        max_dist = min(max_dist, (bottom1 - top2 + contact_distance)/sin_angle);
                    }
                }
            break;
        }
    }
    inst1->x += cos_angle*max_dist;
    inst1->y -= sin_angle*max_dist;
    return max_dist;
}
Exemplo n.º 8
0
double move_contact_object(int object, double angle, double max_dist, bool solid_only)
{
    enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator->inst);
    if (inst1->sprite_index == -1 && (inst1->mask_index == -1)) {
        return -4;
    }

    const double x = inst1->x, y = inst1->y;

    if (collide_inst_inst(object, solid_only, true, x, y) != NULL) {
        return 0;
    }

    const double DMIN = 1, DMAX = 1000; // Arbitrary max for non-positive values, 1000 fits with other implementations.
    const double contact_distance = DMIN;
    double mid_dist = max_dist; // mid_dist is used for the subtraction part.
    if (max_dist <= 0) { // Use the arbitrary max for non-positive values.
        max_dist = DMAX;
    }
    mid_dist = max_dist;
    const double radang = (fmod(fmod(angle, 360) + 360, 360))*(M_PI/180.0);
    const double sin_angle = sin(radang), cos_angle = cos(radang);

    // Subtraction.

    const int quad = int(angle/90.0);

    const bbox_rect_t &box = inst1->$bbox_relative();
    const double x1 = inst1->x, y1 = inst1->y,
                 xscale1 = inst1->image_xscale, yscale1 = inst1->image_yscale,
                 ia1 = inst1->image_angle;
    int left1, top1, right1, bottom1;

    get_border(&left1, &right1, &top1, &bottom1, box.left, box.top, box.right, box.bottom, x1, y1, xscale1, yscale1, ia1);

    for (enigma::iterator it = enigma::fetch_inst_iter_by_int(object); it; ++it)
    {
        const enigma::object_collisions* inst2 = (enigma::object_collisions*)*it;
        if (inst2->sprite_index == -1 && (inst2->mask_index == -1))
            continue;
        if (inst2->id == inst1->id || (solid_only && !inst2->solid))
            continue;
        const bbox_rect_t &box2 = inst2->$bbox_relative();
        const double x2 = inst2->x, y2 = inst2->y,
                     xscale2 = inst2->image_xscale, yscale2 = inst2->image_yscale,
                     ia2 = inst2->image_angle;
        int left2, top2, right2, bottom2;

        get_border(&left2, &right2, &top2, &bottom2, box2.left, box2.top, box2.right, box2.bottom, x2, y2, xscale2, yscale2, ia2);

        if (right2 >= left1 && bottom2 >= top1 && left2 <= right1 && top2 <= bottom1)
        {
            mid_dist = DMIN;
            break;
        }

        switch (quad)
        {
            case 0:
                if ((left2 > right1 || top1 > bottom2) &&
                direction_difference(point_direction(right1, bottom1, left2, top2),angle) >= 0  &&
                direction_difference(point_direction(left1, top1, right2, bottom2),angle) <= 0)
                {
                    if (direction_difference(point_direction(right1, top1, left2, bottom2),angle) > 0)
                    {
                        mid_dist = min(mid_dist, (top1 - bottom2 - contact_distance)/sin_angle);
                    }
                    else
                    {
                        mid_dist = min(mid_dist, (left2 - right1 - contact_distance)/cos_angle);
                    }
                }
            break;
            case 1:
                if ((left1 > right2 || top1 > bottom2) &&
                direction_difference(point_direction(left1, bottom1, right2, top2),angle) <= 0  &&
                direction_difference(point_direction(right1, top1, left2, bottom2),angle) >= 0)
                {
                    if (direction_difference(point_direction(left1, top1, right2, bottom2),angle) > 0)
                    {
                        mid_dist = min(mid_dist, (right2 - left1 + contact_distance)/cos_angle);
                    }
                    else
                    {
                        mid_dist = min(mid_dist, (top1 - bottom2 - contact_distance)/sin_angle);
                    }
                }
            break;
            case 2:
                if ((left1 > right2 || top2 > bottom1) &&
                direction_difference(point_direction(right1, bottom1, left2, top2),angle) <= 0  &&
                direction_difference(point_direction(left1, top1, right2, bottom2),angle) >= 0)
                {
                    if (direction_difference(point_direction(left1, bottom1, right2, top2),angle) > 0)
                    {
                        mid_dist = min(mid_dist, (bottom1 - top2 + contact_distance)/sin_angle);
                    }
                    else
                    {
                        mid_dist = min(mid_dist, (right2 - left1 + contact_distance)/cos_angle);
                    }
                }
            break;
            case 3:
                if ((left2 > right1 || top2 > bottom1) &&
                direction_difference(point_direction(right1, top1, left2, bottom2),angle) <= 0  &&
                direction_difference(point_direction(left1, bottom1, right2, top2),angle) >= 0)
                {
                    if (direction_difference(point_direction(right1, bottom1, left2, top2),angle) > 0)
                    {
                        mid_dist = min(mid_dist, (left2 - right1 - contact_distance)/cos_angle);
                    }
                    else
                    {
                        mid_dist = min(mid_dist, (bottom1 - top2 + contact_distance)/sin_angle);
                    }
                }
            break;
        }
    }

    double current_dist = DMIN;
    {
        // Avoid moving to position which isn't free. mid_dist is not guaranteed to indicate a free position.
        double next_x = x + mid_dist*cos_angle;
        double next_y = y - mid_dist*sin_angle;
        if (collide_inst_inst(object, solid_only, true, next_x, next_y) == NULL) {
            inst1->x = next_x;
            inst1->y = next_y;
            current_dist = mid_dist;
        }
    }

    // Subtraction end.

    for (; current_dist <= max_dist; current_dist++)
    {
        const double next_x = x + current_dist*cos_angle;
        const double next_y = y - current_dist*sin_angle;
        if (collide_inst_inst(object, solid_only, true, next_x, next_y) != NULL) {
            current_dist--;
            break;
        }
        else {
            inst1->x = next_x;
            inst1->y = next_y;
        }
    }

    return current_dist;
}
Exemplo n.º 9
0
double move_outside_object(double angle, double max_dist, const int object, const bool solid_only)
{
    const double DMIN = 0.000001, DMAX = 1000000;
    const double contact_distance = DMIN;
    if (max_dist <= 0)
    {
        max_dist = DMAX;
    }
    double dist = 0;
    angle = ((angle %(variant) 360) + 360) %(variant) 360;
    double radang = angle*(M_PI/180.0);
    const double sin_angle = sin(radang), cos_angle = cos(radang);
    const int quad = int(angle/90.0);
    enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator->inst);
    const bbox_rect_t &box = inst1->$bbox_relative();
    const double x1 = inst1->x, y1 = inst1->y,
                 xscale1 = inst1->image_xscale, yscale1 = inst1->image_yscale,
                 ia1 = inst1->image_angle;
    int left1, top1, right1, bottom1;

    get_border(&left1, &right1, &top1, &bottom1, box.left, box.top, box.right, box.bottom, x1, y1, xscale1, yscale1, ia1);

    for (enigma::iterator it = enigma::fetch_inst_iter_by_int(object); it; ++it)
    {
        const enigma::object_collisions* inst2 = (enigma::object_collisions*)*it;
        if (inst2->id == inst1->id || (solid_only && !inst2->solid))
            continue;
        const bbox_rect_t &box2 = inst2->$bbox_relative();
        const double x2 = inst2->x, y2 = inst2->y,
                     xscale2 = inst2->image_xscale, yscale2 = inst2->image_yscale,
                     ia1 = inst2->image_angle;
        int left2, top2, right2, bottom2;

        get_border(&left2, &right2, &top2, &bottom2, box2.left, box2.top, box2.right, box2.bottom, x2, y2, xscale2, yscale2, ia1);

        if (!(right2 >= left1 && bottom2 >= top1 && left2 <= right1 && top2 <= bottom1))
            continue;

        switch (quad)
        {
            case 0:
                if (direction_difference(point_direction(right1, top1, right2, top2),angle) < 0)
                {
                    dist = max(dist, ((bottom1) - (top2) + contact_distance)/sin_angle);
                }
                else
                {
                    dist = max(dist, ((right2) - (left1) + contact_distance)/cos_angle);
                }
            break;
            case 1:
                if (direction_difference(point_direction(left1, top1, left2, top2),angle) < 0)
                {
                    dist = max(dist, ((left2) - (right1) - contact_distance)/cos_angle);
                }
                else
                {
                    dist = max(dist, ((bottom1) - (top2) + contact_distance)/sin_angle);
                }
            break;
            case 2:
                if (direction_difference(point_direction(left1, bottom1, left2, bottom2),angle) < 0)
                {
                    dist = max(dist, ((top1) - (bottom2) - contact_distance)/sin_angle);
                }
                else
                {
                    dist = max(dist, ((left2) - (right1) - contact_distance)/cos_angle);
                }
            break;
            case 3:
                if (direction_difference(point_direction(right1, bottom1, right2, bottom2),angle) < 0)
                {
                    dist = max(dist, ((right2) - (left1) + contact_distance)/cos_angle);
                }
                else
                {
                    dist = max(dist, ((top1) - (bottom2) - contact_distance)/sin_angle);
                }
            break;
        }
    }
    dist = min(dist, max_dist);
    inst1->x += cos_angle*dist;
    inst1->y -= sin_angle*dist;
    return dist;
}