From ced3d03bdb3ce866d832e03fb212865140905a9a Mon Sep 17 00:00:00 2001 From: Thomas Leyh Date: Sun, 24 Jul 2016 08:14:18 +0200 Subject: Add project files. --- V3/Objects/Selection.cs | 483 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 483 insertions(+) create mode 100644 V3/Objects/Selection.cs (limited to 'V3/Objects/Selection.cs') diff --git a/V3/Objects/Selection.cs b/V3/Objects/Selection.cs new file mode 100644 index 0000000..4ec7ccc --- /dev/null +++ b/V3/Objects/Selection.cs @@ -0,0 +1,483 @@ +using System; +using System.Collections.Generic; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Audio; +using Microsoft.Xna.Framework.Content; +using Microsoft.Xna.Framework.Graphics; +using V3.Data; +using V3.Effects; + +namespace V3.Objects +{ + /// + /// Class for selecting creatures, holding the selection and drawing the selection rectangle on the screen. + /// + // ReSharper disable once ClassNeverInstantiated.Global + public sealed class Selection + { + private IObjectsManager mObjectsManager; + private IEffectsManager mEffectsManager; + private readonly Color mColor = Color.Black; + private Texture2D mTexture; + public List SelectedCreatures { get; private set; } = new List(); + private List TransformList { get; } = new List(); + private readonly CreatureFactory mCreatureFactory; + private int mDeadBodies; + private int mExplosionDeaths; + private Ellipse NecroArea { get; set; } + public Rectangle LastSelection { get; private set; } + private SoundEffect mSoundEffect; + private SoundEffectInstance mSoundEffectInstance; + private IOptionsManager mOptionsManager; + private AchievementsAndStatistics mAchievementsAndStatistics; + + public Selection(ContentManager contentManager, CreatureFactory creatureFactory, IObjectsManager objectsManager, + IEffectsManager effectsManager, IOptionsManager optionsmanager, AchievementsAndStatistics achievementsAndStatistics) + { + mCreatureFactory = creatureFactory; + mObjectsManager = objectsManager; + mEffectsManager = effectsManager; + mOptionsManager = optionsmanager; + mAchievementsAndStatistics = achievementsAndStatistics; + LoadContent(contentManager); + } + + private void LoadContent(ContentManager contentManager) + { + mTexture = contentManager.Load("Sprites/WhiteRectangle"); + mSoundEffect = contentManager.Load("Sounds/zonk2"); + mSoundEffectInstance = mSoundEffect.CreateInstance(); + } + + /// + /// Select all objects in the area of the rectangle between origin and destination. + /// + /// Position in pixels where the mouse button was pressed down. + /// Position in pixels where the mouse button was released. + public void Select(Point origin, Point destination) + { + // Clean last selection + SelectedCreatures.ForEach(e => e.IsSelected=false); + SelectedCreatures.Clear(); + + // New selection + int x, y, width, height; + if (origin.X > destination.X) + { + x = destination.X; + width = origin.X - destination.X; + } + else + { + x = origin.X; + width = destination.X - origin.X; + } + if (origin.Y > destination.Y) + { + y = destination.Y; + height = origin.Y - destination.Y; + } + else + { + y = origin.Y; + height = destination.Y - origin.Y; + } + + // Creates area for necromancer + var necroPos = mObjectsManager.PlayerCharacter; + NecroArea = new Ellipse(new Vector2((int)necroPos.Position.X, (int)necroPos.Position.Y), 1280, 640); + + // List for all objects in the current selection + LastSelection = new Rectangle(x, y, width, height); + var selectedObjects = mObjectsManager.GetObjectsInRectangle(LastSelection); + + // Lists to seperate undead from enemy creatures + var enemyCreatures = new List(); + var undeadCreatures = new List(); + + foreach (var obj in selectedObjects) + { + var creature = obj as ICreature; + // Give priority when selecting undead creatures. + if (creature != null && !creature.IsDead && LastSelection.Intersects(creature.SelectionRectangle) && NecroArea.Contains(creature.Position)) + { + if (creature.Faction != Faction.Undead) + { + enemyCreatures.Add(creature); + } + else + { + undeadCreatures.Add(creature); + } + } + } + SelectedCreatures = undeadCreatures.Count == 0 ? enemyCreatures : undeadCreatures; + + // Make all selectable creatures selected + foreach (var selectedCreature in SelectedCreatures) + { + selectedCreature.IsSelected = true; + } + } + + /// + /// Draw the selection rectangle on the screen. + /// + /// Sprite batch used. + /// Position in pixels where the mouse button was pressed down. + /// Position in pixels where the mouse button was released. + public void Draw(SpriteBatch spriteBatch, Point origin, Point destination) + { + if (origin.X > destination.X) + { + spriteBatch.Draw(mTexture, new Rectangle(destination.X, origin.Y, origin.X - destination.X, 2), mColor); + spriteBatch.Draw(mTexture, new Rectangle(destination.X, destination.Y, origin.X - destination.X, 2), mColor); + } + else + { + spriteBatch.Draw(mTexture, new Rectangle(origin.X, origin.Y, destination.X - origin.X, 2), mColor); + spriteBatch.Draw(mTexture, new Rectangle(origin.X, destination.Y, destination.X - origin.X, 2), mColor); + } + if (origin.Y > destination.Y) + { + spriteBatch.Draw(mTexture, new Rectangle(origin.X, destination.Y, 2, origin.Y - destination.Y), mColor); + spriteBatch.Draw(mTexture, new Rectangle(destination.X, destination.Y, 2, origin.Y - destination.Y), mColor); + } + else + { + spriteBatch.Draw(mTexture, new Rectangle(origin.X, origin.Y, 2, destination.Y - origin.Y), mColor); + spriteBatch.Draw(mTexture, new Rectangle(destination.X, origin.Y, 2, destination.Y - origin.Y), mColor); + } + } + + /// + /// Press 1 to trigger the specialattack of the meatball + /// All non undead creatures at the distance of 200 pixels take damage + /// After the attack the meatball disappears and three zombies will be created + /// + public void Specialattack() + { + foreach (var creature in SelectedCreatures) + { + var meatball = creature as Meatball; + if (meatball != null) + { + // Creates radius for meatballs explosion + var explosionRadius = new Rectangle((int)meatball.Position.X - 200, (int)meatball.Position.Y - 200, 400, 400); + var objectsInMeatballArea = mObjectsManager.GetObjectsInRectangle(explosionRadius); + + // Plays sounds and effects + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(0.5d)); + mEffectsManager.PlayOnce(new Explosion(), meatball.Position.ToPoint(), explosionRadius.Size * new Point(3, 2)); + + // All attackable creatures take damage (own undead creatures won't take damage) + foreach (var attackable in objectsInMeatballArea) + { + var toAttack = attackable as ICreature; + if (toAttack != null && toAttack.Faction != Faction.Undead) + { + toAttack.TakeDamage(meatball.Attack); + if (toAttack.IsDead) + mExplosionDeaths += 1; + } + } + + if (mExplosionDeaths >= 10) + mAchievementsAndStatistics.mKaboom = true; + mExplosionDeaths = 0; + + // The new zombies after explosion + var zombie1 = mCreatureFactory.CreateZombie(meatball.Position, meatball.MovementDirection); + var zombie2 = mCreatureFactory.CreateZombie(new Vector2(meatball.Position.X + 50, meatball.Position.Y + 50), meatball.MovementDirection); + var zombie3 = mCreatureFactory.CreateZombie(new Vector2(meatball.Position.X - 50, meatball.Position.Y - 50), meatball.MovementDirection); + + // Makes zombies be selected after explosion + zombie1.IsSelected = true; + zombie2.IsSelected = true; + zombie3.IsSelected = true; + meatball.IsSelected = false; + SelectedCreatures.Add(zombie1); + SelectedCreatures.Add(zombie2); + SelectedCreatures.Add(zombie3); + SelectedCreatures.Remove(meatball); + + // Remove meatball from game + mObjectsManager.RemoveCreature(meatball); + + // Add zombies to game + mObjectsManager.CreateCreature(zombie1); + mObjectsManager.CreateCreature(zombie2); + mObjectsManager.CreateCreature(zombie3); + + // For every zombie the necromancer gets healed + var heal = mObjectsManager.PlayerCharacter.Life * 0.12; + mObjectsManager.PlayerCharacter.Heal((int)heal); + + break; + } + } + } + + /// + /// Press 2 to create zombies from dead bodies + /// At least one dead body should be in necromancers area + /// + public void TransformZombie() + { + // Creates area for necromancer + var necroPos = mObjectsManager.PlayerCharacter; + NecroArea = new Ellipse(new Vector2((int) necroPos.Position.X, (int) necroPos.Position.Y), 1280, 640); + + // Get all creatures in necromancers area + var necroArea = mObjectsManager.GetCreaturesInEllipse(NecroArea); + + // Every dead body in necromancer area will be transformed to an zombie + // The prince will be transformed to an elite zombie + foreach (var creature in necroArea) + { + if (creature.Faction == Faction.Plebs || creature.Faction == Faction.Kingdom) + { + if (creature.IsDead) + { + ICreature zombie; + if (creature is KingsGuard || creature is King || creature is Prince) + zombie = mCreatureFactory.CreateSkeletonElite(creature.Position, creature.MovementDirection); + else + zombie = mCreatureFactory.CreateZombie(creature.Position, creature.MovementDirection); + + // Add zombie to game + mObjectsManager.CreateCreature(zombie); + + // Remove dead body from game + mObjectsManager.RemoveCreature(creature); + + // Play sounds and effects + mEffectsManager.PlayOnce(new BloodBang(), zombie.Position.ToPoint(), new Point(128)); + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, + TimeSpan.FromSeconds(0.5d)); + + // The number of dead bodies + mDeadBodies++; + + // For every zombie the necromancer gets healed + var heal = mObjectsManager.PlayerCharacter.Life * 0.04; + mObjectsManager.PlayerCharacter.Heal((int)heal); + } + } + } + + // Counts dead bodies in necromancers area and undead creatures + var set = mDeadBodies + mObjectsManager.UndeadCreatures.Count; + if (mObjectsManager.InGraveyardArea(mObjectsManager.PlayerCharacter) && set < 6) + { + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(0.5d)); + for (int i = 1; i <= 6 - set; i++) + { + var positionX = mObjectsManager.PlayerCharacter.Position.X + (float)Math.Sin(i) * 75; + var positionY = mObjectsManager.PlayerCharacter.Position.Y + (float)Math.Cos(i) * 75; + var zombie = mCreatureFactory.CreateZombie(new Vector2(positionX, positionY), mObjectsManager.PlayerCharacter.MovementDirection); + mObjectsManager.CreateCreature(zombie); + zombie.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(1)); + } + } + mDeadBodies = 0; + } + + /// + /// Press 3 to create a meatball in exchange for five zombie + /// At least five zombies should be selected + /// + public void TransformMeatball() + { + // The cost for this transformation + var cost = mObjectsManager.PlayerCharacter.MaxLife * 0.12; + + // Transform only when necromancer life minus the transformations cost is not lower than 1 + if (mObjectsManager.PlayerCharacter.Life - (int)cost >= 1) + { + // Puts all zombies in a seperate list called TransformList + foreach (var creature in SelectedCreatures) + { + var zombie = creature as Zombie; + if (zombie != null && TransformList.Count < 5) + { + TransformList.Add(zombie); + } + } + + // Creates the meatball and makes him selected + if (TransformList.Count >= 5) + { + // Delete zombies from game and SelectedCratures + foreach (var zombie in TransformList) + { + SelectedCreatures.Remove(zombie); + mObjectsManager.RemoveCreature(zombie); + } + + // Add meatball to game + // Position will be randomly chosen from one of the zombies + var randomNumber = new Random(); + var positionMeatball = randomNumber.Next(5); + var meatball = mCreatureFactory.CreateMeatball(TransformList[positionMeatball].Position, + TransformList[positionMeatball].MovementDirection); + meatball.IsSelected = true; + SelectedCreatures.Add(meatball); + mObjectsManager.CreateCreature(meatball); + + // Plays sounds and effects + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(0.5d)); + mEffectsManager.PlayOnce(new BloodExplosion(), meatball.Position.ToPoint(), new Point(256)); + + // Necromancer takes damage + mObjectsManager.PlayerCharacter.TakeDamage((int)cost); + } + TransformList.Clear(); + } + else + { + // Play sound when transformation not possible + mSoundEffectInstance.Volume = mOptionsManager.Options.GetEffectiveVolume(); + mSoundEffectInstance.Play(); + } + } + + + /// + /// Press 4 to create an skeleton in exchange for an zombie + /// At least one zombie should be selected + /// + public void TransformSkeleton() + { + // Iterates through SelectedCreatures and takes the first zombie + foreach (var creature in SelectedCreatures) + { + var zombie = creature as Zombie; + if (zombie != null) + { + // Delete zombie + SelectedCreatures.Remove(zombie); + mObjectsManager.RemoveCreature(zombie); + + // Add skeleton + var skeleton = mCreatureFactory.CreateSkeleton(zombie.Position, zombie.MovementDirection); + skeleton.IsSelected = true; + SelectedCreatures.Add(skeleton); + mObjectsManager.CreateCreature(skeleton); + + // Plays sounds and effects + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(0.5d)); + mEffectsManager.PlayOnce(new BloodFountain(), zombie.Position.ToPoint() - new Point(0, 64), new Point(128)); + + break; + } + } + } + + /// + /// Press 5 to create an skeletonhorse in exchange for three skeletons + /// At least three skeletons should be selected + /// + public void TransformSkeletonHorse() + { + // The cost for this transformation + var cost = mObjectsManager.PlayerCharacter.MaxLife * 0.06; + + // Transform only when necromancer life minus the transformations cost is not lower than 1 + if (mObjectsManager.PlayerCharacter.Life - (int)cost >= 1) + { + + // Puts all skeletons in a seperate list called TransformList + foreach (var creature in SelectedCreatures) + { + var skeleton = creature as Skeleton; + if (skeleton != null && TransformList.Count < 3) + { + TransformList.Add(skeleton); + } + } + + // Creates the skeletonhorse and makes him selected + if (TransformList.Count >= 3) + { + // Delete zombies from game and SelectedCratures + foreach (var skeleton in TransformList) + { + SelectedCreatures.Remove(skeleton); + mObjectsManager.RemoveCreature(skeleton); + } + + // Add skeletonhorse to game + // Position will be randomly chosen from one of the skeletons + var randomNumber = new Random(); + var positionHorse = randomNumber.Next(3); + var skeletonHorse = mCreatureFactory.CreateSkeletonHorse(TransformList[positionHorse].Position, + TransformList[positionHorse].MovementDirection); + skeletonHorse.IsSelected = true; + SelectedCreatures.Add(skeletonHorse); + mObjectsManager.CreateCreature(skeletonHorse); + + // Plays sounds and effects + mObjectsManager.PlayerCharacter.PlayAnimationOnce(MovementState.Special, TimeSpan.FromSeconds(0.5d)); + mEffectsManager.PlayOnce(new HorseEffect(), skeletonHorse.Position.ToPoint() - new Point(0, 16), new Point(128)); + + + // Necromancer takes damage + mObjectsManager.PlayerCharacter.TakeDamage((int)cost); + } + TransformList.Clear(); + } + else + { + // Play sound when transformation not possible + mSoundEffectInstance.Volume = mOptionsManager.Options.GetEffectiveVolume(); + mSoundEffectInstance.Play(); + } + } + + /// + /// If creature leaves area og the necromancer, he gets disselected + /// + public void UpdateSelection() + { + // Creates area for necromancer + var necroPos = mObjectsManager.PlayerCharacter; + NecroArea = new Ellipse(new Vector2((int)necroPos.Position.X, (int)necroPos.Position.Y), 1280, 640); + + foreach (var creature in SelectedCreatures) + { + if (!NecroArea.Contains(creature.Position) || creature.IsDead) + creature.IsSelected = false; + } + + if (mObjectsManager.AddToSelectables.Count > 0) + { + SelectedCreatures.Add(mObjectsManager.AddToSelectables[0]); + mObjectsManager.AddToSelectables.Clear(); + } + } + + /// + /// Give movement command to selected creatures. + /// + /// Desired destination in pixels. + public void Move(Vector2 destination) + { + if (SelectedCreatures.Count == 0) return; + var centreCreature = SelectedCreatures[0]; + // You can not move enemy creatures. + if (centreCreature.Faction != Faction.Undead) return; + centreCreature.Move(destination); + + for (int i = 1; i < SelectedCreatures.Count; i++) + { + Vector2 flockDestination = destination; + Vector2 distance = centreCreature.Position - SelectedCreatures[i].Position; + distance.Normalize(); + distance *= 70; + flockDestination -= distance; + SelectedCreatures[i].Move(flockDestination); + } + } + } +} -- cgit v1.2.1