public void FindNewBehaviour() { if (!isEnabled) { return; } // find the suitable behavior AIBehavior behavior = GetDecision(); // enable the behavior if (behavior != null) { //AIBehavior pastBehavior; // disable the past behavior //if (states.TryGetValue(currentBehavior, out pastBehavior)) //{ // states[currentBehavior].Disable(); //} behavior.Enable(); currentBehavior = behavior.Type; } else { currentBehavior = AIBehaviorType.None; } }
// Disable the AI public void Disable() { isEnabled = false; currentBehavior = AIBehaviorType.None; foreach (KeyValuePair <AIBehaviorType, AIBehavior> behavior in states) { behavior.Value.Disable(); } }
/// <summary> /// Updates all Enemies in the game /// </summary> /// <param name="elapsedTime"> /// The time between this and the previous frame. /// </param> public void Update(float elapsedTime) { List <uint> keyList = game.EnemyAIComponent.Keys.ToList <uint>(); foreach (uint id in keyList) { EnemyAI enemyAI = game.EnemyAIComponent[id]; AIBehaviorType AIBehavior = enemyAI.AIBehaviorType; Position pos = game.PositionComponent[id]; if (pos.RoomID != game.CurrentRoomEid) { continue; } if (game.EnemyComponent[id].Health <= 0) { game.GarbagemanSystem.ScheduleVisit(id); } switch (AIBehavior) { case AIBehaviorType.DefaultMelee: updateTargeting(id); MoveTowardTarget(id); break; case AIBehaviorType.DefaultRanged: updateTargeting(id); MoveTowardTarget(id); break; case AIBehaviorType.Alien: updateTargeting(id); MoveTowardTarget(id); uint targetID = enemyAI.TargetID; float dist = Vector2.Distance(pos.Center, game.PositionComponent[targetID].Center); if (dist < 35) { game.SkillSystem.EnemyUseSkill(SkillType.DamagingPull, id, targetID); } ManageAnimation(id); break; default: break; } } }
/// <summary> /// Updates all Enemies in the game /// </summary> /// <param name="elapsedTime"> /// The time between this and the previous frame. /// </param> public void Update(float elapsedTime) { List <uint> keyList = game.EnemyAIComponent.Keys.ToList <uint>(); foreach (uint id in keyList) { EnemyAI enemyAI = game.EnemyAIComponent[id]; Enemy enemy = game.EnemyComponent[id]; AIBehaviorType AIBehavior = enemyAI.AIBehaviorType; Position pos = game.PositionComponent[id]; Movement movement; if (pos.RoomID != game.CurrentRoomEid) { continue; } if (game.EnemyComponent[id].Health <= 0) { switch (enemy.Type) { case EnemyType.Sludge5: Position pos2 = pos; pos2.Center.X += 70; game.EnemyFactory.CreateEnemy(EnemyType.Sludge4, pos); game.EnemyFactory.CreateEnemy(EnemyType.Sludge4, pos2); game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; case EnemyType.Sludge4: pos2 = pos; pos2.Center.X += 70; game.EnemyFactory.CreateEnemy(EnemyType.Sludge3, pos); game.EnemyFactory.CreateEnemy(EnemyType.Sludge3, pos2); game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; case EnemyType.Sludge3: game.EnemyFactory.CreateEnemy(EnemyType.Sludge2, pos); game.EnemyFactory.CreateEnemy(EnemyType.Sludge2, pos); game.EnemyFactory.CreateEnemy(EnemyType.Sludge2, pos); game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; case EnemyType.Sludge2: game.EnemyFactory.CreateEnemy(EnemyType.Sludge1, pos); game.EnemyFactory.CreateEnemy(EnemyType.Sludge1, pos); game.EnemyFactory.CreateEnemy(EnemyType.Sludge1, pos); game.EnemyFactory.CreateEnemy(EnemyType.Sludge1, pos); game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; case EnemyType.Sludge1: game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; default: game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; } } uint targetID; float dist; switch (AIBehavior) { case AIBehaviorType.DefaultMelee: updateTargeting(id); MoveTowardTarget(id); break; case AIBehaviorType.DefaultRanged: updateTargeting(id); if (!enemyAI.HasTarget) { ManageAnimation(id); continue; } targetID = enemyAI.TargetID; dist = Vector2.Distance(pos.Center, game.PositionComponent[targetID].Center); movement = game.MovementComponent[id]; if (dist > 300) { MoveTowardTarget(id); } else { movement.Direction = Vector2.Zero; game.MovementComponent[id] = movement; //Put spritesheets here string spriteSheet; switch (enemy.Type) { default: spriteSheet = "Spritesheets/Skills/Effects/AlienOrb"; break; } game.SkillSystem.EnemyUseBasicRanged(id, targetID, 1, 1f, spriteSheet, new Rectangle(0, 0, 20, 20)); } ManageAnimation(id); break; case AIBehaviorType.CloakingRanged: updateTargeting(id); if (!enemyAI.HasTarget) { ManageAnimation(id); continue; } targetID = enemyAI.TargetID; dist = Vector2.Distance(pos.Center, game.PositionComponent[targetID].Center); bool isUsingCloak = false; foreach (Cloak cloak in game.CloakComponent.All) { if (cloak.TargetID == id) { if (cloak.TimeLeft > 2 && cloak.StartingTime - cloak.TimeLeft > 2) { isUsingCloak = true; } break; } } movement = game.MovementComponent[id]; if (!isUsingCloak) { if (dist > 300) { MoveTowardTarget(id); } else { movement.Direction = Vector2.Zero; game.MovementComponent[id] = movement; //game.SkillSystem.EnemyUseSkill(SkillType.SniperShot, id, targetID); game.SkillSystem.EnemyUseBasicRanged(id, targetID, 1, 1f, "Spritesheets/Skills/Effects/AlienOrb", new Rectangle(0, 0, 20, 20)); game.SkillSystem.EnemyUseSkill(SkillType.Cloak, id, id); } } else if (movement.Direction.Equals(Vector2.Zero)) { movement.Direction = new Vector2(rand.Next(20) - 10, rand.Next(20) - 10); movement.Direction = Vector2.Normalize(movement.Direction); game.MovementComponent[id] = movement; } ManageAnimation(id); break; case AIBehaviorType.Spider: updateTargeting(id); if (!enemyAI.HasTarget) { ManageAnimation(id); continue; } MoveTowardTarget(id); targetID = enemyAI.TargetID; dist = Vector2.Distance(pos.Center, game.PositionComponent[targetID].Center); if (dist < 50) { game.SkillSystem.EnemyUseSkill(SkillType.DamagingPull, id, targetID); game.SkillSystem.EnemyUseBasicMelee(id, targetID, 1, 1); } ManageAnimation(id); break; default: break; } } }
/// <summary> /// Creates a new enemy and adds it to the game. (No other components created) /// </summary> /// <param name="type">The type of enemy to create.</param> public uint CreateEnemy(EnemyType type, Position position) { uint eid = Entity.NextEntity(); Enemy enemy = new Enemy(); Sprite sprite; SpriteAnimation spriteAnimation = new SpriteAnimation(eid); Collideable collideable; EnemyAI ai; AIBehaviorType aiBehaviorType = AIBehaviorType.None; float moveSpeed = 100; String spritesheet; Rectangle spriteBounds = new Rectangle(0, 0, 64, 64); Color spriteColor = Color.White; switch (type) { case EnemyType.StationaryTarget: enemy.HurtOnTouch = false; enemy.Health = 1; spritesheet = "Spritesheets/Enemies/target2"; break; case EnemyType.MovingTarget: enemy.HurtOnTouch = false; enemy.Health = 1; spritesheet = "Spritesheets/Enemies/target2"; break; case EnemyType.Spider: enemy.HurtOnTouch = false; enemy.Health = 20; spritesheet = "Spritesheets/Enemies/spider"; spriteBounds = new Rectangle(0, 0, 120 / 3, 141 / 4); aiBehaviorType = AIBehaviorType.Spider; moveSpeed = 115; spriteAnimation.FramesPerSecond = 14; break; case EnemyType.CloakingRobot: enemy.HurtOnTouch = false; enemy.Health = 50; spritesheet = "Spritesheets/Enemies/CloakingRobot"; spriteColor = Color.LightCyan; spriteBounds = new Rectangle(0, 0, 65, 75); spriteAnimation.FramesPerSecond = 5; aiBehaviorType = AIBehaviorType.CloakingRanged; position.Radius = 37; break; case EnemyType.BasicShootingRobot: enemy.HurtOnTouch = false; enemy.Health = 50; spritesheet = "Spritesheets/Enemies/BasicShootingRobot"; spriteBounds = new Rectangle(0, 0, 65, 75); spriteAnimation.FramesPerSecond = 5; aiBehaviorType = AIBehaviorType.DefaultRanged; position.Radius = 32; break; case EnemyType.Sludge1: enemy.HurtOnTouch = false; enemy.Health = 20; spritesheet = "Spritesheets/Enemies/Sludge1"; spriteBounds = new Rectangle(0, 0, 16, 16); spriteAnimation.FramesPerSecond = 10; aiBehaviorType = AIBehaviorType.DefaultMelee; position.Radius = 8; break; case EnemyType.Sludge2: enemy.HurtOnTouch = false; enemy.Health = 30; spritesheet = "Spritesheets/Enemies/Sludge2"; spriteBounds = new Rectangle(0, 0, 32, 32); spriteAnimation.FramesPerSecond = 10; aiBehaviorType = AIBehaviorType.DefaultRanged; position.Radius = 16; break; case EnemyType.Sludge3: enemy.HurtOnTouch = false; enemy.Health = 40; spritesheet = "Spritesheets/Enemies/Sludge3"; spriteBounds = new Rectangle(0, 0, 64, 64); spriteAnimation.FramesPerSecond = 10; aiBehaviorType = AIBehaviorType.DefaultRanged; position.Radius = 32; break; case EnemyType.Sludge4: enemy.HurtOnTouch = false; enemy.Health = 50; spritesheet = "Spritesheets/Enemies/Sludge4"; spriteBounds = new Rectangle(0, 0, 128, 128); spriteAnimation.FramesPerSecond = 10; aiBehaviorType = AIBehaviorType.DefaultRanged; position.Radius = 64; break; case EnemyType.Sludge5: enemy.HurtOnTouch = false; enemy.Health = 60; spritesheet = "Spritesheets/Enemies/Sludge5"; spriteBounds = new Rectangle(0, 0, 256, 256); spriteAnimation.FramesPerSecond = 10; aiBehaviorType = AIBehaviorType.DefaultRanged; position.Radius = 128; break; default: throw new Exception("Unknown EnemyType"); } ai = new EnemyAI() { EntityID = eid, AIBehaviorType = aiBehaviorType, }; _game.EnemyAIComponent.Add(eid, ai); enemy.Type = type; enemy.EntityID = eid; position.EntityID = eid; sprite = new Sprite() { EntityID = eid, SpriteSheet = _game.Content.Load <Texture2D>(spritesheet), SpriteColor = spriteColor, SpriteBounds = spriteBounds }; collideable = new Collideable() { EntityID = eid, RoomID = position.RoomID, Bounds = new CircleBounds(position.Center, position.Radius) }; Movement move = new Movement() { EntityID = eid, Speed = moveSpeed, }; _game.SpriteAnimationComponent[eid] = spriteAnimation; _game.CollisionComponent[eid] = collideable; _game.MovementComponent.Add(eid, move); _game.EnemyComponent.Add(eid, enemy); _game.PositionComponent.Add(eid, position); _game.SpriteComponent.Add(eid, sprite); return(eid); }
/// <summary> /// Updates all Enemies in the game /// </summary> /// <param name="elapsedTime"> /// The time between this and the previous frame. /// </param> public void Update(float elapsedTime) { List <uint> keyList = game.EnemyAIComponent.Keys.ToList <uint>(); foreach (uint id in keyList) { EnemyAI enemyAI = game.EnemyAIComponent[id]; AIBehaviorType AIBehavior = enemyAI.AIBehaviorType; Position pos = game.PositionComponent[id]; Movement movement; if (pos.RoomID != game.CurrentRoomEid) { continue; } if (game.EnemyComponent[id].Health <= 0) { game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); } uint targetID; float dist; switch (AIBehavior) { case AIBehaviorType.DefaultMelee: updateTargeting(id); MoveTowardTarget(id); break; case AIBehaviorType.DefaultRanged: updateTargeting(id); targetID = enemyAI.TargetID; dist = Vector2.Distance(pos.Center, game.PositionComponent[targetID].Center); if (true) { bool onCoolDown = false; foreach (CoolDown cd in game.CoolDownComponent.All) { if (cd.Type == SkillType.SniperShot && cd.UserID == id) { onCoolDown = true; break; } } if (!onCoolDown && dist > 299) { MoveTowardTarget(id); } if (!onCoolDown && dist < 300) { game.SkillSystem.EnemyUseSkill(SkillType.SniperShot, id, targetID); movement = game.MovementComponent[id]; Random next = new Random(); movement.Direction = new Vector2(rand.Next(20) - 10, rand.Next(20) - 10); movement.Direction = Vector2.Normalize(movement.Direction); game.MovementComponent[id] = movement; } } ManageAnimation(id); break; case AIBehaviorType.Alien: updateTargeting(id); if (!enemyAI.HasTarget) { ManageAnimation(id); continue; } targetID = enemyAI.TargetID; dist = Vector2.Distance(pos.Center, game.PositionComponent[targetID].Center); bool isUsingCloak = false; foreach (Cloak cloak in game.CloakComponent.All) { if (cloak.TargetID == id) { if (cloak.TimeLeft > 2 && cloak.StartingTime - cloak.TimeLeft > 2) { isUsingCloak = true; } break; } } movement = game.MovementComponent[id]; if (!isUsingCloak) { if (dist > 300) { MoveTowardTarget(id); } else { movement.Direction = Vector2.Zero; game.MovementComponent[id] = movement; game.SkillSystem.EnemyUseSkill(SkillType.SniperShot, id, targetID); game.SkillSystem.EnemyUseSkill(SkillType.Cloak, id, id); } } else if (movement.Direction.Equals(Vector2.Zero)) { movement.Direction = new Vector2(rand.Next(20) - 10, rand.Next(20) - 10); movement.Direction = Vector2.Normalize(movement.Direction); game.MovementComponent[id] = movement; } ManageAnimation(id); break; case AIBehaviorType.Spider: updateTargeting(id); MoveTowardTarget(id); targetID = enemyAI.TargetID; dist = Vector2.Distance(pos.Center, game.PositionComponent[targetID].Center); if (dist < 35) { game.SkillSystem.EnemyUseSkill(SkillType.DamagingPull, id, targetID); } ManageAnimation(id); break; default: break; } } }
/// <summary> /// Creates a new enemy and adds it to the game. (No other components created) /// </summary> /// <param name="type">The type of enemy to create.</param> public uint CreateEnemy(EnemyType type, Position position) { uint eid = Entity.NextEntity(); Enemy enemy = new Enemy(); Sprite sprite; SpriteAnimation spriteAnimation = new SpriteAnimation(eid); Collideable collideable; EnemyAI ai; AIBehaviorType aiBehaviorType = AIBehaviorType.None; float moveSpeed = 100; String spritesheet; Rectangle spriteBounds = new Rectangle(0, 0, 64, 64);; switch (type) { case EnemyType.StationaryTarget: enemy.HurtOnTouch = false; enemy.Health = 1; spritesheet = "Spritesheets/target2"; break; case EnemyType.MovingTarget: enemy.HurtOnTouch = false; enemy.Health = 1; spritesheet = "Spritesheets/target2"; break; case EnemyType.Alien: enemy.HurtOnTouch = false; enemy.Health = 1; spritesheet = "Spritesheets/alien"; spriteBounds = new Rectangle(0, 0, 32, 32); aiBehaviorType = AIBehaviorType.Alien; break; default: throw new Exception("Unknown EnemyType"); } ai = new EnemyAI() { EntityID = eid, AIBehaviorType = aiBehaviorType, }; _game.EnemyAIComponent.Add(eid, ai); enemy.Type = type; enemy.EntityID = eid; position.EntityID = eid; sprite = new Sprite() { EntityID = eid, SpriteSheet = _game.Content.Load <Texture2D>(spritesheet), SpriteBounds = spriteBounds }; collideable = new Collideable() { EntityID = eid, RoomID = position.RoomID, Bounds = new CircleBounds(position.Center, position.Radius) }; Movement move = new Movement() { EntityID = eid, Speed = moveSpeed, }; _game.SpriteAnimationComponent[eid] = spriteAnimation; _game.CollisionComponent[eid] = collideable; _game.MovementComponent.Add(eid, move); _game.EnemyComponent.Add(eid, enemy); _game.PositionComponent.Add(eid, position); _game.SpriteComponent.Add(eid, sprite); return(eid); }
/// <summary> /// Updates all Enemies in the game /// </summary> /// <param name="elapsedTime"> /// The time between this and the previous frame. /// </param> public void Update(float elapsedTime) { List <uint> keyList = game.EnemyAIComponent.Keys.ToList <uint>(); foreach (uint id in keyList) { EnemyAI enemyAI = game.EnemyAIComponent[id]; Enemy enemy = game.EnemyComponent[id]; AIBehaviorType AIBehavior = enemyAI.AIBehaviorType; Position pos = game.PositionComponent[id]; Movement movement; if (pos.RoomID != game.CurrentRoomEid) { continue; } if (game.EnemyComponent[id].Health <= 0) { //Positions for sludge splitting Position pos1, pos2; pos1 = pos2 = pos; pos1.Center.X -= pos.Radius / 2; pos2.Center.X += pos.Radius / 2; switch (enemy.Type) { case EnemyType.Sludge5: game.EnemyFactory.CreateEnemy(EnemyType.Sludge4, pos1); game.EnemyFactory.CreateEnemy(EnemyType.Sludge4, pos2); game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; case EnemyType.Sludge4: game.EnemyFactory.CreateEnemy(EnemyType.Sludge3, pos1); game.EnemyFactory.CreateEnemy(EnemyType.Sludge3, pos2); game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; case EnemyType.Sludge3: game.EnemyFactory.CreateEnemy(EnemyType.Sludge2, pos1); game.EnemyFactory.CreateEnemy(EnemyType.Sludge2, pos2); game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; case EnemyType.Sludge2: game.EnemyFactory.CreateEnemy(EnemyType.Sludge1, pos1); game.EnemyFactory.CreateEnemy(EnemyType.Sludge1, pos2); game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; case EnemyType.Sludge1: game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; default: game.GarbagemanSystem.ScheduleVisit(id, GarbagemanSystem.ComponentType.Enemy); break; } uint eid = Entity.NextEntity(); Position effectPos = pos; effectPos.Radius = 40; effectPos.EntityID = eid; game.PositionComponent.Add(eid, effectPos); TimedEffect timedEffect = new TimedEffect() { EntityID = eid, TimeLeft = 2f, TotalDuration = 2f, }; game.TimedEffectComponent.Add(eid, timedEffect); Sprite sprite = new Sprite() { EntityID = eid, SpriteSheet = game.Content.Load <Texture2D>("Spritesheets/blood"), SpriteBounds = new Rectangle(0, 0, 80, 80), }; game.SpriteComponent.Add(eid, sprite); SpriteAnimation spriteAnimation = new SpriteAnimation() { CurrentAnimationRow = 0, CurrentFrame = 0, EntityID = eid, FramesPerSecond = 20, IsLooping = false, IsPlaying = true, TimePassed = 0f, }; game.SpriteAnimationComponent.Add(eid, spriteAnimation); } uint targetID; float dist; switch (AIBehavior) { case AIBehaviorType.DefaultMelee: updateTargeting(id); if (!enemyAI.HasTarget) { ManageAnimation(id); continue; } MoveTowardTarget(id); targetID = enemyAI.TargetID; game.SkillSystem.EnemyUseBasicMelee(id, targetID, 1, 1); ManageAnimation(id); break; case AIBehaviorType.DefaultRanged: updateTargeting(id); if (!enemyAI.HasTarget) { ManageAnimation(id); continue; } bool onCooldown = false; foreach (CoolDown cd in game.CoolDownComponent.All) { if (cd.Type == SkillType.BasicRangedAttack && cd.UserID == id) { onCooldown = true; break; } } if (onCooldown) { //wait/move random direction continue; } targetID = enemyAI.TargetID; dist = Vector2.Distance(pos.Center, game.PositionComponent[targetID].Center); movement = game.MovementComponent[id]; if (dist > 300) { MoveTowardTarget(id); } else { //movement.Direction = Vector2.Zero; //game.MovementComponent[id] = movement; //Put spritesheets here string spriteSheet; Rectangle spriteBounds; int damage; switch (enemy.Type) { case EnemyType.Sludge5: case EnemyType.Sludge4: spriteSheet = "Spritesheets/Skills/Effects/SludgeShotBig"; spriteBounds = new Rectangle(0, 0, 64, 58); damage = 2; break; case EnemyType.Sludge3: case EnemyType.Sludge2: spriteSheet = "Spritesheets/Skills/Effects/SludgeShotSmall"; spriteBounds = new Rectangle(0, 0, 16, 15); damage = 1; break; default: spriteSheet = "Spritesheets/Skills/Effects/AlienOrb"; spriteBounds = new Rectangle(0, 0, 20, 20); damage = 1; break; } game.SkillSystem.EnemyUseBasicRanged(id, targetID, damage, 3f, spriteSheet, spriteBounds); movement.Direction = new Vector2(rand.Next(20) - 10, rand.Next(20) - 10); movement.Direction = Vector2.Normalize(movement.Direction); game.MovementComponent[id] = movement; } ManageAnimation(id); break; case AIBehaviorType.CloakingRanged: updateTargeting(id); if (!enemyAI.HasTarget) { ManageAnimation(id); continue; } targetID = enemyAI.TargetID; dist = Vector2.Distance(pos.Center, game.PositionComponent[targetID].Center); bool isUsingCloak = false; foreach (Cloak cloak in game.CloakComponent.All) { if (cloak.TargetID == id) { if (cloak.TimeLeft > 2 && cloak.StartingTime - cloak.TimeLeft > 2) { isUsingCloak = true; } break; } } movement = game.MovementComponent[id]; if (!isUsingCloak) { if (dist > 300) { MoveTowardTarget(id); } else { movement.Direction = Vector2.Zero; game.MovementComponent[id] = movement; //game.SkillSystem.EnemyUseSkill(SkillType.SniperShot, id, targetID); game.SkillSystem.EnemyUseBasicRanged(id, targetID, 1, 1f, "Spritesheets/Skills/Effects/AlienOrb", new Rectangle(0, 0, 20, 20)); game.SkillSystem.EnemyUseSkill(SkillType.Cloak, id, id); } } else if (movement.Direction.Equals(Vector2.Zero)) { movement.Direction = new Vector2(rand.Next(20) - 10, rand.Next(20) - 10); movement.Direction = Vector2.Normalize(movement.Direction); game.MovementComponent[id] = movement; } ManageAnimation(id); break; case AIBehaviorType.Spider: updateTargeting(id); if (!enemyAI.HasTarget) { ManageAnimation(id); continue; } MoveTowardTarget(id); targetID = enemyAI.TargetID; dist = Vector2.Distance(pos.Center, game.PositionComponent[targetID].Center); if (dist < 50) { game.SkillSystem.EnemyUseSkill(SkillType.DamagingPull, id, targetID); game.SkillSystem.EnemyUseBasicMelee(id, targetID, 1, 1); } ManageAnimation(id); break; default: break; } } }