예제 #1
0
        public MightBeCollision Enact(GridManager gridManager, EventManager eventManager, double endtime)
        {
            if (myPhysicsObject.X != start_x ||
                myPhysicsObject.Y != start_y ||
                myPhysicsObject.Vx != start_vx ||
                myPhysicsObject.Vy != start_vy)
            {
                return(new MightBeCollision());
            }

            myPhysicsObject.RemoveFromGrid(gridManager);

            myPhysicsObject.X    = myPhysicsObject.X + (Time - myPhysicsObject.Time) * myPhysicsObject.Vx;
            myPhysicsObject.Y    = myPhysicsObject.Y + (Time - myPhysicsObject.Time) * myPhysicsObject.Vy;
            myPhysicsObject.Time = Time;


            var dx     = otherPhysicsObject.X - myPhysicsObject.X;
            var dy     = otherPhysicsObject.Y - myPhysicsObject.Y;
            var normal = new Vector(dx, dy).NewUnitized();

            callback(myPhysicsObject);

            EventManager.WhatHappensNext(myPhysicsObject, gridManager, eventManager, endtime);

            return(new MightBeCollision(new Collision(
                                            myPhysicsObject.X + normal.NewScaled((myPhysicsObject as PhysicsObject <Ball>).shape.Radius).x,
                                            myPhysicsObject.Y + normal.NewScaled((myPhysicsObject as PhysicsObject <Ball>).shape.Radius).y,
                                            normal.x,
                                            normal.y,
                                            true
                                            )));
        }
예제 #2
0
            public MightBeCollision Enact(GridManager gridManager, EventManager eventManager, double endTime)
            {
                if (physicsObject1.X != start_x1 ||
                    physicsObject1.Y != start_y1 ||
                    physicsObject2.X != start_x2 ||
                    physicsObject2.Y != start_y2 ||
                    physicsObject1.Vx != start_vx1 ||
                    physicsObject1.Vy != start_vy1 ||
                    physicsObject2.Vx != start_vx2 ||
                    physicsObject2.Vy != start_vy2)
                {
                    return(new MightBeCollision());
                }


                physicsObject1.RemoveFromGrid(gridManager);
                physicsObject2.RemoveFromGrid(gridManager);

                physicsObject1.X    = x1;
                physicsObject1.Y    = y1;
                physicsObject1.Time = Time;

                physicsObject2.X    = x2;
                physicsObject2.Y    = y2;
                physicsObject2.Time = Time;

                // update the V of both

                // when a collision happen how does it go down?
                // the velocities we care about are normal to the line
                // we find the normal and take the dot product
                var dx     = physicsObject1.X - physicsObject2.X;
                var dy     = physicsObject1.Y - physicsObject2.Y;
                var normal = new Vector(dx, dy).NewUnitized();

                var v1 = normal.Dot(physicsObject1.Velocity);
                var m1 = physicsObject1.Mass;

                var v2 = normal.Dot(physicsObject2.Velocity);
                var m2 = physicsObject2.Mass;

                MightBeCollision res;


                if (physicsObject1.Mobile == false)
                {
                    physicsObject2.Velocity = normal.NewScaled(-2 * v2).NewAdded(physicsObject2.Velocity);
                    res = new MightBeCollision(new Collision(
                                                   physicsObject2.X + normal.NewScaled((physicsObject2 as PhysicsObject <Ball>).shape.Radius).x,
                                                   physicsObject2.Y + normal.NewScaled((physicsObject2 as PhysicsObject <Ball>).shape.Radius).y,
                                                   normal.NewScaled(-2 * v2 * m2).x,
                                                   normal.NewScaled(-2 * v2 * m2).y,
                                                   false
                                                   ));
                }
                else if (physicsObject2.Mobile == false)
                {
                    physicsObject1.Velocity = normal.NewScaled(-2 * v1).NewAdded(physicsObject1.Velocity);
                    res = new MightBeCollision(new Collision(
                                                   physicsObject2.X + normal.NewScaled((physicsObject2 as PhysicsObject <Ball>).shape.Radius).x,
                                                   physicsObject2.Y + normal.NewScaled((physicsObject2 as PhysicsObject <Ball>).shape.Radius).y,
                                                   normal.NewScaled(-2 * v1 * m1).x,
                                                   normal.NewScaled(-2 * v1 * m1).y,
                                                   false
                                                   ));
                }
                else
                {
                    // we do the physics and we get a quadratic for vf2
                    var c1 = (v1 * m1) + (v2 * m2);
                    var c2 = (v1 * v1 * m1) + (v2 * v2 * m2);

                    var A = (m2 * m2) + (m2 * m1);
                    var B = -2 * m2 * c1;
                    var C = (c1 * c1) - (c2 * m1);


                    double vf2;

                    if (A != 0)
                    {
                        // b^2 - 4acS
                        var D = (B * B) - (4 * A * C);

                        if (D >= 0)
                        {
                            var vf2_plus  = (-B + Math.Sqrt(D)) / (2 * A);
                            var vf2_minus = (-B - Math.Sqrt(D)) / (2 * A);

                            if (IsGood(vf2_minus, v2) && IsGood(vf2_plus, v2) && vf2_plus != vf2_minus)
                            {
                                if (Math.Abs(v2 - vf2_plus) > Math.Abs(v2 - vf2_minus))
                                {
                                    if (Math.Abs(v2 - vf2_minus) > CLOSE)
                                    {
                                        throw new Exception("we are getting physicsObject2 vf2s: " + vf2_plus + "," + vf2_minus + " for vi2: " + v2);
                                    }
                                    vf2 = vf2_plus;
                                }
                                else
                                {
                                    if (Math.Abs(v2 - vf2_plus) > CLOSE)
                                    {
                                        throw new Exception("we are getting physicsObject2 vf2s: " + vf2_plus + "," + vf2_minus + " for vi2: " + v2);
                                    }
                                    vf2 = vf2_minus;
                                }
                            }
                            else if (IsGood(vf2_minus, v2))
                            {
                                vf2 = vf2_minus;
                            }
                            else if (IsGood(vf2_plus, v2))
                            {
                                vf2 = vf2_plus;
                            }
                            else
                            {
                                throw new Exception("we are getting no vfs");
                            }
                        }
                        else
                        {
                            throw new Exception("should not be negative");
                        }
                    }
                    else
                    {
                        throw new Exception("A should not be 0! if A is zer something has 0 mass");
                    }
                    physicsObject2.Velocity = normal.NewScaled(vf2).NewAdded(normal.NewScaled(-v2)).NewAdded(physicsObject2.Velocity);

                    var f   = (vf2 - v2) * m2;
                    var vf1 = v1 - (f / m1);
                    physicsObject1.Velocity = normal.NewScaled(vf1).NewAdded(normal.NewScaled(-v1)).NewAdded(physicsObject1.Velocity);
                    res = new MightBeCollision(new Collision(
                                                   physicsObject2.X + normal.NewScaled((physicsObject2 as PhysicsObject <Ball>).shape.Radius).x,
                                                   physicsObject2.Y + normal.NewScaled((physicsObject2 as PhysicsObject <Ball>).shape.Radius).y,
                                                   normal.NewScaled(vf1).x,
                                                   normal.NewScaled(vf1).y,
                                                   false
                                                   ));
                }


                WhatHappensNext(physicsObject1, gridManager, eventManager, endTime);
                WhatHappensNext(physicsObject2, gridManager, eventManager, endTime);

                return(res);
            }