//compiles the path public List<Coord> GetPath(Coord startPos, Coord endPos, ref Map m) { //round down coords to lock to tiles int startX = (int)(startPos.X); int startY = (int)(startPos.Y); int endX = (int)(endPos.X); int endY = (int)(endPos.Y); //create nodemap Node[,] nodeMap = new Node[m.ObjectMap.GetLength(0), m.ObjectMap.GetLength(1)]; for (int x = 0; x < nodeMap.GetLength(0); x++) { for (int y = 0; y < nodeMap.GetLength(1); y++) { if (m.ObjectMap[x, y] != null) { nodeMap[x, y] = new Node(new Coord(x, y), m.ObjectMap[x, y].collision, new Coord(endX, endY), null); } else { nodeMap[x, y] = new Node(new Coord(x, y), false, new Coord(endX, endY), null); } } } bool success = Search(nodeMap[startX, startY], new Coord(startX, startY), new Coord(endX, endY), ref nodeMap); if (success) { List<Coord> path = new List<Coord>(); Node n = nodeMap[endX, endY]; while (n.parent != null) { path.Add(new Coord(n.location.X + (random.Next(-3, 3) * .1), n.location.Y + (random.Next(-3, 3) * .1))); n = n.parent; } path.Reverse(); return path; } else { //return empty list if search is not successful return new List<Coord>(); } }
//returns true if the entity should shoot public bool UpdateAI(ref Map m, double elapsedTime, Coord player) { //define the triangle within which the character scans List<Coord> triangle = new List<Coord>(); triangle.Add(loc); triangle.Add(new Coord((loc.X + Math.Cos(direction + scanArc) * visionRange), (loc.Y + Math.Sin(direction + scanArc) * visionRange))); triangle.Add(new Coord((loc.X + Math.Cos(direction - scanArc) * visionRange), (loc.Y + Math.Sin(direction - scanArc) * visionRange))); //update timer scanTimer += elapsedTime; if (moveQueue.Count > 0) { //Find the shortest way to turn to the direction it's headed in if (heading - direction <= Math.PI && heading - direction > 0) { Rotate(10 * turnSpeed); if (direction > heading) { direction = heading; } } else if (direction - heading >= -Math.PI && heading - direction <= 0) { Rotate(10 * -turnSpeed); if (direction < heading) { direction = heading; } } if (Move(elapsedTime, moveQueue.Peek())) { Coord temp = new Coord(moveQueue.Peek().X - loc.X, moveQueue.Peek().Y - loc.Y); heading = Math.Atan2(temp.Y, temp.X); moveQueue.Dequeue(); } } else { //if the player is not yet found, pan to look for him and listen for his shots if (!aggro) { if (playerLoc != null) { List<Coord> path = GetPath(loc, playerLoc, ref m); foreach(Coord c in path) { moveQueue.Enqueue(c); } playerLoc = null; } //pan around looking for player if (scanTimer < scanTime / 4) { Rotate(2 * turnSpeed); } else if (scanTimer < scanTime * 3 / 4) { Rotate(-2 * turnSpeed); } else if (scanTimer < scanTime) { Rotate(2 * turnSpeed); } else { scanTimer = 0; } //Pathfinding with sound if (m.sounds.Count > 0) { Coord start = m.sounds[m.sounds.Count - 1]; double dist = Math.Sqrt(Math.Pow(start.X - loc.X, 2) + Math.Pow(start.Y - loc.Y, 2)); if (dist < scanRange) { //find a path to the sound and put it on move queue moveQueue.Clear(); List<Coord> path = GetPath(loc, m.sounds[m.sounds.Count - 1], ref m); foreach (Coord point in path) { moveQueue.Enqueue(point); } } } } else { playerLoc = player; direction = Math.Atan2(player.Y - loc.Y, player.X - loc.X); } } if (IsPointInPolygon(triangle, player)) { aggro = true; if (weapon.CheckFireRate(elapsedTime)) { return true; } else { return false; } } else { aggro = false; return false; } }
//Creates a single riot enemy public static void CreateRiotEnemy(ref List<Enemy> enemies, ContentManager Content, Camera c, Map m, double x, double y, float dir) { enemies.Add(new RiotEnemy(Content, x, y, "NoTexture", PlayerPos.CalcRectangle(c.camPos.X, c.camPos.Y, x, y, m.TileSize, c.xOffset, c.yOffset), dir)); }
//Shoots the player's current gun public static void ShootWeapon(Character player, MouseState mState, MouseState oldMState, List<Projectile> projectiles, bool temp, Camera c, ContentManager Content, Queue<SoundEffect> curSounds, Dictionary<string, SoundEffect> soundEffects, ref Map m) { if (!player.IsMeleeing && !(SkillSystem.skills[2].Active && player.IsSprinting)) { if (player.Weapon.Auto) { if (oldMState.LeftButton == ButtonState.Pressed) { if (temp) { SoundEffect TempSound; //enqueue gunshot sound //only shoot if not a null projectile Projectile p = player.Weapon.Shoot(Content, player, c, m.TileSize, player); if (p != null) { //create new projectile projectiles.Add(p); //load and enqueue sound soundEffects.TryGetValue("gunshot", out TempSound); curSounds.Enqueue(player.Weapon.ShootSound); m.sounds.Add(player.Loc); //add the player's sound to the map's sound queue for AI to detect m.sounds.Add(player.Loc); c.screenShake = true; } else { player.Weapon.Shoot(Content, player, c, m.TileSize, player); //enqueue gun click sound if empty soundEffects.TryGetValue("emptyClick", out TempSound); curSounds.Enqueue(TempSound); } } } } else { if (oldMState.LeftButton == ButtonState.Pressed && mState.LeftButton != ButtonState.Pressed) { if (temp) { if (player.Weapon.Name.Equals("Shotgun")) { SoundEffect TempSound; //enqueue gunshot sound //only shoot if not a null projectile Projectile p = player.Weapon.Shoot(Content, player, c, m.TileSize, player); if (p != null) { player.Weapon.Ammo[0] += 2; Projectile p2 = player.Weapon.Shoot(Content, player, c, m.TileSize, player); Projectile p3 = player.Weapon.Shoot(Content, player, c, m.TileSize, player); projectiles.Add(p); projectiles.Add(p2); projectiles.Add(p3); soundEffects.TryGetValue("shotgunSound.wav", out TempSound); curSounds.Enqueue(player.Weapon.ShootSound); m.sounds.Add(player.Loc); c.screenShake = true; } else { player.Weapon.Shoot(Content, player, c, m.TileSize, player); //enqueue gun click sound if empty soundEffects.TryGetValue("emptyClick", out TempSound); curSounds.Enqueue(TempSound); } } else { SoundEffect TempSound; //enqueue gunshot sound //only shoot if not a null projectile Projectile p = player.Weapon.Shoot(Content, player, c, m.TileSize, player); if (p != null) { projectiles.Add(p); soundEffects.TryGetValue("gunshot", out TempSound); curSounds.Enqueue(player.Weapon.ShootSound); m.sounds.Add(player.Loc); c.screenShake = true; } else { player.Weapon.Shoot(Content, player, c, m.TileSize, player); //enqueue gun click sound if empty soundEffects.TryGetValue("emptyClick", out TempSound); curSounds.Enqueue(TempSound); } } } } } } }
//Creates a single normal enemy public static void CreateNormalEnemy(ref List<Enemy> enemies, ContentManager Content, Camera c, Map m, double x, double y, float dir) { Enemy e = new Enemy(Content, x, y, "NoTexture", PlayerPos.CalcRectangle(c.camPos.X, c.camPos.Y, x, y, m.TileSize, c.xOffset, c.yOffset), dir); e.EntTexture = Content.Load<Texture2D>("Enemy" + rng.Next(1, 4)); enemies.Add(e); }