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