Пример #1
0
        }   // end of Setup()

        /// <summary>
        /// c'tor for use when targetting a point in space rather than an object.
        /// </summary>
        /// <param name="position"></param>
        /// <param name="targetPosition"></param>
        /// <param name="launcher"></param>
        /// <param name="verbPayload"></param>
        /// <param name="trackingMode"></param>
        /// <param name="color"></param>
        /// <returns></returns>
        static public CruiseMissile Create(
            Vector3 position,                                       // Starting position.
            Vector3 targetPosition,                                 // Location we're trying to hit.
            GameActor launcher,                                     // Actor that launched this missile.
            float initialRotation,                                  //
            GameThing.Verbs verbPayload,
            int damage,
            MissileChassis.BehaviorFlags behavior,
            Classification.Colors color,
            float desiredSpeed,
            float missileLifetime,
            bool wantSmoke)
        {
            CruiseMissile cm = NextAvailable();

            cm.Setup(
                position,
                launcher,
                initialRotation,
                verbPayload,
                damage,
                behavior,
                color,
                desiredSpeed,
                wantSmoke);

            //Vector3 forward = Vector3.Normalize(targetPosition - position);
            //Vector3 side = Vector3.Cross(Vector3.UnitZ, forward);
            //if (side.LengthSquared() < 0.01f)
            //{
            //    side = Vector3.Cross(Vector3.UnitY, forward);
            //}
            //side.Normalize();
            //Vector3 up = Vector3.Normalize(Vector3.Cross(forward, side));
            //Matrix l2w = Matrix.Identity;
            //l2w.Right = forward;
            //l2w.Up = up;
            //l2w.Forward = side;
            //l2w.Translation = position;
            //cm.Movement.LocalMatrix = l2w;

            MissileChassis missileChassis = cm.Chassis as MissileChassis;

            Vector3 direction = targetPosition - launcher.WorldCollisionCenter;
            Vector3 delta     = Vector3.Normalize(direction);

            float desiredPitch = (float)(Math.Atan2(delta.Z, new Vector2(delta.X, delta.Y).Length()));

            missileChassis.PitchAngle = desiredPitch;

            missileChassis.DeathTime      = Time.GameTimeTotalSeconds + missileLifetime * 1.1f;
            missileChassis.TargetPosition = position + delta * desiredSpeed * missileLifetime * 10f;
            missileChassis.TargetObject   = null;

            return(cm);
        }   // end of CruiseMissile Create
Пример #2
0
        }   // end of CruiseMissile Create

        /// <summary>
        /// c'tor to use when shooting at a particular object
        /// </summary>
        /// <param name="position"></param>
        /// <param name="targetPosition"></param>
        /// <param name="targetThing"></param>
        /// <param name="launcher"></param>
        /// <param name="verbPayload"></param>
        /// <param name="trackingMode"></param>
        /// <param name="color"></param>
        /// <returns></returns>
        static public CruiseMissile Create(
            Vector3 position,                                       // Starting position.
            GameThing targetThing,                                  // Object we're trying to hit.
            GameActor launcher,                                     // Actor that launched this missile.
            float initialRotation,                                  //
            GameThing.Verbs verbPayload,
            int damage,
            MissileChassis.BehaviorFlags behavior,
            Classification.Colors color,
            float desiredSpeed,
            float missileLifetime,
            bool wantSmoke)
        {
            CruiseMissile cm = NextAvailable();

            cm.Setup(
                position,
                launcher,
                initialRotation,
                verbPayload,
                damage,
                behavior,
                color,
                desiredSpeed,
                wantSmoke);

            MissileChassis missileChassis = cm.Chassis as MissileChassis;

            // Set initial speed taking into account the velocity of the launcher.
            Vector3 missileVelocity = new Vector3((float)Math.Cos(initialRotation), (float)Math.Sin(initialRotation), 0);
            float   dot             = Vector3.Dot(missileVelocity, launcher.Movement.Velocity);

            missileChassis.Speed = Math.Max(desiredSpeed, dot);

            missileChassis.DeathTime      = Time.GameTimeTotalSeconds + missileLifetime;
            missileChassis.TargetPosition = targetThing.WorldCollisionCenter;
            missileChassis.TargetObject   = targetThing;

            return(cm);
        }   // end of CruiseMissile Create
