source: 2013/27/JaakkoL/RampageRebellion/RampageRebellion/RampageRebellion/RREnemySpawner.cs @ 4490

Revision 4490, 10.1 KB checked in by jaollipa, 10 years ago (diff)

PRE-ALPHA 1.0

Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using System.Xml;
6using System.IO;
7using System.Threading;
8using System.Diagnostics;
9using Jypeli;
10using Jypeli.Assets;
11using Jypeli.Controls;
12using Jypeli.Effects;
13using Jypeli.Widgets;
14
15/* Teemun TODO
16 * - Arcade Mode: high score
17 * - Enemy AI
18 * - Common enemy framework
19 * - Actual level design: -THR
20 */
21public class RREnemySpawner
22{
23    private string gameMode = "";
24    private Thread spawnerThread;
25    public bool isPaused = false;
26
27    public RREnemySpawner(string requestedGameMode)
28    {
29        gameMode = requestedGameMode;
30
31        if (gameMode == "arcade")
32        {
33            spawnerThread = new Thread(arcade);
34        }
35        else if (gameMode == "levels")
36        {
37            List<RRLevel> levelList = new List<RRLevel>();
38            levelList = loadLevelsFromXML();
39            spawnerThread = new Thread(delegate() { executeLevelList(levelList); });
40        }
41        else
42        {
43            // Throw an exception!
44        }
45
46        spawnerThread.Start();
47        spawnerThread.IsBackground = true;
48    }
49
50    public void arcade()
51    {
52        Stopwatch stopwatch = new Stopwatch();
53        stopwatch.Start();
54
55        double multiplier = 1.0;
56
57        RampageRebellion game = RampageRebellion.getGame();
58        Jypeli.Timer t = new Jypeli.Timer();
59        t.Interval = 1.0;
60
61        t.Timeout += delegate {
62            // The multiplier function
63            multiplier = (Math.Pow(1.01, (double)stopwatch.ElapsedMilliseconds / 10000));
64            Console.WriteLine(multiplier);
65            game.Add(new SmallEnemy(inCenteredXCoordinates(RandomGen.NextInt(-300, 300)), 
66                                    inRelativeYCoordinates(RandomGen.NextInt(0, 200), "Small"),
67                                    multiplier));
68            t.Interval = RandomGen.NextDouble(1.0, 2.0);
69        };
70        t.Start();
71
72        // Stops the stopwatch when paused, and resumes it when unpaused. // DOESN'T WORK!!
73        while (true)
74        {
75            if (isPaused) { stopwatch.Stop(); Console.WriteLine("Stopped"); }
76            while (isPaused) { Thread.Sleep(1); }
77            if (!isPaused) { stopwatch.Start(); Console.WriteLine("Resumed"); }
78        }
79    }
80
81    private List<RRLevel> loadLevelsFromXML()
82    {
83        // The string to contain the XML data
84        String XMLFile;
85
86        // The type of the enemy to be created
87        String enemyType = "";
88
89        // The coordinates for the enemy
90        double x = 0.0;
91        double y = 0.0;
92
93        List<RRLevel> levelList = new List<RRLevel>();
94
95        // Read the XML data from the file
96        using (StreamReader sr = new StreamReader("Content/levels.xml"))
97        {
98            XMLFile = sr.ReadToEnd();
99        }
100
101        using (XmlReader reader = XmlReader.Create(new StringReader(XMLFile)))
102        {
103            while (reader.ReadToFollowing("level"))
104            {
105                // Creates a new level object to which the waves are added
106                RRLevel currentLevel = new RRLevel();
107
108                // The XMLReader first reads to the first element and then to that element's siblings
109                // This way it doesn't "leak" and read every element in the file
110                reader.ReadToFollowing("wave");
111                do
112                {
113                    reader.ReadToFollowing("enemy");
114                    do
115                    {
116                        reader.MoveToFirstAttribute();      // The type of the enemy (small, medium etc.)
117                        enemyType = reader.Value;
118                        reader.MoveToNextAttribute();       // The x-coordinate
119                        x = Convert.ToDouble(reader.Value);
120                        reader.MoveToNextAttribute();       // The y-coordinate
121                        y = Convert.ToDouble(reader.Value);
122
123                        // In the relative coordinates, the top left corner of the enemy
124                        // is in the top left corner of the screen when (x, y) = (0, 0)
125                        x = inCenteredXCoordinates(x);
126                        y = inRelativeYCoordinates(y, enemyType);
127
128                        // Adds an enemy to the current RRLevel object
129                        if (enemyType == "Small") currentLevel.addEnemy(new SmallEnemy(x, y));
130                        else if (enemyType == "Medium") currentLevel.addEnemy(new MediumEnemy(x, y));
131                        else if (enemyType == "Big") currentLevel.addEnemy(new BigEnemy(x, y));
132                        else if (enemyType == "Boss") currentLevel.addEnemy(new BossEnemy(x, y));
133                        else
134                        {
135                            // Throw an exception, since the type of the enemy is unknown.
136                        }
137
138                    } while (reader.ReadToNextSibling("enemy"));
139
140                    // Notifies the Level object that we're moving to a new wave
141                    currentLevel.initNewWave();
142
143                } while (reader.ReadToNextSibling("wave"));
144
145                // Adds the current Level object to the list of level objects
146                levelList.Add(currentLevel);
147                currentLevel = null;
148            }
149        }
150
151        // Debugging: Reads back the structure
152        /*foreach (RRLevel level in levelList)
153        {
154            Console.WriteLine("Level");
155            level.listAll();
156        }*/
157
158        return levelList;
159    }
160
161    private void executeLevelList(List<RRLevel> levelList)
162    {
163        while (levelList.Count > 0)
164        {
165            while (levelList[0].wavesLeft() > 0)
166            {
167                levelList[0].spawnThisWave();
168
169                // Wait until there are no more enemies, and then spawn the next wave.
170                while (levelList[0].enemiesLeftInCurrentWave() > 0) { Thread.Sleep(1); }
171                levelList[0].removeThisWave();
172
173                // Wait for two seconds before launching the next wave.
174                Thread.Sleep(2000);
175
176                // Play wave end music
177                SoundEffect waveIncoming = Jypeli.Game.LoadSoundEffect("Bomb2-Warp2");
178                waveIncoming.Play();
179
180                Thread.Sleep(2890);
181
182                while (isPaused) { Thread.Sleep(1); }
183            }
184
185            // Remove the finished level
186            levelList.RemoveAt(0);
187
188            RampageRebellion.getGame().UpgradeMenu();
189        }
190
191        // We're done!
192        RampageRebellion.getGame().GameEnd();
193    }
194
195    // The first correction term gets the enemy's center to the top left screen
196    // and the second term moves the enemy so that it isn't immediately destroyed.
197    private double inRelativeXCoordinates(double originalX, string enemyType)
198    {
199        return originalX - 517 + (getEnemySizeByType(enemyType) / 2);
200    }
201
202    private double inRelativeYCoordinates(double originalY, string enemyType)
203    {
204        return (-originalY) + 485 - (getEnemySizeByType(enemyType) / 2);
205    }
206
207    private double inCenteredXCoordinates(double originalX)
208    {
209        return originalX - 190;
210    }
211    private double getEnemySizeByType(string enemyType)
212    {
213        if (enemyType == "Small") return RampageRebellion.SMALLENEMY_SIZE;
214        else if (enemyType == "Medium") return RampageRebellion.MEDENEMY_SIZE;
215        else if (enemyType == "Big") return RampageRebellion.BIGENEMY_SIZE;
216        else if (enemyType == "Boss") return RampageRebellion.BOSS_SIZE;
217        else return 0; // Shouldn't ever happen!
218    }
219
220    private class RRLevel
221    {
222        private List<RRWave> waveList = new List<RRWave>();
223        private RRWave currentWave = new RRWave();
224
225        public void addEnemy(RREnemy enemy)
226        {
227            currentWave.addEnemy(enemy);
228        }
229
230        // Called when the parser is moving to the next wave, so the current wave should be added to the list
231        public void initNewWave()
232        {
233            waveList.Add(currentWave);
234
235            // Resets the wave
236            currentWave = null;
237            currentWave = new RRWave();
238        }
239
240        public void spawnThisWave()
241        {
242            if (waveList.Count > 0)
243            {
244                waveList[0].spawn();
245            }
246            else
247            {
248                // Throw an exception!
249            }
250        }
251
252        // Mostly for debugging; should use spawnThisWave() instead
253        public void spawnAllWaves()
254        {
255            foreach (RRWave wave in waveList)
256            {
257                wave.spawn();
258            }
259        }
260
261        public int enemiesLeftInCurrentWave()
262        {
263            return waveList[0].enemiesLeft();
264        }
265
266        // Mostly for debugging purposes
267        public void listAll()
268        {
269            foreach (RRWave wave in waveList)
270            {
271                Console.WriteLine("\tWave");
272                wave.listAll();
273            }
274        }
275
276        public int wavesLeft()
277        {
278            return waveList.Count;
279        }
280
281        public void removeThisWave()
282        {
283            waveList.RemoveAt(0);
284        }
285    }
286
287    private class RRWave
288    {
289        private List<RREnemy> enemyList = new List<RREnemy>();
290
291        public void addEnemy(RREnemy enemy)
292        {
293            enemyList.Add(enemy);
294        }
295
296        public void spawn()
297        {
298            RampageRebellion game = RampageRebellion.getGame();
299
300            foreach (RREnemy enemy in enemyList)
301            {
302                game.Add(enemy);
303            }
304        }
305
306        public int enemiesLeft()
307        {
308            // We must manually remove destroyed enemies
309            enemyList.RemoveAll(delegate(RREnemy e)
310            {
311                if (e.IsDestroyed) return true;
312                else return false;
313            });
314            return enemyList.Count;
315        }
316
317        public void listAll()
318        {
319            foreach (RREnemy enemy in enemyList)
320            {
321                Console.WriteLine("\t\tEnemy");
322            }
323        }
324    }
325}
Note: See TracBrowser for help on using the repository browser.