コード例 #1
0
        /// <summary>
        /// Performs a bounce collision (a collision which modifies velocity and acceleration), and separates the objects if so.
        /// </summary>
        /// <param name="sphere">The Sphere to perform collision against.</param>
        /// <param name="thisMass">The mass of this instance.</param>
        /// <param name="otherMass">Th e mass of the argument cube.</param>
        /// <param name="elasticity">The ratio of velocity to preserve.</param>
        /// <returns>Whether a collision occurred.</returns>
        public bool CollideAgainstBounce(Sphere sphere, float thisMass, float otherMass, float elasticity)
        {
#if DEBUG
            if (thisMass == 0 && otherMass == 0)
            {
                throw new ArgumentException("Both masses cannot be 0.  For equal masses pick a non-zero value");
            }
#endif
            if (CollideAgainstMove(sphere, thisMass, otherMass))
            {
                // Get the relative velocity of this circle to the argument circle:
                Vector3 relativeVelocity = new Vector3(
                    this.TopParent.XVelocity - sphere.TopParent.XVelocity,
                    this.TopParent.YVelocity - sphere.TopParent.YVelocity,
                    this.TopParent.ZVelocity - sphere.TopParent.ZVelocity);


#if FRB_MDX
                float velocityNormalDotResult = Vector3.Dot(relativeVelocity, LastMoveCollisionReposition);
#else
                float velocityNormalDotResult;
                Vector3.Dot(ref relativeVelocity, ref LastMoveCollisionReposition, out velocityNormalDotResult);
#endif

                if (velocityNormalDotResult >= 0)
                {
                    return(true);
                }

#if FRB_MDX
                //Vector2 tangentVector = new Vector2((float)mLastCollisionTangent.X, (float)mLastCollisionTangent.Y);
                // Perform the bounce if the relative velocity and the tangent are the opposite direction.

                Vector3 reverseNormal = -Vector3.Normalize(LastMoveCollisionReposition);

                float   length           = Vector3.Dot(relativeVelocity, reverseNormal);
                Vector3 velocityOnNormal = Vector3.Multiply(reverseNormal, length);
#else
                Vector3 reverseNormal = -LastMoveCollisionReposition;
                reverseNormal.Normalize();

                float   length = Vector3.Dot(relativeVelocity, reverseNormal);
                Vector3 velocityOnNormal;
                Vector3.Multiply(ref reverseNormal, length, out velocityOnNormal);
#endif


                sphere.TopParent.Velocity.X += (1 + elasticity) * thisMass / (thisMass + otherMass) * velocityOnNormal.X;
                sphere.TopParent.Velocity.Y += (1 + elasticity) * thisMass / (thisMass + otherMass) * velocityOnNormal.Y;
                sphere.TopParent.Velocity.Z += (1 + elasticity) * thisMass / (thisMass + otherMass) * velocityOnNormal.Z;

                this.TopParent.Velocity.X -= (1 + elasticity) * otherMass / (thisMass + otherMass) * velocityOnNormal.X;
                this.TopParent.Velocity.Y -= (1 + elasticity) * otherMass / (thisMass + otherMass) * velocityOnNormal.Y;
                this.TopParent.Velocity.Z -= (1 + elasticity) * otherMass / (thisMass + otherMass) * velocityOnNormal.Z;

                return(true);
            }
            return(false);
        }