Пример #3
0
        /// <summary>
        /// Start, end and radii are passed in from a mover.  This method tests
        /// this mover's swept ellipsoid against all the non-moving things as
        /// well as all the other movers which appear after it in the list.
        /// The "first" param is the index of the next item in the list.
        ///
        /// The listAll param seems to determine whether we just keep the nearest hit
        /// or keep them all.  It appears that listAll=false is used for physics collision
        /// testing while listAll=true is used for WHEN Bumped testing.  But, of course,
        /// this is just a guess on my part since it's not documented.  Argh.
        /// </summary>
        /// <param name="startPos0">start position of swept sphere</param>
        /// <param name="endPos0">end position of swept sphere</param>
        /// <param name="radii0">Radii of swept ellipsoid.</param>
        /// <param name="first">This is the index of the first mover to check for collisions with.  Start, end, and radii come from the previous mover.  TODO (****) Change numbering so this is more clear.</param>
        /// <param name="listAll">When true, all hits are listed.  When false, only the nearest hit is listed.</param>
        /// <param name="hits"></param>
        /// <returns></returns>
        private bool CollisionCheck(Vector3 startPos0, Vector3 endPos0, Vector3 radii0, int first, bool listAll, List <HitInfo> hits)
        {
            /// These are structs, no real allocation done here.
            CollInfo curCollPrim = new CollInfo();

            curCollPrim.DistSq = Single.MaxValue;

            CollInfo best = new CollInfo();

            best.DistSq = Single.MaxValue;
            bool hit = false;

            // Test the current swept ellipsoid against all the non-moving things.
            List <CollisionPrimitive> relevants = things;

            for (int ithing = 0; ithing < relevants.Count; ++ithing)
            {
                CollisionPrimitive thing = relevants[ithing];

                if (thing.Owner.Ignored)
                {
                    continue;
                }

                // Note we used the Z part of the radii.  So, on squashed movers we
                // might get some intersection.
                // TODO (****) Actually figure out how to test a swept ellipsoid against
                // the Primitive based collision shapes.
                if (thing.Collide(startPos0, endPos0, radii0.Z, ref curCollPrim))
                {
                    if (listAll)
                    {
                        HitInfo hitScratch = MakeHitScratch(curCollPrim, radii0.X);
                        hits.Add(hitScratch);
                        curCollPrim.DistSq = Single.MaxValue;
                    }
                    else
                    if (curCollPrim.DistSq <= best.DistSq)
                    {
                        hit     = true;
                        best    = curCollPrim;
                        endPos0 = best.Center;

                        if (best.Touching)
                        {
                            HitInfo hitScratch = MakeHitScratch(best, radii0.X);
                            hits.Add(hitScratch);
                        }
                    }
                }
            }

            // Test the current mover against the remaining movers in the list.
            // Note that in the case of hit testing blips this index may be -1.
            int curMoverIndex = first - 1;

            // If listAll is true, then we're testing for bump so test the full
            // list since we have to worry about TouchCushions.
            if (listAll)
            {
                first = 0;
            }
            for (int second = first; second < movers.Count; ++second)
            {
                Mover sphere = movers[second];

                // Don't test against self.
                if (second == curMoverIndex)
                {
                    continue;
                }

                if (sphere.Owner.Ignored)
                {
                    continue;
                }

                // Don't collide missiles with their launcher.  Note that this assumes
                // that the launcher is always in the list _ahead_ of the missile.
                MissileChassis mc = movers[second].Owner.Chassis as MissileChassis;
                if (mc != null && curMoverIndex >= 0 && mc.Launcher == movers[curMoverIndex].Owner)
                {
                    continue;
                }

                Vector3 radii1 = sphere.Radius * sphere.Owner.SquashScale;

                Vector3 hitContactPosition = Vector3.Zero;
                Vector3 hitNormal          = Vector3.UnitZ;
                float   hitT    = -1;
                bool    hitTest = SweptPrims.SweptEllipsoidSweptEllipsoid(startPos0, endPos0, radii0, sphere.Center, sphere.Center + sphere.Delta, sphere.Radius * sphere.Owner.SquashScale, ref hitContactPosition, ref hitNormal, ref hitT);

                if (hitTest)
                {
                    Vector3 posAtCollision = MyMath.Lerp(startPos0, endPos0, hitT);
                    // Already touching?
                    if (hitT <= 0)
                    {
                        sphere.SetCollPrimTouching(startPos0, posAtCollision, hitContactPosition, -hitNormal, sphere.Center + hitT * sphere.Delta, ref curCollPrim);
                    }
                    else
                    {
                        sphere.SetCollPrim(startPos0, posAtCollision, hitContactPosition, -hitNormal, sphere.Center + hitT * sphere.Delta, ref curCollPrim);
                    }

                    if (listAll)
                    {
                        HitInfo hitScratch = MakeHitScratch(curCollPrim, radii0.X);
                        hits.Add(hitScratch);
                        curCollPrim.DistSq = Single.MaxValue;
                    }
                    else
                    if (curCollPrim.DistSq <= best.DistSq)
                    {
                        best = curCollPrim;
                        hit  = true;

                        if (best.Touching)
                        {
                            HitInfo hitScratch = MakeHitScratch(best, radii0.X);
                            hits.Add(hitScratch);
                        }
                    }
                } // end if hitTest
            }     // end of loop over other movers.

            if (hit)
            {
                Debug.Assert(!listAll, "Hit shouldn't get set when listing all hits");
                /// If it's touching, we've already applied, otherwise
                /// do it here.
                if (!best.Touching)
                {
                    HitInfo hitScratch = MakeHitScratch(best, radii0.X);
                    hits.Add(hitScratch);
                }
            }
            if (listAll && (hits.Count > 1))
            {
                hits.Sort(comparer);
            }
            return(hits.Count > 0);
        }
