Пример #1
0
        public override Pool <ProjectileData> .Node FireProjectile(Vector2 direction, float leakedTime)
        {
            Pool <ProjectileData> .Node node = new Pool <ProjectileData> .Node();

            Direction = direction;
            RefreshGroups();

            if (!AutoFire)
            {
                if (Interval > 0)
                {
                    return(node);
                }
                else
                {
                    Interval = CoolOffTime;
                }
            }

            for (int g = 0; g < GroupCount; g++)
            {
                if (Projectiles.AvailableCount >= SpokeCount)
                {
                    float rotation = 0;
                    bool  left     = true;

                    for (int n = 0; n < SpokeCount; n++)
                    {
                        node = Projectiles.Get();

                        node.Item.Position   = transform.position;
                        node.Item.Speed      = Speed;
                        node.Item.Scale      = Scale;
                        node.Item.TimeToLive = TimeToLive;
                        node.Item.Gravity    = Gravity;
                        if (UseFollowTarget && FollowTargetType == FollowTargetType.LockOnShot && Target != null)
                        {
                            Groups[g].Direction = (Target.transform.position - transform.position).normalized;
                        }
                        node.Item.Color           = Color.Evaluate(0);
                        node.Item.Acceleration    = Acceleration;
                        node.Item.FollowTarget    = UseFollowTarget;
                        node.Item.FollowIntensity = FollowIntensity;
                        node.Item.Target          = Target;

                        if (left)
                        {
                            node.Item.Velocity = Speed * Rotate(Groups[g].Direction, rotation).normalized;
                            rotation          += SpokeSpacing;
                        }
                        else
                        {
                            node.Item.Velocity = Speed * Rotate(Groups[g].Direction, -rotation).normalized;
                        }

                        // Setup outline if we have one
                        if (ProjectilePrefab.Outline != null && DrawOutlines)
                        {
                            Pool <ProjectileData> .Node outlineNode = ProjectileOutlines.Get();

                            outlineNode.Item.Position = node.Item.Position;
                            outlineNode.Item.Scale    = node.Item.Scale + OutlineSize;
                            outlineNode.Item.Color    = OutlineColor.Evaluate(0);

                            node.Item.Outline = outlineNode;
                        }

                        // Keep track of active projectiles
                        PreviousActiveProjectileIndexes[ActiveProjectileIndexesPosition] = node.NodeIndex;
                        ActiveProjectileIndexesPosition++;
                        if (ActiveProjectileIndexesPosition < ActiveProjectileIndexes.Length)
                        {
                            PreviousActiveProjectileIndexes[ActiveProjectileIndexesPosition] = -1;
                        }
                        else
                        {
                            Debug.Log("Error: Projectile was fired before list of active projectiles was refreshed.");
                        }

                        UpdateProjectile(ref node, leakedTime);

                        left = !left;
                    }

                    if (Groups[g].InvertRotation)
                    {
                        Groups[g].Direction = Rotate(Groups[g].Direction, -RotationSpeed);
                    }
                    else
                    {
                        Groups[g].Direction = Rotate(Groups[g].Direction, RotationSpeed);
                    }
                }
            }

            return(node);
        }
