+ ClientSize adaption
+ more statistics and timing * improved FastPixel with working code for odd row images
This commit is contained in:
parent
7028323a80
commit
fa5ad89d6b
75
FastPixel.cs
75
FastPixel.cs
@ -5,13 +5,13 @@ using System.Drawing.Imaging;
|
||||
class FastPixel {
|
||||
private byte[] rgbValues;
|
||||
private BitmapData bmpData;
|
||||
private IntPtr bmpPtr;
|
||||
private bool locked = false;
|
||||
|
||||
private bool _isAlpha = false;
|
||||
private Bitmap _bitmap;
|
||||
private int _width;
|
||||
private int _height;
|
||||
private int bytesPerPixel;
|
||||
|
||||
public int Width {
|
||||
get { return this._width; }
|
||||
@ -37,6 +37,7 @@ class FastPixel {
|
||||
this._isAlpha = (this.Bitmap.PixelFormat == (this.Bitmap.PixelFormat | PixelFormat.Alpha));
|
||||
this._width = bitmap.Width;
|
||||
this._height = bitmap.Height;
|
||||
this.bytesPerPixel = (this._isAlpha)?4:3;
|
||||
}
|
||||
|
||||
public void Lock() {
|
||||
@ -45,16 +46,21 @@ class FastPixel {
|
||||
|
||||
Rectangle rect = new Rectangle(0, 0, this.Width, this.Height);
|
||||
this.bmpData = this.Bitmap.LockBits(rect, ImageLockMode.ReadWrite, this.Bitmap.PixelFormat);
|
||||
this.bmpPtr = this.bmpData.Scan0;
|
||||
this.rgbValues = new byte[(this.Width * this.Height) * this.bytesPerPixel];
|
||||
|
||||
int bytes;
|
||||
if (this.IsAlphaBitmap) {
|
||||
bytes = (this.Width * this.Height) * 4;
|
||||
} else {
|
||||
bytes = (this.Width * this.Height) * 3;
|
||||
unsafe {
|
||||
byte* ptr= (byte*)this.bmpData.Scan0;
|
||||
int offset = this.bmpData.Stride - this.bmpData.Width * this.bytesPerPixel;
|
||||
for(int y = 0; y < this.Height; y++, ptr += offset) {
|
||||
for(int x = 0; x < this.Width; x++, ptr += this.bytesPerPixel) {
|
||||
int index = ((y * this.Width + x) * this.bytesPerPixel);
|
||||
this.rgbValues[index] = ptr[0];
|
||||
this.rgbValues[index+1] = ptr[1];
|
||||
this.rgbValues[index+2] = ptr[2];
|
||||
if (this.bytesPerPixel == 4) this.rgbValues[index+3] = ptr[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
this.rgbValues = new byte[bytes];
|
||||
System.Runtime.InteropServices.Marshal.Copy(this.bmpPtr, rgbValues, 0, this.rgbValues.Length);
|
||||
this.locked = true;
|
||||
}
|
||||
|
||||
@ -63,8 +69,21 @@ class FastPixel {
|
||||
throw new Exception("Bitmap not locked.");
|
||||
|
||||
// Copy the RGB values back to the bitmap;
|
||||
if (setPixels)
|
||||
System.Runtime.InteropServices.Marshal.Copy(this.rgbValues, 0, this.bmpPtr, this.rgbValues.Length);
|
||||
if (setPixels) {
|
||||
unsafe {
|
||||
byte* ptr= (byte*)this.bmpData.Scan0;
|
||||
int offset = this.bmpData.Stride - this.bmpData.Width * this.bytesPerPixel;
|
||||
for(int y = 0; y < this.Height; y++, ptr += offset) {
|
||||
for(int x = 0; x < this.Width; x++, ptr += this.bytesPerPixel) {
|
||||
int index = ((y * this.Width + x) * this.bytesPerPixel);
|
||||
ptr[0] = this.rgbValues[index];
|
||||
ptr[1] = this.rgbValues[index+1];
|
||||
ptr[2] = this.rgbValues[index+2];
|
||||
if (this.bytesPerPixel == 4) ptr[3] = this.rgbValues[index+3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unlock the bits.;
|
||||
this.Bitmap.UnlockBits(bmpData);
|
||||
@ -75,19 +94,11 @@ class FastPixel {
|
||||
if (!this.locked)
|
||||
throw new Exception("Bitmap not locked.");
|
||||
|
||||
if (this.IsAlphaBitmap) {
|
||||
for (int index = 0; index < this.rgbValues.Length; index += 4) {
|
||||
for (int index = 0; index < this.rgbValues.Length; index += this.bytesPerPixel) {
|
||||
this.rgbValues[index] = colour.B;
|
||||
this.rgbValues[index + 1] = colour.G;
|
||||
this.rgbValues[index + 2] = colour.R;
|
||||
this.rgbValues[index + 3] = colour.A;
|
||||
}
|
||||
} else {
|
||||
for (int index = 0; index < this.rgbValues.Length; index += 3) {
|
||||
this.rgbValues[index] = colour.B;
|
||||
this.rgbValues[index + 1] = colour.G;
|
||||
this.rgbValues[index + 2] = colour.R;
|
||||
}
|
||||
if (this.bytesPerPixel == 4) this.rgbValues[index + 3] = colour.A;
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,18 +110,11 @@ class FastPixel {
|
||||
if (!this.locked)
|
||||
throw new Exception("Bitmap not locked.");
|
||||
|
||||
if (this.IsAlphaBitmap) {
|
||||
int index = ((y * this.Width + x) * 4);
|
||||
int index = ((y * this.Width + x) * this.bytesPerPixel);
|
||||
this.rgbValues[index] = colour.B;
|
||||
this.rgbValues[index + 1] = colour.G;
|
||||
this.rgbValues[index + 2] = colour.R;
|
||||
this.rgbValues[index + 3] = colour.A;
|
||||
} else {
|
||||
int index = ((y * this.Width + x) * 3);
|
||||
this.rgbValues[index] = colour.B;
|
||||
this.rgbValues[index + 1] = colour.G;
|
||||
this.rgbValues[index + 2] = colour.R;
|
||||
}
|
||||
if (this.bytesPerPixel == 4) this.rgbValues[index + 3] = colour.A;
|
||||
}
|
||||
|
||||
public Color GetPixel(Point location) {
|
||||
@ -121,19 +125,14 @@ class FastPixel {
|
||||
if (!this.locked)
|
||||
throw new Exception("Bitmap not locked.");
|
||||
|
||||
if (this.IsAlphaBitmap) {
|
||||
int index = ((y * this.Width + x) * 4);
|
||||
int index = ((y * this.Width + x) * this.bytesPerPixel);
|
||||
int b = this.rgbValues[index];
|
||||
int g = this.rgbValues[index + 1];
|
||||
int r = this.rgbValues[index + 2];
|
||||
if (this.bytesPerPixel == 4) {
|
||||
int a = this.rgbValues[index + 3];
|
||||
return Color.FromArgb(a, r, g, b);
|
||||
} else {
|
||||
int index = ((y * this.Width + x) * 3);
|
||||
int b = this.rgbValues[index];
|
||||
int g = this.rgbValues[index + 1];
|
||||
int r = this.rgbValues[index + 2];
|
||||
}
|
||||
return Color.FromArgb(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ namespace vampi {
|
||||
|
||||
public class Output_GUI : Output {
|
||||
const int statsHeight = 45;
|
||||
double scale = 1;
|
||||
int scale = 1;
|
||||
Form f = new Form();
|
||||
FastPixel fp;
|
||||
Graphics fg;
|
||||
@ -18,11 +18,8 @@ namespace vampi {
|
||||
Bitmap stats;
|
||||
|
||||
public Output_GUI() {
|
||||
field = new Bitmap(Settings.size, Settings.size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
||||
stats = new Bitmap(300, Output_GUI.statsHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
||||
fp = new FastPixel(field);
|
||||
fg = Graphics.FromHwnd(f.Handle);
|
||||
fg.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||
this.field = new Bitmap(Settings.size, Settings.size, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
||||
this.stats = new Bitmap(f.ClientSize.Width, Output_GUI.statsHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
@ -38,9 +35,16 @@ namespace vampi {
|
||||
g.Clear(Settings.guiColorEmpty);
|
||||
g.Dispose();
|
||||
|
||||
if (Math.Min(f.ClientSize.Width, f.ClientSize.Height-Output_GUI.statsHeight) < Settings.size) {
|
||||
f.ClientSize = new Size(Settings.size, Settings.size+Output_GUI.statsHeight);
|
||||
}
|
||||
|
||||
fp = new FastPixel(field);
|
||||
fg = Graphics.FromHwnd(f.Handle);
|
||||
fg.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||
fg.Clear(Color.White); // clear window background
|
||||
calculateScale();
|
||||
f.Show();
|
||||
calculateScale();
|
||||
}
|
||||
|
||||
~Output_GUI() {
|
||||
@ -54,11 +58,13 @@ namespace vampi {
|
||||
}
|
||||
|
||||
public void calculateScale() {
|
||||
scale = (double)(Math.Min(f.ClientSize.Height - Output_GUI.statsHeight, f.ClientSize.Width) / Settings.size);
|
||||
scale = (int)Math.Floor((double)Math.Min(f.ClientSize.Height - Output_GUI.statsHeight, f.ClientSize.Width) / (double)Settings.size);
|
||||
if (scale<1) scale = 1;
|
||||
}
|
||||
|
||||
public void FormResize(object sender, EventArgs e) {
|
||||
calculateScale();
|
||||
stats = new Bitmap(f.ClientSize.Width, Output_GUI.statsHeight, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
|
||||
fg = Graphics.FromHwnd(f.Handle);
|
||||
fg.InterpolationMode = InterpolationMode.NearestNeighbor;
|
||||
fg.Clear(Color.White);
|
||||
@ -66,7 +72,7 @@ namespace vampi {
|
||||
|
||||
public override void doOutput() {
|
||||
this.drawGameMap();
|
||||
if (Program.AnzSimDone % 2 == 0) this.drawStatistics();
|
||||
this.drawStatistics();
|
||||
Application.DoEvents();
|
||||
}
|
||||
|
||||
@ -123,19 +129,22 @@ namespace vampi {
|
||||
}
|
||||
}
|
||||
fp.Unlock(true);
|
||||
fg.DrawImage(this.field, 0, Output_GUI.statsHeight, (int)(Settings.size * this.scale), (int)(Settings.size * this.scale));
|
||||
fg.DrawImage(this.field, 0, Output_GUI.statsHeight, Settings.size * this.scale, Settings.size * this.scale);
|
||||
f.Update();
|
||||
}
|
||||
|
||||
public void drawStatistics() {
|
||||
if (!f.Visible) this.requestAbort = true;
|
||||
Graphics g = Graphics.FromImage(this.stats);
|
||||
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
|
||||
g.Clear(Color.White);
|
||||
int lineSpc = 10;
|
||||
|
||||
int Ecount = Einwohner.Count; // sflaeche.countTypeOccurrences(Typliste.EINWOHNER);
|
||||
int Vcount = Vampir.Count; // sflaeche.countTypeOccurrences(Typliste.VAMPIR);
|
||||
g.DrawString(String.Format("Steps Done: {0:D5}", Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 0);
|
||||
g.DrawString(String.Format("Step: {0:D5}", Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 0);
|
||||
g.DrawString(String.Format("T{0:N} = {1:D}/sec", Program.lastCalcTime+Program.lastStatsTime, (int)Math.Floor(1000/(Program.lastCalcTime+Program.lastStatsTime))), Settings.guiFont, Settings.guiFontBrush, 100, 0);
|
||||
g.DrawString(String.Format("C{0:N} D{1:N}", Program.lastCalcTime, Program.lastStatsTime), Settings.guiFont, Settings.guiFontBrush, 200, 0);
|
||||
g.DrawString(String.Format(String.Format("Einwohner: {0:D} / Vampire: {1:D}", Ecount, Vcount), Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 1*lineSpc);
|
||||
g.DrawString(String.Format(String.Format("Verhältnis Vampire/Einwohner = 1/{0:N5}", (double)Ecount / Vcount), Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 2*lineSpc);
|
||||
g.DrawString(String.Format(String.Format("Bedeckung: {0:N5} %", (double)(Ecount + Vcount) / (Settings.size*Settings.size) * 100), Program.AnzSimDone), Settings.guiFont, Settings.guiFontBrush, 5, 3*lineSpc);
|
||||
|
12
Program.cs
12
Program.cs
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Timers;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace vampi {
|
||||
class Program {
|
||||
@ -13,16 +14,27 @@ namespace vampi {
|
||||
}
|
||||
public static Random random = new Random();
|
||||
public static Spielflaeche sflaeche = new Spielflaeche(Settings.size, Settings.coveragePercent, Settings.vampireRatio);
|
||||
public static double lastCalcTime = 0;
|
||||
public static double lastStatsTime = 0;
|
||||
|
||||
static void Main(string[] args) {
|
||||
Output output = new Output_GUI();
|
||||
Stopwatch sw = new Stopwatch();
|
||||
|
||||
for (anz_sim_done=0; anz_sim_done < anz_sim; anz_sim_done++) {
|
||||
if (anz_sim_done % Settings.drawEveryNthStep == 0) {
|
||||
sw.Reset();
|
||||
sw.Start();
|
||||
output.doOutput();
|
||||
sw.Stop();
|
||||
Program.lastStatsTime = sw.Elapsed.TotalMilliseconds;
|
||||
}
|
||||
if (output.requestAbort) break;
|
||||
sw.Reset();
|
||||
sw.Start();
|
||||
sflaeche.simulateStep();
|
||||
sw.Stop();
|
||||
Program.lastCalcTime = sw.Elapsed.TotalMilliseconds;
|
||||
}
|
||||
}//Main
|
||||
}//class
|
||||
|
@ -3,7 +3,7 @@ using System.Drawing;
|
||||
|
||||
namespace vampi {
|
||||
public abstract class Settings {
|
||||
public const int size = 43;
|
||||
public const int size = 500;
|
||||
public const int coveragePercent = 77;
|
||||
public const int vampireRatio = 3;
|
||||
public const int drawEveryNthStep = 1;
|
||||
@ -13,10 +13,13 @@ namespace vampi {
|
||||
public const ConsoleColor colorVampire = ConsoleColor.Red;
|
||||
public const ConsoleColor colorEmpty = ConsoleColor.Gray;
|
||||
|
||||
public static Color[] guiColorHuman = {Color.FromArgb(0, 60, 0), Color.LimeGreen};
|
||||
/* public static Color guiColorHuman = Color.LimeGreen;
|
||||
public static Color guiColorHumanInfected = Color.DarkMagenta;
|
||||
public static Color guiColorVampire = Color.Red;
|
||||
*/ public static Color[] guiColorHuman = {Color.FromArgb(0, 60, 0), Color.LimeGreen};
|
||||
public static Color[] guiColorHumanInfected = {Color.FromArgb(60, 0, 60), Color.DarkMagenta};
|
||||
public static Color[] guiColorVampire = {Color.FromArgb(60, 0, 0), Color.Red};
|
||||
public static Color guiColorEmpty = Color.Gray;
|
||||
public static Color guiColorEmpty = Color.Silver;
|
||||
|
||||
public static Font guiFont = new Font("sans-serif", 8);
|
||||
public static Brush guiFontBrush = Brushes.Black;
|
||||
|
@ -24,7 +24,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<AssemblyName>vampi</AssemblyName>
|
||||
<RootNamespace>vampi</RootNamespace>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<ApplicationIcon>.</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
@ -39,7 +39,7 @@
|
||||
<AssemblyName>vampi</AssemblyName>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<RootNamespace>vampi</RootNamespace>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
||||
<ApplicationIcon>.</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
Reference in New Issue
Block a user