Lots of new and improved things; mainly a 10x (I'm bullshitting here) performance improvement and many other small fixes and nice things

This commit is contained in:
Finn Erdmann 2023-01-10 22:50:13 +01:00
parent 3cef3e10b7
commit 432ab66333
3 changed files with 435 additions and 105 deletions

View file

@ -37,10 +37,14 @@ partial class MainForm1
this.buttonRepopulate = new System.Windows.Forms.Button(); this.buttonRepopulate = new System.Windows.Forms.Button();
this.zoomInButton = new System.Windows.Forms.Button(); this.zoomInButton = new System.Windows.Forms.Button();
this.zoomOutButton = new System.Windows.Forms.Button(); this.zoomOutButton = new System.Windows.Forms.Button();
this.buttonTickOnce = new System.Windows.Forms.Button();
this.buttonTick = new System.Windows.Forms.Button(); this.buttonTick = new System.Windows.Forms.Button();
this.buttonClear = new System.Windows.Forms.Button(); this.buttonClear = new System.Windows.Forms.Button();
this.numericRenderSleep = new System.Windows.Forms.NumericUpDown();
this.buttonGameArea = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.scalingSlider)).BeginInit(); ((System.ComponentModel.ISupportInitialize)(this.scalingSlider)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericRenderSleep)).BeginInit();
this.SuspendLayout(); this.SuspendLayout();
// //
// pictureBox // pictureBox
@ -110,6 +114,17 @@ partial class MainForm1
this.zoomOutButton.UseVisualStyleBackColor = true; this.zoomOutButton.UseVisualStyleBackColor = true;
this.zoomOutButton.Click += new System.EventHandler(this.zoomOutButton_Click); this.zoomOutButton.Click += new System.EventHandler(this.zoomOutButton_Click);
// //
// buttonTickOnce
//
this.buttonTickOnce.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.buttonTickOnce.Location = new System.Drawing.Point(608, 41);
this.buttonTickOnce.Name = "buttonTickOnce";
this.buttonTickOnce.Size = new System.Drawing.Size(87, 23);
this.buttonTickOnce.TabIndex = 6;
this.buttonTickOnce.Text = "TICK";
this.buttonTickOnce.UseVisualStyleBackColor = true;
this.buttonTickOnce.Click += new System.EventHandler(this.buttonTickOnce_Click);
//
// buttonTick // buttonTick
// //
this.buttonTick.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.buttonTick.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
@ -117,7 +132,7 @@ partial class MainForm1
this.buttonTick.Name = "buttonTick"; this.buttonTick.Name = "buttonTick";
this.buttonTick.Size = new System.Drawing.Size(87, 23); this.buttonTick.Size = new System.Drawing.Size(87, 23);
this.buttonTick.TabIndex = 6; this.buttonTick.TabIndex = 6;
this.buttonTick.Text = "TICK"; this.buttonTick.Text = "⏯ PLAY";
this.buttonTick.UseVisualStyleBackColor = true; this.buttonTick.UseVisualStyleBackColor = true;
this.buttonTick.Click += new System.EventHandler(this.buttonTick_Click); this.buttonTick.Click += new System.EventHandler(this.buttonTick_Click);
// //
@ -132,24 +147,60 @@ partial class MainForm1
this.buttonClear.UseVisualStyleBackColor = true; this.buttonClear.UseVisualStyleBackColor = true;
this.buttonClear.Click += new System.EventHandler(this.buttonClear_Click); this.buttonClear.Click += new System.EventHandler(this.buttonClear_Click);
// //
// numericRenderSleep
//
this.numericRenderSleep.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.numericRenderSleep.DecimalPlaces = 1;
this.numericRenderSleep.Increment = new decimal(new int[] {
167,
0,
0,
65536});
this.numericRenderSleep.Location = new System.Drawing.Point(512, 12);
this.numericRenderSleep.Maximum = new decimal(new int[] {
10000,
0,
0,
0});
this.numericRenderSleep.Name = "numericRenderSleep";
this.numericRenderSleep.Size = new System.Drawing.Size(87, 23);
this.numericRenderSleep.TabIndex = 9;
this.numericRenderSleep.UpDownAlign = System.Windows.Forms.LeftRightAlignment.Left;
this.numericRenderSleep.ValueChanged += new System.EventHandler(this.renderSleep_Changed);
//
// buttonGameArea
//
this.buttonGameArea.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.buttonGameArea.Location = new System.Drawing.Point(512, 41);
this.buttonGameArea.Name = "buttonGameArea";
this.buttonGameArea.Size = new System.Drawing.Size(87, 23);
this.buttonGameArea.TabIndex = 10;
this.buttonGameArea.Text = "SHOW AREA";
this.buttonGameArea.UseVisualStyleBackColor = true;
this.buttonGameArea.Click += new System.EventHandler(this.buttonGameArea_Click);
//
// MainForm1 // MainForm1
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Black; this.BackColor = System.Drawing.Color.Black;
this.ClientSize = new System.Drawing.Size(800, 450); this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.buttonGameArea);
this.Controls.Add(this.numericRenderSleep);
this.Controls.Add(this.buttonClear); this.Controls.Add(this.buttonClear);
this.Controls.Add(this.buttonTick); this.Controls.Add(this.buttonTick);
this.Controls.Add(this.zoomOutButton); this.Controls.Add(this.zoomOutButton);
this.Controls.Add(this.zoomInButton); this.Controls.Add(this.zoomInButton);
this.Controls.Add(this.buttonRepopulate); this.Controls.Add(this.buttonRepopulate);
this.Controls.Add(this.buttonTickOnce);
this.Controls.Add(this.scalingSlider); this.Controls.Add(this.scalingSlider);
this.Controls.Add(this.debugLabel); this.Controls.Add(this.debugLabel);
this.Controls.Add(this.pictureBox); this.Controls.Add(this.pictureBox);
this.Name = "MainForm1"; this.Name = "MainForm1";
this.Text = "MainForm1"; this.Text = "Game of Life :D";
((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.scalingSlider)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.scalingSlider)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericRenderSleep)).EndInit();
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
@ -165,4 +216,7 @@ partial class MainForm1
private Button zoomOutButton; private Button zoomOutButton;
private Button buttonTick; private Button buttonTick;
private Button buttonClear; private Button buttonClear;
private Button buttonTickOnce;
private NumericUpDown numericRenderSleep;
private Button buttonGameArea;
} }

