Game_of_Life-NET/Game_of_Life/Pixelmap.cs
2022-12-13 21:16:22 +01:00

297 lines
No EOL
8.8 KiB
C#

namespace Game_of_Life;
public class Pixelmap
{
private int height;
private int width;
private int[,] map;
private int scalingFactor;
private int[] midPoint;
private int viewWidth;
private int viewHeight;
private int scalingAbsolute;
private Color[] colors = {Color.Black, Color.White, Color.OrangeRed};
// gameWindow = [leftBound, rightBound, upperBound, lowerBound]
private int[] gameWindow = {0, 0, 0, 0};
public Pixelmap(int height, int width, int scalingFactor)
{
this.height = height;
this.width = width;
map = new int[width, height];
this.scalingFactor = scalingFactor;
this.midPoint = new int[] { width / 2, height / 2 };
this.scalingAbsolute = 0;
}
public void setScalingFactor(int scalingFactor)
{
this.scalingFactor = scalingFactor;
}
public void setScalingAbsolute(int scalingAbsolute)
{
this.scalingAbsolute = scalingAbsolute;
}
public void clear()
{
map = new int[width, height];
gameWindow = new int[] {0, 0, 0, 0};
}
public void setPixel(int x, int y, int val)
{
val = val >= 3 ? 0 : val;
map[x, y] = val;
if (x == 0)
{
x = 1;
} else if (x == width)
{
x--;
}
if (y == 0)
{
y = 1;
} else if (y == height)
{
y--;
}
if (x < midPoint[0] - gameWindow[0])
{
gameWindow[0] = midPoint[0]-x;
}
if (x > midPoint[0] + gameWindow[1])
{
gameWindow[1] = midPoint[0] - x;
}
if (y < midPoint[1] - gameWindow[2])
{
gameWindow[2] = midPoint[1] - y;
}
if (y > midPoint[1] + gameWindow[3])
{
gameWindow[3] = midPoint[1] - y;
}
}
public void cyclePixel(int x, int y)
{
float aspectRatio = (float)viewHeight / (float)viewWidth;
// set width and needed height of the border of the viewable area
int borderWidth = width - scalingAbsolute;
int borderHeight = (int)Math.Ceiling((float)borderWidth * aspectRatio);
// scaling factors for both dimensions
float scaleWidth = (float)viewWidth / (float)borderWidth;
float scaleHeight = (float)viewHeight / (float)borderHeight;
// set both left and right bound for the area being viewed
int leftBound = (int)Math.Floor(midPoint[0] - ((float)borderWidth / (float)2));
if (leftBound < 0)
{
leftBound = 0;
}
int upperBound = (int)Math.Floor(midPoint[1] - ((float)borderHeight / (float)2));
if (upperBound < 0)
{
upperBound = 0;
}
float xTrans = (float)(x-scaleWidth) / scaleWidth;
float yTrans = (float)(y-scaleHeight) / scaleHeight;
int pixelX = (int)Math.Ceiling(xTrans + (float)leftBound);
int pixelY = (int)Math.Ceiling(yTrans + (float)upperBound);
int val = map[pixelX, pixelY] + 1;
setPixel(pixelX, pixelY, val);
}
public Graphics paintOnGraphics(Graphics g, int viewWidth, int viewHeight)
{
g.Clear(Color.Black);
Color penColor = Color.FromArgb(125, Color.Beige);
Pen linePen = new Pen(penColor, 1);
this.viewHeight = viewHeight;
this.viewWidth = viewWidth;
int[] viewMid = { viewWidth / 2, viewHeight / 2 };
float aspectRatio = (float)viewHeight / (float)viewWidth;
// set width and needed height of the border of the viewable area
int borderWidth = width - scalingAbsolute;
int borderHeight = (int)Math.Ceiling((float)borderWidth * aspectRatio);
// scaling factors for both dimensions
float scaleWidth = (float)viewWidth / (float)borderWidth;
float scaleHeight = (float)viewHeight / (float)borderHeight;
// ensure that pixel width and height are always at least 1px
int scalePixelWidth;
if (scaleWidth < 1)
{
scalePixelWidth = 1;
}
else
{
scalePixelWidth = (int)Math.Ceiling(scaleWidth);
}
int scalePixelHeight;
if (scaleHeight < 1)
{
scalePixelHeight = 1;
}
else
{
scalePixelHeight = (int)Math.Ceiling(scaleHeight);
}
// set both left and right bound for the area being viewed
int leftBound = (int)Math.Ceiling(midPoint[0] - ((float)borderWidth / (float)2));
if (leftBound < 0)
{
leftBound = 0;
}
int rightBound = (int)Math.Ceiling(midPoint[0] + ((float)borderWidth / (float)2));
if (rightBound > width)
{
rightBound = width;
}
// set both upper and lower bound for the area being viewed
int upperBound = (int)Math.Ceiling(midPoint[1] - ((float)borderHeight / (float)2));
if (upperBound < 0)
{
upperBound = 0;
}
int lowerBound = (int)Math.Ceiling(midPoint[1] + ((float)borderHeight / (float)2));
if (lowerBound > height)
{
lowerBound = height;
}
for (int w = leftBound; w < rightBound; w++)
{
for (int h = upperBound; h < lowerBound; h++)
{
int deltaW = w - midPoint[0];
int deltaH = h - midPoint[1];
Color pixelColor = colors[map[w, h]];
if (!pixelColor.Equals(Color.Black))
{
int x = (int)(viewMid[0] + (deltaW * scaleWidth));
int y = (int)(viewMid[1] + (deltaH * scaleHeight));
int pixelWidth = (int)scalePixelWidth;
int pixelHeight = (int)scalePixelHeight;
if (x < 0)
{
int deltaX = 0 - x;
x = 0;
pixelWidth = scalePixelWidth - deltaX;
}
else if (x + (int)scalePixelWidth > viewWidth)
{
int deltaX = viewWidth - x;
pixelWidth = deltaX;
}
if (y < 0)
{
int deltaY = 0 - y;
y = 0;
pixelHeight = scalePixelHeight - deltaY;
}
else if (y + (int)scalePixelHeight > viewHeight)
{
int deltaY = viewHeight - y;
pixelWidth = deltaY;
}
Brush pixelBrush = new SolidBrush(pixelColor);
g.FillRectangle(pixelBrush,
new Rectangle(x, (int)(viewMid[1] + (deltaH * scaleHeight)), (int)scalePixelWidth, (int)scalePixelHeight));
}
}
}
return g;
}
public void Tick()
{
int[,] mapBuffer = new int[width, height];
// for (int w = midPoint[0]-gameWindow[0]; w < midPoint[0] + gameWindow[1]; w++)
for (int w = 1; w < width - 1; w++)
{
// for (int h = midPoint[1] - gameWindow[2]; h < midPoint[1] + gameWindow[3]; h++)
for (int h = 1; h < height - 1; h++)
{
int neighbors = 0;
// iterate through all neighbors
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
if (map[(w - 1) + x, (h - 1) + y] != 0)
{
neighbors += 1;
}
}
}
if (map[w, h] == 0)
{
if (neighbors == 3)
{
mapBuffer[w, h] = 1;
}
}
else
{
// since the current entity is also being counted...
neighbors--;
switch (neighbors)
{
// dies
case < 2:
mapBuffer[w, h] = 0;
break;
// lives
case 2:
mapBuffer[w, h] = 1;
break;
// lives
case 3:
mapBuffer[w, h] = 1;
break;
// dies
case > 3:
mapBuffer[w, h] = 0;
break;
}
}
}
}
map = mapBuffer;
return;
}
}