From 432ab66333bdfe237ad293fedd6cc789debcb050 Mon Sep 17 00:00:00 2001 From: Finn Erdmann Date: Tue, 10 Jan 2023 22:50:13 +0100 Subject: [PATCH] Lots of new and improved things; mainly a 10x (I'm bullshitting here) performance improvement and many other small fixes and nice things --- Game_of_Life/MainForm1.Designer.cs | 58 ++++- Game_of_Life/MainForm1.cs | 145 ++++++++++--- Game_of_Life/Pixelmap.cs | 337 ++++++++++++++++++++++------- 3 files changed, 435 insertions(+), 105 deletions(-) diff --git a/Game_of_Life/MainForm1.Designer.cs b/Game_of_Life/MainForm1.Designer.cs index 0b41902..7cc0e80 100644 --- a/Game_of_Life/MainForm1.Designer.cs +++ b/Game_of_Life/MainForm1.Designer.cs @@ -37,10 +37,14 @@ partial class MainForm1 this.buttonRepopulate = new System.Windows.Forms.Button(); this.zoomInButton = 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.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.scalingSlider)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericRenderSleep)).BeginInit(); this.SuspendLayout(); // // pictureBox @@ -110,6 +114,17 @@ partial class MainForm1 this.zoomOutButton.UseVisualStyleBackColor = true; 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 // 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.Size = new System.Drawing.Size(87, 23); this.buttonTick.TabIndex = 6; - this.buttonTick.Text = "TICK"; + this.buttonTick.Text = "⏯ PLAY"; this.buttonTick.UseVisualStyleBackColor = true; this.buttonTick.Click += new System.EventHandler(this.buttonTick_Click); // @@ -132,24 +147,60 @@ partial class MainForm1 this.buttonClear.UseVisualStyleBackColor = true; 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 // this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.Color.Black; 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.buttonTick); this.Controls.Add(this.zoomOutButton); this.Controls.Add(this.zoomInButton); this.Controls.Add(this.buttonRepopulate); + this.Controls.Add(this.buttonTickOnce); this.Controls.Add(this.scalingSlider); this.Controls.Add(this.debugLabel); this.Controls.Add(this.pictureBox); this.Name = "MainForm1"; - this.Text = "MainForm1"; + this.Text = "Game of Life :D"; ((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit(); ((System.ComponentModel.ISupportInitialize)(this.scalingSlider)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.numericRenderSleep)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -165,4 +216,7 @@ partial class MainForm1 private Button zoomOutButton; private Button buttonTick; private Button buttonClear; + private Button buttonTickOnce; + private NumericUpDown numericRenderSleep; + private Button buttonGameArea; } \ No newline at end of file diff --git a/Game_of_Life/MainForm1.cs b/Game_of_Life/MainForm1.cs index 12ada93..0199351 100644 --- a/Game_of_Life/MainForm1.cs +++ b/Game_of_Life/MainForm1.cs @@ -1,25 +1,26 @@ -using System.ComponentModel; +using System.Diagnostics; using System.Drawing.Drawing2D; -using System.Windows.Forms; -using System.Windows.Forms.VisualStyles; namespace Game_of_Life; public partial class MainForm1 : Form { private int scalingFactor = 10; - private int scalingAbsolute = 0; + private int scalingAbsolute; private int scalingMax; Pixelmap pixelmap; private int fieldHeight; private int fieldWidth; + private List renderThreads = new List(); + private decimal renderSleep = 0; + private bool showGameArea = false; public MainForm1() { InitializeComponent(); - fieldHeight = 1800; - fieldWidth = 3200; + fieldHeight = 160; + fieldWidth = 300; if (fieldWidth % 2 == 0) { scalingMax = fieldWidth - 2; @@ -34,15 +35,18 @@ public partial class MainForm1 : Form scalingSlider.Maximum = scalingMax; pixelmap = new Pixelmap(fieldHeight, fieldWidth, scalingFactor); + + /* Random rand = new Random(); - + 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 width = pictureBox.Size.Width; @@ -51,7 +55,15 @@ public partial class MainForm1 : Form pictureBox.SizeMode = PictureBoxSizeMode.AutoSize; 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); } @@ -94,9 +106,9 @@ public partial class MainForm1 : Form } scalingSlider.Value = scalingAbsolute; - pixelmap.setScalingFactor(scalingFactor); - pixelmap.setScalingAbsolute(scalingAbsolute); - pictureBox.Refresh(); + pixelmap.SetScalingFactor(scalingFactor); + pixelmap.SetScalingAbsolute(scalingAbsolute); + pictureBox.Invalidate(); } private void scalingSlider_Changed(object sender, EventArgs e) @@ -107,26 +119,32 @@ public partial class MainForm1 : Form scalingAbsolute += 1; scalingSlider.Value = scalingAbsolute; } - pixelmap.setScalingAbsolute(scalingAbsolute); - pictureBox.Refresh(); + pixelmap.SetScalingAbsolute(scalingAbsolute); + pictureBox.Invalidate(); + } + + private void renderSleep_Changed(object sender, EventArgs e) + { + renderSleep = numericRenderSleep.Value; } private void buttonRepopulate_Click(object sender, EventArgs e) { - pixelmap.clear(); + pixelmap.Clear(); Random rand = new Random(); 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) { - pixelmap.cyclePixel(MousePosition.X, MousePosition.Y); - pictureBox.Refresh(); + var cursorLocation = PointToClient(Cursor.Position); + pixelmap.CyclePixel(cursorLocation.X, cursorLocation.Y); + pictureBox.Invalidate(); } private void zoomInButton_Click(object sender, EventArgs e) @@ -152,7 +170,7 @@ public partial class MainForm1 : Form } scalingSlider.Value = scalingAbsolute; - pixelmap.setScalingAbsolute(scalingAbsolute); + pixelmap.SetScalingAbsolute(scalingAbsolute); } private void zoomOutButton_Click(object sender, EventArgs e) @@ -178,18 +196,95 @@ public partial class MainForm1 : Form } 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) + { + 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(); - pictureBox.Refresh(); + pictureBox.Invalidate(); } private void buttonClear_Click(object sender, EventArgs e) { - pixelmap.clear(); - pictureBox.Refresh(); + pixelmap.Clear(); + 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(); } } diff --git a/Game_of_Life/Pixelmap.cs b/Game_of_Life/Pixelmap.cs index 8a30fd8..7aca940 100644 --- a/Game_of_Life/Pixelmap.cs +++ b/Game_of_Life/Pixelmap.cs @@ -6,81 +6,82 @@ public class Pixelmap private int width; private int[,] map; private int scalingFactor; - private int[] midPoint; + public 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 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]; - + gameWindow = new int[] { width, 0, height, 0 }; + this.scalingFactor = scalingFactor; this.midPoint = new int[] { width / 2, height / 2 }; this.scalingAbsolute = 0; } - public void setScalingFactor(int scalingFactor) + public void SetScalingFactor(int scalingFactor) { this.scalingFactor = scalingFactor; } - public void setScalingAbsolute(int scalingAbsolute) + public void SetScalingAbsolute(int scalingAbsolute) { this.scalingAbsolute = scalingAbsolute; } - public void clear() + public void Clear() { 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; 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; - } + SetBounds(x, y); } - public void cyclePixel(int x, int y) + + public void CyclePixel(int x, int y) { float aspectRatio = (float)viewHeight / (float)viewWidth; @@ -105,35 +106,35 @@ public class Pixelmap upperBound = 0; } - float xTrans = (float)(x-scaleWidth) / scaleWidth; - float yTrans = (float)(y-scaleHeight) / scaleHeight; + float xTrans = (float)(x- scaleWidth - 0.5 * scaleWidth) / scaleWidth; + float yTrans = (float)(y- scaleHeight + 0.5 * 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); + 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); Color penColor = Color.FromArgb(125, Color.Beige); Pen linePen = new Pen(penColor, 1); - this.viewHeight = viewHeight; - this.viewWidth = viewWidth; + viewHeight = viewportHeight; + 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 int borderWidth = width - scalingAbsolute; - int borderHeight = (int)Math.Ceiling((float)borderWidth * aspectRatio); + int borderHeight = (int)Math.Ceiling(borderWidth * aspectRatio); // scaling factors for both dimensions - float scaleWidth = (float)viewWidth / (float)borderWidth; - float scaleHeight = (float)viewHeight / (float)borderHeight; + float scaleWidth = viewportWidth / (float)borderWidth; + float scaleHeight = viewportHeight / (float)borderHeight; // ensure that pixel width and height are always at least 1px int scalePixelWidth; @@ -157,24 +158,24 @@ public class Pixelmap } // 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) { 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) { 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) + int upperBound = (int)Math.Ceiling(midPoint[1] - (borderHeight / (float)2)); + 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) { lowerBound = height; @@ -182,7 +183,7 @@ public class Pixelmap 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 deltaH = h - midPoint[1]; @@ -190,10 +191,10 @@ public class Pixelmap 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; + 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) { @@ -201,9 +202,9 @@ public class Pixelmap x = 0; pixelWidth = scalePixelWidth - deltaX; } - else if (x + (int)scalePixelWidth > viewWidth) + else if (x + scalePixelWidth > viewportWidth) { - int deltaX = viewWidth - x; + int deltaX = viewportWidth - x; pixelWidth = deltaX; } @@ -213,15 +214,141 @@ public class Pixelmap y = 0; pixelHeight = scalePixelHeight - deltaY; } - else if (y + (int)scalePixelHeight > viewHeight) + else if (y + scalePixelHeight > viewportHeight) { - int deltaY = viewHeight - y; + int deltaY = viewportHeight - y; pixelWidth = deltaY; } Brush pixelBrush = new SolidBrush(pixelColor); 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() { - 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 = 1; w < width - 1; w++) + for (int w = gameWindow[0] - 2; w < gameWindow[1] + 2; w++) { - // for (int h = midPoint[1] - gameWindow[2]; h < midPoint[1] + gameWindow[3]; h++) - for (int h = 1; h < height - 1; h++) + for (int h = gameWindow[2] - 2; h < gameWindow[3] + 2; h++) { + if (w < 0) + { + continue; + } + else if (w >= width) + { + continue; + } + + if (h < 0) + { + continue; + } + else if (h >= height) + { + continue; + } + int neighbors = 0; + var rand = new Random(); + int numOptions = colors.Length; // 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; } } } + int currCell = 0; + + try + { + currCell = map[w, h]; + } catch (Exception e) { continue; } + if (map[w, h] == 0) { if (neighbors == 3) { + SetBounds(w, h); mapBuffer[w, h] = 1; } } @@ -274,11 +454,13 @@ public class Pixelmap // lives case 2: mapBuffer[w, h] = 1; + SetBounds(w, h); break; // lives case 3: mapBuffer[w, h] = 1; + SetBounds(w, h); break; // dies @@ -291,7 +473,6 @@ public class Pixelmap } map = mapBuffer; - - return; + mapBuffer = null; } } \ No newline at end of file