public void parseLevelFromXML(string fileName) { float worldscale = WorldController.DEFAULT_SCALE; var xml = XDocument.Load(fileName); var height = xml.Root.Element("levelheight").Value; var width = xml.Root.Element("levelwidth").Value; levelHeight = Convert.ToInt32(height); levelWidth = Convert.ToInt32(width); var dragons = from d in xml.Root.Descendants("dragon") select new { X = d.Element("x").Value, Y = d.Element("y").Value }; int temp = 0; foreach (var dragon in dragons) { if (temp == 0) { Dragon playerDragon = new Dragon(dragonTexture, new Vector2((Convert.ToInt32(dragon.X) / worldscale), Convert.ToInt32(dragon.Y) / worldscale), new Vector2(dragonTexture.Width / worldscale, dragonTexture.Height / worldscale), fireBreath); playerDragon.OnFireTexture = dragonOnFireTexture; playerDragon.TurningTexture = dragonTurningTexture; racerList.Add(playerDragon); temp++; } else if (temp == 1) { Dragon playerDragon = new Dragon(enemyTexture1, new Vector2((Convert.ToInt32(dragon.X) / worldscale), Convert.ToInt32(dragon.Y) / worldscale), new Vector2(dragonTexture.Width / worldscale, dragonTexture.Height / worldscale), fireBreath); playerDragon.OnFireTexture = enemy1OnFireTexture; playerDragon.TurningTexture = enemy1TurningTexture; racerList.Add(playerDragon); temp++; } else if (temp == 2) { Dragon playerDragon = new Dragon(enemyTexture2, new Vector2((Convert.ToInt32(dragon.X) / worldscale), Convert.ToInt32(dragon.Y) / worldscale), new Vector2(dragonTexture.Width / worldscale, dragonTexture.Height / worldscale), fireBreath); playerDragon.OnFireTexture = enemy2OnFireTexture; playerDragon.TurningTexture = enemy2TurningTexture; racerList.Add(playerDragon); temp++; } else { Dragon playerDragon = new Dragon(enemyTexture3, new Vector2((Convert.ToInt32(dragon.X) / worldscale), Convert.ToInt32(dragon.Y) / worldscale), new Vector2(dragonTexture.Width / worldscale, dragonTexture.Height / worldscale), fireBreath); playerDragon.OnFireTexture = enemy3OnFireTexture; playerDragon.TurningTexture = enemy3TurningTexture; racerList.Add(playerDragon); temp++; } } var planets = from p in xml.Root.Descendants("planet") select new { Type = p.Element("type").Value, Radius = p.Element("radius").Value, X = p.Element("x").Value, Y = p.Element("y").Value }; foreach (var planet in planets) { PlanetaryObject newPlanet; Vector2 pos = new Vector2(Convert.ToInt32(planet.X) / WorldController.DEFAULT_SCALE, Convert.ToInt32(planet.Y) / WorldController.DEFAULT_SCALE); float radius = Convert.ToSingle(planet.Radius) / WorldController.DEFAULT_SCALE; if (planet.Type == "regular") { newPlanet = new RegularPlanet(regularPlanetTexture, pos, radius); } else if (planet.Type == "gaseous") { newPlanet = new GaseousPlanet(gaseousTexture, pos, radius, flamingTexture, igniteTexture); } else if (planet.Type == "lava") { newPlanet = new LavaPlanet(lavaPlanetTexture, pos, radius); } else { newPlanet = null; } planetList.Add(newPlanet); } var gates = from g in xml.Root.Descendants("gate") select new { Planet1 = g.Element("planet1").Value, Planet2 = g.Element("planet2").Value }; foreach (var gate in gates) { Gate newGate = new Gate(gateTexture, planetList[Convert.ToInt32(gate.Planet1)], planetList[Convert.ToInt32(gate.Planet2)]); gateList.Add(newGate); } IEnumerable <XElement> ais = xml.Root.Descendants("ai"); foreach (XElement ai in ais) { //Debug.Print("ai"); List <Vector2> newAI = new List <Vector2>(); var waypoints = from wp in ai.Descendants("waypoint") select new { x = wp.Element("x").Value, y = wp.Element("y").Value }; foreach (var waypoint in waypoints) { newAI.Add(new Vector2(Convert.ToInt32(waypoint.x), Convert.ToInt32(waypoint.y))); } newAI.Reverse(); aiList.Add(newAI); } var textMessages = from t in xml.Root.Descendants("text") select new { Content = t.Element("content").Value, Start = t.Element("start").Value, End = t.Element("end").Value }; foreach (var textMessage in textMessages) { FloatingText t = new FloatingText(textMessage.Content, Convert.ToInt32(textMessage.Start) / (int)worldscale, Convert.ToInt32(textMessage.End) / (int)worldscale); textList.Add(t); } }
/// <summary> /// This function examines the environment and uses potential fields to determine the AI's next direction to move in /// </summary> /// <param name="gameTime">Snapshot of timing values.</param> /// <returns>Vector2 encoding the next direction this dragon should move in.</returns> public Vector2 GetAction(GameTime gameTime, Dictionary <Dragon, int> gates, bool isPathAI) { // Do not need to recalculate our direction every frame. Just every 10 ticks. if ((racer.Id + gameTime.TotalGameTime.Ticks) % 1 == 0) { if (!isPathAI || aiPath.Count == 0) { //Set the current gates currentGates = gates; //Process the world //ChangeStateIfApplicable(); //Potential fields and computation if (currentGates[racer] != level.Gates.Count) { //Debug.Print("here"); SelectGoal(false); } //MarkGoalTiles(); //move = GetMoveAlongShortestShortestPathToAGoalTile(); List <Vector2> potentials = new List <Vector2>(); potentials.Add(gradientPotentialGoal(racer.Position, GoalPosition(), 1.0f)); //change radius of goal if (currentGates[racer] == 0) { //Debug.Print("" + level.Width); potentials.Add(gradientPotentialEdge(racer.Position, new Vector2(level.Width / 10.0f, level.Height / 20.0f), 1.0f)); } //TODO come up with a way to not loop through all objects AND detect the lava projectiles foreach (PlanetaryObject planet in level.Planets) { PlanetaryObject p1 = null; PlanetaryObject p2 = null; if (goalGate != null) { p1 = goalGate.Planet1; p2 = goalGate.Planet2; } GaseousPlanet gp = null; LavaPlanet lp = null; if (planet is GaseousPlanet) { gp = planet as GaseousPlanet; } if (planet is LavaPlanet) { lp = planet as LavaPlanet; } if (lp != null) { potentials.Add(gradientPotentialLava(racer.Position, planet.Position, planet.Radius)); } else if ((gp == null)) { if (((p1 != null) && (p2 != null)) && ((planet != p1) || (planet != p2))) { potentials.Add(gradientPotentialObstacle(racer.Position, planet.Position, planet.Radius)); } } } Vector2 totalPotential = totalGradientPotential(potentials); goal = Vector2.Normalize(totalPotential); if (currentGates[racer] == level.Gates.Count) { goal = new Vector2(0.0f, 0.0f); } return(goal); //return totalPotential; } //the AI uses a defined path else { currentGates = gates; if (currentGates[racer] != level.Gates.Count) { //Debug.Print("here"); SelectGoal(false); } SelectGoal(true); //Select or change the current goal in the path float distToPath = 15.0f; if (currPath == aiPath.Count - 1) { distToPath = 8.0f; } //ai reached the last waypoint on edge of level so loop back to the original goal if (reachedPath(racer.Position, goalPath, distToPath)) { if (currPath == aiPath.Count - 1) { Debug.Print("" + racer.Id + ": " + currPath + " " + aiPath[currPath]); currPath = 0; } else { //Debug.Print("" + racer.Id + ": " + currPath + " " + aiPath[currPath]); currPath++; } if (((currPath == aiPath.Count - 2) || (currPath == aiPath.Count - 3)) && racer.Position.X >= (level.Width - 100) / 10) { //Debug.Print("here" + racer.Id); currPath = aiPath.Count - 1; } } /*//ai reach the current waypoint and is not at end of level, so increment the waypoint he is on * else if (reachedPath(racer.Position, goalPath, 2.0f)) * { * Debug.Print("close"); * currPath++; * }*/ SelectGoal(true); //have waypoint goal set, so now compute how to get to that goal List <Vector2> potentials = new List <Vector2>(); potentials.Add(gradientPotentialWaypoint(racer.Position, goalPath, 1.0f)); //change radius of goal //potentials.Add(gradientPotentialGoal(racer.Position, GoalPosition(), 1.0f)); //TODO come up with a way to not loop through all objects AND detect the lava projectiles foreach (PlanetaryObject planet in level.Planets) { PlanetaryObject p1 = null; PlanetaryObject p2 = null; if (goalGate != null) { p1 = goalGate.Planet1; p2 = goalGate.Planet2; } GaseousPlanet gp = null; LavaPlanet lp = null; if (planet is GaseousPlanet) { gp = planet as GaseousPlanet; //ADD BACK IN TO REMOVE WAYPOINT IN GAS PLANETS if (gp.OnFire) { foreach (Vector2 waypt in aiPath) { Vector2 pt = waypt; if (gp.Fixture.TestPoint(ref pt)) { Debug.Print("removing waypoint in planet"); aiPath.Remove(waypt); break; } } } } if (planet is LavaPlanet) { lp = planet as LavaPlanet; } if (lp != null) { potentials.Add(gradientWaypointObstacle(racer.Position, planet.Position, planet.Radius)); } else if ((gp == null) || gp.OnFire) { if (((p1 != null) && (p2 != null)) && ((planet != p1) || (planet != p2))) { potentials.Add(gradientWaypointObstacle(racer.Position, planet.Position, planet.Radius)); } } } Vector2 totalPotential = totalGradientPotential(potentials); goal = Vector2.Normalize(totalPotential); if (currentGates[racer] == level.Gates.Count) { goal = new Vector2(0.0f, 0.0f); } return(goal); } } //TODO: Consider adding period fire breath to AI // If we're in front of a gaseous planet or a player then light it on fire /*if (state == FSMState.Attacking && CanShootTargetNow()) * { * action |= ControlCode.Fire; * }*/ return(goal); }