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