Location: England Joined: Mar 2009
Posts: 803

OK wrote it in C++ now. I've let it return the distance the instance moved, maybe it should return the instance it collides with though (but that would make it less efficient).
double move_contact_object(double angle, double dist, const int object, const bool precise = false, const bool solid_only = false) { const double contact_distance = ((precise) ? 0.000001 : 1); dist = abs(dist); angle = ((angle mod 360) + 360) mod 360; enigma::object_collisions* const inst1 = ((enigma::object_collisions*)enigma::instance_event_iterator>inst); const int quad = int(angle/90.0); for (enigma::inst_iter *it = enigma::fetch_inst_iter_by_int(object); it != NULL; it = it>next) { const enigma::object_collisions* inst2 = (enigma::object_collisions*)it>inst; if (inst2>id == inst1>id  solid_only && !inst2>solid) {continue;}
if (inst2>x + inst2>bbox_right >= inst1>x + inst1>bbox_left && inst2>y + inst2>bbox_bottom >= inst1>y + inst1>bbox_top && inst2>x + inst2>bbox_left <= inst1>x + inst1>bbox_right && inst2>y + inst2>bbox_top <= inst1>y + inst1>bbox_bottom) { dist = 0; break; } switch (quad) { case 0: if ((inst2>x + inst2>bbox_left > inst1>x + inst1>bbox_right  inst1>y + inst1>bbox_top > inst2>y + inst2>bbox_bottom) && direction_difference(angle, point_direction(inst1>x + inst1>bbox_right, inst1>y + inst1>bbox_bottom, inst2>x + inst2>bbox_left, inst2>y + inst2>bbox_top)) >= 0 && direction_difference(angle, point_direction(inst1>x + inst1>bbox_left, inst1>y + inst1>bbox_top, inst2>x + inst2>bbox_right, inst2>y + inst2>bbox_bottom)) <= 0) { if (direction_difference(angle, point_direction(inst1>x + inst1>bbox_right, inst1>y + inst1>bbox_top, inst2>x + inst2>bbox_left, inst2>y + inst2>bbox_bottom)) > 0) { dist = min(dist, (inst1>y + inst1>bbox_top  (inst2>y + inst2>bbox_bottom)  contact_distance)/sin(degtorad(angle))); } else { dist = min(dist, (inst2>x + inst2>bbox_left  (inst1>x + inst1>bbox_right)  contact_distance)/cos(degtorad(angle))); } } break; case 1: if ((inst1>x + inst1>bbox_left > inst2>x + inst2>bbox_right  inst1>y + inst1>bbox_top > inst2>y + inst2>bbox_bottom) && direction_difference(angle, point_direction(inst1>x + inst1>bbox_left, inst1>y + inst1>bbox_bottom, inst2>x + inst2>bbox_right, inst2>y + inst2>bbox_top)) <= 0 && direction_difference(angle, point_direction(inst1>x + inst1>bbox_right, inst1>y + inst1>bbox_top, inst2>x + inst2>bbox_left, inst2>y + inst2>bbox_bottom)) >= 0) { if (direction_difference(angle, point_direction(inst1>x + inst1>bbox_left, inst1>y + inst1>bbox_top, inst2>x + inst2>bbox_right, inst2>y + inst2>bbox_bottom)) > 0) { dist = min(dist, (inst2>x + inst2>bbox_right  (inst1>x + inst1>bbox_left) + contact_distance)/cos(degtorad(angle))); } else { dist = min(dist, (inst1>y + inst1>bbox_top  (inst2>y + inst2>bbox_bottom)  contact_distance)/sin(degtorad(angle))); } } break; case 2: if ((inst1>x + inst1>bbox_left > inst2>x + inst2>bbox_right  inst2>y + inst2>bbox_top > inst1>y + inst1>bbox_bottom) && direction_difference(angle, point_direction(inst1>x + inst1>bbox_right, inst1>y + inst1>bbox_bottom, inst2>x + inst2>bbox_left, inst2>y + inst2>bbox_top)) <= 0 && direction_difference(angle, point_direction(inst1>x + inst1>bbox_left, inst1>y + inst1>bbox_top, inst2>x + inst2>bbox_right, inst2>y + inst2>bbox_bottom)) >= 0) { if (direction_difference(angle, point_direction(inst1>x + inst1>bbox_left, inst1>y + inst1>bbox_bottom, inst2>x + inst2>bbox_right, inst2>y + inst2>bbox_top)) > 0) { dist = min(dist, (inst1>y + inst1>bbox_bottom  (inst2>y + inst2>bbox_top) + contact_distance)/sin(degtorad(angle))); } else { dist = min(dist, (inst2>x + inst2>bbox_right  (inst1>x + inst1>bbox_left) + contact_distance)/cos(degtorad(angle))); } } break; case 3: if ((inst2>x + inst2>bbox_left > inst1>x + inst1>bbox_right  inst2>y + inst2>bbox_top > inst1>y + inst1>bbox_bottom) && direction_difference(angle, point_direction(inst1>x + inst1>bbox_right, inst1>y + inst1>bbox_top, inst2>x + inst2>bbox_left, inst2>y + inst2>bbox_bottom)) <= 0 && direction_difference(angle, point_direction(inst1>x + inst1>bbox_left, inst1>y + inst1>bbox_bottom, inst2>x + inst2>bbox_right, inst2>y + inst2>bbox_top)) >= 0) { if (direction_difference(angle, point_direction(inst1>x + inst1>bbox_right, inst1>y + inst1>bbox_bottom, inst2>x + inst2>bbox_left, inst2>y + inst2>bbox_top)) > 0) { dist = min(dist, (inst2>x + inst2>bbox_left  (inst1>x + inst1>bbox_right)  contact_distance)/cos(degtorad(angle))); } else { dist = min(dist, (inst1>y + inst1>bbox_bottom  (inst2>y + inst2>bbox_top) + contact_distance)/sin(degtorad(angle))); } } break; } } inst1>x += cos(degtorad(angle))*dist; inst1>y = sin(degtorad(angle))*dist; return dist; }
inline int move_contact_all(const double direction, const double speed, const bool precise = false) { return move_contact_object(direction, speed, all, precise); }
inline int move_contact_solid(const double direction, const double speed, const bool precise = false) { return move_contact_object(direction, speed, all, precise, true); }
inline int move_contact(const double direction, const double speed, const bool precise = false) { return move_contact_object(direction, speed, all, precise); }
