diff --git a/AirBomber/AirBomber/AbstractMap.cs b/AirBomber/AirBomber/AbstractMap.cs index 450c122..ca27fbb 100644 --- a/AirBomber/AirBomber/AbstractMap.cs +++ b/AirBomber/AirBomber/AbstractMap.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -9,6 +10,7 @@ namespace AirBomber internal abstract class AbstractMap { private IDrawningObject _drawningObject = null; + private Bitmap? _staticBitMap; protected int[,] _map = null; protected int _width; protected int _height; @@ -20,6 +22,7 @@ namespace AirBomber public Bitmap CreateMap(int width, int height, IDrawningObject drawningObject) { + _staticBitMap = null; _width = width; _height = height; _drawningObject = drawningObject; @@ -30,10 +33,56 @@ namespace AirBomber } return DrawMapWithObject(); } + + /// Проверяет наличие непроходимых участков в заданной области + /// Заданная область + /// i-ый индекс первого барьера, который был найден в области + /// j-ый индекс первого барьера, который был найден в области + /// Есть ли барьеры + protected bool BarriersInArea(RectangleF area, ref int iBarrier, ref int jBarrier) + { + if (!(0 < area.Left && area.Right < _width && 0 < area.Top && area.Bottom < _height)) + { + return true; // Если область попала за карту, считаем что она столкнулась с барьером + } + int rightArea = (int)Math.Ceiling(area.Right / _size_x); + int bottomArea = (int)Math.Ceiling(area.Bottom / _size_y); + for (int i = (int)(area.Left / _size_x); i < rightArea; i++) + { + for (int j = (int)(area.Top / _size_y); j < bottomArea; j++) + { + if (_map[i, j] == _barrier) + { + iBarrier = i; + jBarrier = j; + return true; + } + } + } + return false; + } + protected bool BarriersInArea(RectangleF area) + { + int a = 0, b = 0; + return BarriersInArea(area, ref a, ref b); + } + + public Bitmap MoveObject(Direction direction) { - // TODO проверка, что объект может переместится в требуемом направлении - if (true) + var rect = _drawningObject.GetCurrentPosition(); + var step = _drawningObject.Step; + // Вычисляем области смещения объекта + RectangleF? area = null; + if (direction == Direction.Left) + area = new(rect.Left - step, rect.Top, step, rect.Height); + else if (direction == Direction.Right) + area = new(rect.Right, rect.Top, step, rect.Height); + else if (direction == Direction.Up) + area = new(rect.Left, rect.Top - step, rect.Width, step); + else if (direction == Direction.Down) + area = new(rect.Left, rect.Bottom, rect.Width, step); + if (area.HasValue && !BarriersInArea(area.Value)) { _drawningObject.MoveObject(direction); } @@ -48,17 +97,37 @@ namespace AirBomber int x = _random.Next(0, 10); int y = _random.Next(0, 10); _drawningObject.SetObject(x, y, _width, _height); - // TODO првоерка, что объект не "накладывается" на закрытые участки - return true; - } - private Bitmap DrawMapWithObject() - { - Bitmap bmp = new(_width, _height); - if (_drawningObject == null || _map == null) + + // Если натыкаемся на барьер помещаем левый верхний угол чуть ниже этого барьера + // если при этом выходим за карту, пермещаем правый нижный угол чуть выше этого барьера + // если объект выходит за карту, генирируем новые координаты рандомно + int currI = 0, currJ = 0; + var areaObject = _drawningObject.GetCurrentPosition(); + int cntOut = 10000; // Количество итераций до выхода из цикла + while (BarriersInArea(areaObject, ref currI, ref currJ) && --cntOut >= 0) { - return bmp; + if ((currJ + 1) * _size_y + areaObject.Height <= _height) + { + areaObject.Location = new PointF((currI + 1) * _size_x, (currJ + 1) * _size_y); + } + else if ((currI - 1) * _size_x - areaObject.Width >= 0) + { + areaObject = new((currI - 1) * _size_x - areaObject.Width, (currJ - 1) * _size_y - areaObject.Height, areaObject.Width, areaObject.Height); + } + else + { + areaObject.Location = new PointF(_random.Next(0, _width - (int)areaObject.Width), + _random.Next(0, _height - (int)areaObject.Height)); + } } - Graphics gr = Graphics.FromImage(bmp); + _drawningObject.SetObject((int)areaObject.X, (int)areaObject.Y, _width, _height); + return cntOut >= 0; + } + private void DrawMap() + { + if (_staticBitMap != null) return; + _staticBitMap = new(_width, _height); + Graphics gr = Graphics.FromImage(_staticBitMap); for (int i = 0; i < _map.GetLength(0); ++i) { for (int j = 0; j < _map.GetLength(1); ++j) @@ -73,6 +142,20 @@ namespace AirBomber } } } + } + + private Bitmap DrawMapWithObject() + { + Bitmap bmp = new(_width, _height); + if (_drawningObject == null || _map == null) + { + return bmp; + } + Graphics gr = Graphics.FromImage(bmp); + if (_staticBitMap == null) + DrawMap(); + if (_staticBitMap != null) + gr.DrawImage(_staticBitMap, 0, 0); _drawningObject.DrawningObject(gr); return bmp; } diff --git a/AirBomber/AirBomber/DrawningAirplane.cs b/AirBomber/AirBomber/DrawningAirplane.cs index 2c2e221..811956e 100644 --- a/AirBomber/AirBomber/DrawningAirplane.cs +++ b/AirBomber/AirBomber/DrawningAirplane.cs @@ -211,9 +211,9 @@ /// Получение текущей позиции объекта /// /// - public (float Left, float Right, float Top, float Bottom) GetCurrentPosition() + public RectangleF GetCurrentPosition() { - return (_startPosX, _startPosY, _startPosX + _airplaneWidth, _startPosY + _airplaneHeight); + return new(_startPosX, _startPosY, _airplaneWidth, _airplaneHeight); } } } \ No newline at end of file diff --git a/AirBomber/AirBomber/DrawningObject.cs b/AirBomber/AirBomber/DrawningObject.cs index af617fb..d79a291 100644 --- a/AirBomber/AirBomber/DrawningObject.cs +++ b/AirBomber/AirBomber/DrawningObject.cs @@ -17,7 +17,7 @@ namespace AirBomber public float Step => _airplane?.Airplane?.Step ?? 0; - public (float Left, float Right, float Top, float Bottom) GetCurrentPosition() + public RectangleF GetCurrentPosition() { return _airplane.GetCurrentPosition(); } diff --git a/AirBomber/AirBomber/FormMap.Designer.cs b/AirBomber/AirBomber/FormMap.Designer.cs index c7b8330..61a199a 100644 --- a/AirBomber/AirBomber/FormMap.Designer.cs +++ b/AirBomber/AirBomber/FormMap.Designer.cs @@ -144,6 +144,7 @@ // // buttonCreateModif // + this.buttonCreateModif.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); this.buttonCreateModif.Location = new System.Drawing.Point(104, 390); this.buttonCreateModif.Name = "buttonCreateModif"; this.buttonCreateModif.Size = new System.Drawing.Size(110, 23); diff --git a/AirBomber/AirBomber/FormMap.resx b/AirBomber/AirBomber/FormMap.resx index 1af7de1..2c0949d 100644 --- a/AirBomber/AirBomber/FormMap.resx +++ b/AirBomber/AirBomber/FormMap.resx @@ -1,64 +1,4 @@ - - - + @@ -117,4 +57,7 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 17, 17 + \ No newline at end of file diff --git a/AirBomber/AirBomber/IDrawningObject.cs b/AirBomber/AirBomber/IDrawningObject.cs index 2b2330c..6077012 100644 --- a/AirBomber/AirBomber/IDrawningObject.cs +++ b/AirBomber/AirBomber/IDrawningObject.cs @@ -38,6 +38,6 @@ namespace AirBomber /// Получение текущей позиции объекта /// /// - (float Left, float Right, float Top, float Bottom) GetCurrentPosition(); + RectangleF GetCurrentPosition(); } }