Esempio n. 1
0
        /*
         * Handle a collision between two units
         */
        public void CheckUnitCollision(GameUnit g1, GameUnit g2)
        {
            Vector2 normal = g1.Position - g2.Position;
            float distance = normal.Length();
            normal.Normalize();

            if (distance < g1.Size)
            {
                g1.Position += normal * (g1.Size - distance) / 2;
                g2.Position -= normal * (g2.Size - distance) / 2;

                Vector2 relVel = g1.Vel - g2.Vel;

                float impulse = (-(1 + COLL_COEFF) * Vector2.Dot(normal, relVel)) / (Vector2.Dot(normal, normal) * (1 / g1.Mass + 1 / g2.Mass));

                g1.Vel += (impulse / g1.Mass) * normal;
                g2.Vel -= (impulse / g2.Mass) * normal;
            }
        }
Esempio n. 2
0
        /*
         * Handle a collision between two units
         */
        public void CheckUnitCollision(GameUnit g1, GameUnit g2)
        {
            Vector2 normal = g1.Position - g2.Position;
            float distance = normal.Length();

            // Don't check collision between player and ally
            if (g1.Faction == UnitFaction.ALLY && g2.Type == UnitType.PLAYER ||
                g2.Faction == UnitFaction.ALLY && g1.Type == UnitType.PLAYER ||
                distance == 0)
            {
                return;
            }

            normal.Normalize();

            if (distance < (g1.Size + g2.Size)/2)
            {
                //System.Diagnostics.Debug.WriteLine("1 pos: " + g1.Position + " 2pos: " + g2.Position +
                //    " 1size: " + g1.Size + " 2size: " + g2.Size + " norm: " + normal + " dist: " + distance);
                if (g1.Static)
                {
                    g2.Position -= normal * ((g2.Size + g1.Size) / 2 - distance);
                }
                else if (g2.Static)
                {
                    g1.Position += normal * ((g1.Size + g2.Size) / 2 - distance);
                }
                else
                {
                    g1.Position += normal * ((g1.Size + g2.Size) / 2 - distance) / 2;
                    g2.Position -= normal * ((g2.Size + g1.Size) / 2 - distance) / 2;
                }
                //System.Diagnostics.Debug.WriteLine(g1.Position + " " + g2.Position);

                Vector2 relVel = g1.Vel - g2.Vel;

                float impulse = (-(1 + COLL_COEFF) * Vector2.Dot(normal, relVel)) / (Vector2.Dot(normal, normal) * (1 / g1.Mass + 1 / g2.Mass));

                if(!g1.Static) g1.Vel += (impulse / g1.Mass) * normal;
                if(!g2.Static) g2.Vel -= (impulse / g2.Mass) * normal;
            }
        }
Esempio n. 3
0
 /*
  * Add a unit to the game
  */
 public void AddUnit(GameUnit unit)
 {
     unit.ID = Units.Count;
     Units.Add(unit);
 }
Esempio n. 4
0
        private void UpdateUnit(GameUnit unit, Level level)
        {
            if (!unit.Exists) return;

            // Infection vitality update
            if (unit.Lost)
            {
                unit.InfectionVitality -= INFECTION_RECOVER_SPEED;
                unit.InfectionVitality = MathHelper.Clamp(
                    unit.InfectionVitality, 0, unit.max_infection_vitality);
            }
            else
            {
                unit.InfectionVitality += INFECTION_RECOVER_SPEED;
                unit.InfectionVitality = MathHelper.Clamp(
                    unit.InfectionVitality, 0, unit.max_infection_vitality);
            }
            // If infection vitality is 0, convert the unit, or defeat the boss
            if (unit.InfectionVitality == 0)
            {
                if (unit.Type == UnitType.BOSS)
                {
                    level.BossesDefeated++;
                    unit.Exists = false;
                }
                else
                {
                    ConvertedUnits.Add(unit);
                }
            }

            // Attack cooldown
            unit.AttackCoolDown = (int)MathHelper.Clamp(
                --unit.AttackCoolDown, 0, ATTACK_COOLDOWN);

            // Apply ally attrition if they are outside of range
            if (unit.Faction == UnitFaction.ALLY && Player != null && !unit.inRange(Player, ALLY_FOLLOW_RANGE))
            {
                unit.Health -= ALLY_ATTRITION;
            }
            // Check health
            if (unit.Health <= 0)
            {
                DeadUnits.Add(unit);
            }
        }
