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

Revision 5656, 17.0 KB checked in by mijoilmo, 6 years ago (diff)

fraktaaleja!

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