Пример #2
0
        protected override void UpdateProjectile(ref Pool <ProjectileData> .Node node, float tick)
        {
            if (node.Active)
            {
                node.Item.TimeToLive -= tick;

                // Projectile is active
                if (node.Item.TimeToLive > 0)
                {
                    UpdateProjectileNodePulse(tick, ref node.Item);

                    // apply acceleration
                    node.Item.Velocity *= (1 + node.Item.Acceleration * tick);

                    // follow target
                    if (FollowTargetType == FollowTargetType.Homing && node.Item.FollowTarget && node.Item.Target != null)
                    {
                        node.Item.Speed += Acceleration * tick;
                        node.Item.Speed  = Mathf.Clamp(node.Item.Speed, -MaxSpeed, MaxSpeed);

                        Vector2 desiredVelocity = (new Vector2(Target.transform.position.x, Target.transform.position.y) - node.Item.Position).normalized;
                        desiredVelocity *= node.Item.Speed;

                        Vector2 steer = desiredVelocity - node.Item.Velocity;
                        node.Item.Velocity = Vector2.ClampMagnitude(node.Item.Velocity + steer * node.Item.FollowIntensity * tick, node.Item.Speed);
                    }
                    else
                    {
                        // apply gravity
                        node.Item.Velocity += node.Item.Gravity * tick;
                    }

                    // calculate where projectile will be at the end of this frame
                    Vector2 deltaPosition = node.Item.Velocity * tick;
                    float   distance      = deltaPosition.magnitude;

                    // If flag set - return projectiles that are no longer in view
                    if (CullProjectilesOutsideCameraBounds)
                    {
                        Bounds bounds = new Bounds(node.Item.Position, new Vector3(node.Item.Scale, node.Item.Scale, node.Item.Scale));
                        if (!GeometryUtility.TestPlanesAABB(Planes, bounds))
                        {
                            ReturnNode(node);
                            return;
                        }
                    }

                    float radius = 0;
                    if (node.Item.Outline.Item != null)
                    {
                        radius = node.Item.Outline.Item.Scale / 2f;
                    }
                    else
                    {
                        radius = node.Item.Scale / 2f;
                    }

                    // Update foreground and outline color data
                    UpdateProjectileColor(ref node.Item);

                    int result = -1;
                    if (CollisionDetection == CollisionDetectionType.Raycast)
                    {
                        result = Physics2D.Raycast(node.Item.Position, deltaPosition, ContactFilter, RaycastHitBuffer, distance);
                    }
                    else if (CollisionDetection == CollisionDetectionType.CircleCast)
                    {
                        result = Physics2D.CircleCast(node.Item.Position, radius, deltaPosition, ContactFilter, RaycastHitBuffer, distance);
                    }

                    if (result > 0)
                    {
                        // Put whatever hit code you want here such as damage events

                        // Collision was detected, should we bounce off or destroy the projectile?
                        if (BounceOffSurfaces)
                        {
                            // Calculate the position the projectile is bouncing off the wall at
                            Vector2 projectedNewPosition     = node.Item.Position + (deltaPosition * RaycastHitBuffer[0].fraction);
                            Vector2 directionOfHitFromCenter = RaycastHitBuffer[0].point - projectedNewPosition;
                            float   distanceToContact        = (RaycastHitBuffer[0].point - projectedNewPosition).magnitude;
                            float   remainder = radius - distanceToContact;

                            // reposition projectile to the point of impact
                            node.Item.Position = projectedNewPosition - (directionOfHitFromCenter.normalized * remainder);

                            // reflect the velocity for a bounce effect -- will work well on static surfaces
                            node.Item.Velocity = Vector2.Reflect(node.Item.Velocity, RaycastHitBuffer[0].normal);

                            // calculate remaining distance after bounce
                            deltaPosition = node.Item.Velocity * tick * (1 - RaycastHitBuffer[0].fraction);

                            // When gravity is applied, the positional change here is actually parabolic
                            node.Item.Position += deltaPosition;

                            // Absorbs energy from bounce
                            node.Item.Velocity = new Vector2(node.Item.Velocity.x * (1 - BounceAbsorbtionX), node.Item.Velocity.y * (1 - BounceAbsorbtionY));

                            //handle outline
                            if (node.Item.Outline.Item != null)
                            {
                                node.Item.Outline.Item.Position = node.Item.Position;
                            }
                        }
                        else
                        {
                            //check result

                            LayerMask mask    = LayerMask.GetMask("Player");
                            var       result2 = Physics2D.CircleCast(node.Item.Position, radius, deltaPosition, distance, mask, -10000);
                            //var result2 = Physics2D.CircleCast(node.Item.Position, radius, deltaPosition, ContactFilter, RaycastHitBuffer, distance);

                            if (result2)
                            {
                                result2.collider.GetComponentInParent <HPCharacterController>().getDamage(1);
                            }
                            ReturnNode(node);
                        }
                    }
                    else
                    {
                        //No collision -move projectile
                        node.Item.Position += deltaPosition;
                        UpdateProjectileColor(ref node.Item);

                        // Update outline position
                        if (node.Item.Outline.Item != null)
                        {
                            node.Item.Outline.Item.Position = node.Item.Position;
                        }
                    }
                }
                else
                {
                    // End of life - return to pool
                    ReturnNode(node);
                }
            }
        }
 protected abstract void UpdateProjectile(ref Pool <ProjectileData> .Node node, float tick);