ИИ для 2D игры - C#
Формулировка задачи:
Требовалось понять, не мешают ли стены (элементы world != 2) одному персонажу видеть другого. Решил делать через уравнение прямой y = k*x + b, в итоге видит через стены, за неделю так и не понял в чем проблема. plx,ply - координаты одного персонажа, x,y - другого.
Листинг программы
- private bool FOV(int plx, int ply)
- {
- if (x == plx)k = 0;
- else k = (Convert.ToDouble(y - ply) / Convert.ToDouble(x - plx));
- if (k > 0 ) b = System.Math.Min(ply, y);
- else b = System.Math.Max(ply, y);
- int i = System.Math.Min(plx, x);
- do // Выполнить хоть раз
- {
- if (k > -1)
- {
- for (int j = Convert.ToInt32(k * (i) + b); j < Convert.ToInt32(k * (i+1) + b); j++)
- {
- if (world[i, b + j] != 2) return false;
- }
- }
- else for (int j = Convert.ToInt32(k * (i) + b); j > Convert.ToInt32(k * (i + 1) + b); j--)
- {
- if (world[i, b + j] != 2) return false;
- }
- ++i;
- } while (i < System.Math.Max(plx, x)) ;
- return true;
Решение задачи: «ИИ для 2D игры»
textual
Листинг программы
- class FloatComparer : IComparer<float>
- {
- private float Epsilon = 1e-6f;
- public int Compare(float x, float y)
- {
- if (Math.Abs(x - y) < Epsilon)
- return 0;
- return x < y ? -1 : 1;
- }
- }
- // Центром системы координат считается центр клетки мира (0; 0)
- // Размер клеток - 1x1
- class CellsEnumerator
- {
- // Возвращает клетки, пересекающиеся с отрезком [first; second]
- public IEnumerable<Point> GetCellsBetween(PointF first, PointF second)
- {
- if (first.X > second.X)
- {
- var temp = first;
- first = second;
- second = temp;
- }
- float left = first.X;
- float right = second.X;
- // В случае попадания в одну вертикаль мира, разведём точки в стороны
- if ((int)Math.Floor(left + 0.5) == (int)Math.Floor(right + 0.5))
- {
- left = (float)Math.Floor(left + 0.5) - 0.5f + 0.1f;
- right = left + 0.8f;
- }
- float bottom = Math.Min(first.Y, second.Y);
- float top = Math.Max(first.Y, second.Y);
- // Строим уравнение прямой y = kx + b, содержащий отрезкок
- float k = (second.Y - first.Y) / (right - left);
- float b = first.Y - k * left;
- var xLines = GetBorderLinesBetween(left, right).ToArray();
- var yLines = GetBorderLinesBetween(bottom, top).ToArray();
- var result = new List<Point>();
- var nodes = new List<PointF>();
- foreach (var x in xLines)
- {
- float y = x * k + b;
- if (_comparer.Compare(y, (float)Math.Floor(y) + 0.5f) == 0)
- {
- nodes.Add(new PointF(x, y));
- continue;
- }
- int cellX = (int)Math.Floor(x + 0.6);
- int cellY = (int)Math.Floor(y + 0.5);
- result.Add(new Point(cellX, cellY));
- result.Add(new Point(cellX - 1, cellY));
- }
- foreach (var y in yLines)
- {
- float x = (y - b) / k;
- if (_comparer.Compare(x, (float)Math.Floor(x) + 0.5f) == 0)
- {
- nodes.Add(new PointF(x, y));
- continue;
- }
- int cellX = (int)Math.Floor(x + 0.5);
- int cellY = (int)Math.Floor(y + 0.6);
- result.Add(new Point(cellX, cellY));
- result.Add(new Point(cellX, cellY - 1));
- }
- foreach (var node in nodes.Distinct())
- {
- var leftBottomX = (int)Math.Floor(node.X + 0.5 - 0.1);
- var leftBottomY = (int)Math.Floor(node.Y + 0.5 - 0.1);
- for (int dx = 0; dx < 2; dx++)
- for (int dy = 0; dy < 2; dy++)
- result.Add(new Point(leftBottomX + dx, leftBottomY + dy));
- }
- return result.Distinct();
- }
- private IEnumerable<float> GetBorderLinesBetween(float min, float max)
- {
- var x = (float)Math.Ceiling(min + 0.5) - 0.5f;
- while (_comparer.Compare(x, max) < 0)
- yield return x++;
- }
- private readonly FloatComparer _comparer = new FloatComparer();
- };
- class MainForm : Form
- {
- PointF first = PointF.Empty;
- PointF second = PointF.Empty;
- List<Point> cells = new List<Point>();
- public MainForm()
- {
- var tb = new TextBox { Parent = this };
- var enumerator = new CellsEnumerator();
- tb.TextChanged += (_, __) =>
- {
- float[] numbers;
- try
- {
- numbers = Regex.Split(tb.Text, @"\s")
- .Select(word => float.Parse(word, CultureInfo.InvariantCulture))
- .ToArray();
- if (numbers.Length == 4)
- {
- first = new PointF(numbers[0], numbers[1]);
- second = new PointF(numbers[2], numbers[3]);
- cells = enumerator.GetCellsBetween(first, second).ToList();
- Invalidate();
- }
- }
- catch (FormatException) { }
- };
- tb.Text = "0 0 1 1";
- }
- protected override void OnPaint(PaintEventArgs e)
- {
- e.Graphics.TranslateTransform(10, 220);
- e.Graphics.ScaleTransform(20, -20);
- e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
- for (float x = -0.5f; x < 10.5f; x++)
- e.Graphics.DrawLine(new Pen(Color.Green, 0.05f), x, -0.5f, x, 9.5f);
- for (float y = -0.5f; y < 10.5f; y++)
- e.Graphics.DrawLine(new Pen(Color.Green, 0.05f), -0.5f, y, 9.5f, y);
- foreach (var cell in cells)
- {
- e.Graphics.DrawRectangle(new Pen(Color.Blue, 0.05f), cell.X - 0.5f, cell.Y - 0.5f, 1, 1);
- }
- e.Graphics.DrawLine(new Pen(Color.Red, 0.05f), first, second);
- }
- }
- void Main()
- {
- new CellsEnumerator().GetCellsBetween(new PointF(0, 0), new PointF(0, 1)).Dump();
- Application.Run(new MainForm());
- }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д