ИИ для 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());
}

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 4.333 из 5
Похожие ответы