264 |
|
|
265 |
StoneContact::StoneContact(Actor *a, GridPos p, |
StoneContact::StoneContact(Actor *a, GridPos p, |
266 |
const V3 &cp, const V3 &n) |
const V3 &cp, const V3 &n) |
267 |
: actor(a), stonepos(p) |
: actor(a), stonepos(p), |
268 |
, response(STONE_REBOUND) |
response(STONE_REBOUND), |
269 |
, contact_point(cp), normal(n) |
contact_point(cp), |
270 |
, is_collision(false) |
normal(n), |
271 |
, fake_collision(false) |
is_collision(false), |
272 |
, is_contact(true) |
fake_collision(false), |
273 |
|
is_contact(true) |
274 |
{} |
{} |
275 |
|
|
276 |
StoneContact::StoneContact() |
StoneContact::StoneContact() |
277 |
: is_collision(false) |
: is_collision(false), |
278 |
, fake_collision(false) |
fake_collision(false), |
279 |
, is_contact(false) |
is_contact(false) |
280 |
{} |
{} |
281 |
|
|
282 |
DirectionBits |
DirectionBits |
628 |
static void |
static void |
629 |
handle_contacts(Actor *a) |
handle_contacts(Actor *a) |
630 |
{ |
{ |
631 |
// Contacts with stones |
/* |
632 |
|
** Handle contacts with stones |
633 |
|
*/ |
634 |
StoneContactList cl; |
StoneContactList cl; |
635 |
find_stone_contacts(a, cl); |
find_stone_contacts(a, cl); |
636 |
V3 normal = accumulate(cl.begin(), cl.end(), V3(), handle_stone_contact); |
V3 normal = accumulate(cl.begin(), cl.end(), V3(), handle_stone_contact); |
637 |
|
|
638 |
ActorInfo &ai = *a->get_actorinfo(); |
ActorInfo &a1 = *a->get_actorinfo(); |
639 |
|
|
640 |
|
a1.vel = reflect(a1.vel, normal); |
641 |
|
|
642 |
ai.vel = reflect(ai.vel, normal); |
/* |
643 |
|
** Handle contacts with other actors |
644 |
|
*/ |
645 |
|
V3 p1 = a1.pos; |
646 |
|
double r1 = a1.radius; |
647 |
|
double m1 = a1.mass; |
648 |
|
|
|
// Contacts with other actors |
|
649 |
unsigned s=level->actorlist.size(); |
unsigned s=level->actorlist.size(); |
650 |
unsigned i; |
for (unsigned j=0; j<s; ++j) |
|
for (i=0; i<s && level->actorlist[i] != a; ++i) |
|
|
; |
|
|
for (unsigned j=i+1; j<s; ++j) |
|
651 |
{ |
{ |
652 |
ActorInfo &v = *level->actorlist[i]->get_actorinfo(); |
if (level->actorlist[j] == a) continue; |
|
ActorInfo &w = *level->actorlist[j]->get_actorinfo(); |
|
653 |
|
|
654 |
V3 p1 = v.pos; |
ActorInfo &a2 = *level->actorlist[j]->get_actorinfo(); |
655 |
V3 p2 = w.pos; |
V3 p2 = a2.pos; |
656 |
double r1 = v.radius; |
double r2 = a2.radius; |
|
double r2 = w.radius; |
|
657 |
|
|
658 |
bool contactp = length(p1-p2) < r1+r2; |
bool contactp = length(p1-p2) < r1+r2; |
659 |
if (contactp) |
if (contactp) |
660 |
{ |
{ |
661 |
V3 n = normalize(p1-p2); // normal to contact surface |
V3 n = normalize(p1-p2); // normal to contact surface |
662 |
V3 v1 = n * (v.vel*n); |
V3 v1 = n * (a1.vel*n); |
663 |
V3 v2 = n * (w.vel*n); |
V3 v2 = n * (a2.vel*n); |
664 |
|
|
665 |
bool collisionp = (v2-v1)*(p2-p1) < 0; |
bool collisionp = (v2-v1)*(p2-p1) < 0; |
666 |
if (collisionp) { |
if (collisionp) { |
667 |
double m1 = v.mass; |
double m2 = a2.mass; |
|
double m2 = w.mass; |
|
668 |
double M = m1+m2; |
double M = m1+m2; |
669 |
|
|
670 |
v.vel += -v1 + (v2*(2*m2) + v1*(m1-m2)) / M; |
a1.vel += -v1 + (v2*(2*m2) + v1*(m1-m2)) / M; |
671 |
w.vel += -v2 + (v1*(2*m1) + v2*(m2-m1)) / M; |
a2.vel += -v2 + (v1*(2*m1) + v2*(m2-m1)) / M; |
672 |
sound::PlaySound("ballcollision"); |
sound::PlaySound("ballcollision"); |
673 |
} |
} |
674 |
} |
} |