예제 #1
0
        /// <summary>
        /// Fire a missile from the given shooter's position at the target position.
        /// </summary>
        /// <param name="shooter"></param>
        /// <param name="targetPos"></param>
        /// <param name="color"></param>
        /// <param name="verbPayload"></param>
        /// <returns></returns>
        public bool Fire(GameActor shooter,
                         Vector3 targetPos,
                         Classification.Colors color,
                         GameThing.Verbs verbPayload,
                         int damage)
        {
            if (numActiveBleeps < kMaxBleeps)
            {
                float speed     = shooter.BlipSpeed;
                float time2Live = shooter.BlipRange / speed;
                Bleep bleep     = new Bleep();
                bleep.Position    = shooter.WorldGlowPosition;
                bleep.StartHeight = bleep.Position.Z;
                bleep.Position.Z  = shooter.WorldCollisionCenter.Z;
                bleep.Velocity    = Vector3.Normalize(targetPos - bleep.Position) * speed;
                float vdotv = Vector3.Dot(bleep.Velocity, shooter.Movement.Velocity);
                if (vdotv > 0)
                {
                    /// If the bullet is moving the same direction as the shooter,
                    /// add in the shooter's speed in the bullet's direction.
                    /// This will only speed up the bullet, not change it's firing
                    /// direction.
                    vdotv          /= bleep.Velocity.LengthSquared();
                    bleep.Velocity += bleep.Velocity * vdotv;
                }
                bleep.Life        = bleep.TTL = time2Live;
                bleep.VerbPayload = verbPayload;
                bleep.Damage      = damage;

                Vector4 color4 = Classification.ColorVector4(color);
                /// Brighten up the color a bit.
                color4.X    = MyMath.SmoothStep(0.0f, 1.0f, color4.X);
                color4.Y    = MyMath.SmoothStep(0.0f, 1.0f, color4.Y);
                color4.Z    = MyMath.SmoothStep(0.0f, 1.0f, color4.Z);
                bleep.Color = new Color(color4);

                bleep.TTTerraHit = CheckTerrainHit(bleep, speed);

                if (shooter.ActiveBleeps.Bleeps.Count == 0)
                {
                    Shooters.Add(shooter);
                }
                shooter.ActiveBleeps.Bleeps.Add(bleep);

                // Increment the number of active bleeps.  Without this, on the
                // current frame we can end up shooting enough new bleeps to
                // exceed the max.
                ++numActiveBleeps;

                return(true);
            }
            return(false);
        }
예제 #2
0
        /// <summary>
        /// Look ahead over the life of this bleep (since it's strictly inertial)
        /// for when (if ever) it would strike terrain or path. We do the single
        /// LOS check with background on firing, but checks against other objects
        /// (which are probably moving) every frame.
        /// </summary>
        /// <param name="bleep"></param>
        /// <param name="speed"></param>
        /// <returns></returns>
        private float CheckTerrainHit(Bleep bleep, float speed)
        {
            Vector3 start = bleep.Position;
            Vector3 end   = start + bleep.Velocity * bleep.TTL;

            Vector3 terrainHitPos = Vector3.Zero;
            float   ttTerraHit    = bleep.Life * 2;

            if (SimWorld.Terra.Terrain.LOSCheckTerrainAndPath(start, end, ref terrainHitPos))
            {
                Vector3 total      = end - start;
                float   invRangeSq = bleep.Life / total.LengthSquared();

                Vector3 toTerraHit = terrainHitPos - start;

                ttTerraHit = Vector3.Dot(toTerraHit, total) * invRangeSq;
            }
            return(ttTerraHit);
        }
