Compare commits

...

2 Commits

Author SHA1 Message Date
a768d109b5 Финальные правки 2023-11-19 00:10:06 +04:00
530345052e До редактирования формы 2023-11-18 23:42:06 +04:00
16 changed files with 529 additions and 114 deletions

View File

@ -23,4 +23,8 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="MovementStrategy\" />
</ItemGroup>
</Project>

View File

@ -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;
}
}
}

View File

@ -29,11 +29,14 @@
private void InitializeComponent()
{
BomberPictureBox = new PictureBox();
CreateButton = new Button();
ButtonCreateBomberBase = new Button();
ButtonRight = new Button();
ButtonDown = new Button();
ButtonLeft = new Button();
ButtonUp = new Button();
MovementStrategyComboBox = new ComboBox();
ButtonCreateBomber = new Button();
ButtonPerformMove = new Button();
((System.ComponentModel.ISupportInitialize)BomberPictureBox).BeginInit();
SuspendLayout();
//
@ -47,16 +50,16 @@
BomberPictureBox.TabIndex = 0;
BomberPictureBox.TabStop = false;
//
// CreateButton
// ButtonCreateBomberBase
//
CreateButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
CreateButton.Location = new Point(12, 419);
CreateButton.Name = "CreateButton";
CreateButton.Size = new Size(75, 30);
CreateButton.TabIndex = 1;
CreateButton.Text = "Создать";
CreateButton.UseVisualStyleBackColor = true;
CreateButton.Click += ButtonCreate_Click;
ButtonCreateBomberBase.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
ButtonCreateBomberBase.Location = new Point(177, 407);
ButtonCreateBomberBase.Name = "ButtonCreateBomberBase";
ButtonCreateBomberBase.Size = new Size(159, 42);
ButtonCreateBomberBase.TabIndex = 1;
ButtonCreateBomberBase.Text = "Создать бомбардировщик";
ButtonCreateBomberBase.UseVisualStyleBackColor = true;
ButtonCreateBomberBase.Click += ButtonCreateBomberBase_Click;
//
// ButtonRight
//
@ -106,16 +109,52 @@
ButtonUp.UseVisualStyleBackColor = true;
ButtonUp.Click += ButtonMove_Click;
//
// MovementStrategyComboBox
//
MovementStrategyComboBox.Anchor = AnchorStyles.Top | AnchorStyles.Right;
MovementStrategyComboBox.DropDownStyle = ComboBoxStyle.DropDownList;
MovementStrategyComboBox.FormattingEnabled = true;
MovementStrategyComboBox.Items.AddRange(new object[] { "Перемещать в центр", "Перемещать вправо вниз" });
MovementStrategyComboBox.Location = new Point(706, 12);
MovementStrategyComboBox.Name = "MovementStrategyComboBox";
MovementStrategyComboBox.Size = new Size(166, 23);
MovementStrategyComboBox.TabIndex = 6;
//
// ButtonCreateBomber
//
ButtonCreateBomber.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
ButtonCreateBomber.Location = new Point(12, 407);
ButtonCreateBomber.Name = "ButtonCreateBomber";
ButtonCreateBomber.Size = new Size(159, 42);
ButtonCreateBomber.TabIndex = 7;
ButtonCreateBomber.Text = "Создать продвинутый бомбардировщик";
ButtonCreateBomber.UseVisualStyleBackColor = true;
ButtonCreateBomber.Click += ButtonCreateBomber_Click;
//
// ButtonPerformMove
//
ButtonPerformMove.Anchor = AnchorStyles.Top | AnchorStyles.Right;
ButtonPerformMove.Location = new Point(706, 50);
ButtonPerformMove.Name = "ButtonPerformMove";
ButtonPerformMove.Size = new Size(166, 31);
ButtonPerformMove.TabIndex = 8;
ButtonPerformMove.Text = "Сделать шаг";
ButtonPerformMove.UseVisualStyleBackColor = true;
ButtonPerformMove.Click += ButtonPerformStep_Click;
//
// BomberForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(884, 461);
Controls.Add(ButtonPerformMove);
Controls.Add(ButtonCreateBomber);
Controls.Add(MovementStrategyComboBox);
Controls.Add(ButtonUp);
Controls.Add(ButtonLeft);
Controls.Add(ButtonDown);
Controls.Add(ButtonRight);
Controls.Add(CreateButton);
Controls.Add(ButtonCreateBomberBase);
Controls.Add(BomberPictureBox);
Name = "BomberForm";
StartPosition = FormStartPosition.CenterScreen;
@ -128,10 +167,13 @@
#endregion
private PictureBox BomberPictureBox;
private Button CreateButton;
private Button ButtonCreateBomberBase;
private Button ButtonRight;
private Button ButtonDown;
private Button ButtonLeft;
private Button ButtonUp;
private ComboBox MovementStrategyComboBox;
private Button ButtonCreateBomber;
private Button ButtonPerformMove;
}
}

