Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
4.0 kB
2
Indexable
Never
using System;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;

namespace Game.World.Views.Spreads.Jobs
{
    [BurstCompile]
    public struct CreateGradationMapJob : IJob
    {
        public NativeArray<int> GradationMap;
        public int Gradations;
        public int Width;
        public int Height;

        public NativeArray<bool> Filled;
        public NativeList<int> PointQueue;

        private int _pixelsCount;
        private int _filledCount;
        private int _pixelsPerColor;
        private NativeArray<int> _remaining;
        private Unity.Mathematics.Random _random;

        public void Execute()
        {
            _random = new Unity.Mathematics.Random((uint)Environment.TickCount);
            _pixelsCount = Width * Height;
            _pixelsPerColor = _pixelsCount / Gradations;
            _filledCount = 0;
            _remaining = new NativeArray<int>(Gradations, Allocator.Temp);
            for (int i = 0; i < Gradations; i++)
            {
                _remaining[i] = _pixelsPerColor;
            }

            for (int gradation = 0; gradation < Gradations; gradation++)
            {
                int startX = _random.NextInt(0, Width);
                int startY = _random.NextInt(0, Height);
                FillCircle(startX, startY, gradation);
            }
        }

        private void FillCircle(int startX, int startY, int gradation)
        {
            PointQueue.Clear();
            PointQueue.Add(startX + startY * Width);
            SetFilledValue(startX, startY, true);
            GradationMap[startX + startY * Width] = gradation;
            _filledCount++;
            _remaining[gradation]--;

            while (PointQueue.Length > 0 && _remaining[gradation] > 0)
            {
                int currentPoint = PointQueue[0];
                PointQueue.RemoveAtSwapBack(0);

                int x = currentPoint % Width;
                int y = currentPoint / Width;

                TryFill(x + 1, y, gradation);
                TryFill(x - 1, y, gradation);
                TryFill(x, y + 1, gradation);
                TryFill(x, y - 1, gradation);
                TryFill(x + 1, y + 1, gradation); // діагоналі для створення круглих форм
                TryFill(x - 1, y - 1, gradation); // діагоналі для створення круглих форм
                TryFill(x + 1, y - 1, gradation); // діагоналі для створення круглих форм
                TryFill(x - 1, y + 1, gradation); // діагоналі для створення круглих форм
            }

            if (_remaining[gradation] > 0)
            {
                int nextX = _random.NextInt(0, Width);
                int nextY = _random.NextInt(0, Height);
                FillCircle(nextX, nextY, gradation);
            }
        }

        private void TryFill(int x, int y, int gradation)
        {
            if (x >= 0 && x < Width && y >= 0 && y < Height && !GetFilledValue(x, y))
            {
                int index = x + y * Width;
                PointQueue.Add(index);
                SetFilledValue(x, y, true);
                GradationMap[index] = gradation;
                _filledCount++;
                _remaining[gradation]--;
            }
        }

        private bool GetFilledValue(int x, int y)
        {
            if (x < 0 || x >= Width || y < 0 || y >= Height)
            {
                throw new ArgumentOutOfRangeException("Error 0");
            }
            int index = y * Width + x;
            return Filled[index];
        }

        private void SetFilledValue(int x, int y, bool value)
        {
            if (x < 0 || x >= Width || y < 0 || y >= Height)
            {
                throw new ArgumentOutOfRangeException("Error 1");
            }
            int index = y * Width + x;
            Filled[index] = value;
        }
    }
}
Leave a Comment