/// <summary> /// This currently just saves the name of the level to the /Content/Saves directory in xml form /// </summary> /// <param name="level">the level to be saved</param> /// <param name="fileName">the name of the file to save it to, no extensions, no paths</param> public static void saveGame(Level level, String fileName) { if (!level.player.isDead) { //create a new writer for the file using UTF-8 XmlTextWriter xml = new XmlTextWriter(fileName, Encoding.UTF8); String filename = level.levelName.Split("\\".ToCharArray()).Last(); //write the level's filename xml.WriteStartElement("Level"); xml.WriteAttributeString("fileName", filename); //write out <player x="?" y="?" coins="?"></player> xml.WriteStartElement("player"); xml.WriteAttributeString("x", level.player.position.X.ToString()); xml.WriteAttributeString("y", level.player.position.Y.ToString()); xml.WriteAttributeString("coins", level.player.numCoins.ToString()); xml.WriteFullEndElement(); //write out each coin as <coin x="?" y="?"></coin> where ? is an integer foreach (Vector2 coin in level.usedCoins) { xml.WriteStartElement("coin"); xml.WriteAttributeString("x", coin.X.ToString()); xml.WriteAttributeString("y", coin.Y.ToString()); xml.WriteFullEndElement(); } //write out each used button as <button x="?" y="?" numTimes="?"></button> Where ? is an integer foreach (KeyValuePair<Vector2, int> button in level.usedButtons) { xml.WriteStartElement("button"); xml.WriteAttributeString("x", button.Key.X.ToString()); xml.WriteAttributeString("y", button.Key.Y.ToString()); xml.WriteAttributeString("numTimes", button.Value.ToString()); xml.WriteFullEndElement(); } //writeout hook position & data xml.WriteStartElement("hook"); xml.WriteAttributeString("x", level.player.theHook.position.X.ToString()); xml.WriteAttributeString("y", level.player.theHook.position.Y.ToString()); xml.WriteAttributeString("extended", level.player.hookExtended.ToString()); xml.WriteFullEndElement(); //write </Level> and close the IO operations xml.WriteFullEndElement(); xml.Close(); MoonPrison.displayMessage("Game Saved"); } }
/// <summary> /// Allows the game to run logic such as updating the world, /// checking for collisions, gathering input, and playing audio. /// </summary> /// <param name="gameTime">Provides a snapshot of timing values.</param> protected override void Update(GameTime gameTime) { //get the new state of the game MouseState ms = Mouse.GetState(); KeyboardState ks = Keyboard.GetState(); float dt = (float)gameTime.ElapsedGameTime.TotalSeconds; removeOldMessages(); if ((ks.IsKeyDown(Keys.Escape) && isKeyUp)) { menu.isDisplayed = !menu.isDisplayed; isKeyUp = false; } if (ks.IsKeyUp(Keys.Escape)) { isKeyUp = true; } if (ks.IsKeyDown(Keys.F5)) { saveGame(StorageContainer.TitleLocation + FileIOManager.SAVE_PREFIX + "quick-" + level.levelName + FileIOManager.SAVE_EXTENSION); } if (ks.IsKeyDown(Keys.F6)) { try { loadGame(StorageContainer.TitleLocation + FileIOManager.SAVE_PREFIX + "quick-" + level.levelName + FileIOManager.SAVE_EXTENSION); } catch (Exception e) { displayMessage("No quicksave found"); e.ToString(); } } if (menu.isDisplayed || level == null) { menu.Update(ms, ks, this); } else if (easter && ks.IsKeyDown(Keys.Y)) { int tempCoins = level.player.numCoins; level = FileIOManager.loadLevel(StorageContainer.TitleLocation + FileIOManager.LEVEL_PREFIX + LEVEL_ORDER[++levelNumber],Content); level.LoadContent_OLD(Content); level.player.numCoins = tempCoins; easter = false; hasEaster = true; displayMessage("Resolution succeded: now using 'OLDSKOOL'"); } else { Particle_Engine.ParticleEngine.update(dt); //update components if (!level.gameOver) { int[] soundNums = level.Update(dt, ms, ks, IsActive); for (int i = 0; i < soundNums.Length; i++) { if (soundNums[i] == 1) { FX[i].Play(); } } //if the lazer isnt playing, play it once if (soundNums[2] == 2 && !lazer.State.Equals(SoundState.Playing)) lazer.Play(); //if it was playing but should stop before firing, then stop it if (soundNums[2] < 2 && lazer.State.Equals(SoundState.Playing)) { lazer.Dispose(); lazer = FX[FX.Length -1].CreateInstance(); } } else { displayMessage("Press 'r' to restart the level or ESC to exit"); if (ks.IsKeyDown(Keys.R)) { int tempCoins = level.player.numCoins - level.usedCoins.Count; Particle_Engine.ParticleEngine.reset(); level = FileIOManager.loadLevel(StorageContainer.TitleLocation + FileIOManager.LEVEL_PREFIX + level.levelName,Content); if (!hasEaster) level.LoadContent(Content); else level.LoadContent_OLD(Content); level.player.numCoins = tempCoins; } } if (level.levelCompleted) { if (linearOrder) { int tempCoins = level.player.numCoins; if (tempCoins % EASTER_EGG_THRESHOLD == 0 && !hasEaster && levelNumber < LEVEL_ORDER.Length - 1 && tempCoins > 0) { easter = true; } else if (levelNumber < LEVEL_ORDER.Length - 1 && !easter) { Particle_Engine.ParticleEngine.reset(); level = FileIOManager.loadLevel(StorageContainer.TitleLocation + FileIOManager.LEVEL_PREFIX + LEVEL_ORDER[++levelNumber], Content); if (!hasEaster) level.LoadContent(Content); else { hasEaster = false; level.LoadContent_OLD(Content); } level.player.numCoins = tempCoins; } } else { menu.isDisplayed = true; } } } base.Update(gameTime); }
public static Level loadLevel(string fileName,ContentManager Content) { Level level = new Level(); level.levelName = fileName.Split("\\".ToCharArray()).Last(); //read in the level layout FileStream file = new FileStream(fileName + ".level", FileMode.OpenOrCreate, FileAccess.Read); StreamReader fileIn = new StreamReader(file); Vector2 endpos = Vector2.Zero; level.levelW = int.Parse(fileIn.ReadLine()); level.levelH = int.Parse(fileIn.ReadLine()); level.layout = new Tile[level.levelW, level.levelH]; for (int y = 0; y < level.levelH; y++) { String line = fileIn.ReadLine(); String[] buffer = line.Split(new char[] { ' ' }); for (int x = 0; x < level.levelW; x++) { level.layout[x, y] = new Tile(int.Parse(buffer[x])); Vector2 position = new Vector2(); position.X = x * Level.tileWidth + Level.tileWidth / 2; position.Y = y * Level.tileHeight + Level.tileHeight / 2; level.layout[x, y].position = position; level.layout[x, y].setWidth(Level.tileWidth); level.layout[x, y].setHeight(Level.tileHeight); level.layout[x, y].updateBound(); } } fileIn.Close(); file.Close(); //read the associated XML file XmlTextReader xml = new XmlTextReader(fileName + ".xml"); while (xml.Read()) { if (xml.Name == "level" && xml.HasAttributes) { int x = int.Parse(xml.GetAttribute("endX")); int y = int.Parse(xml.GetAttribute("endY")); level.layout[x, y].assignBooleans(6); int px = int.Parse(xml.GetAttribute("startX")); int py = int.Parse(xml.GetAttribute("startY")); level.player.position = new Vector2(px * Level.tileWidth + Level.tileWidth / 2, py * Level.tileHeight); } //if the node is a tag if (xml.NodeType == XmlNodeType.Element) { //if the tag is a button if (xml.Name == "button") { Dictionary<string, string> enemyFields = new Dictionary<string, string>(); Dictionary<string, string> buttonFields = new Dictionary<string, string>(); LinkedList<string> messages = new LinkedList<string>(); int buttonX = int.Parse(xml.GetAttribute("x")); int buttonY = int.Parse(xml.GetAttribute("y")); int numUses = int.Parse(xml.GetAttribute("uses")); string[] useActions = new string[numUses]; Vector3[][] targets = new Vector3[numUses][]; xml.MoveToAttribute(0); for (int i = 0; i < xml.AttributeCount; i++) { buttonFields.Add(xml.Name, xml.Value); xml.MoveToNextAttribute(); } //while we haven't gotten to the end of the button xml.Read(); while (xml.Name != "button") { if (xml.NodeType == XmlNodeType.Element && xml.Name.StartsWith("use")) { LinkedList<Vector3> useTargets = new LinkedList<Vector3>(); int number = int.Parse(xml.Name.Substring(3)); string variety = xml.GetAttribute("type"); useActions[number] = variety; xml.Read(); while (!xml.Name.StartsWith("use")) { //read in nodes, which are all targets //each target has a point corresponding to a tile in the layout and a type to change that tile to if (xml.NodeType == XmlNodeType.Element && xml.Name == "target") { int x = int.Parse(xml.GetAttribute("x")); int y = int.Parse(xml.GetAttribute("y")); int type = int.Parse(xml.GetAttribute("type")); useTargets.AddLast(new Vector3(x, y, type)); level.layout[x, y].isChangedbyButton = true; } else if (xml.NodeType == XmlNodeType.Element && xml.Name == "enemy") { xml.MoveToAttribute(0); for (int i = 0; i < xml.AttributeCount; i++) { enemyFields.Add(xml.Name, xml.Value); xml.MoveToNextAttribute(); } } else if (xml.NodeType == XmlNodeType.Element && xml.Name == "display") { messages.AddLast(xml.GetAttribute("message")); } xml.Read(); } targets[number] = useTargets.ToArray(); } xml.Read(); } Button b = new Button(); b.useActions = useActions; b.enemyParams = enemyFields; b.messages = messages; b.tiles = targets.ToArray(); foreach (KeyValuePair<string, string> entry in buttonFields) { if (entry.Key == "uses") { b.totalUses = int.Parse(entry.Value); b.isMultipleUse = (b.totalUses > 1); } else if (entry.Key == "cycles") { b.cycles = Boolean.Parse(entry.Value); } else if (entry.Key == "sensor") { b.isMotionSensor = Boolean.Parse(entry.Value); } } if (b.isMotionSensor) { b.assignBooleans(7); } level.layout[buttonX, buttonY] = b; Vector2 position = new Vector2(); position.X = buttonX * Level.tileWidth + Level.tileWidth/2; position.Y = buttonY * Level.tileHeight+Level.tileHeight/2; level.layout[buttonX, buttonY].position = position; level.layout[buttonX, buttonY].setWidth(Level.tileWidth); level.layout[buttonX, buttonY].setHeight(Level.tileHeight); level.layout[buttonX, buttonY].origin = new Vector2(Level.tileWidth, Level.tileHeight) * .05f; level.layout[buttonX, buttonY].updateBound(); } //the player xml name sets player initial position else if (xml.Name == "player") { int playerX = int.Parse(xml.GetAttribute("x")); int playerY = int.Parse(xml.GetAttribute("y")); level.player.position = new Vector2(playerX * Level.tileWidth, playerY * Level.tileHeight); } //enemy expects an initial position else if (xml.Name == "enemy") { Dictionary<string,string> fields = new Dictionary<string,string>(); xml.MoveToAttribute(0); for (int i = 0; i < xml.AttributeCount; i++) { fields.Add(xml.Name,xml.Value); xml.MoveToNextAttribute(); } level.enemies.AddLast(FileIOManager.createEnemyWithParams(fields)); } } } xml.Close(); return level; }
//do actual game loading - to be called from ShellMenu public void loadGame(string fileName) { MoonPrison.clearMessages(); level = FileIOManager.loadGame(fileName, Content); level.LoadContent(Content); if (this.LEVEL_ORDER.Contains(level.levelName)) { linearOrder = true; levelNumber = Array.IndexOf(LEVEL_ORDER, level.levelName); } System.Threading.Thread.Sleep(50); }