@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