コード例 #1
0
    void TickBasicProjectiles(float delta)
    {
        removeListBasic_.Clear();

        float time = Time.time;

        for (int i = 0; i < basicProjectiles_.Count; ++i)
        {
            var p = basicProjectiles_[i];
            if (p.IsLastFrame)
            {
                if (p.CurrentTarget != null && p.StickySoundRepeater != null)
                {
                    p.StickySoundRepeater.StopClip();
                }

                removeListBasic_.Add(p);
            }
            else
            {
                bool outOfTime     = p.DieTime > 0.0f && time >= p.DieTime;
                bool endOfDistance = p.DistanceTraveled >= p.MaxDistance;
                if (!p.IsLastFrame && (endOfDistance || outOfTime))
                {
                    p.SpriteInfo.Renderer.color = Color.white;
                    p.IsLastFrame = true;
                }

                if (p.IsFirstFrame)
                {
                    p.IsFirstFrame = false;
                }

                float   frameSpeed = p.Speed * delta * Timers.EnemyTimer;
                Vector3 movement   = p.Direction * frameSpeed;

                if (p.ReflectOnEdges)
                {
                    float newX = p.Position.x + movement.x;
                    float newY = p.Position.y + movement.y;
                    if (newX < -arenaBoundsX_ || newX > arenaBoundsX_)
                    {
                        movement    = new Vector3(-movement.x, movement.y, 0.0f);
                        p.Direction = new Vector3(-p.Direction.x, p.Direction.y, 0.0f);
                    }

                    if (newY < -arenaBoundsY_ || newY > arenaBoundsY_)
                    {
                        movement    = new Vector3(movement.x, -movement.y, 0.0f);
                        p.Direction = new Vector3(p.Direction.x, -p.Direction.y, 0.0f);
                    }
                }

                p.Position += movement;

                if (p.StickToTarget && p.CurrentTarget != null)
                {
                    if (p.CurrentTarget.Hp <= 0)
                    {
                        // Target we are stuck to died. Scan for a new one close by or continue moving if nothing found.
                        if (p.StickySoundRepeater != null)
                        {
                            p.StickySoundRepeater.StopClip();
                        }

                        p.CurrentTarget = null;
                        int idxClosest = BlackboardScript.GetIdxClosestEnemy(p.Position, 1.5f, 5);
                        if (idxClosest >= 0)
                        {
                            var closeEnemy = BlackboardScript.Enemies[idxClosest];
                            p.Direction = (closeEnemy.transform.position - p.Position).normalized;
                        }
                        else
                        {
                            // Maintain direction
                        }
                    }
                    else
                    {
                        // Keep sticking to target at specific offset
                        p.Position = p.CurrentTarget.transform.position + p.StickOffset;
                        p.CurrentTarget.SetSlowmotion(0.5f);
                        Vector3 damageDirection = (p.StickOffset * -1).normalized;
                        p.CurrentTarget.ApplyDamage(p.Damage, damageDirection, 0.25f, false);
                        GameManager.Instance.TriggerBlood(p.Position + damageDirection * 0.2f, 8.0f, floorBloodRnd: 0.1f);
                        GameManager.Instance.ShakeCamera(0.1f);
                    }
                }
                else if (p.Type == ProjectileType.HarmsEnemies)
                {
                    // TODO PE: This should be changed to colliders. Might enable walls too?
                    // Find enemies hit by projectile
                    if (BlackboardScript.GetEnemies(p.Position, p.Radius, 1) > 0)
                    {
                        int       matchIdx = BlackboardScript.Matches[0].Idx;
                        ActorBase enemy    = BlackboardScript.Enemies[matchIdx];
                        if (p.StickToTarget)
                        {
                            // Begin sticking to target
                            p.CurrentTarget = enemy;
                            p.StickOffset   = (p.SpriteInfo.Transform.position - enemy.transform.position) * 0.9f;

                            if (p.StickySoundRepeater != null)
                            {
                                p.StickySoundRepeater.StartClipWithRandomPitch(p.CollisionSound);
                            }
                            else
                            {
                                AudioManager.Instance.PlayClipWithRandomPitch(AudioManager.Instance.MiscAudioSource, p.CollisionSound);
                            }
                        }

                        float damage = Basic.CalcDamage(p);
                        if (p.CustomCollisionResponse != null)
                        {
                            p.CustomCollisionResponse(p, enemy, damage, p.Direction);
                        }
                        else
                        {
                            GameManager.Instance.DamageEnemy(enemy, damage, p.Direction, p.Force);
                        }

                        if (p.DieOnCollision)
                        {
                            removeListBasic_.Add(p);
                        }

                        if (p.ReflectOnCollision)
                        {
                            if (UnityEngine.Random.value < 0.5f)
                            {
                                p.Direction = Vector3.Reflect(p.Direction, Vector3.up);
                            }
                            else
                            {
                                p.Direction = Vector3.Reflect(p.Direction, Vector3.right);
                            }
                        }
                    }
                }
                else if (p.Type == ProjectileType.HarmsPlayer && DoDeflect)
                {
                    Vector3 dir      = p.Position - DeflectSource;
                    float   distance = dir.magnitude;
                    if (distance <= DeflectRadius)
                    {
                        // Projectile deflected
                        dir.Normalize();
                        p.Direction = Vector3.Reflect(p.Direction, dir) * 3;
                        float rot_z = Mathf.Atan2(p.Direction.y, p.Direction.x) * Mathf.Rad2Deg;
                        p.SpriteInfo.Transform.rotation = Quaternion.Euler(0f, 0f, rot_z);
                        p.Color = new Color(0.8f, 1.0f, 1.0f);
                        p.SpriteInfo.Renderer.color = p.Color;
                        p.Type = ProjectileType.HarmsEnemies;
                        p.SpriteInfo.Transform.gameObject.layer = LayerFromProjectileType(p.Type);
                    }
                }

                if (p.RotationSpeed > 0.0f)
                {
                    p.SpriteInfo.Transform.rotation = Quaternion.Euler(0.0f, 0.0f, Time.time * (p.CurrentTarget == null ? p.RotationSpeed : p.RotationSpeedWhenStuck));
                }

                if (p.SwayFactor > 0.0f)
                {
                    Vector3 perpendicular = new Vector3(-p.Direction.y, p.Direction.x, 0).normalized;
                    p.SpriteInfo.Transform.position = p.Position + (Mathf.Sin(Time.time * 10) * p.SwayFactor * perpendicular);
                }
                else
                {
                    p.SpriteInfo.Transform.position = p.Position;
                }

                p.DistanceTraveled += frameSpeed;
            }
        }

        DoDeflect = false;

        for (int i = 0; i < removeListBasic_.Count; ++i)
        {
            ProjectileCache.Instance.ReturnSprite(removeListBasic_[i].SpriteInfo);
            removeListBasic_[i].Reset();
            projectileCache_.ReturnObject(removeListBasic_[i]);
            basicProjectiles_.Remove(removeListBasic_[i]);
        }
    }