View file

@ -1,25 +1,26 @@
using System.ComponentModel; using System.Diagnostics;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
namespace Game_of_Life; namespace Game_of_Life;
public partial class MainForm1 : Form public partial class MainForm1 : Form
{ {
private int scalingFactor = 10; private int scalingFactor = 10;
private int scalingAbsolute = 0; private int scalingAbsolute;
private int scalingMax; private int scalingMax;
Pixelmap pixelmap; Pixelmap pixelmap;
private int fieldHeight; private int fieldHeight;
private int fieldWidth; private int fieldWidth;
private List<Thread> renderThreads = new List<Thread>();
private decimal renderSleep = 0;
private bool showGameArea = false;
public MainForm1() public MainForm1()
{ {
InitializeComponent(); InitializeComponent();
fieldHeight = 1800; fieldHeight = 160;
fieldWidth = 3200; fieldWidth = 300;
if (fieldWidth % 2 == 0) if (fieldWidth % 2 == 0)
{ {
scalingMax = fieldWidth - 2; scalingMax = fieldWidth - 2;
@ -34,15 +35,18 @@ public partial class MainForm1 : Form
scalingSlider.Maximum = scalingMax; scalingSlider.Maximum = scalingMax;
pixelmap = new Pixelmap(fieldHeight, fieldWidth, scalingFactor); pixelmap = new Pixelmap(fieldHeight, fieldWidth, scalingFactor);
/*
Random rand = new Random(); Random rand = new Random();
for (int i = 0; i < 4000; i++) for (int i = 0; i < 4000; i++)
{ {
pixelmap.setPixel(rand.Next(fieldWidth), rand.Next(fieldHeight), rand.Next(3)); pixelmap.SetPixel(rand.Next(fieldWidth), rand.Next(fieldHeight), rand.Next(3));
} }
*/
} }
private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) private void pictureBox1_Paint(object sender, PaintEventArgs e)
{ {
int height = pictureBox.Size.Height; int height = pictureBox.Size.Height;
int width = pictureBox.Size.Width; int width = pictureBox.Size.Width;
@ -51,7 +55,15 @@ public partial class MainForm1 : Form
pictureBox.SizeMode = PictureBoxSizeMode.AutoSize; pictureBox.SizeMode = PictureBoxSizeMode.AutoSize;
pictureBox.InterpolationMode = InterpolationMode.NearestNeighbor; pictureBox.InterpolationMode = InterpolationMode.NearestNeighbor;
pixelmap.paintOnGraphics(graphics, width, height); debugLabel.Text = $"{renderSleep}";
if (!showGameArea)
{
pixelmap.paintOnGraphics(graphics, width, height);
} else
{
pixelmap.paintGameArea(graphics, width, height);
showGameArea = false;
}
// Thread.Sleep(1000); // Thread.Sleep(1000);
} }
@ -94,9 +106,9 @@ public partial class MainForm1 : Form
} }
scalingSlider.Value = scalingAbsolute; scalingSlider.Value = scalingAbsolute;
pixelmap.setScalingFactor(scalingFactor); pixelmap.SetScalingFactor(scalingFactor);
pixelmap.setScalingAbsolute(scalingAbsolute); pixelmap.SetScalingAbsolute(scalingAbsolute);
pictureBox.Refresh(); pictureBox.Invalidate();
} }
private void scalingSlider_Changed(object sender, EventArgs e) private void scalingSlider_Changed(object sender, EventArgs e)
@ -107,26 +119,32 @@ public partial class MainForm1 : Form
scalingAbsolute += 1; scalingAbsolute += 1;
scalingSlider.Value = scalingAbsolute; scalingSlider.Value = scalingAbsolute;
} }
pixelmap.setScalingAbsolute(scalingAbsolute); pixelmap.SetScalingAbsolute(scalingAbsolute);
pictureBox.Refresh(); pictureBox.Invalidate();
}
private void renderSleep_Changed(object sender, EventArgs e)
{
renderSleep = numericRenderSleep.Value;
} }
private void buttonRepopulate_Click(object sender, EventArgs e) private void buttonRepopulate_Click(object sender, EventArgs e)
{ {
pixelmap.clear(); pixelmap.Clear();
Random rand = new Random(); Random rand = new Random();
for (int i = 0; i < 4000; i++) for (int i = 0; i < 4000; i++)
{ {
pixelmap.setPixel(rand.Next(fieldWidth), rand.Next(fieldHeight), rand.Next(3)); pixelmap.SetPixel(rand.Next(fieldWidth), rand.Next(fieldHeight), rand.Next(3));
} }
pictureBox.Refresh(); pictureBox.Invalidate();
} }
private void pictureBox_Click(object sender, EventArgs e) private void pictureBox_Click(object sender, EventArgs e)
{ {
pixelmap.cyclePixel(MousePosition.X, MousePosition.Y); var cursorLocation = PointToClient(Cursor.Position);
pictureBox.Refresh(); pixelmap.CyclePixel(cursorLocation.X, cursorLocation.Y);
pictureBox.Invalidate();
} }
private void zoomInButton_Click(object sender, EventArgs e) private void zoomInButton_Click(object sender, EventArgs e)
@ -152,7 +170,7 @@ public partial class MainForm1 : Form
} }
scalingSlider.Value = scalingAbsolute; scalingSlider.Value = scalingAbsolute;
pixelmap.setScalingAbsolute(scalingAbsolute); pixelmap.SetScalingAbsolute(scalingAbsolute);
} }
private void zoomOutButton_Click(object sender, EventArgs e) private void zoomOutButton_Click(object sender, EventArgs e)
@ -178,18 +196,95 @@ public partial class MainForm1 : Form
} }
scalingSlider.Value = scalingAbsolute; scalingSlider.Value = scalingAbsolute;
pixelmap.setScalingAbsolute(scalingAbsolute); pixelmap.SetScalingAbsolute(scalingAbsolute);
}
delegate void SetRefreshPictureBoxCallback();
private void RefreshPictureBox()
{
try
{
if (pictureBox.InvokeRequired)
{
SetRefreshPictureBoxCallback d = RefreshPictureBox;
Invoke(d, new object[] { });
}
else
{
pictureBox.Invalidate();
}
}
catch (ThreadInterruptedException)
{
throw new Exception("Thread interrupted");
} catch(Exception e)
{
throw new Exception("");
}
}
private void RenderTick()
{
try
{
while (true)
{
var stopwatch = Stopwatch.StartNew();
pixelmap.Tick();
RefreshPictureBox();
while ((decimal)stopwatch.Elapsed.Milliseconds <= renderSleep)
{
Thread.Sleep(1);
}
}
}
catch (Exception)
{
RefreshPictureBox();
// ignored; can exit without much consequences
}
} }
private void buttonTick_Click(object sender, EventArgs e) private void buttonTick_Click(object sender, EventArgs e)
{
if (renderThreads.Count == 0)
{
var rThread = new Thread(RenderTick);
rThread.Start();
renderThreads.Add(rThread);
buttonTick.Text = "⏸PAUSE";
} else
{
renderThreads.ForEach(r => { r.Interrupt(); });
renderThreads.Clear();
buttonTick.Text = "⏯PLAY";
}
}
private void buttonTickOnce_Click(object sender, EventArgs e)
{ {
pixelmap.Tick(); pixelmap.Tick();
pictureBox.Refresh(); pictureBox.Invalidate();
} }
private void buttonClear_Click(object sender, EventArgs e) private void buttonClear_Click(object sender, EventArgs e)
{ {
pixelmap.clear(); pixelmap.Clear();
pictureBox.Refresh(); var mp = pixelmap.midPoint;
pixelmap.SetPixel(mp[0], mp[1], 1);
pixelmap.SetPixel((int)mp[0], (int)mp[1] - 1, 1);
pixelmap.SetPixel((int)mp[0], (int)mp[1] - 2, 1);
pixelmap.SetPixel((int)mp[0] - 1, (int)mp[1] - 1, 1);
pixelmap.SetPixel((int)mp[0] + 1, (int)mp[1] - 2, 1);
pictureBox.Invalidate();
}
private void buttonGameArea_Click(object sender, EventArgs e)
{
showGameArea = true;
pictureBox.Invalidate();
} }
} }