View File

@ -1,8 +1,12 @@
using AirBomber.MovementStrategy;
using AirBomber.Rendering;
namespace AirBomber
{
public partial class BomberForm : Form
{
private BomberRenderer? _bomberRenderer;
private BomberRendererBase? _bomberRenderer;
private AbstractStrategy? _strategy;
public BomberForm()
{
@ -21,12 +25,11 @@ namespace AirBomber
BomberPictureBox.Image = bmp;
}
private void ButtonCreate_Click(object sender, EventArgs e)
private void ButtonCreateBomber_Click(object sender, EventArgs e)
{
Random random = new Random();
_bomberRenderer = new BomberRenderer();
_bomberRenderer.Init(
_bomberRenderer = new BomberRenderer(
random.Next(100, 300),
random.Next(1000, 3000),
Color.FromArgb(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256)),
@ -36,8 +39,26 @@ namespace AirBomber
BomberPictureBox.Width,
BomberPictureBox.Height
);
_bomberRenderer.SetPosition(random.Next(10, 60), random.Next(10, 60));
MovementStrategyComboBox.Enabled = true;
Draw();
}
private void ButtonCreateBomberBase_Click(object sender, EventArgs e)
{
Random random = new Random();
_bomberRenderer = new BomberRendererBase(
random.Next(100, 200),
random.Next(1000, 1800),
Color.FromArgb(random.Next(0, 256), random.Next(0, 256), random.Next(0, 256)),
BomberPictureBox.Width,
BomberPictureBox.Height
);
_bomberRenderer.SetPosition(random.Next(20, 100), random.Next(20, 100));
MovementStrategyComboBox.Enabled = true;
Draw();
}
@ -69,5 +90,45 @@ namespace AirBomber
Draw();
}
private void ButtonPerformStep_Click(object sender, EventArgs e)
{
if (_bomberRenderer is null)
return;
if (MovementStrategyComboBox.Enabled)
{
_strategy = MovementStrategyComboBox.SelectedIndex switch
{
0 => new MoveToCenterStrategy(),
1 => new MoveToDownRightStrategy(),
_ => null,
};
if (_strategy is null)
return;
_strategy.SetData(
new ObjectEntityRenderer(_bomberRenderer),
BomberPictureBox.Width,
BomberPictureBox.Height
);
MovementStrategyComboBox.Enabled = false;
}
if (_strategy is null)
return;
_strategy.MakeStep();
Draw();
if (_strategy.GetStatus() == Status.Finish)
{
MovementStrategyComboBox.Enabled = true;
_strategy = null;
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -1,4 +1,4 @@
namespace AirBomber
namespace AirBomber.MovementStrategy
{
public enum DirectionType
{

View File

@ -0,0 +1,12 @@
namespace AirBomber.MovementStrategy
{
public interface IMovableObject
{
ObjectParameters? ObjectPosition { get; }
int Step { get; }
bool CanMove(DirectionType Direction);
void MoveObject(DirectionType Direction);
}
}

View File

@ -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();
}
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -0,0 +1,9 @@
namespace AirBomber.MovementStrategy
{
public enum Status
{
NotInit = 1,
InProgress,
Finish,
}
}

View File

@ -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));
}
}
}
}

View File

@ -1,33 +1,53 @@
namespace AirBomber
using AirBomber.Entities;
using AirBomber.MovementStrategy;
namespace AirBomber.Rendering
{
public class BomberRenderer
public class BomberRendererBase
{
/// <summary>
/// Класс, отвечающий за прорисовку и перемещение объекта-сущности
/// </summary>
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);
}
}
}