コード例 #2
0
        /// <summary>
        /// Collision method that returns whether collision has occurred and repositions this and the
        /// argument Sphere to prevent overlap.
        /// </summary>
        /// <param name="sphere">The other Sphere to collide against.</param>
        /// <param name="thisMass">The mass of the calling Sphere.  This value is used relative to "otherMass".  Both cannot be 0.</param>
        /// <param name="otherMass">The mass of the argument Sphere.  This value is used relative to "thisMass".  Both cannot be 0.</param>
        /// <returns>Whether the calling Sphere and the argument Sphere are touching.</returns>
        #endregion
        public bool CollideAgainstMove(Sphere sphere, float thisMass, float otherMass)
        {
#if DEBUG
            if (thisMass == 0 && otherMass == 0)
            {
                throw new ArgumentException("Both masses cannot be 0.  For equal masses pick a non-zero value");
            }
#endif
            if (mLastDependencyUpdate != TimeManager.CurrentTime)
            {
                UpdateDependencies(TimeManager.CurrentTime);
            }
            if (sphere.mLastDependencyUpdate != TimeManager.CurrentTime)
            {
                sphere.UpdateDependencies(TimeManager.CurrentTime);
            }

            float differenceX = sphere.Position.X - Position.X;
            float differenceY = sphere.Position.Y - Position.Y;
            float differenceZ = sphere.Position.Z - Position.Z;

            float differenceSquared =
                differenceX * differenceX + differenceY * differenceY + differenceZ * differenceZ;

            if (differenceSquared < (Radius + sphere.Radius) * (Radius + sphere.Radius))
            {
                double  distanceToMove = Radius + sphere.Radius - System.Math.Sqrt(differenceSquared);
                Vector3 moveVector     = new Vector3(differenceX, differenceY, differenceZ);
                moveVector.Normalize();

                float amountToMoveThis = otherMass / (thisMass + otherMass);

                LastMoveCollisionReposition = moveVector * (float)(-distanceToMove * amountToMoveThis);

                sphere.LastMoveCollisionReposition = moveVector * (float)(distanceToMove * (1 - amountToMoveThis));

                if (mParent != null)
                {
                    TopParent.Position += LastMoveCollisionReposition;

                    ForceUpdateDependencies();
                }
                else
                {
                    Position += LastMoveCollisionReposition;
                }

                if (sphere.mParent != null)
                {
                    sphere.TopParent.Position += sphere.LastMoveCollisionReposition;

                    sphere.ForceUpdateDependencies();
                }
                else
                {
                    sphere.Position += sphere.LastMoveCollisionReposition;
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
コード例 #3
0
        /// <summary>
        /// Returns whether this instance overlaps the argument cube, and separates the two instances according to their relative masses.
        /// </summary>
        /// <param name="cube">The cube to perform collision against.</param>
        /// <param name="thisMass">The mass of this instance.</param>
        /// <param name="otherMass">The mass of the cube.</param>
        /// <returns>Whether the objects were overlapping before the reposition.</returns>
        public bool CollideAgainstMove(AxisAlignedCube cube, float thisMass, float otherMass)
        {
#if DEBUG
            if (thisMass == 0 && otherMass == 0)
            {
                throw new ArgumentException("Both masses cannot be 0.  For equal masses pick a non-zero value");
            }
#endif
            if (LastDependencyUpdate != TimeManager.CurrentTime)
            {
                UpdateDependencies(TimeManager.CurrentTime);
            }
            if (cube.LastDependencyUpdate != TimeManager.CurrentTime)
            {
                cube.UpdateDependencies(TimeManager.CurrentTime);
            }


            Vector3 relativeCenter = Position - cube.Position;

            if (System.Math.Abs(relativeCenter.X) - Radius > cube.ScaleX ||
                System.Math.Abs(relativeCenter.Y) - Radius > cube.ScaleY ||
                System.Math.Abs(relativeCenter.Z) - Radius > cube.ScaleZ)
            {
                return(false);
            }

            Vector3 nearest = GetNearestPoint(cube, relativeCenter);

            float distance = (nearest - relativeCenter).LengthSquared();

            if (distance > Radius * Radius)
            {
                return(false);
            }

            double  distanceToMove = Radius - System.Math.Sqrt((double)distance);
            Vector3 moveVector     = relativeCenter - nearest;
            moveVector.Normalize();

            float amountToMoveThis = otherMass / (thisMass + otherMass);

            LastMoveCollisionReposition = moveVector * (float)(distanceToMove * amountToMoveThis);

            Vector3 cubeReposition = moveVector * (float)(-distanceToMove * (1 - amountToMoveThis));
            cube.mLastMoveCollisionReposition = cubeReposition;

            if (mParent != null)
            {
                TopParent.Position += LastMoveCollisionReposition;
                ForceUpdateDependencies();
            }
            else
            {
                Position += LastMoveCollisionReposition;
            }

            if (cube.mParent != null)
            {
                cube.TopParent.Position += cube.LastMoveCollisionReposition;
                ForceUpdateDependencies();
            }
            else
            {
                cube.Position += cube.LastMoveCollisionReposition;
            }

            return(true);
        }
コード例 #4
0
        public bool UpdateElementVisibility(HierarchyNode parentNode)
        {
            bool didChange = false;

            if (mCircleVisibleRepresentation != null)
            {
                mCircleVisibleRepresentation.Position = this.Position;
            }
            else
            {
                mSpriteVisibleRepresentation.Position = this.Position;
            }
            mText.Position = this.Position;

            #region Update the attachment visibility

            bool shouldConnectionBeVisible = parentNode != null;

            if (shouldConnectionBeVisible != mParentLine.Visible)
            {
                mParentLine.Visible            = shouldConnectionBeVisible;
                mParentAttachmentPoint.Visible = mParentLine.Visible;
                didChange = true;
            }

            #endregion

            #region If visible, update the position of the line itself

            if (mParentLine.Visible)
            {
                Vector3 vectorToParent = this.Position - parentNode.Position;

                if (vectorToParent.X == 0 && vectorToParent.Y == 0 && vectorToParent.Z == 0)
                {
                    return(didChange);
                }


                float radius = 0;

                if (mCircleVisibleRepresentation != null)
                {
                    radius = mCircleVisibleRepresentation.Radius;
                }
                else
                {
                    radius = mSpriteVisibleRepresentation.ScaleX;
                }

                vectorToParent.Normalize();

                Vector3 endPoint1 = this.Position - vectorToParent * radius;

                Vector3 endPoint2 = parentNode.Position + vectorToParent * radius;

                if (mParentAttachmentPoint.Position != endPoint2)
                {
                    didChange = true;
                }
                mParentAttachmentPoint.Position = endPoint2;

                mParentLine.SetFromAbsoluteEndpoints(endPoint1, endPoint2);
            }

            #endregion

            return(didChange);
        }