예제 #3
0
        /// <summary>
        /// Test to see if a bleep hit anything, object or terrain.
        /// </summary>
        /// <param name="shooter"></param>
        /// <param name="bleeps"></param>
        /// <param name="particle"></param>
        /// <returns></returns>
        private bool HitSomething(GameActor shooter, Bleep bleep)
        {
            Vector3 start = bleep.Position;
            Vector3 end   = start + bleep.Velocity * Time.GameTimeFrameSeconds;

            Vector3 terrainHit = end;
            bool    hitTerrain = bleep.Life - bleep.TTL >= bleep.TTTerraHit;

            if (hitTerrain)
            {
                /// terrain hit is current position
                /// - what we've travelled already (vel * (life - ttl))
                /// + time from beginning to terrain hit (vel * ttTerraHit)
                /// We use end as current position because we've already updated TTL
                /// but haven't yet advanced .Position. When we do advance .Position,
                /// it will be to "end".
                terrainHit = end + bleep.Velocity * (bleep.TTTerraHit - (bleep.Life - bleep.TTL));
            }

            const float kBleepRadius = 0.25f;
            GameActor   hitThing     = null;
            Vector3     hitPoint     = terrainHit;

            if (CollSys.TestAll(
                    start,
                    end,
                    kBleepRadius,
                    _scratchHitInfo))
            {
                for (int i = 0; i < _scratchHitInfo.Count; ++i)
                {
                    GameActor other = _scratchHitInfo[i].Other;
                    if (!ExcludedHitThing(shooter, other))
                    {
                        hitThing = other;
                        hitPoint = _scratchHitInfo[i].Contact;
                        break;
                    }
                }
                _scratchHitInfo.Clear();
            }

            if (hitTerrain && (hitThing != null))
            {
                if (Vector3.DistanceSquared(start, terrainHit) < Vector3.DistanceSquared(start, hitPoint))
                {
                    hitThing = null;
                    hitPoint = terrainHit;
                }
            }

            if (hitThing != null)
            {
                OnHit(shooter, hitThing, hitPoint, bleep);
            }
            else if (hitTerrain)
            {
                OnHit(shooter, null, hitPoint, bleep);
                ExplosionManager.CreateSpark(hitPoint, 3, 0.4f, 1.0f);
            }

            return(hitTerrain || (hitThing != null));;
        }
예제 #4
0
        /// <summary>
        /// Take care of necessary callbacks when a Bleep hits a thing.
        /// </summary>
        /// <param name="shooter"></param>
        /// <param name="hitThing"></param>
        /// <param name="bleep"></param>
        private void OnHit(GameActor shooter, GameThing hitThing, Vector3 hitPos, Bleep bleep)
        {
            Debug.Assert(shooter != null);

            shooter.OnBlipHit(hitThing, hitPos, bleep.VerbPayload, bleep.Damage);
        }
예제 #5
0
        /// <summary>
        /// Update all birds in the air.
        /// </summary>
        public override void Update()
        {
            numActiveBleeps = 0;
            int vtxIdx = 0;

            if (Shooters.Count > 0)
            {
                float dt = Time.GameTimeFrameSeconds;

                for (int shooterIdx = Shooters.Count - 1; shooterIdx >= 0; --shooterIdx)
                {
                    GameActor shooter = Shooters[shooterIdx];

                    List <Bleep> bleeps = shooter.ActiveBleeps.Bleeps;

                    for (int i = bleeps.Count - 1; i >= 0; --i)
                    {
                        Bleep bleep = bleeps[i];
                        bleep.TTL -= dt;
                        if (bleep.TTL <= 0)
                        {
                            OnExpire(shooter);
                            RemoveParticle(shooter, bleeps, i);
                        }
                        else if (HitSomething(shooter, bleep))
                        {
                            RemoveParticle(shooter, bleeps, i);
                        }
                        else
                        {
                            // Update the current blip.
                            bleep.Position.X += bleep.Velocity.X * dt;
                            bleep.Position.Y += bleep.Velocity.Y * dt;
                            bleep.Position.Z += bleep.Velocity.Z * dt;

                            bleeps[i] = bleep;

                            // If we have room in the buffer to render it, do so.
                            if (numActiveBleeps < kMaxBleeps)
                            {
                                BleepVertex vert = new BleepVertex();
                                vert.Position = bleep.Position;
                                vert.Color    = bleep.Color.PackedValue;
                                vert.TexCoord = new Vector4(
                                    0.0f, 0.0f,
                                    1.0f - bleep.TTL / bleep.Life,
                                    bleep.StartHeight);

                                verts[vtxIdx++] = vert;

                                vert.TexCoord.X = 1.0f;
                                verts[vtxIdx++] = vert;
                                vert.TexCoord.Y = 1.0f;
                                verts[vtxIdx++] = vert;
                                vert.TexCoord.X = 0.0f;
                                verts[vtxIdx++] = vert;

                                ++numActiveBleeps;
                            }
                            else
                            {
                                Debug.Assert(false, "We should never get here.  If we do it means that we're allowing Fire() to happen when we're already maxed out.");
                            }
                        }
                    }

                    Debug.Assert(shooter.ActiveBleeps.Bleeps == bleeps);
                    if (bleeps.Count == 0)
                    {
                        Shooters.RemoveAt(shooterIdx);
                    }
                }
            }
            if (numActiveBleeps > 0)
            {
                UpdateBuffer(numActiveBleeps);
            }
        }
예제 #6
0
 private void Start()
 {
     speakBehavior = new Bleep();
     moveBehavior  = new Walk();
 }