Esempio n. 5
0
        /*
         * Sets the velocity of the unit based on its next move
         */
        private void setVelocity(GameUnit unit)
        {
            if (unit.HasNextMove())
            {
                // Calculate direction of acceleration
                Vector2 vel = unit.Vel;
                Vector2 vel_mod = unit.NextMove - unit.Position;

                // If the unit is close enough to target don't move
                if (unit.NextMove == unit.Target && vel_mod.Length() < TARGET_STOP_DIST)
                {
                    vel_mod = Vector2.Zero;
                }
                else
                {
                    vel_mod.Normalize();
                    vel_mod *= unit.Accel;
                }

                //TEMP
                if (unit.Faction == UnitFaction.ALLY && Player != null)
                {
                    if ((unit.Position - unit.Target).Length() < 50)
                    {
                        unit.Speed = (int)(Player.Speed * 1.2);
                    }
                    else
                    {
                        unit.Speed = Player.Speed * 2;
                    }
                }

                // Clamp values to max speeds
                vel += vel_mod;

                if (vel.Length() > unit.Speed)
                {
                    vel.Normalize();
                    vel *= unit.Speed;
                }
                unit.Vel = vel;
            }
        }
Esempio n. 6
0
        /*
         * Process combat between two units
         */
        private void ProcessCombat(GameUnit unit)
        {
            if (unit.AttackCoolDown > 0) return;
            if (unit.Attacking != null &&
                unit.inRange(unit.Attacking, unit.AttackRange + unit.Size/2 + unit.Attacking.Size/2))
            {
                Attack(unit, unit.Attacking);
                unit.Attacking = null;
            }

            // Attack other unit. If no other, attack player
            /*
            if(closest != null) {
                Attack(unit, closest);
            }
            else if (Player.Exists && unit.AttackCoolDown == 0 &&
                unit.Faction == UnitFaction.ENEMY && unit.inRange(Player, unit.AttackRange+Player.Size/2))
            {
                Attack(unit, Player);
            }*/
        }
Esempio n. 7
0
        /*
         * Move this unit according to its current velocity vector
         */
        private void moveUnit(GameUnit unit)
        {
            // Damping
            Vector2 vel = unit.Vel;

            Vector2 vel_mod = vel;
            if (vel_mod.Length() != 0)
            {
                vel_mod.Normalize();
                vel_mod *= unit.Decel;
                vel -= vel_mod;
            }

            // Apply drag
            if ((vel - Vector2.Zero).Length() < unit.Decel * 3/4) { vel = Vector2.Zero; }
            else if (Math.Abs(vel.X) < unit.Decel * 3 / 4) vel.X = 0;
            else if (Math.Abs(vel.Y) < unit.Decel * 3 / 4) vel.Y = 0;
            unit.Vel = vel;
            unit.Position += unit.Vel;
        }
Esempio n. 8
0
 /*
  * A* to target
  */
 private bool findTarget(GameUnit unit, Vector2 target, Map map, int limit)
 {
     List<Vector2> path = Pathfinder.findPath(map, unit.Position, unit.Target, limit, false);
     // Set the next move to the last node in the path with no obstacles in the way
     if (path != null)
     {
         for (int i = path.Count - 1; i > 0; i--)
         {
             if (!map.rayCastHasObstacle(unit.Position, path[i], unit.Size / 2))
             {
                 unit.NextMove = path[i];
                 unit.Lost = false;
                 return true;
             }
         }
         return true;
     }
     else
     {
         double d = unit.distance(Player);
         if (unit.Faction == UnitFaction.ALLY &&
             (Player == null || unit.distance(Player) > LOST_ALLY_DISTANCE))
         {
             unit.Lost = true;
         }
         return false;
     }
 }
Esempio n. 9
0
        /*
         * Returns the closest unit of a different faction from the specified one
         */
        private GameUnit findClosestEnemyInRange(GameUnit unit, int range)
        {
            UnitFaction faction = unit.Faction;

            int x_index = (int)MathHelper.Clamp((unit.Position.X / COMBAT_GRID_CELL_SIZE),
                0, combatRangeGrid.GetLength(1) - 1);
            int y_index = (int)MathHelper.Clamp((unit.Position.Y / COMBAT_GRID_CELL_SIZE),
                0, combatRangeGrid.GetLength(0) - 1);

            // Find the closeset unit according to the combatRangeGrid. Performance optimized.
            GameUnit closest = null;
            double closestDistance = Double.MaxValue;

            List<Point> adjacent = getAdjacent(new Point(x_index, y_index));
            foreach (Point loc in adjacent)
            {
                foreach (GameUnit other in combatRangeGrid[loc.Y, loc.X])
                {
                    //double distance_sq = unit.distance_sq(other);

                    float xdiff = other.Position.X - unit.Position.X;
                    float ydiff = other.Position.Y - unit.Position.Y;
                    double distance_sq = xdiff * xdiff + ydiff * ydiff;

                    if (unit != other && faction != other.Faction && other.Type != UnitType.BOSS &&
                        distance_sq < (range + unit.Size/2 + other.Size/2)*(range + unit.Size/2 + other.Size/2) &&
                        (closest == null || distance_sq < closestDistance))
                    {
                        closest = other;
                        closestDistance = distance_sq;
                    }
                }
            }
            return closest;
        }
