@djpiotrs, post #3
// Wykrywa kolizje miedzy dwiema kulami i w razie wykrycia kolizji
// wylicza nowe wartosci skladowych predkosci.
// zrodlo algorytmow: http://www.tarabuk.cba.pl/niecentralne.htm
// argumenty: ball *object1 - wskaznik do obiektu struktury ball, kula #1
// ball *object2 - wskaznik do obiektu struktury ball, kula #2
void CollisionDetect(ball *object1, ball *object2) {
// definicja zmiennych okreslajacych wspolrzedne srodkow kul w chwili t+1,
// (po przesunieciu o aktualny wektor predkosci)
double obj1_newpos_X = object1->position.x + object1->velocity.x * collision_distance * speed;
double obj1_newpos_Y = object1->position.y - object1->velocity.y / (double)65536.0;
double obj1_newpos_Z = object1->position.z + object1->velocity.z * collision_distance * speed;
double obj2_newpos_X = object2->position.x + object2->velocity.x * collision_distance * speed;
double obj2_newpos_Y = object2->position.y - object2->velocity.y / (double)65536.0;
double obj2_newpos_Z = object2->position.z + object2->velocity.z * collision_distance * speed;
// obliczenie odleglosci miedzy srodkami kul w chwili t+1
double newdistance_x = abs(obj1_newpos_X - obj2_newpos_X);
double newdistance_y = abs(obj1_newpos_Y - obj2_newpos_Y);
double newdistance_z = abs(obj1_newpos_Z - obj2_newpos_Z);
double newdistance_xyz = sqrt(math_sqr(newdistance_x) + math_sqr(newdistance_y) + math_sqr(newdistance_z));
// jesli odleglosc miedzy srodkami kul w chwili t+1 <= sumie promieni obu kul, nastepuje kolizja
if (newdistance_xyz < object1->radius + object2->radius) {
// zwieksz licznik kolizji i wyswietl nowa wartosc w oknie dialogowym
collision_counter++;
change_text(IDC_EDIT_COLLISIONCOUNT, std::to_string(collision_counter));
// definicje zmiennych okreslajacych aktualne wartosci skladowych predkosci,
// wspolrzednych srodkow kul oraz odleglosci miedzy srodkami kul
double obj1_velocity_X = object1->velocity.x;
double obj1_velocity_Y = object1->velocity.y;
double obj1_velocity_Z = object1->velocity.z;
double obj2_velocity_X = object2->velocity.x;
double obj2_velocity_Y = object2->velocity.y;
double obj2_velocity_Z = object2->velocity.z;
double obj1_currpos_X = object1->position.x;
double obj1_currpos_Y = object1->position.y;
double obj1_currpos_Z = object1->position.z;
double obj2_currpos_X = object2->position.x;
double obj2_currpos_Y = object2->position.y;
double obj2_currpos_Z = object2->position.z;
double currdistance_x = obj1_currpos_X - obj2_currpos_X;
double currdistance_y = obj1_currpos_Y - obj2_currpos_Y;
double currdistance_z = obj1_currpos_Z - obj2_currpos_Z;
double currdistance_xz = sqrt(math_sqr(currdistance_x) + math_sqr(currdistance_z));
double currdistance_xyz = sqrt(math_sqr(currdistance_x) + math_sqr(currdistance_y) + math_sqr(currdistance_z));
// definicja zmiennej okreslajacych mase kul
double mass = object1->mass / object2->mass;
double ctg_fi = currdistance_z / currdistance_x;
double fi = 0.0 + atan(ctg_fi) + 0.5 * PI; // kat pomiedzy osia X ukladu XYZ a osia A ukladu pomocniczego ABC
// definicja zmiennej okreslajacej miare kata psi
// pomiedzy osia
double psi = acos(currdistance_xz / currdistance_xyz);
// deklaracje zmiennych pomocniczych
double obj1_velocity_XZ, obj2_velocity_XZ, obj1_velocity_XYZ, obj2_velocity_XYZ;
double sin_theta1, sin_theta2, tg_theta1, tg_theta2, theta1, theta2;
double tg_gamma1, tg_gamma2, gamma1, gamma2;
double ABC_W1x, ABC_W1y, ABC_W1z, ABC_W2x, ABC_W2y, ABC_W2z, ABC_W1xz, ABC_W2xz;
double ABC_W1x_s1, ABC_W2x_s1, ABC_W1y_s1, ABC_W2y_s1, ABC_W1z_s1, ABC_W1z_s2, ABC_W2z_s1, ABC_W2z_s2;
double obj1_velocity_Y_s1, obj1_velocity_Y_s2, obj2_velocity_Y_s1, obj2_velocity_Y_s2;
// jesli aktywna jest transmisja szeregowa, zapal LED-y przypisane kulom, miedzy ktorymi wystapila kolizja
if (using_serial) {
set_LED(object1);
set_LED(object2);
}
// dlugosci wektorow predkosci wypadkowych na plaszczyznie XZ i w XYZ
obj1_velocity_XZ = sqrt(math_sqr(obj1_velocity_X) + math_sqr(obj1_velocity_Z));
obj2_velocity_XZ = sqrt(math_sqr(obj2_velocity_X) + math_sqr(obj2_velocity_Z));
obj1_velocity_XYZ = sqrt(math_sqr(obj1_velocity_X) + math_sqr(obj1_velocity_Y) + math_sqr(obj1_velocity_Z));
obj2_velocity_XYZ = sqrt(math_sqr(obj2_velocity_X) + math_sqr(obj2_velocity_Y) + math_sqr(obj2_velocity_Z));
// obliczanie katow THETA pomiedzy wektorami predkosci wypadkowych kul na plaszczyznie XZ a osia X
// ukladu wspolrzednych XYZ
sin_theta1 = obj1_velocity_Z / obj1_velocity_XZ;
sin_theta2 = obj2_velocity_Z / obj2_velocity_XZ;
tg_theta1 = obj1_velocity_Z / obj1_velocity_X;
tg_theta2 = obj2_velocity_Z / obj2_velocity_X;
// kat theta musi byc liczony z (co)tangensa!! Ze wzgledu na wartosc sinusa/cosinusa,
// ktory w mianowniku zawsze ma liczbe dodatnia
theta1 = 0.0 + atan(tg_theta1); // kat pomiedzy wektorem predkosci obj1_velocity_XZ oraz osia X
theta2 = 0.0 + atan(tg_theta2); // kat pomiedzy wektorem predkosci obj2_velocity_XZ oraz osia X
if (sin_theta1 < 0) theta1 = theta1 + PI;
if (sin_theta2 < 0) theta2 = theta2 + PI;
// ponizsze jest, zeby miara katow nie byla ujemna. W sumie zbedne.
if (theta1 < 0) theta1 = 2 * PI + theta1;
if (theta2 < 0) theta2 = 2 * PI + theta2;
// obliczanie katow GAMMA pomiedzy wektorami predkosci wypadkowych kul na plaszczyznie YZ a osia X
// ukladu wspolrzednych XYZ
tg_gamma1 = obj1_velocity_X / obj1_velocity_XZ;
tg_gamma2 = obj2_velocity_X / obj2_velocity_XZ;
if (((obj1_velocity_X < 0) && (obj1_velocity_Z >= 0)) || ((obj1_velocity_X >= 0) && (obj1_velocity_Z < 0))) { tg_gamma1 = -tg_gamma1; }
if (((obj2_velocity_X < 0) && (obj2_velocity_Z >= 0)) || ((obj2_velocity_X >= 0) && (obj2_velocity_Z < 0))) { tg_gamma2 = -tg_gamma2; }
gamma1 = 0.0 + atan(tg_gamma1);
gamma2 = 0.0 + atan(tg_gamma2);
// ponizsze jest, zeby miara katow nie byla ujemna. W sumie zbedne.
if (gamma1 < 0) gamma1 = 2 * PI + gamma1;
if (gamma2 < 0) gamma2 = 2 * PI + gamma2;
// wyliczanie skladowych predkosci koncowych W obu kul po zderzeniu w ukladzie ABC
// *_s1, *_s2 - skladniki do koncowych rownan
ABC_W1x_s1 = obj1_velocity_XZ * cos(theta1 - fi);
ABC_W2x_s1 = obj2_velocity_XZ * cos(theta2 - fi);
ABC_W1y_s1 = obj1_velocity_XYZ * sin(gamma1 - psi);
ABC_W2y_s1 = obj2_velocity_XYZ * sin(gamma1 - psi);
ABC_W1z_s1 = obj1_velocity_XZ * ((mass - restitution) / (mass + restitution)) * sin(theta1 - fi);
ABC_W1z_s2 = obj2_velocity_XZ * ((restitution + 1) / (mass + 1)) * sin(theta2 - fi);
ABC_W2z_s1 = obj1_velocity_XZ * ((mass * (restitution + 1)) / (mass + 1)) * sin(theta1 - fi);
ABC_W2z_s2 = obj2_velocity_XZ * ((1 - restitution * mass) / (mass + 1)) * sin(theta2 - fi);
if (((obj1_velocity_X < 0) && (obj1_velocity_Z >= 0)) || ((obj1_velocity_X >= 0) && (obj1_velocity_Z < 0))) {
ABC_W1x_s1 = -ABC_W1x_s1;
ABC_W1z_s1 = -ABC_W1z_s1;
ABC_W2z_s1 = -ABC_W2z_s1;
}
if (((obj2_velocity_X < 0) && (obj2_velocity_Z >= 0)) || ((obj2_velocity_X >= 0) && (obj2_velocity_Z < 0))) {
ABC_W2x_s1 = -ABC_W2x_s1;
ABC_W1z_s2 = -ABC_W1z_s2;
ABC_W2z_s2 = -ABC_W2z_s2;
}
ABC_W1x = ABC_W1x_s1;
ABC_W2x = ABC_W2x_s1;
ABC_W1y = ABC_W1y_s1;
ABC_W2y = ABC_W2y_s1;
ABC_W1z = ABC_W1z_s1 + ABC_W1z_s2;
ABC_W2z = ABC_W2z_s1 + ABC_W2z_s2;
ABC_W1xz = sqrt(math_sqr(ABC_W1x) + math_sqr(ABC_W1z));
ABC_W2xz = sqrt(math_sqr(ABC_W2x) + math_sqr(ABC_W2z));
// wyliczanie skladowych predkosci koncowych w ukladzie XYZ
obj1_velocity_Y_s1 = ABC_W1y * cos(psi);
obj1_velocity_Y_s2 = ABC_W1xz * sin(psi);
obj2_velocity_Y_s1 = ABC_W2y * cos(psi);
obj2_velocity_Y_s2 = ABC_W2xz * sin(psi);
if (((obj1_velocity_X < 0) && (obj1_velocity_Z >= 0)) || ((obj1_velocity_X >= 0) && (obj1_velocity_Z < 0))) { obj1_velocity_Y_s2 = -obj1_velocity_Y_s2; }
if (((obj2_velocity_X < 0) && (obj2_velocity_Z >= 0)) || ((obj2_velocity_X >= 0) && (obj2_velocity_Z < 0))) { obj2_velocity_Y_s2 = -obj2_velocity_Y_s2; }
obj1_velocity_X = ABC_W1x * cos(fi) - ABC_W1z * sin(fi);
obj1_velocity_Z = ABC_W1x * sin(fi) + ABC_W1z * cos(fi);
obj2_velocity_X = ABC_W2x * cos(fi) - ABC_W2z * sin(fi);
obj2_velocity_Z = ABC_W2x * sin(fi) + ABC_W2z * cos(fi);
obj1_velocity_Y = obj1_velocity_Y_s1 + obj1_velocity_Y_s2;
obj2_velocity_Y = obj2_velocity_Y_s1 + obj2_velocity_Y_s2;
// sprawdzanie kolizji ze scianami...
if ((obj1_currpos_X + object1->radius >= (double)area.x / 2) || (obj1_currpos_X - object1->radius <= 0 - (double)area.x / 2)) {
obj2_velocity_X = -obj2_velocity_X;
object2->rotation_dir.x = -1.0 * object2->rotation_dir.x;
}
if ((obj1_currpos_Z + object1->radius >= (double)area.z / 2) || (obj1_currpos_Z - object1->radius <= 0 - (double)area.z / 2)) {
obj2_velocity_Z = -obj2_velocity_Z;
object2->rotation_dir.z = -1.0 * object2->rotation_dir.z;
}
if ((obj2_currpos_X + object2->radius >= (double)area.x / 2) || (obj2_currpos_X - object2->radius <= 0 - (double)area.x / 2)) {
obj1_velocity_X = -obj1_velocity_X;
object1->rotation_dir.x = -1.0 * object1->rotation_dir.x;
}
if ((obj2_currpos_Z + object2->radius >= (double)area.z / 2) || (obj2_currpos_Z - object2->radius <= 0 - (double)area.z / 2)) {
obj1_velocity_Z = -obj1_velocity_Z;
object1->rotation_dir.z = -1.0 * object1->rotation_dir.z;
}
if (obj1_currpos_Y + object1->radius >= (double)area.y / 2) { obj1_velocity_Y = -obj1_velocity_Y; }
if (obj2_currpos_Y + object2->radius >= (double)area.y / 2) { obj2_velocity_Y = -obj2_velocity_Y; }
object1->velocity.x = obj1_velocity_X;
object1->velocity.y = obj1_velocity_Y;
object1->velocity.z = obj1_velocity_Z;
object2->velocity.x = obj2_velocity_X;
object2->velocity.y = obj2_velocity_Y;
object2->velocity.z = obj2_velocity_Z;
}
}Dla gracza wystarczy to co jest , było ... .
@snajper, post #2
@marskow, post #8
@djpiotrs, post #9
@snajper, post #15
złej baletnicy przeszkadza romb u spodnicy
@selur, post #17
Amosowe strzelanki, platformowki i inne zrecznosciowki wygladaja biednie...
@djpiotrs, post #18
@selur, post #19