Human AI with pathfinding and room hazard avoidance

This commit is contained in:
Regalis
2015-11-23 01:22:38 +02:00
parent 77024a31fb
commit c456fa3c90
32 changed files with 665 additions and 126 deletions
@@ -9,6 +9,8 @@ namespace Barotrauma
{
protected List<AIObjective> subObjectives;
protected float priority;
public virtual bool IsCompleted()
{
return false;
@@ -21,7 +23,7 @@ namespace Barotrauma
/// <summary>
/// makes the character act according to the objective, or according to any subobjectives that
/// need to be completed before this one (starting from the one with the highest priority)
/// need to be completed before this one
/// </summary>
/// <param name="character">the character who's trying to achieve the objective</param>
public void TryComplete(float deltaTime, Character character)
@@ -38,5 +40,15 @@ namespace Barotrauma
}
protected virtual void Act(float deltaTime, Character character) { }
public virtual float GetPriority(Character character)
{
return 0.0f;
}
public virtual bool IsDuplicate(AIObjective otherObjective)
{
return true;
}
}
}
@@ -0,0 +1,89 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Barotrauma
{
class AIObjectiveFindSafety : AIObjective
{
const float SearchHullInterval = 1.0f;
const float MinSafety = 50.0f;
AIObjectiveGoTo gotoObjective;
float currenthullSafety;
float searchHullTimer;
protected override void Act(float deltaTime, Character character)
{
if (character.AnimController.CurrentHull == null || GetHullSafety(character.AnimController.CurrentHull) > MinSafety)
{
character.AIController.SteeringManager.SteeringSeek(character.AnimController.CurrentHull.Position);
gotoObjective = null;
return;
}
if (searchHullTimer>0.0f)
{
searchHullTimer -= deltaTime;
return;
}
searchHullTimer = SearchHullInterval;
Hull bestHull = null;
float bestValue = currenthullSafety;
foreach (Hull hull in Hull.hullList)
{
if (hull == character.AnimController.CurrentHull) continue;
float hullValue = GetHullSafety(hull);
hullValue -= (float)Math.Sqrt(Math.Abs(character.Position.X- hull.Position.X));
hullValue -= (float)Math.Sqrt(Math.Abs(character.Position.Y - hull.Position.Y)*2.0f);
if (bestHull==null || hullValue > bestValue)
{
bestHull = hull;
bestValue = hullValue;
}
}
if (bestHull != null)
{
gotoObjective = new AIObjectiveGoTo(bestHull.AiTarget, character);
//character.AIController.SelectTarget(bestHull.AiTarget);
}
gotoObjective.TryComplete(deltaTime, character);
}
public override float GetPriority(Character character)
{
if (character.AnimController.CurrentHull == null) return 0.0f;
currenthullSafety = GetHullSafety(character.AnimController.CurrentHull);
priority = 100.0f - currenthullSafety;
return priority;
}
private float GetHullSafety(Hull hull)
{
float waterPercentage = (hull.Volume / hull.FullVolume)*100.0f;
float fireAmount = 0.0f;
foreach (FireSource fireSource in hull.FireSources)
{
fireAmount += fireSource.Size.X;
}
float safety = 100.0f - fireAmount - waterPercentage;
if (hull.OxygenPercentage < 30.0f) safety -= (30.0f-hull.OxygenPercentage)*3.0f;
return safety;
}
}
}
@@ -0,0 +1,33 @@
using Barotrauma.Items.Components;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Barotrauma
{
class AIObjectiveGoTo : AIObjective
{
AITarget target;
private Character character;
public AIObjectiveGoTo(AITarget target, Character character)
{
this.character = character;
this.target = target;
}
protected override void Act(float deltaTime, Character character)
{
if (target == null) return;
character.AIController.SelectTarget(target);
character.AIController.SteeringManager.SteeringSeek(ConvertUnits.ToDisplayUnits(target.Position));
}
}
}
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Barotrauma
{
class AIObjectiveManager
{
private List<AIObjective> objectives;
private Character character;
public AIObjectiveManager(Character character)
{
this.character = character;
objectives = new List<AIObjective>();
}
public void AddObjective(AIObjective objective)
{
if (objectives.Find(o => o.IsDuplicate(objective)) != null) return;
objectives.Add(objective);
}
public void UpdateObjectives()
{
if (!objectives.Any()) return;
//remove completed objectives
objectives = objectives.FindAll(o => !o.IsCompleted());
//sort objectives according to priority
objectives.Sort((x, y) => x.GetPriority(character).CompareTo(y.GetPriority(character)));
}
public void DoCurrentObjective(float deltaTime)
{
if (!objectives.Any()) return;
objectives[0].TryComplete(deltaTime, character);
}
}
}
@@ -18,5 +18,13 @@ namespace Barotrauma
{
//item.AIOperate(float deltaTime, Character character) or something
}
public override bool IsDuplicate(AIObjective otherObjective)
{
AIObjectiveOperateItem operateItem = otherObjective as AIObjectiveOperateItem;
if (operateItem == null) return false;
return (operateItem.targetItem == targetItem);
}
}
}