ИИ для 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()); }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д