View file

@ -6,81 +6,82 @@ public class Pixelmap
private int width; private int width;
private int[,] map; private int[,] map;
private int scalingFactor; private int scalingFactor;
private int[] midPoint; public int[] midPoint;
private int viewWidth; private int viewWidth;
private int viewHeight; private int viewHeight;
private int scalingAbsolute; private int scalingAbsolute;
private Color[] colors = {Color.Black, Color.White, Color.OrangeRed}; private Color[] colors = {Color.Black, Color.White, Color.OrangeRed};
// gameWindow = [leftBound, rightBound, upperBound, lowerBound] // gameWindow = [leftBound, rightBound, upperBound, lowerBound]
private int[] gameWindow = {0, 0, 0, 0}; public int[] gameWindow = { 0, 0, 0, 0 };
public Pixelmap(int height, int width, int scalingFactor) public Pixelmap(int height, int width, int scalingFactor)
{ {
this.height = height; this.height = height;
this.width = width; this.width = width;
map = new int[width, height]; map = new int[width, height];
gameWindow = new int[] { width, 0, height, 0 };
this.scalingFactor = scalingFactor; this.scalingFactor = scalingFactor;
this.midPoint = new int[] { width / 2, height / 2 }; this.midPoint = new int[] { width / 2, height / 2 };
this.scalingAbsolute = 0; this.scalingAbsolute = 0;
} }
public void setScalingFactor(int scalingFactor) public void SetScalingFactor(int scalingFactor)
{ {
this.scalingFactor = scalingFactor; this.scalingFactor = scalingFactor;
} }
public void setScalingAbsolute(int scalingAbsolute) public void SetScalingAbsolute(int scalingAbsolute)
{ {
this.scalingAbsolute = scalingAbsolute; this.scalingAbsolute = scalingAbsolute;
} }
public void clear() public void Clear()
{ {
map = new int[width, height]; map = new int[width, height];
gameWindow = new int[] {0, 0, 0, 0}; gameWindow = new int[] { width, 0, height, 0 };
} }
public void setPixel(int x, int y, int val) private void SetBounds(int x, int y)
{
x = x == 0 ? 2 : x;
y = y == 0 ? 2 : y;
x = x == width ? width - 2 : x;
y = y == height ? height - 2 : y;
if (x < gameWindow[0])
{
gameWindow[0] = x;
}
if (x > gameWindow[1])
{
gameWindow[1] = x;
}
if (y < gameWindow[2])
{
gameWindow[2] = y;
}
if (y > gameWindow[3])
{
gameWindow[3] = y;
}
}
public void SetPixel(int x, int y, int val)
{ {
val = val >= 3 ? 0 : val; val = val >= 3 ? 0 : val;
map[x, y] = val; map[x, y] = val;
if (x == 0) SetBounds(x, y);
{
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)
public void CyclePixel(int x, int y)
{ {
float aspectRatio = (float)viewHeight / (float)viewWidth; float aspectRatio = (float)viewHeight / (float)viewWidth;
@ -105,35 +106,35 @@ public class Pixelmap
upperBound = 0; upperBound = 0;
} }
float xTrans = (float)(x-scaleWidth) / scaleWidth; float xTrans = (float)(x- scaleWidth - 0.5 * scaleWidth) / scaleWidth;
float yTrans = (float)(y-scaleHeight) / scaleHeight; float yTrans = (float)(y- scaleHeight + 0.5 * scaleHeight) / scaleHeight;
int pixelX = (int)Math.Ceiling(xTrans + (float)leftBound); int pixelX = (int)Math.Ceiling(xTrans + (float)leftBound);
int pixelY = (int)Math.Ceiling(yTrans + (float)upperBound); int pixelY = (int)Math.Ceiling(yTrans + (float)upperBound);
int val = map[pixelX, pixelY] + 1; int val = map[pixelX, pixelY] + 1;
setPixel(pixelX, pixelY, val); SetPixel(pixelX, pixelY, val);
} }
public Graphics paintOnGraphics(Graphics g, int viewWidth, int viewHeight) public Graphics paintOnGraphics(Graphics g, int viewportWidth, int viewportHeight)
{ {
g.Clear(Color.Black); g.Clear(Color.Black);
Color penColor = Color.FromArgb(125, Color.Beige); Color penColor = Color.FromArgb(125, Color.Beige);
Pen linePen = new Pen(penColor, 1); Pen linePen = new Pen(penColor, 1);
this.viewHeight = viewHeight; viewHeight = viewportHeight;
this.viewWidth = viewWidth; viewWidth = viewportWidth;
int[] viewMid = { viewWidth / 2, viewHeight / 2 }; int[] viewMid = { viewportWidth / 2, viewportHeight / 2 };
float aspectRatio = (float)viewHeight / (float)viewWidth; float aspectRatio = viewportHeight / (float)viewportWidth;
// set width and needed height of the border of the viewable area // set width and needed height of the border of the viewable area
int borderWidth = width - scalingAbsolute; int borderWidth = width - scalingAbsolute;
int borderHeight = (int)Math.Ceiling((float)borderWidth * aspectRatio); int borderHeight = (int)Math.Ceiling(borderWidth * aspectRatio);
// scaling factors for both dimensions // scaling factors for both dimensions
float scaleWidth = (float)viewWidth / (float)borderWidth; float scaleWidth = viewportWidth / (float)borderWidth;
float scaleHeight = (float)viewHeight / (float)borderHeight; float scaleHeight = viewportHeight / (float)borderHeight;
// ensure that pixel width and height are always at least 1px // ensure that pixel width and height are always at least 1px
int scalePixelWidth; int scalePixelWidth;
@ -157,24 +158,24 @@ public class Pixelmap
} }
// set both left and right bound for the area being viewed // set both left and right bound for the area being viewed
int leftBound = (int)Math.Ceiling(midPoint[0] - ((float)borderWidth / (float)2)); int leftBound = (int)Math.Ceiling(midPoint[0] - (borderWidth / (float)2));
if (leftBound < 0) if (leftBound < 0)
{ {
leftBound = 0; leftBound = 0;
} }
int rightBound = (int)Math.Ceiling(midPoint[0] + ((float)borderWidth / (float)2)); int rightBound = (int)Math.Ceiling(midPoint[0] + (borderWidth / (float)2));
if (rightBound > width) if (rightBound > width)
{ {
rightBound = width; rightBound = width;
} }
// set both upper and lower bound for the area being viewed // set both upper and lower bound for the area being viewed
int upperBound = (int)Math.Ceiling(midPoint[1] - ((float)borderHeight / (float)2)); int upperBound = (int)Math.Ceiling(midPoint[1] - (borderHeight / (float)2));
if (upperBound < 0) if (upperBound < 1)
{ {
upperBound = 0; upperBound = 1;
} }
int lowerBound = (int)Math.Ceiling(midPoint[1] + ((float)borderHeight / (float)2)); int lowerBound = (int)Math.Ceiling(midPoint[1] + (borderHeight / (float)2));
if (lowerBound > height) if (lowerBound > height)
{ {
lowerBound = height; lowerBound = height;
@ -182,7 +183,7 @@ public class Pixelmap
for (int w = leftBound; w < rightBound; w++) for (int w = leftBound; w < rightBound; w++)
{ {
for (int h = upperBound; h < lowerBound; h++) for (int h = (upperBound - 1); h < lowerBound; h++)
{ {
int deltaW = w - midPoint[0]; int deltaW = w - midPoint[0];
int deltaH = h - midPoint[1]; int deltaH = h - midPoint[1];
@ -190,10 +191,10 @@ public class Pixelmap
Color pixelColor = colors[map[w, h]]; Color pixelColor = colors[map[w, h]];
if (!pixelColor.Equals(Color.Black)) if (!pixelColor.Equals(Color.Black))
{ {
int x = (int)(viewMid[0] + (deltaW * scaleWidth)); int x = (int)(viewMid[0] + (deltaW * scaleWidth) + 0.5 * scaleWidth);
int y = (int)(viewMid[1] + (deltaH * scaleHeight)); int y = (int)(viewMid[1] + (deltaH * scaleHeight) + 0.5 * scaleHeight);
int pixelWidth = (int)scalePixelWidth; int pixelWidth = scalePixelWidth;
int pixelHeight = (int)scalePixelHeight; int pixelHeight = scalePixelHeight;
if (x < 0) if (x < 0)
{ {
@ -201,9 +202,9 @@ public class Pixelmap
x = 0; x = 0;
pixelWidth = scalePixelWidth - deltaX; pixelWidth = scalePixelWidth - deltaX;
} }
else if (x + (int)scalePixelWidth > viewWidth) else if (x + scalePixelWidth > viewportWidth)
{ {
int deltaX = viewWidth - x; int deltaX = viewportWidth - x;
pixelWidth = deltaX; pixelWidth = deltaX;
} }
@ -213,15 +214,141 @@ public class Pixelmap
y = 0; y = 0;
pixelHeight = scalePixelHeight - deltaY; pixelHeight = scalePixelHeight - deltaY;
} }
else if (y + (int)scalePixelHeight > viewHeight) else if (y + scalePixelHeight > viewportHeight)
{ {
int deltaY = viewHeight - y; int deltaY = viewportHeight - y;
pixelWidth = deltaY; pixelWidth = deltaY;
} }
Brush pixelBrush = new SolidBrush(pixelColor); Brush pixelBrush = new SolidBrush(pixelColor);
g.FillRectangle(pixelBrush, g.FillRectangle(pixelBrush,
new Rectangle(x, (int)(viewMid[1] + (deltaH * scaleHeight)), (int)scalePixelWidth, (int)scalePixelHeight)); new Rectangle(x, (int)(viewMid[1] + (deltaH * scaleHeight)), scalePixelWidth, scalePixelHeight));
}
}
}
return g;
}
public Graphics paintGameArea(Graphics g, int viewportWidth, int viewportHeight)
{
g.Clear(Color.Black);
Color penColor = Color.FromArgb(125, Color.Beige);
Pen linePen = new Pen(penColor, 1);
viewHeight = viewportHeight;
viewWidth = viewportWidth;
int[] viewMid = { viewportWidth / 2, viewportHeight / 2 };
float aspectRatio = viewportHeight / (float)viewportWidth;
// set width and needed height of the border of the viewable area
int borderWidth = width - scalingAbsolute;
int borderHeight = (int)Math.Ceiling(borderWidth * aspectRatio);
// scaling factors for both dimensions
float scaleWidth = viewportWidth / (float)borderWidth;
float scaleHeight = viewportHeight / (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] - (borderWidth / (float)2));
if (leftBound < 0)
{
leftBound = 0;
}
int rightBound = (int)Math.Ceiling(midPoint[0] + (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] - (borderHeight / (float)2));
if (upperBound < 1)
{
upperBound = 1;
}
int lowerBound = (int)Math.Ceiling(midPoint[1] + (borderHeight / (float)2));
if (lowerBound > height)
{
lowerBound = height;
}
int[,] gameMap = new int[width, height];
for (int w2 = gameWindow[0] - 1; w2 <= gameWindow[1] + 1; w2++)
//for (int w = 1; w < width - 1; w++)
{
for (int h2 = gameWindow[2] - 1; h2 <= gameWindow[3] + 1; h2++)
{
gameMap[w2, h2] = 2;
}
}
for (int w = leftBound; w < rightBound; w++)
{
for (int h = (upperBound - 1); h < lowerBound; h++)
{
int deltaW = w - midPoint[0];
int deltaH = h - midPoint[1];
Color pixelColor = colors[gameMap[w,h]];
if (!pixelColor.Equals(Color.Black))
{
int x = (int)(viewMid[0] + (deltaW * scaleWidth) + 0.5 * scaleWidth);
int y = (int)(viewMid[1] + (deltaH * scaleHeight) + 0.5 * scaleHeight);
int pixelWidth = scalePixelWidth;
int pixelHeight = scalePixelHeight;
if (x < 0)
{
int deltaX = 0 - x;
x = 0;
pixelWidth = scalePixelWidth - deltaX;
}
else if (x + scalePixelWidth > viewportWidth)
{
int deltaX = viewportWidth - x;
pixelWidth = deltaX;
}
if (y < 0)
{
int deltaY = 0 - y;
y = 0;
pixelHeight = scalePixelHeight - deltaY;
}
else if (y + scalePixelHeight > viewportHeight)
{
int deltaY = viewportHeight - y;
pixelWidth = deltaY;
}
Brush pixelBrush = new SolidBrush(pixelColor);
g.FillRectangle(pixelBrush,
new Rectangle(x, (int)(viewMid[1] + (deltaH * scaleHeight)), scalePixelWidth, scalePixelHeight));
} }
} }
} }
@ -230,32 +357,85 @@ public class Pixelmap
public void Tick() public void Tick()
{ {
int[,] mapBuffer = new int[width, height]; int[,]? mapBuffer = new int[width, height];
// for (int w = midPoint[0]-gameWindow[0]; w < midPoint[0] + gameWindow[1]; w++) for (int w = gameWindow[0] - 2; w < gameWindow[1] + 2; 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 = gameWindow[2] - 2; h < gameWindow[3] + 2; h++)
for (int h = 1; h < height - 1; h++)
{ {
if (w < 0)
{
continue;
}
else if (w >= width)
{
continue;
}
if (h < 0)
{
continue;
}
else if (h >= height)
{
continue;
}
int neighbors = 0; int neighbors = 0;
var rand = new Random();
int numOptions = colors.Length;
// iterate through all neighbors // iterate through all neighbors
for (int x = 0; x < 3; x++) for (int x = -1; x < 2; x++)
{ {
for (int y = 0; y < 3; y++) for (int y = -1; y < 2; y++)
{ {
if (map[(w - 1) + x, (h - 1) + y] != 0) int mx = x + w;
int my = y + h;
if (mx < 0)
{
break;
} else if (mx >= width)
{
break;
}
if (my < 0)
{
break;
} else if (my >= height)
{
break;
}
int cell = 0;
try
{
cell = map[x + w, y + h];
} catch (Exception e)
{
break;
}
if (cell > 0)
{ {
neighbors += 1; neighbors += 1;
} }
} }
} }
int currCell = 0;
try
{
currCell = map[w, h];
} catch (Exception e) { continue; }
if (map[w, h] == 0) if (map[w, h] == 0)
{ {
if (neighbors == 3) if (neighbors == 3)
{ {
SetBounds(w, h);
mapBuffer[w, h] = 1; mapBuffer[w, h] = 1;
} }
} }
@ -274,11 +454,13 @@ public class Pixelmap
// lives // lives
case 2: case 2:
mapBuffer[w, h] = 1; mapBuffer[w, h] = 1;
SetBounds(w, h);
break; break;
// lives // lives
case 3: case 3:
mapBuffer[w, h] = 1; mapBuffer[w, h] = 1;
SetBounds(w, h);
break; break;
// dies // dies
@ -291,7 +473,6 @@ public class Pixelmap
} }
map = mapBuffer; map = mapBuffer;
mapBuffer = null;
return;
} }
} }