Let's turn this into a simple sequence of points.
We know that we are going in one of four directions.
var steps = new (int dx, int dy)[] { (1, 0), (0, 1), (-1, 0), (0, -1) };
To create a spiral we move the first direction once, then the second once; then the next two twice, then the next two three times, then the next two four times, etc. If we hit the end of the list we then cycle back to the start. So if we start with n = 0
then we repeat each direction n / 2 + 1
times (knowing that this is integer maths).
Here's my Spiral
generator method:
public IEnumerable<Point> Spiral(int x, int y)
{
yield return new Point(x, y);
var steps = new(int dx, int dy)[] { (1, 0), (0, 1), (-1, 0), (0, -1) };
var i = 0;
var n = 0;
while (true)
{
for (var j = 0; j < n / 2 + 1; j++)
{
var (sx, sy) = steps[i];
x += sx;
y += sy;
yield return new Point(x, y);
}
if (++i >= steps.Length)
i = 0;
n++;
}
}
The first 50 points (i.e. Spiral(0, 0).Take(50)
) are then this:
(0, 0), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1), (2, -1), (2, 0), (2, 1), (2, 2), (1, 2), (0, 2), (-1, 2), (-2, 2), (-2, 1), (-2, 0), (-2, -1), (-2, -2), (-1, -2), (0, -2), (1, -2), (2, -2), (3, -2), (3, -1), (3, 0), (3, 1), (3, 2), (3, 3), (2, 3), (1, 3), (0, 3), (-1, 3), (-2, 3), (-3, 3), (-3, 2), (-3, 1), (-3, 0), (-3, -1), (-3, -2), (-3, -3), (-2, -3), (-1, -3), (0, -3), (1, -3), (2, -3), (3, -3), (4, -3)
Now, it's super easy to generate the spiral you want.
If I assume that you're starting at the middle of the screen, then this is it:
IEnumerable<Point> query =
Spiral(1920 / 2, 1080 / 2)
.Where(z => z.X >= 0 && z.X < 1920)
.Where(z => z.Y >= 0 && z.Y < 1080)
.Take(1920 * 1080);
If we want to verify with the smaller screen as given in your question, the that looks like this:
IEnumerable<Point> query =
Spiral(0, 0)
.Where(z => z.Y >= -1 && z.Y <= 1)
.Where(z => z.X >= -2 && z.X <= 2)
.Take(5 * 3);
That gives:
(0, 0), (1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1), (2, -1), (2, 0), (2, 1), (-2, 1), (-2, 0), (-2, -1)
Here it is wrapped up in a single method:
public static void Spiral()
{
IEnumerable<Point> SpiralPoints(int x, int y)
{
yield return new Point(x, y);
var steps = new(int dx, int dy)[] { (1, 0), (0, 1), (-1, 0), (0, -1) };
var i = 0;
var n = 0;
while (true)
{
for (var j = 0; j < n / 2 + 1; j++)
{
var (sx, sy) = steps[i];
x += sx;
y += sy;
yield return new Point(x, y);
}
if (++i >= steps.Length)
i = 0;
n++;
}
}
var w = Screen.PrimaryScreen.Bounds.Width;
var h = Screen.PrimaryScreen.Bounds.Height;
var l = Screen.PrimaryScreen.Bounds.Left;
var r = Screen.PrimaryScreen.Bounds.Right;
var t = Screen.PrimaryScreen.Bounds.Top;
var b = Screen.PrimaryScreen.Bounds.Bottom;
foreach (Point point in SpiralPoints(w / 2, h / 2)
.Where(z => z.X >= l && z.X < r)
.Where(z => z.Y >= t && z.Y < b)
.Take(w * h))
{
/* Do Stuff With Each Point Here */
}
}
Math.min(your_x_coord, max_x_screencoord)
(and the same for Y) into your code. Do that until both coords are out of the screenbounds and you are done. - then loop for both coords till the max value of both. Maybe that gets you onto a path to solve it yourself. – Lunkhead