source: 2014/30/MikkoI/frakt/frakt/frakt/Game1.cs @ 5693

Revision 5693, 21.6 KB checked in by mijoilmo, 6 years ago (diff)
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Threading;
5using Microsoft.Xna.Framework;
6using Microsoft.Xna.Framework.Audio;
7using Microsoft.Xna.Framework.Content;
8using Microsoft.Xna.Framework.GamerServices;
9using Microsoft.Xna.Framework.Graphics;
10using Microsoft.Xna.Framework.Input;
11using Microsoft.Xna.Framework.Media;
12using System.IO;
13
14namespace frakt
15{
16    /// <summary>
17    /// This is the main type for your game
18    /// </summary>
19    public class WooooFract : Microsoft.Xna.Framework.Game
20    {
21        GraphicsDeviceManager graphics;
22        SpriteBatch spriteBatch;
23        Vector2 viewportSize;
24        KeyboardState keyboardState;
25        KeyboardState oldKeyboardState;
26        MouseState mouseState;
27        MouseState oldMouseState;
28
29        SpriteFont command;
30
31        Vector2 imageSize = Vector2.Zero;
32
33        Texture2D pixel;
34        System.Drawing.Bitmap image;
35        Texture2D referenceImage;
36
37        string commandStr = "";
38        bool infoHide = false;
39        string errorMessage = "";
40
41        decimal[,][] pointData;
42
43        decimal[] gridOffset = new decimal[2] { 0, 0 };
44        decimal[] gridScale = new decimal[2] { 4, 4 };
45        int[] calcResolution = new int[2] { 10, 10 };
46        int calcIterations = 1;
47
48        GameTime gameTime;
49
50        Color[] data;
51
52        public WooooFract()
53        {
54            graphics = new GraphicsDeviceManager(this);
55            graphics.PreferredBackBufferWidth = 500;
56            graphics.PreferredBackBufferHeight = 500;
57            Content.RootDirectory = "Content";
58        }
59
60        /// <summary>
61        /// Allows the game to perform any initialization it needs to before starting to run.
62        /// This is where it can query for any required services and load any non-graphic
63        /// related content.  Calling base.Initialize will enumerate through any components
64        /// and initialize them as well.
65        /// </summary>
66        protected override void Initialize()
67        {
68            // TODO: Add your initialization logic here
69            pixel = new Texture2D(GraphicsDevice, 1, 1);
70            pixel.SetData(new UInt32[] { UInt32.MaxValue });
71
72            base.Initialize();
73
74            renderImage();
75        }
76
77        void renderImage()
78        {
79            GraphicsDevice.Textures[0] = null;
80
81            //if (calcResolution[0] > 2048) { calcResolution[0] = 2048; }
82            //if (calcResolution[1] > 2048) { calcResolution[1] = 2048; }
83
84            int threads = 1;
85
86            imageSize = new Vector2(calcResolution[0], calcResolution[1]);
87            if (image!=null) image.Dispose();
88            System.Drawing.Bitmap[] images = new System.Drawing.Bitmap[threads];
89
90            //alusta fraktaalin numeerinen data
91            this.pointData = new decimal[(int)imageSize.X, (int)imageSize.Y][];
92
93            image = new System.Drawing.Bitmap((int)imageSize.X, (int)imageSize.Y);
94
95           
96            Thread[] apurit = new Thread[threads];
97
98            this.data = new Color[(int)imageSize.X * (int)imageSize.Y];
99
100            for (int y = 0; y < threads; y++)
101            {
102                int yy = y;
103                apurit[y] = new Thread(delegate(object o)
104                {
105                    int alku = ((int)imageSize.Y / threads) * yy;
106                    int loppu = ((int)imageSize.Y / threads) * (yy + 1);
107                    if (yy == threads - 1) { loppu = (int)imageSize.Y; }
108                   
109                    Test(alku, loppu);
110                });
111
112                apurit[y].Start(null);
113            }
114
115            for (int y = 0; y < threads; y++)
116            {
117                apurit[y].Join();
118            }
119
120            /*//yhdistä threadien omat imaget
121            int totalHeight = 0;
122            for (var g = 0; g < threads; g++) { totalHeight += images[g].Height; }
123
124            image = new System.Drawing.Bitmap((int)imageSize.X, (int)totalHeight);
125
126            */
127
128            Vector2 refSize = new Vector2(Math.Min(image.Width, 2048), Math.Min(image.Height, 2048));
129
130            Color[] pixels = new Color[(int)(refSize.X * refSize.Y)];
131            for (int y = 0; y < refSize.Y; y++)
132            {
133                for (int x = 0; x < refSize.X; x++)
134                {
135                    System.Drawing.Color c = image.GetPixel(x, y);
136                    pixels[(y * (int)refSize.X) + x] = new Color(c.R, c.G, c.B, c.A);
137                }
138            }
139
140            referenceImage = new Texture2D(GraphicsDevice, (int)refSize.X, (int)refSize.Y);
141            referenceImage.SetData<Color>(pixels);
142        }
143
144        void Test(int alku, int loppu)
145        {
146            Random random = new Random();
147
148            System.Drawing.Bitmap thisImage = new System.Drawing.Bitmap((int)imageSize.X, loppu - alku);
149
150            for (int y = alku; y < loppu; y++)
151            {
152                for (int x = 0; x < imageSize.X; x++)
153                {
154                    decimal VectorX = (gridScale[0] / (int)imageSize.X) * x - (gridScale[0] / 2M) + gridOffset[0];
155                    decimal VectorY = (gridScale[1] / (int)imageSize.Y) * y - (gridScale[1] / 2M) + gridOffset[1];
156                    pointData[x, y] = new decimal[4] { VectorX, VectorY, VectorX, VectorY };
157                    for (int iterations = 0; iterations < calcIterations; iterations++)
158                    {
159                        if (doesPointEscape(this.pointData[x, y]))
160                        {
161                            image.SetPixel(x, y, getColor(iterations, calcIterations + 1));
162                            break;
163                        }
164                        else
165                        {
166                            pointData[x, y] = iteration2d(pointData[x, y]);
167                        }
168                    }
169                }
170            }
171        }
172
173        bool doesPointEscape(decimal[] vec)
174        {
175            if (vec[0] * vec[0] + vec[1] * vec[1] > 4) return true;
176            return false;
177        }
178
179        decimal[] iteration2d(decimal[] vec)
180        {
181            decimal[] nvec = new decimal[4];
182            decimal branchLevel = 2M;
183            nvec[0] =
184                branchLevel * vec[0] - vec[1] * vec[1] - branchLevel * vec[1] * vec[0] * vec[0]; // branch
185            //vec[0] * vec[0] - vec[1] * vec[1] + vec[2]; // mandelbrot
186            nvec[1] =
187                branchLevel * vec[1] - vec[0] * vec[0] - branchLevel * vec[0] * vec[1] * vec[1]; // branch
188            //2M * vec[0] * vec[1] + vec[3]; // mandelbrot
189            nvec[2] = vec[2];
190            nvec[3] = vec[3];
191            return nvec;
192        }
193
194        /// <summary>
195        /// LoadContent will be called once per game and is the place to load
196        /// all of your content.
197        /// </summary>
198        protected override void LoadContent()
199        {
200            // Create a new SpriteBatch, which can be used to draw textures.
201            spriteBatch = new SpriteBatch(GraphicsDevice);
202            command = Content.Load<SpriteFont>("fonts/c");
203
204            // TODO: use this.Content to load your game content here
205        }
206
207        /// <summary>
208        /// UnloadContent will be called once per game and is the place to unload
209        /// all content.
210        /// </summary>
211        protected override void UnloadContent()
212        {
213
214        }
215
216        /// <summary>
217        /// Allows the game to run logic such as updating the world,
218        /// checking for collisions, gathering input, and playing audio.
219        /// </summary>
220        /// <param name="gameTime">Provides a snapshot of timing values.</param>
221
222        bool isKeyPressed(Keys key)
223        {
224            return keyboardState.IsKeyDown(key) && oldKeyboardState.IsKeyUp(key);
225        }
226
227        void runCommand(String commandStr)
228        {
229            char splitChar;
230            Char.TryParse(" ", out splitChar);
231            string[] commandSplit = commandStr.Split(splitChar);
232            try
233            {
234                switch (commandSplit[0])
235                {
236                    case "I"://set iterations
237                        calcIterations = Convert.ToInt32(commandSplit[1]);
238                        break;
239                    case "R"://set resolution
240                        switch (commandSplit[1])
241                        {
242                            case "X":
243                                calcResolution[0] = Convert.ToInt32(commandSplit[2]);
244                                break;
245                            case "Y":
246                                calcResolution[1] = Convert.ToInt32(commandSplit[2]);
247                                break;
248                            case "F":
249                                calcResolution[0] = Window.ClientBounds.Width;
250                                calcResolution[1] = Window.ClientBounds.Height;
251                                break;
252                            case "A":
253                                calcResolution[0] = Math.Max(calcResolution[0], calcResolution[1]);
254                                calcResolution[1] = Math.Max(calcResolution[0], calcResolution[1]);
255                                break;
256                            case "I":
257                                calcResolution[0] = Math.Min(calcResolution[0], calcResolution[1]);
258                                calcResolution[1] = Math.Min(calcResolution[0], calcResolution[1]);
259                                break;
260                            default:
261                                calcResolution[0] = Convert.ToInt32(commandSplit[1]);
262                                calcResolution[1] = Convert.ToInt32(commandSplit[1]);
263                                break;
264                        }
265                        break;
266                    case "P"://set position
267                        switch (commandSplit[1])
268                        {
269                            case "X":
270                                gridOffset[0] = decimal.Parse(commandSplit[2]);
271                                break;
272                            case "Y":
273                                gridOffset[1] = decimal.Parse(commandSplit[2]);
274                                break;
275                            case "O":
276                                gridOffset[0] = 0;
277                                gridOffset[1] = 0;
278                                break;
279                            default:
280                                gridOffset[0] = decimal.Parse(commandSplit[1]);
281                                gridOffset[1] = decimal.Parse(commandSplit[1]);
282                                break;
283                        }
284                        break;
285                    case "H"://hide / show hud
286                        infoHide = !infoHide;
287                        break;
288                    case "W"://set window size
289                        graphics.IsFullScreen = false;
290                        switch (commandSplit[1])
291                        {
292                            case "X":
293                                graphics.PreferredBackBufferWidth = Convert.ToInt32(commandSplit[2]);
294                                break;
295                            case "Y":
296                                graphics.PreferredBackBufferHeight = Convert.ToInt32(commandSplit[2]);
297                                break;
298                            case "F":
299                                graphics.PreferredBackBufferWidth = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width;
300                                graphics.PreferredBackBufferHeight = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height;
301                                graphics.IsFullScreen = true;
302                                break;
303                            default:
304                                graphics.PreferredBackBufferWidth = Convert.ToInt32(commandSplit[1]);
305                                graphics.PreferredBackBufferHeight = Convert.ToInt32(commandSplit[1]);
306                                break;
307                        }
308                        graphics.ApplyChanges();
309                        break;
310                    case "S"://Save image
311                        string filePath = "";
312                        if (commandSplit.Length == 1)
313                        {
314                            filePath = DateTime.Now.ToString("MM-dd-yy H;mm;ss") + ".png";
315                        }
316                        else
317                        {
318                            filePath = commandSplit[1] + ".png";
319                        }
320                        //Stream stream = File.Create(filePath);
321                        image.Save(filePath);
322                        //stream.Dispose();
323                        break;
324                    case "RUN"://render
325                        renderImage();
326                        break;
327                    case "EXIT"://exit
328                        Exit();
329                        break;
330                }
331            }
332            catch (System.Exception e)
333            {
334                errorMessage = e.Message;
335            }
336        }
337
338        void commandTypeCheck()
339        {
340            if (isKeyPressed(Keys.Enter))
341            {
342                runCommand(commandStr);
343                commandStr = "";
344            }
345            if (isKeyPressed(Keys.Back))
346            {
347                if (commandStr != "")
348                    commandStr = commandStr.Substring(0, commandStr.Length - 1);
349            }
350            if (isKeyPressed(Keys.D1)) { commandStr += "1"; }
351            if (isKeyPressed(Keys.D2)) { commandStr += "2"; }
352            if (isKeyPressed(Keys.D3)) { commandStr += "3"; }
353            if (isKeyPressed(Keys.D4)) { commandStr += "4"; }
354            if (isKeyPressed(Keys.D5)) { commandStr += "5"; }
355            if (isKeyPressed(Keys.D6)) { commandStr += "6"; }
356            if (isKeyPressed(Keys.D7)) { commandStr += "7"; }
357            if (isKeyPressed(Keys.D8)) { commandStr += "8"; }
358            if (isKeyPressed(Keys.D9)) { commandStr += "9"; }
359            if (isKeyPressed(Keys.D0)) { commandStr += "0"; }
360            if (isKeyPressed(Keys.OemComma)) { commandStr += ","; }
361
362            if (isKeyPressed(Keys.Q)) { commandStr += "Q"; }
363            if (isKeyPressed(Keys.W)) { commandStr += "W"; }
364            if (isKeyPressed(Keys.E)) { commandStr += "E"; }
365            if (isKeyPressed(Keys.R)) { commandStr += "R"; }
366            if (isKeyPressed(Keys.T)) { commandStr += "T"; }
367            if (isKeyPressed(Keys.Y)) { commandStr += "Y"; }
368            if (isKeyPressed(Keys.U)) { commandStr += "U"; }
369            if (isKeyPressed(Keys.I)) { commandStr += "I"; }
370            if (isKeyPressed(Keys.O)) { commandStr += "O"; }
371            if (isKeyPressed(Keys.P)) { commandStr += "P"; }
372            if (isKeyPressed(Keys.A)) { commandStr += "A"; }
373            if (isKeyPressed(Keys.S)) { commandStr += "S"; }
374            if (isKeyPressed(Keys.D)) { commandStr += "D"; }
375            if (isKeyPressed(Keys.F)) { commandStr += "F"; }
376            if (isKeyPressed(Keys.G)) { commandStr += "G"; }
377            if (isKeyPressed(Keys.H)) { commandStr += "H"; }
378            if (isKeyPressed(Keys.J)) { commandStr += "J"; }
379            if (isKeyPressed(Keys.K)) { commandStr += "K"; }
380            if (isKeyPressed(Keys.L)) { commandStr += "L"; }
381            if (isKeyPressed(Keys.Z)) { commandStr += "Z"; }
382            if (isKeyPressed(Keys.X)) { commandStr += "X"; }
383            if (isKeyPressed(Keys.C)) { commandStr += "C"; }
384            if (isKeyPressed(Keys.V)) { commandStr += "V"; }
385            if (isKeyPressed(Keys.B)) { commandStr += "B"; }
386            if (isKeyPressed(Keys.N)) { commandStr += "N"; }
387            if (isKeyPressed(Keys.M)) { commandStr += "M"; }
388            if (isKeyPressed(Keys.Space)) { commandStr += " "; }
389        }
390
391        protected override void Update(GameTime gameTime)
392        {
393            // Allows the game to exit
394
395            this.gameTime = gameTime;
396
397            this.keyboardState = Keyboard.GetState();
398
399            if (isKeyPressed(Keys.Left))
400            {
401                gridOffset[0] -= gridScale[0] / 10M;//kymmenes imagen koosta
402                renderImage();
403            }
404            else if (isKeyPressed(Keys.Right))
405            {
406                gridOffset[0] += gridScale[0] / 10M;
407                renderImage();
408            }
409            if (isKeyPressed(Keys.Up))
410            {
411                gridOffset[1] -= gridScale[1] / 10M;
412                renderImage();
413            }
414            else if (isKeyPressed(Keys.Down))
415            {
416                gridOffset[1] += gridScale[1] / 10M;
417                renderImage();
418            }
419
420            if (isKeyPressed(Keys.Add))
421            {
422                if (keyboardState.IsKeyDown(Keys.LeftShift))
423                {
424                    calcResolution[0] *= 2;
425                    calcResolution[1] *= 2;
426                }
427                else
428                {
429                    calcResolution[0] += 1;
430                    calcResolution[1] += 1;
431                }
432                renderImage();
433            }
434            else if (isKeyPressed(Keys.Subtract))
435            {
436                if (keyboardState.IsKeyDown(Keys.LeftShift))
437                {
438                    calcResolution[0] /= 2;
439                    calcResolution[1] /= 2;
440                }
441                else
442                {
443                    calcResolution[0] -= 1;
444                    calcResolution[1] -= 1;
445                }
446                if (calcResolution[0] < 1 || calcResolution[1] < 1) { calcResolution = new int[2] { 1, 1 }; };
447                renderImage();
448            }
449
450            if (isKeyPressed(Keys.OemPlus))
451            {
452                if (keyboardState.IsKeyDown(Keys.LeftShift))
453                {
454                    calcIterations *= 2;
455                }
456                else
457                {
458                    calcIterations += 1;
459                }
460                renderImage();
461            }
462            else if (isKeyPressed(Keys.OemMinus))
463            {
464                if (keyboardState.IsKeyDown(Keys.LeftShift))
465                {
466                    calcIterations /= 2;
467                }
468                else
469                {
470                    calcIterations -= 1;
471                }
472                if (calcIterations < 1) { calcIterations = 1; };
473                renderImage();
474            }
475
476            if (keyboardState.IsKeyDown(Keys.Escape))
477                this.Exit();
478
479            commandTypeCheck();
480
481            this.mouseState = Mouse.GetState();
482
483            if (this.mouseState.ScrollWheelValue != this.oldMouseState.ScrollWheelValue)
484            {
485                if (this.mouseState.ScrollWheelValue > this.oldMouseState.ScrollWheelValue)
486                {
487                    gridScale[0] /= 1.1M;
488                    gridScale[1] /= 1.1M;
489                }
490                else if (this.mouseState.ScrollWheelValue < this.oldMouseState.ScrollWheelValue)
491                {
492                    gridScale[0] *= 1.1M;
493                    gridScale[1] *= 1.1M;
494                }
495                renderImage();
496            }
497
498            // TODO: Add your update logic here
499
500            this.oldMouseState = mouseState;
501            this.oldKeyboardState = keyboardState;
502
503            base.Update(gameTime);
504        }
505
506        void startRender()
507        {
508            viewportSize.X = Window.ClientBounds.Width;
509            viewportSize.Y = Window.ClientBounds.Height;
510        }
511
512        /// <summary>
513        /// This is called when the game should draw itself.
514        /// </summary>
515        /// <param name="gameTime">Provides a snapshot of timing values.</param>
516        System.Drawing.Color getColor(float index, float size)
517        {
518            Color[] palette = { new Color(0, 0, 0), new Color(255, 0, 0), new Color(255, 255, 0), new Color(0, 255, 0), new Color(0, 255, 255), new Color(0, 0, 255), new Color(0, 0, 0) };
519            index = Math.Abs(index);
520            index = index % size;
521            size--;
522            float realIndex = ((float)Math.Floor(index) / size) * (palette.Length - 1);
523            Color col1 = palette[(int)Math.Floor(realIndex)];
524            Color col2 = palette[(int)Math.Ceiling(realIndex)];
525            float rel = realIndex - (float)Math.Floor(realIndex);
526            return convertColor(Color.Lerp(col1, col2, rel));
527        }
528        System.Drawing.Color convertColor(Color color)
529        {
530            return System.Drawing.Color.FromArgb(color.R, color.G, color.B);
531        }
532        protected override void Draw(GameTime gameTime)
533        {
534            GraphicsDevice.Clear(Color.White);
535            // TODO: Add your drawing code here
536
537            spriteBatch.Begin();
538            spriteBatch.Draw(referenceImage, new Rectangle(0, 0, Window.ClientBounds.Width, Window.ClientBounds.Height), Color.White);
539            spriteBatch.DrawString(command, commandStr, new Vector2(0, 0), Color.Gray);
540            if (!infoHide)
541            {
542                spriteBatch.DrawString(command,
543                    "i:" + calcIterations + " r:(" + calcResolution[0] + "," + calcResolution[1] +
544                    ")\nP:(" + gridOffset[0] +
545                    ",\n" + gridOffset[1] +
546                    ")\ns:" + gridScale[0]
547                    , new Vector2(0, Window.ClientBounds.Height - command.LineSpacing * 4), Color.HotPink);
548                spriteBatch.DrawString(command, errorMessage, new Vector2(Window.ClientBounds.Width - command.MeasureString(errorMessage).X, 0), Color.Red);
549            }
550            spriteBatch.End();
551
552            base.Draw(gameTime);
553        }
554    }
555}
Note: See TracBrowser for help on using the repository browser.