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

Revision 5701, 24.2 KB checked in by mijoilmo, 5 years ago (diff)

frakt
hiirellä navigointi

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