Esempio n. 10
0
        /*
         * Converts an enemy to an ally or vice versa, handling stat changes as necessary
         */
        private void Convert(GameUnit unit)
        {
            if (Player == null) return;
            if (unit.Faction == UnitFaction.ALLY)
            {
                unit.Faction = UnitFaction.ENEMY;
                Player.NumAllies--;
                if (Player.NumAllies < MAX_ALLIES) { Player.MaxAllies = false; }
            }
            else if (unit.Faction == UnitFaction.ENEMY)
            {
                unit.Faction = UnitFaction.ALLY;
                Player.NumAllies++;
                if (Player.NumAllies >= MAX_ALLIES) { Player.MaxAllies = true; }
            }

            Units.Remove(unit);
            AddUnit(factory.createUnit(unit.Type, unit.Faction, unit.Level, unit.Position, unit.Immune));
            // Change stats like speed etc as necessary
        }
Esempio n. 11
0
 private void Attack(GameUnit aggressor, GameUnit victim)
 {
     aggressor.AttackCoolDown = ATTACK_COOLDOWN;
     victim.Health -= Math.Max(aggressor.Attack - victim.Defense, 0);
 }
Esempio n. 12
0
        /*
         * Determine the next move for this unit with
         * targeting specific to each unit type AI
         */
        public void setNextMove(GameUnit unit, Level level, bool playerFrontBlocked)
        {
            if (unit.Position.X < 0 || unit.Position.Y < 0) return;

            Vector2 prev_move = unit.NextMove;

            UnitFaction faction = unit.Faction;     // Unit faction, only called once

            // If an ally unit is lost, do this
            if (faction == UnitFaction.ALLY && unit.Lost)
            {
                if (rand.NextDouble() < 0.01 && Player != null)
                {
                    unit.Target = Player.Position;
                    findTarget(unit, Player.Position, level.Map, MAX_ASTAR_DIST);
                }
                else if(rand.NextDouble() < 0.05)
                {
                    unit.Target = unit.Position + new Vector2(rand.Next(600) - 300, rand.Next(600) - 300);
                    unit.NextMove = unit.Target;
                }
                return;
            }

            // Select target
            bool random_walk = false;
            switch (unit.Type)
            {
                case UnitType.TANK:
                    // tank AI
                    if (Player != null && Player.Exists &&
                        faction == UnitFaction.ENEMY && Player.inRange(unit, ENEMY_CHASE_RANGE))
                    {
                        unit.Target = Player.Position;
                    }
                    else if (rand.NextDouble() < 0.05)
                    {
                        // Random walk
                        random_walk = true;
                        unit.Target = unit.Position + new Vector2(rand.Next(600)-300, rand.Next(600)-300);
                    }

                    if (faction == UnitFaction.ALLY && Player != null)
                    {
                        if (playerFrontBlocked)
                        {
                            unit.Target = Player.Position;
                        }
                        else
                        {
                            unit.Target = Player.Front;
                        }
                    }

                    // Chase the closest enemy in range
                    GameUnit closest = findClosestEnemyInRange(unit, ATTACK_LOCK_RANGE);
                    if (closest != null)
                    {
                        unit.Target = closest.Position;
                        unit.Attacking = closest;
                    }

                    if(faction == UnitFaction.ALLY && Player != null && !Player.inRange(unit, ALLY_FOLLOW_RANGE))
                    {
                        unit.Target = Player.Position;
                    }
                    break;
                case UnitType.RANGED:
                    // ranged AI
                    break;
                case UnitType.FLYING:
                    // flying AI
                    break;
                default:
                    // Player case, do nothing
                    break;
            }

            unit.NextMove = unit.Target;
            if (unit.HasTarget())
            {
                /*
                // If the target is the player, use the player location map
                if (unit.Target.Equals(Player.Position) &&
                    Math.Abs(unit.TilePosition.X - Player.TilePosition.X) +
                    Math.Abs(unit.TilePosition.Y - Player.TilePosition.Y) < PLAYER_PATHFIND_FIELD_SIZE)
                {
                    Vector2 moveToPlayerTile = findMoveToPlayer(unit, level.Map);
                    unit.NextMove = new Vector2(moveToPlayerTile.X * Map.TILE_SIZE,
                        moveToPlayerTile.Y * Map.TILE_SIZE);
                }*/

                // Pathfind to target if necessary

                    if (!random_walk &&
                        level.Map.rayCastHasObstacle(unit.Position, unit.Target, unit.Size / 2))
                    {
                        if (rand.NextDouble() < 0.1)
                        {
                            findTarget(unit, unit.Target, level.Map, MAX_ASTAR_DIST);
                        }
                        else
                        {
                            unit.NextMove = prev_move;
                        }
                    }

            }
        }