Пример #4
0
        /// <summary>
        /// Give the actor hitting the other and the other a chance
        /// to respond to impact.
        /// </summary>
        /// <param name="mover"></param>
        /// <param name="hitInfo"></param>
        private void ApplyCollision(Mover mover, HitInfo hitInfo)
        {
            Debug.Assert(hitInfo.Other != null);
            if (mover.Owner.ActorHoldingThis == hitInfo.Other)
            {
                /// I'm touching what's holding me.
                return;
            }
            if (hitInfo.Other.ActorHoldingThis == mover.Owner)
            {
                /// I'm touching what I'm holding.
                return;
            }

            if (InGame.inGame.IsPickedUp(mover.Owner) && InGame.inGame.LastClonedThing == hitInfo.Other)
            {
                // Don't collide the selected object with the recent clone.
                clearLastClonedThing = false;
                return;
            }

            mover.Owner.ApplyCollisions(ref hitInfo);
            AdjustDelta(mover, hitInfo);

            GameActor other = hitInfo.Other;

            // The ordering of tests can change so we need to check if either of
            // the acotrs involved are missiles.
            if (mover.Owner is CruiseMissile || other is CruiseMissile)
            {
                // Actor has been hit by cruise missile.
                // Yes, it kind of sucks to have this here but none of the collision
                // information is stored on the Actor so we have to use it while we have it.
                // Note that we don't allow missiles to hit their launcher.
                if (other is CruiseMissile)
                {
                    MissileChassis mc = other.Chassis as MissileChassis;
                    if (mc != null && mc.Launcher != mover.Owner)
                    {
                        mc.HitTarget(mover.Owner, hitInfo);
                    }
                }
                else
                {
                    MissileChassis mc = mover.Owner.Chassis as MissileChassis;
                    if (mc != null && mc.Launcher != other)
                    {
                        mc.HitTarget(other, hitInfo);
                    }
                }
            }
            else
            {
                // Normal path that happens when two actors bump.
                hitInfo.Center = hitInfo.Struck;
                hitInfo.Normal = -hitInfo.Normal;
                hitInfo.Other  = mover.Owner;
                hitInfo.Offset = MakeOffset(hitInfo, other.CollisionRadius);
                other.ApplyCollisions(ref hitInfo);
                AdjustDelta(hitInfo.OtherMover, hitInfo);
            }
        }   // end of ApplyCollision()
Пример #5
0
        private void Setup(Vector3 position,                      // Starting position.
                           GameActor launcher,                    // Actor that launched this missile.
                           float initialRotation,
                           GameThing.Verbs verbPayload,
                           int damage,
                           MissileChassis.BehaviorFlags behavior,
                           Classification.Colors color,
                           float desiredSpeed,
                           bool wantSmoke)
        {
            smokeEnabled = wantSmoke;

            // Or, we could change the sound to something other than the rumble.
            if (!smokeEnabled)
            {
                XmlActorParams.IdleSoundName = null;
            }

            MissileChassis missileChassis = Chassis as MissileChassis;

            missileChassis.Missile      = this;
            missileChassis.Launcher     = launcher;
            missileChassis.VerbPayload  = verbPayload;
            missileChassis.Damage       = damage;
            missileChassis.Behavior     = behavior;
            missileChassis.Rotation     = initialRotation;
            missileChassis.DesiredSpeed = desiredSpeed;

            Mass = 10.0f;

            Movement.Position = position;

            // Calculate initial missile speed.
            float   initialSpeed = desiredSpeed;
            Vector3 gunVel       = launcher.Movement.Velocity;
            Vector3 shotVel      = new Vector3((float)Math.Cos(initialRotation), (float)Math.Sin(initialRotation), 0f) * initialSpeed;

            if (gunVel.X != 0 || gunVel.Y != 0)
            {
                // Add in some of the launcher's velocity.  Missile will
                // gradually adjust its speed to its desired velocity.
                Vector3 gunVelNorm  = Vector3.Normalize(gunVel);
                Vector3 shotVelNorm = Vector3.Normalize(shotVel);
                float   dot         = Vector3.Dot(gunVelNorm, shotVelNorm);
                Vector3 proj        = gunVel * dot;
                initialSpeed = proj.Length() * MyMath.Direction(dot);
            }
            // Don't allow initial speed to be negative because it looks odd.
            missileChassis.Speed = Math.Max(desiredSpeed, initialSpeed);

            classification.Color = color;

            InitSmokeEmitter(Classification.ColorVector4(classification.Color));

            InitMuzzleFlash(Classification.ColorVector4(classification.Color), 2.0f, 8.0f);

            missileChassis.IgnoreGlassWalls = true;
            missileChassis.Feelers.Clear();     // Don't want missiles to hit glass walls.

            // Register for collisions.
            //InGame.inGame.RegisterCollide(this);
        }   // end of Setup()