diff --git a/AirBomber/AirBomber.csproj b/AirBomber/AirBomber.csproj index 13ee123..24f6cce 100644 --- a/AirBomber/AirBomber.csproj +++ b/AirBomber/AirBomber.csproj @@ -23,4 +23,8 @@ + + + + \ No newline at end of file diff --git a/AirBomber/BomberEntity.cs b/AirBomber/BomberEntity.cs deleted file mode 100644 index ddf7de2..0000000 --- a/AirBomber/BomberEntity.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace AirBomber -{ - public class BomberEntity - { - public int Speed { get; private set; } - public double Weight { get; private set; } - public Color BodyColor { get; private set; } - public Color AdditionalColor { get; private set; } - public bool Bombs { get; private set; } - public bool FuelTanks { get; private set; } - public double Step => (double)Speed * 100 / Weight * 5 / 2; - - public void Init(int Speed, double Weight, Color BodyColor, Color AdditionalColor, bool FuelTanks, bool Bombs) - { - this.Speed = Speed; - this.Weight = Weight; - this.BodyColor = BodyColor; - this.AdditionalColor = AdditionalColor; - this.FuelTanks = FuelTanks; - this.Bombs = Bombs; - } - } -} diff --git a/AirBomber/BomberForm.cs b/AirBomber/BomberForm.cs index 92e4316..7dffb5e 100644 --- a/AirBomber/BomberForm.cs +++ b/AirBomber/BomberForm.cs @@ -1,8 +1,10 @@ +using AirBomber.Rendering; + namespace AirBomber { public partial class BomberForm : Form { - private BomberRenderer? _bomberRenderer; + private BomberRendererBase? _bomberRenderer; public BomberForm() { @@ -24,7 +26,7 @@ namespace AirBomber private void ButtonCreate_Click(object sender, EventArgs e) { Random random = new Random(); - _bomberRenderer = new BomberRenderer(); + _bomberRenderer = new BomberRendererBase(); _bomberRenderer.Init( random.Next(100, 300), diff --git a/AirBomber/Entities/BomberEntity.cs b/AirBomber/Entities/BomberEntity.cs new file mode 100644 index 0000000..1eed6a6 --- /dev/null +++ b/AirBomber/Entities/BomberEntity.cs @@ -0,0 +1,17 @@ +namespace AirBomber.Entities +{ + public class BomberEntity : BomberEntityBase + { + public Color AdditionalColor { get; private set; } + public bool Bombs { get; private set; } + public bool FuelTanks { get; private set; } + + public BomberEntity(int Speed, double Weight, Color BodyColor, Color AdditionalColor, bool FuelTanks, bool Bombs) + : base(Speed, Weight, BodyColor) + { + this.AdditionalColor = AdditionalColor; + this.FuelTanks = FuelTanks; + this.Bombs = Bombs; + } + } +} diff --git a/AirBomber/Entities/BomberEntityBase.cs b/AirBomber/Entities/BomberEntityBase.cs new file mode 100644 index 0000000..a7f25d8 --- /dev/null +++ b/AirBomber/Entities/BomberEntityBase.cs @@ -0,0 +1,17 @@ +namespace AirBomber.Entities +{ + public class BomberEntityBase + { + public int Speed { get; private set; } + public double Weight { get; private set; } + public Color BodyColor { get; private set; } + public double Step => (double)Speed * 100 / Weight * 5 / 2; + + public BomberEntityBase(int Speed, double Weight, Color BodyColor) + { + this.Speed = Speed; + this.Weight = Weight; + this.BodyColor = BodyColor; + } + } +} diff --git a/AirBomber/MovementStrategy/AbstractStrategy.cs b/AirBomber/MovementStrategy/AbstractStrategy.cs new file mode 100644 index 0000000..5dc1b9b --- /dev/null +++ b/AirBomber/MovementStrategy/AbstractStrategy.cs @@ -0,0 +1,76 @@ +namespace AirBomber.MovementStrategy +{ + public abstract class AbstractStrategy + { + private IMovableObject? _movableObject; + + private Status _state = Status.NotInit; + + protected int FieldWidth { get; private set; } + protected int FieldHeight { get; private set; } + + public Status GetStatus() { return _state; } + + public void SetData(IMovableObject MovableObject, int Width, int Height) + { + if (MovableObject is null) + { + _state = Status.NotInit; + return; + } + + _state = Status.InProgress; + _movableObject = MovableObject; + + FieldWidth = Width; + FieldHeight = Height; + } + + public void MakeStep() + { + if (_state != Status.InProgress) + return; + + if (IsTargetDestination()) + { + _state = Status.Finish; + return; + } + + MoveToTarget(); + } + + protected bool MoveLeft() => MoveTo(DirectionType.Left); + protected bool MoveRight() => MoveTo(DirectionType.Right); + protected bool MoveUp() => MoveTo(DirectionType.Up); + protected bool MoveDown() => MoveTo(DirectionType.Down); + + protected ObjectParameters? ObjectParameters => _movableObject?.ObjectPosition; + + protected int? GetStep() + { + if (_state != Status.InProgress) + return null; + + return _movableObject?.Step; + } + + protected abstract void MoveToTarget(); + + protected abstract bool IsTargetDestination(); + + private bool MoveTo(DirectionType DirectionType) + { + if (_state != Status.InProgress) + return false; + + if (_movableObject?.CanMove(DirectionType) ?? false) + { + _movableObject.MoveObject(DirectionType); + return true; + } + + return false; + } + } +} diff --git a/AirBomber/DirectionType.cs b/AirBomber/MovementStrategy/DirectionType.cs similarity index 72% rename from AirBomber/DirectionType.cs rename to AirBomber/MovementStrategy/DirectionType.cs index dfc1798..bac5115 100644 --- a/AirBomber/DirectionType.cs +++ b/AirBomber/MovementStrategy/DirectionType.cs @@ -1,4 +1,4 @@ -namespace AirBomber +namespace AirBomber.MovementStrategy { public enum DirectionType { diff --git a/AirBomber/MovementStrategy/IMovableObject.cs b/AirBomber/MovementStrategy/IMovableObject.cs new file mode 100644 index 0000000..160393c --- /dev/null +++ b/AirBomber/MovementStrategy/IMovableObject.cs @@ -0,0 +1,12 @@ +namespace AirBomber.MovementStrategy +{ + public interface IMovableObject + { + ObjectParameters? ObjectPosition { get; } + int Step { get; } + + bool CanMove(DirectionType Direction); + + void MoveObject(DirectionType Direction); + } +} diff --git a/AirBomber/MovementStrategy/MoveToCenterStrategy.cs b/AirBomber/MovementStrategy/MoveToCenterStrategy.cs new file mode 100644 index 0000000..2192f57 --- /dev/null +++ b/AirBomber/MovementStrategy/MoveToCenterStrategy.cs @@ -0,0 +1,44 @@ +namespace AirBomber.MovementStrategy +{ + public class MoveToCenterStrategy : AbstractStrategy + { + protected override bool IsTargetDestination() + { + ObjectParameters? ObjParams = ObjectParameters; + if (ObjParams is null) + return false; + + float FieldMiddleHorizontal = FieldWidth / 2; + float FieldMiddleVertical = FieldHeight / 2; + + return + Math.Abs(ObjParams.ObjectMiddleHorizontal - FieldMiddleHorizontal) < GetStep() && + Math.Abs(ObjParams.ObjectMiddleVertical - FieldMiddleVertical) < GetStep(); + } + + protected override void MoveToTarget() + { + ObjectParameters? ObjParams = ObjectParameters; + if (ObjParams is null) + return; + + float diffX = ObjParams.ObjectMiddleHorizontal - FieldWidth / 2; + if (Math.Abs(diffX) > GetStep()) + { + if (diffX > 0) + MoveLeft(); + else + MoveRight(); + } + + float diffY = ObjParams.ObjectMiddleVertical - FieldHeight / 2; + if (Math.Abs(diffY) > GetStep()) + { + if (diffY > 0) + MoveUp(); + else + MoveDown(); + } + } + } +} diff --git a/AirBomber/MovementStrategy/MoveToDownRightStrategy.cs b/AirBomber/MovementStrategy/MoveToDownRightStrategy.cs new file mode 100644 index 0000000..b858fd7 --- /dev/null +++ b/AirBomber/MovementStrategy/MoveToDownRightStrategy.cs @@ -0,0 +1,43 @@ +namespace AirBomber.MovementStrategy +{ + public class MoveToDownRightStrategy : AbstractStrategy + { + protected override bool IsTargetDestination() + { + ObjectParameters? ObjParams = ObjectParameters; + if (ObjParams is null) + return false; + + return + ObjParams.RightBorder <= FieldWidth && + ObjParams.RightBorder + GetStep() >= FieldWidth && + ObjParams.BottomBorder <= FieldHeight && + ObjParams.BottomBorder + GetStep() >= FieldHeight; + } + + protected override void MoveToTarget() + { + ObjectParameters? ObjParams = ObjectParameters; + if (ObjParams is null) + return; + + float diffX = ObjParams.RightBorder - FieldWidth; + if (Math.Abs(diffX) > GetStep()) + { + if (diffX > 0) + MoveLeft(); + else + MoveRight(); + } + + float diffY = ObjParams.BottomBorder - FieldHeight; + if (Math.Abs(diffY) > GetStep()) + { + if (diffY > 0) + MoveUp(); + else + MoveDown(); + } + } + } +} diff --git a/AirBomber/MovementStrategy/ObjectEntityRenderer.cs b/AirBomber/MovementStrategy/ObjectEntityRenderer.cs new file mode 100644 index 0000000..ff1dba7 --- /dev/null +++ b/AirBomber/MovementStrategy/ObjectEntityRenderer.cs @@ -0,0 +1,36 @@ +using AirBomber.Rendering; + +namespace AirBomber.MovementStrategy +{ + public class ObjectEntityRenderer : IMovableObject + { + private readonly BomberRendererBase? _entityRenderer = null; + + public ObjectEntityRenderer(BomberRendererBase? EntityRenderer) + { + _entityRenderer = EntityRenderer; + } + + public ObjectParameters? ObjectPosition + { + get + { + if (_entityRenderer is null || _entityRenderer.EntityBomber is null) + return null; + + return new ObjectParameters( + _entityRenderer.PosX, + _entityRenderer.PosY, + _entityRenderer.EntityWidth, + _entityRenderer.EntityHeight + ); + } + } + + public int Step => (int)(_entityRenderer?.EntityBomber?.Step ?? 0); + + public bool CanMove(DirectionType Direction) => _entityRenderer?.CanMove(Direction) ?? false; + + public void MoveObject(DirectionType Direction) => _entityRenderer?.MoveEntity(Direction); + } +} diff --git a/AirBomber/MovementStrategy/ObjectParameters.cs b/AirBomber/MovementStrategy/ObjectParameters.cs new file mode 100644 index 0000000..7720875 --- /dev/null +++ b/AirBomber/MovementStrategy/ObjectParameters.cs @@ -0,0 +1,27 @@ +namespace AirBomber.MovementStrategy +{ + public class ObjectParameters + { + private readonly int _x; + private readonly int _y; + + private readonly int _width; + private readonly int _height; + + public int LeftBorder => _x; + public int TopBorder => _y; + public int RightBorder => _x + _width; + public int BottomBorder => _y + _height; + + public int ObjectMiddleHorizontal => _x + _width / 2; + public int ObjectMiddleVertical => _y + _height / 2; + + public ObjectParameters(int X, int Y, int Width, int Height) + { + _x = X; + _y = Y; + _width = Width; + _height = Height; + } + } +} diff --git a/AirBomber/MovementStrategy/Status.cs b/AirBomber/MovementStrategy/Status.cs new file mode 100644 index 0000000..041c7ee --- /dev/null +++ b/AirBomber/MovementStrategy/Status.cs @@ -0,0 +1,9 @@ +namespace AirBomber.MovementStrategy +{ + public enum Status + { + NotInit = 1, + InProgress, + Finish, + } +} diff --git a/AirBomber/Rendering/BomberRenderer.cs b/AirBomber/Rendering/BomberRenderer.cs new file mode 100644 index 0000000..f17a167 --- /dev/null +++ b/AirBomber/Rendering/BomberRenderer.cs @@ -0,0 +1,55 @@ +using AirBomber.Entities; + +namespace AirBomber.Rendering +{ + public class BomberRenderer : BomberRendererBase + { + public BomberRenderer(int Speed, double Weight, Color BodyColor, Color AdditionalColor, bool FuelTanks, bool Bombs, int Width, int Height) + : base(Speed, Weight, BodyColor, Width, Height, 200, 200) + { + if (EntityBomber is not null) + EntityBomber = new BomberEntity(Speed, Weight, BodyColor, AdditionalColor, FuelTanks, Bombs); + } + + public override void DrawEntity(Graphics g) + { + if (EntityBomber is not BomberEntity DerivedEntityBomber) + return; + + base.DrawEntity(g); + + Brush AdditionalBrush = new SolidBrush(DerivedEntityBomber.AdditionalColor); + + /** Отрисовка дополнительных элементов */ + if (DerivedEntityBomber.FuelTanks) + { + Point[] LeftGasTank = { + new Point(_startPosX + 50, _startPosY + 85), + new Point(_startPosX + 75, _startPosY + 85), + new Point(_startPosX + 75, _startPosY + 70), + new Point(_startPosX + 50, _startPosY + 70), + }; + g.FillPolygon(AdditionalBrush, LeftGasTank); + + Point[] RightGasTank = { + new Point(_startPosX + 50, _startPosY + 115), + new Point(_startPosX + 75, _startPosY + 115), + new Point(_startPosX + 75, _startPosY + 130), + new Point(_startPosX + 50, _startPosY + 130), + }; + g.FillPolygon(AdditionalBrush, RightGasTank); + } + + if (DerivedEntityBomber.Bombs) + { + Point LeftBombStartXY = new Point(_startPosX + 110, _startPosY + 115); + Size LeftBombSize = new Size(50, 25); + g.FillEllipse(AdditionalBrush, new Rectangle(LeftBombStartXY, LeftBombSize)); + + Point RightBombStartXY = new Point(_startPosX + 110, _startPosY + 60); + Size RightBombSize = new Size(50, 25); + g.FillEllipse(AdditionalBrush, new Rectangle(RightBombStartXY, RightBombSize)); + } + } + } +} diff --git a/AirBomber/BomberRenderer.cs b/AirBomber/Rendering/BomberRendererBase.cs similarity index 50% rename from AirBomber/BomberRenderer.cs rename to AirBomber/Rendering/BomberRendererBase.cs index e2a7ef0..ae5ceb0 100644 --- a/AirBomber/BomberRenderer.cs +++ b/AirBomber/Rendering/BomberRendererBase.cs @@ -1,33 +1,53 @@ -namespace AirBomber +using AirBomber.Entities; +using AirBomber.MovementStrategy; + +namespace AirBomber.Rendering { - public class BomberRenderer + public class BomberRendererBase { /// /// Класс, отвечающий за прорисовку и перемещение объекта-сущности /// - public BomberEntity? EntityBomber { get; private set; } + public BomberEntityBase? EntityBomber { get; protected set; } private int _pictureWidth; private int _pictureHeight; - private int _startPosX; - private int _startPosY; + protected int _startPosX; + protected int _startPosY; - private readonly int _bomberWidth = 200; - private readonly int _bomberHeight = 200; + protected readonly int _bomberWidth = 200; + protected readonly int _bomberHeight = 200; - public bool Init(int Speed, double Weight, Color BodyColor, Color AdditionalColor, bool FuelTanks, bool Bombs, int Width, int Height) + public int PosX => _startPosX; + public int PosY => _startPosY; + + public int EntityWidth => _bomberWidth; + public int EntityHeight => _bomberHeight; + + public BomberRendererBase(int Speed, double Weight, Color BodyColor, int Width, int Height) { if (Width < _bomberWidth || Height < _bomberHeight) - return false; + return; _pictureWidth = Width; _pictureHeight = Height; - EntityBomber = new BomberEntity(); - EntityBomber.Init(Speed, Weight, BodyColor, AdditionalColor, FuelTanks, Bombs); + EntityBomber = new BomberEntityBase(Speed, Weight, BodyColor); + } - return true; + public BomberRendererBase(int Speed, double Weight, Color BodyColor, int Width, int Height, int EntityWidth, int EntityHeight) + { + if (Width < _bomberWidth || Height < _bomberHeight) + return; + + _pictureWidth = Width; + _pictureHeight = Height; + + _bomberWidth = EntityWidth; + _bomberHeight = EntityHeight; + + EntityBomber = new BomberEntityBase(Speed, Weight, BodyColor); } public void SetPosition(int x, int y) @@ -39,7 +59,7 @@ x = 0; else if (x + _bomberWidth > _pictureWidth) x = _pictureWidth - _bomberWidth; - + _startPosX = x; if (y < 0) @@ -50,56 +70,63 @@ _startPosY = y; } + public bool CanMove(DirectionType direction) + { + if (EntityBomber is null) + return false; + + return direction switch + { + DirectionType.Left => _startPosX - EntityBomber.Step > 0, + DirectionType.Up => _startPosY - EntityBomber.Step > 0, + DirectionType.Right => _startPosX + _bomberWidth + EntityBomber.Step <= _pictureWidth, + DirectionType.Down => _startPosY + _bomberHeight + EntityBomber.Step <= _pictureHeight, + + _ => false, + }; + } + public void MoveEntity(DirectionType Direction) { - if (EntityBomber == null) + if (EntityBomber == null || !CanMove(Direction)) return; switch (Direction) { - case DirectionType.Up: - if (_startPosY - EntityBomber.Step > 0) - _startPosY -= (int)EntityBomber.Step; - - break; - - case DirectionType.Down: - if (_startPosY + _bomberHeight + EntityBomber.Step <= _pictureHeight) - _startPosY += (int)EntityBomber.Step; - - break; - case DirectionType.Left: - if (_startPosX - EntityBomber.Step > 0) - _startPosX -= (int)EntityBomber.Step; + _startPosX -= (int)EntityBomber.Step; + break; + case DirectionType.Up: + _startPosY -= (int)EntityBomber.Step; break; case DirectionType.Right: - if (_startPosX + _bomberWidth + EntityBomber.Step <= _pictureWidth) - _startPosX += (int)EntityBomber.Step; + _startPosX += (int)EntityBomber.Step; + break; + case DirectionType.Down: + _startPosY += (int)EntityBomber.Step; break; } } - - public void DrawEntity(Graphics g) + + public virtual void DrawEntity(Graphics g) { if (EntityBomber == null) return; - Pen pen = new Pen(EntityBomber.BodyColor); + Pen Pen = new Pen(EntityBomber.BodyColor); Brush Brush = new SolidBrush(EntityBomber.BodyColor); - Brush AdditionalBrush = new SolidBrush(EntityBomber.AdditionalColor); /** Отрисовка основной части */ Point[] LeftWing = { new Point(_startPosX + 90, _startPosY), - new Point(_startPosX + 100, _startPosY), - new Point(_startPosX + 108, _startPosY + 85), - new Point(_startPosX + 90, _startPosY + 85), + new Point(_startPosX + 100, _startPosY), + new Point(_startPosX + 108, _startPosY + 85), + new Point(_startPosX + 90, _startPosY + 85), }; - g.DrawPolygon(pen, LeftWing); + g.DrawPolygon(Pen, LeftWing); Point[] RightWing = { new Point(_startPosX + 90, _startPosY + 200), @@ -107,7 +134,7 @@ new Point(_startPosX + 108, _startPosY + 115), new Point(_startPosX + 90, _startPosY + 115), }; - g.DrawPolygon(pen, RightWing); + g.DrawPolygon(Pen, RightWing); Point[] Body = { new Point(_startPosX + 35, _startPosY + 85), @@ -115,7 +142,7 @@ new Point(_startPosX + 200, _startPosY + 115), new Point(_startPosX + 35, _startPosY + 115), }; - g.DrawPolygon(pen, Body); + g.DrawPolygon(Pen, Body); Point[] Nose = { new Point(_startPosX, _startPosY + 100), @@ -130,7 +157,7 @@ new Point(_startPosX + 200, _startPosY + 85), new Point(_startPosX + 170, _startPosY + 85), }; - g.DrawPolygon(pen, BackLeftWing); + g.DrawPolygon(Pen, BackLeftWing); Point[] BackRightWing = { new Point(_startPosX + 170, _startPosY + 130), @@ -138,39 +165,7 @@ new Point(_startPosX + 200, _startPosY + 115), new Point(_startPosX + 170, _startPosY + 115), }; - g.DrawPolygon(pen, BackRightWing); - - - /** Отрисовка дополнительных элементов */ - if (EntityBomber.FuelTanks) - { - Point[] LeftGasTank = { - new Point(_startPosX + 50, _startPosY + 85), - new Point(_startPosX + 75, _startPosY + 85), - new Point(_startPosX + 75, _startPosY + 70), - new Point(_startPosX + 50, _startPosY + 70), - }; - g.FillPolygon(AdditionalBrush, LeftGasTank); - - Point[] RightGasTank = { - new Point(_startPosX + 50, _startPosY + 115), - new Point(_startPosX + 75, _startPosY + 115), - new Point(_startPosX + 75, _startPosY + 130), - new Point(_startPosX + 50, _startPosY + 130), - }; - g.FillPolygon(AdditionalBrush, RightGasTank); - } - - if (EntityBomber.Bombs) - { - Point LeftBombStartXY = new Point(_startPosX + 110, _startPosY + 115); - Size LeftBombSize = new Size(50, 25); - g.FillEllipse(AdditionalBrush, new Rectangle(LeftBombStartXY, LeftBombSize)); - - Point RightBombStartXY = new Point(_startPosX + 110, _startPosY + 60); - Size RightBombSize = new Size(50, 25); - g.FillEllipse(AdditionalBrush, new Rectangle(RightBombStartXY, RightBombSize)); - } + g.DrawPolygon(Pen, BackRightWing); } } }