Esempio n. 13
0
 // Returns an instance of a unit of the given type and faction
 public GameUnit createUnit(UnitType type, UnitFaction faction, int level, Vector2 pos, bool immune)
 {
     GameUnit enemy;
         switch (type)
         {
             case UnitType.TANK:
                 enemy = new GameUnit(faction == UnitFaction.ALLY? textures[ALLY_TANK_l] : textures[ENEMY_TANK_l],
                     faction == UnitFaction.ALLY? textures[ALLY_TANK_r] : textures[ENEMY_TANK_r], type, faction, level, immune);
                 break;
             case UnitType.RANGED:
                 enemy = new GameUnit(faction == UnitFaction.ALLY ? textures[ALLY_RANGED] : textures[ENEMY_RANGED],
                     faction == UnitFaction.ALLY ? textures[ALLY_TANK_r] : textures[ENEMY_TANK_r], type, faction, level, immune);
                 break;
             case UnitType.FLYING:
                 enemy = new GameUnit(faction == UnitFaction.ALLY ? textures[ALLY_FLYING] : textures[ENEMY_FLYING],
                     faction == UnitFaction.ALLY ? textures[ALLY_TANK_r] : textures[ENEMY_TANK_r], type, faction, level, immune);
                 break;
             case UnitType.BOSS:
                 enemy = new GameUnit(textures[PLASMID], textures[PLASMID], type, faction, level, immune);
                 break;
             default:
                 enemy = null;
                 break;
         }
         if (enemy != null)
         {
             enemy.Position = pos;
         }
         return enemy;
 }
Esempio n. 14
0
        /*
         * Handle a collision between a unit and wall
         */
        public void CheckWallCollision(GameUnit unit, Map map)
        {
            List<Vector2> dirs = new List<Vector2>();
            dirs.Add(new Vector2(0, 1));
            dirs.Add(new Vector2(1, 0));
            dirs.Add(new Vector2(0, -1));
            dirs.Add(new Vector2(-1, 0));
            dirs.Add(new Vector2(1, 1));
            dirs.Add(new Vector2(1, -1));
            dirs.Add(new Vector2(-1, 1));
            dirs.Add(new Vector2(-1, -1));

            foreach (Vector2 dir in dirs)
            {
                if(!map.canMoveToWorldPos(unit.Position + dir * unit.Size/2))
                {
                    int i = 0;
                    while (i++ < unit.Size && !map.canMoveToWorldPos(unit.Position + dir * unit.Size/2))
                    {
                        unit.Position -= dir;
                    }
                }
            }
        }
Esempio n. 15
0
 /*
  * Use point location field to find the player (NOT IN USE)
  */
 private Vector2 findMoveToPlayer(GameUnit unit, Map map)
 {
     return playerLocationField[(int)unit.Position.Y / Map.TILE_SIZE, (int)unit.Position.X / Map.TILE_SIZE];
 }
Esempio n. 16
0
 /*
  * Handle a collision between a unit and wall
  */
 public void CheckWallCollision(GameUnit unit, Map map)
 {
 }
Esempio n. 17
0
        /*
         * Process collisions for every unit
         */
        public void ProcessCollisions(GameUnit unit, Map map)
        {
            if (unit == null) return;

            int x_index = (int)MathHelper.Clamp((unit.Position.X / CELL_SIZE),
                0, cellGrid.GetLength(1) - 1);
            int y_index = (int)MathHelper.Clamp((unit.Position.Y / CELL_SIZE),
                0, cellGrid.GetLength(0) - 1);

            List<Point> adjacent = getAdjacent(new Point(x_index, y_index));
            foreach (Point loc in adjacent)
            {
                foreach (GameUnit other in cellGrid[loc.Y, loc.X])
                {
                    // Don't check collision for the same units or if they are in the same position (will crash)
                    if (unit != other && unit.Position != other.Position && !unit.Ghost)
                    {
                        CheckUnitCollision(unit, other);
                    }
                }
            }
            CheckWallCollision(unit, map);
        }