private SoundInfo LoadSound(XElement soundNode, string basePath)
        {
            SoundInfo sound = new SoundInfo { Name = soundNode.RequireAttribute("name").Value };

            sound.Loop = soundNode.TryAttribute<bool>("loop");

            sound.Volume = soundNode.TryAttribute<float>("volume", 1);

            XAttribute pathattr = soundNode.Attribute("path");
            XAttribute trackAttr = soundNode.Attribute("track");
            if (pathattr != null)
            {
                sound.Type = AudioType.Wav;
                sound.Path = FilePath.FromRelative(pathattr.Value, basePath);
            }
            else if (trackAttr != null)
            {
                sound.Type = AudioType.NSF;

                int track;
                if (!trackAttr.Value.TryParse(out track) || track <= 0) throw new GameXmlException(trackAttr, "Sound track attribute must be an integer greater than zero.");
                sound.NsfTrack = track;

                sound.Priority = soundNode.TryAttribute<byte>("priority", 100);
            }
            else
            {
                sound.Type = AudioType.Unknown;
            }

            return sound;
        }
示例#2
0
        public static Effect ParseEffect(XElement effectNode)
        {
            var name = effectNode.RequireAttribute("name").Value;
            var value = effectNode.RequireAttribute("value").Value;

            return e => { e.GetComponent<VarsComponent>().Set(name, value); };
        }
 public SceneBindingInfo Load(XElement node)
 {
     var info = new SceneBindingInfo();
     info.Source = node.RequireAttribute("source").Value;
     info.Target = node.RequireAttribute("target").Value;
     return info;
 }
        private PaletteInfo PaletteFromXml(XElement node, string baseDir)
        {
            var palette = new PaletteInfo();

            var imagePathRelative = node.RequireAttribute("image").Value;
            palette.ImagePath = FilePath.FromRelative(imagePathRelative, baseDir);
            palette.Name = node.RequireAttribute("name").Value;

            return palette;
        }
示例#5
0
        public void Load(Project project, XElement node)
        {
            var palette = new PaletteInfo();

            var imagePathRelative = node.RequireAttribute("image").Value;
            palette.ImagePath = FilePath.FromRelative(imagePathRelative, project.BaseDir);
            palette.Name = node.RequireAttribute("name").Value;

            project.AddPalette(palette);
        }
示例#6
0
        private static MenuStateInfo LoadMenuState(XElement node, string basePath)
        {
            var info = new MenuStateInfo();

            info.Name = node.RequireAttribute("name").Value;

            info.Fade = node.TryAttribute<bool>("fade");

            var startNode = node.Element("SelectOption");
            if (startNode != null)
            {
                var startNameAttr = startNode.Attribute("name");
                var startVarAttr = startNode.Attribute("var");

                if (startNameAttr != null)
                {
                    info.StartOptionName = startNameAttr.Value;
                }

                if (startVarAttr != null)
                {
                    info.StartOptionVar = startVarAttr.Value;
                }
            }

            info.Commands = LoadCommands(node, basePath);

            return info;
        }
        public IIncludedObject Load(Project project, XElement xmlNode)
        {
            var info = new EntityInfo() {
                Name = xmlNode.RequireAttribute("name").Value,
                MaxAlive = xmlNode.TryAttribute<int>("maxAlive", 50),
                GravityFlip = xmlNode.TryElementValue<bool>("GravityFlip"),
                Components = new List<IComponentInfo>()
            };

            ReadEditorData(xmlNode, info);

            var deathNode = xmlNode.Element("Death");
            if (deathNode != null)
                info.Death = _effectReader.Load(deathNode);

            foreach (var compReader in ComponentReaders)
            {
                var element = compReader.NodeName != null ? xmlNode.Element(compReader.NodeName) : xmlNode;
                if (element != null)
                {
                    var comp = compReader.Load(element, project);
                    if (comp != null)
                        info.Components.Add(comp);
                }
            }

            if (info.PositionComponent == null)
                info.Components.Add(new PositionComponentInfo());

            if (info.MovementComponent == null && HasMovementEffects(info))
                info.Components.Add(new MovementComponentInfo() { EffectInfo = new MovementEffectPartInfo() });

            project.AddEntity(info);
            return info;
        }
示例#8
0
        public Entity(XElement xmlNode, string basePath)
        {
            Name = xmlNode.RequireAttribute("name").Value;

            // find the primary sprite
            var spriteNode = xmlNode.Element("Sprite");

            if (spriteNode != null)
            {
                // if it doesn't have a tilesheet, use the first for the entity
                var sheetNode = xmlNode.Element("Tilesheet");

                if (sheetNode == null)
                {
                    MainSprite = Sprite.FromXml(spriteNode, basePath);
                }
                else
                {
                    string sheetPath = System.IO.Path.Combine(basePath, sheetNode.Value);
                    var sheet = Image.FromFile(sheetPath);
                    MainSprite = Sprite.FromXml(spriteNode, sheet);
                }

                MainSprite.Play();
                Program.AnimateTick += Program_FrameTick;
            }
        }
 public IEffectPartInfo Load(XElement partNode)
 {
     return new AddInventoryEffectPartInfo() {
         ItemName = partNode.RequireAttribute("item").Value,
         Quantity = partNode.TryAttribute<int>("quantity", 1)
     };
 }
        public static InventoryInfo FromXml(XElement inventoryNode, string basePath)
        {
            InventoryInfo info = new InventoryInfo();
            info.Name = inventoryNode.RequireAttribute("name").Value;

            var useAttr = inventoryNode.Attribute("use");
            if (useAttr != null)
            {
                info.UseFunction = useAttr.Value;
            }

            var iconNode = inventoryNode.Element("Icon");
            if (iconNode != null)
            {
                info.IconOn = FilePath.FromRelative(iconNode.RequireAttribute("on").Value, basePath);
                info.IconOff = FilePath.FromRelative(iconNode.RequireAttribute("off").Value, basePath);
            }

            info.IconLocation = new Point(iconNode.GetInteger("x"), iconNode.GetInteger("y"));

            var numberNode = inventoryNode.Element("Number");
            if (numberNode != null)
            {
                info.NumberLocation = new Point(numberNode.GetInteger("x"), numberNode.GetInteger("y"));
            }

            bool b = true;
            inventoryNode.TryBool("selectable", out b);
            info.Selectable = b;

            return info;
        }
        public SceneCommandInfo Load(XElement node, string basePath)
        {
            var info = new SceneSoundCommandInfo();

            info.SoundInfo = new SoundInfo { Name = node.RequireAttribute("name").Value };

            return info;
        }
        public Sprite LoadSprite(XElement element, string basePath)
        {
            var sprite = LoadSprite(element);

            var tileattr = element.RequireAttribute("tilesheet");
            sprite.SheetPath = FilePath.FromRelative(tileattr.Value, basePath);

            return sprite;
        }
 public SceneCommandInfo Load(XElement node, string basePath)
 {
     var info = new SceneAddCommandInfo();
     var nameAttr = node.Attribute("name");
     if (nameAttr != null) info.Name = nameAttr.Value;
     info.Object = node.RequireAttribute("object").Value;
     info.X = node.GetAttribute<int>("x");
     info.Y = node.GetAttribute<int>("y");
     return info;
 }
示例#14
0
        public static PauseWeaponInfo FromXml(XElement weaponNode, string basePath)
        {
            PauseWeaponInfo info = new PauseWeaponInfo();
            info.Name = weaponNode.RequireAttribute("name").Value;
            info.Weapon = weaponNode.RequireAttribute("weapon").Value;

            info.IconOn = FilePath.FromRelative(weaponNode.RequireAttribute("on").Value, basePath);
            info.IconOff = FilePath.FromRelative(weaponNode.RequireAttribute("off").Value, basePath);

            info.Location = new Point(weaponNode.GetInteger("x"), weaponNode.GetInteger("y"));

            XElement meter = weaponNode.Element("Meter");
            if (meter != null)
            {
                info.Meter = MeterInfo.FromXml(meter, basePath);
            }

            return info;
        }
        public HandlerTransfer Load(XElement node)
        {
            HandlerTransfer transfer = new HandlerTransfer();

            var modeAttr = node.Attribute("mode");
            var mode = HandlerMode.Next;
            if (modeAttr != null)
            {
                Enum.TryParse<HandlerMode>(modeAttr.Value, true, out mode);
            }

            transfer.Mode = mode;

            if (mode == HandlerMode.Push)
            {
                transfer.Pause = node.TryAttribute<bool>("pause");
            }

            if (mode != HandlerMode.Pop)
            {
                switch (node.RequireAttribute("type").Value.ToLower())
                {
                    case "stage":
                        transfer.Type = HandlerType.Stage;
                        break;

                    case "scene":
                        transfer.Type = HandlerType.Scene;
                        break;

                    case "menu":
                        transfer.Type = HandlerType.Menu;
                        break;
                }

                transfer.Name = node.RequireAttribute("name").Value;
            }

            transfer.Fade = node.TryAttribute<bool>("fade");

            return transfer;
        }
 public SceneCommandInfo Load(XElement node, string basePath)
 {
     var info = new SceneFillMoveCommandInfo();
     info.Name = node.RequireAttribute("name").Value;
     info.Duration = node.GetAttribute<int>("duration");
     info.X = node.GetAttribute<int>("x");
     info.Y = node.GetAttribute<int>("y");
     info.Width = node.GetAttribute<int>("width");
     info.Height = node.GetAttribute<int>("height");
     return info;
 }
示例#17
0
        public static Effect ParseEffect(XElement node)
        {
            string soundname = node.RequireAttribute("name").Value;
            bool playing = node.TryAttribute<bool>("playing", true);

            return entity =>
            {
                entity.GetOrCreateComponent("Sound");
                SoundMessage msg = new SoundMessage(entity, soundname, playing);
                entity.SendMessage(msg);
            };
        }
示例#18
0
        public void Load(Project project, XElement xmlNode)
        {
            var info = new FontInfo();

            info.Name = xmlNode.RequireAttribute("name").Value;
            info.CharWidth = xmlNode.GetAttribute<int>("charwidth");
            info.CaseSensitive = xmlNode.GetAttribute<bool>("cased");

            foreach (var lineNode in xmlNode.Elements("Line"))
            {
                var x = lineNode.GetAttribute<int>("x");
                var y = lineNode.GetAttribute<int>("y");

                var lineText = lineNode.Value;

                info.AddLine(x, y, lineText);
            }

            info.ImagePath = FilePath.FromRelative(xmlNode.RequireAttribute("image").Value, project.BaseDir);

            project.AddFont(info);
        }
        public SceneCommandInfo Load(XElement node, string basePath)
        {
            var info = new SceneConditionCommandInfo();

            info.ConditionExpression = node.RequireAttribute("condition").Value;

            var attr = node.Attribute("entity");
            if (attr != null)
            {
                info.ConditionEntity = attr.Value;
            }

            info.Commands = _commandReader.LoadCommands(node, basePath);

            return info;
        }
 public SceneCommandInfo Load(XElement node, string basePath)
 {
     var info = new SceneFillCommandInfo();
     var nameAttr = node.Attribute("name");
     if (nameAttr != null) info.Name = nameAttr.Value;
     var colorAttr = node.RequireAttribute("color");
     var color = colorAttr.Value;
     var split = color.Split(',');
     info.Red = byte.Parse(split[0]);
     info.Green = byte.Parse(split[1]);
     info.Blue = byte.Parse(split[2]);
     info.X = node.GetAttribute<int>("x");
     info.Y = node.GetAttribute<int>("y");
     info.Width = node.GetAttribute<int>("width");
     info.Height = node.GetAttribute<int>("height");
     info.Layer = node.TryAttribute<int>("layer");
     return info;
 }
        private StateInfo ReadState(XElement stateNode)
        {
            var info = new StateInfo();
            info.Name = stateNode.RequireAttribute("name").Value;

            var logic = new List<IEffectPartInfo>();
            var init = new List<IEffectPartInfo>();

            foreach (var child in stateNode.Elements())
            {
                switch (child.Name.LocalName)
                {
                    case "Trigger":
                        var t = _triggerReader.Load(child);

                        if (t.Priority == null)
                            t.Priority = ((IXmlLineInfo)child).LineNumber;

                        info.Triggers.Add(t);
                        break;

                    case "Initialize":
                        init.AddRange(child.Elements().Select(e => _effectReader.LoadPart(e)));
                        break;

                    case "Logic":
                        logic.AddRange(child.Elements().Select(e => _effectReader.LoadPart(e)));
                        break;

                    default:
                        var mode = child.TryAttribute<string>("mode");
                        if (mode != null && mode.ToUpper() == "REPEAT")
                            logic.Add(_effectReader.LoadPart(child));
                        else
                            init.Add(_effectReader.LoadPart(child));
                        break;
                }
            }

            info.Initializer = new EffectInfo() { Parts = init };
            info.Logic = new EffectInfo() { Parts = logic };

            return info;
        }
        protected void LoadBase(HandlerInfo handler, XElement node, string basePath)
        {
            handler.Name = node.RequireAttribute("name").Value;

            var spriteLoader = new SpriteXmlReader();
            foreach (var spriteNode in node.Elements("Sprite"))
            {
                var info = new HandlerSpriteInfo();
                info.Sprite = spriteLoader.LoadSprite(spriteNode, basePath);
                handler.Objects.Add(info.Name, info);
            }

            var meterLoader = new MeterXmlReader(new SceneBindingXmlReader());
            foreach (var meterNode in node.Elements("Meter"))
            {
                var meter = meterLoader.LoadMeter(meterNode, basePath);
                handler.Objects.Add(meter.Name, meter);
            }
        }
        public static BlockPatternInfo FromXml(XElement xmlNode)
        {
            var info = new BlockPatternInfo();

            info.Entity = xmlNode.RequireAttribute("entity").Value;
            info.LeftBoundary = xmlNode.GetInteger("left");
            info.RightBoundary = xmlNode.GetInteger("right");
            info.Length = xmlNode.GetInteger("length");

            info.Blocks = new List<BlockInfo>();
            foreach (XElement blockInfo in xmlNode.Elements("Block"))
            {
                BlockInfo block = new BlockInfo();
                block.pos = new PointF((float)blockInfo.GetDouble("x"), (float)blockInfo.GetDouble("y"));
                block.on = blockInfo.GetInteger("on");
                block.off = blockInfo.GetInteger("off");

                info.Blocks.Add(block);
            }

            return info;
        }
        public MeterInfo LoadMeter(XElement meterNode, string basePath)
        {
            MeterInfo meter = new MeterInfo();

            meter.Name = meterNode.TryAttribute<string>("name") ?? "";

            meter.Position = new PointF(meterNode.GetAttribute<float>("x"), meterNode.GetAttribute<float>("y"));

            XAttribute imageAttr = meterNode.RequireAttribute("image");
            meter.TickImage = FilePath.FromRelative(imageAttr.Value, basePath);

            XAttribute backAttr = meterNode.Attribute("background");
            if (backAttr != null)
            {
                meter.Background = FilePath.FromRelative(backAttr.Value, basePath);
            }

            bool horiz = false;
            XAttribute dirAttr = meterNode.Attribute("orientation");
            if (dirAttr != null)
            {
                horiz = (dirAttr.Value == "horizontal");
            }
            meter.Orient = horiz ? MegaMan.Common.MeterInfo.Orientation.Horizontal : MegaMan.Common.MeterInfo.Orientation.Vertical;

            int x = meterNode.TryAttribute<int>("tickX");
            int y = meterNode.TryAttribute<int>("tickY");

            meter.TickOffset = new Point(x, y);

            XElement soundNode = meterNode.Element("Sound");
            if (soundNode != null) meter.Sound = IncludeFileXmlReader.LoadSound(soundNode, basePath);

            XElement bindingNode = meterNode.Element("Binding");
            if (bindingNode != null) meter.Binding = _bindingReader.Load(bindingNode);

            return meter;
        }
示例#25
0
        public static EntityPlacement LoadEntityPlacement(XElement entity)
        {
            EntityPlacement info = new EntityPlacement();

            info.Id = entity.TryAttribute<string>("id", Guid.NewGuid().ToString());

            var nameAttr = entity.Attribute("name");
            if (nameAttr == null)
                nameAttr = entity.RequireAttribute("entity");

            info.entity = nameAttr.Value;

            string state = "Start";
            XAttribute stateAttr = entity.Attribute("state");
            if (stateAttr != null) state = stateAttr.Value;
            info.state = state;

            info.screenX = entity.GetAttribute<int>("x");
            info.screenY = entity.GetAttribute<int>("y");

            var dirAttr = entity.Attribute("direction");
            if (dirAttr != null)
            {
                Direction dir = Direction.Left;
                Enum.TryParse<Direction>(dirAttr.Value, true, out dir);
                info.direction = dir;
            }

            var respawnAttr = entity.Attribute("respawn");
            if (respawnAttr != null)
            {
                RespawnBehavior respawn = RespawnBehavior.Offscreen;
                Enum.TryParse<RespawnBehavior>(respawnAttr.Value, true, out respawn);
                info.respawn = respawn;
            }

            return info;
        }
示例#26
0
        public static SoundInfo FromXml(XElement soundNode, string basePath)
        {
            SoundInfo sound = new SoundInfo {Name = soundNode.RequireAttribute("name").Value};

            bool loop;
            soundNode.TryBool("loop", out loop);
            sound.Loop = loop;

            float vol;
            if (!soundNode.TryFloat("volume", out vol)) vol = 1;
            sound.Volume = vol;

            XAttribute pathattr = soundNode.Attribute("path");
            XAttribute trackAttr = soundNode.Attribute("track");
            if (pathattr != null)
            {
                sound.Type = AudioType.Wav;
                sound.Path = FilePath.FromRelative(pathattr.Value, basePath);
            }
            else if (trackAttr != null)
            {
                sound.Type = AudioType.NSF;

                int track;
                if (!trackAttr.Value.TryParse(out track) || track <= 0) throw new GameXmlException(trackAttr, "Sound track attribute must be an integer greater than zero.");
                sound.NsfTrack = track;

                int priority;
                if (!soundNode.TryInteger("priority", out priority)) priority = 100;
                sound.Priority = (byte)priority;
            }
            else
            {
                sound.Type = AudioType.Unknown;
            }

            return sound;
        }
示例#27
0
        public static MeterInfo FromXml(XElement meterNode, string basePath)
        {
            MeterInfo meter = new MeterInfo();
            meter.Position = new PointF(meterNode.GetFloat("x"), meterNode.GetFloat("y"));

            XAttribute imageAttr = meterNode.RequireAttribute("image");
            meter.TickImage = FilePath.FromRelative(imageAttr.Value, basePath);

            XAttribute backAttr = meterNode.Attribute("background");
            if (backAttr != null)
            {
                meter.Background = FilePath.FromRelative(backAttr.Value, basePath);
            }

            bool horiz = false;
            XAttribute dirAttr = meterNode.Attribute("orientation");
            if (dirAttr != null)
            {
                horiz = (dirAttr.Value == "horizontal");
            }
            meter.Orient = horiz? Orientation.Horizontal : Orientation.Vertical;

            int x = 0; int y = 0;
            meterNode.TryInteger("tickX", out x);
            meterNode.TryInteger("tickY", out y);

            meter.TickOffset = new Point(x, y);

            XElement soundNode = meterNode.Element("Sound");
            if (soundNode != null) meter.Sound = SoundInfo.FromXml(soundNode, basePath);

            XElement bindingNode = meterNode.Element("Binding");
            if (bindingNode != null) meter.Binding = SceneBindingInfo.FromXml(bindingNode);

            return meter;
        }
示例#28
0
        public static Effect LoadSpawnEffect(XElement node)
        {
            if (node == null) throw new ArgumentNullException("node");

            string name = node.RequireAttribute("name").Value;
            string statename = "Start";
            if (node.Attribute("state") != null) statename = node.Attribute("state").Value;
            XElement posNodeX = node.Element("X");
            XElement posNodeY = node.Element("Y");
            Effect posEff = null;
            if (posNodeX != null)
            {
                posEff = PositionComponent.ParsePositionBehavior(posNodeX, Axis.X);
            }
            if (posNodeY != null) posEff += PositionComponent.ParsePositionBehavior(posNodeY, Axis.Y);
            return entity =>
            {
                GameEntity spawn = entity.Spawn(name);
                if (spawn == null) return;
                StateMessage msg = new StateMessage(entity, statename);
                spawn.SendMessage(msg);
                if (posEff != null) posEff(spawn);
            };
        }
示例#29
0
        public static Effect LoadEffectAction(XElement node)
        {
            Effect effect = e => { };

            switch (node.Name.LocalName)
            {
                case "Call":
                    effect = GetLateBoundEffect(node.Value);
                    break;

                case "Spawn":
                    effect = LoadSpawnEffect(node);
                    break;

                case "Remove":
                    effect = entity => { entity.Remove(); };
                    break;

                case "Die":
                    effect = entity => { entity.Die(); };
                    break;

                case "AddInventory":
                    string itemName = node.RequireAttribute("item").Value;
                    int quantity = node.TryAttribute<int>("quantity", 1);

                    effect = entity =>
                    {
                        Game.CurrentGame.Player.CollectItem(itemName, quantity);
                    };
                    break;

                case "RemoveInventory":
                    string itemNameUse = node.RequireAttribute("item").Value;
                    int quantityUse = node.TryAttribute<int>("quantity", 1);

                    effect = entity =>
                    {
                        Game.CurrentGame.Player.UseItem(itemNameUse, quantityUse);
                    };
                    break;

                case "UnlockWeapon":
                    string weaponName = node.RequireAttribute("name").Value;

                    effect = entity =>
                    {
                        Game.CurrentGame.Player.UnlockWeapon(weaponName);
                    };
                    break;

                case "DefeatBoss":
                    string name = node.RequireAttribute("name").Value;

                    effect = entity =>
                    {
                        Game.CurrentGame.Player.DefeatBoss(name);
                    };
                    break;

                case "Lives":
                    int add = int.Parse(node.RequireAttribute("add").Value);
                    effect = entity =>
                    {
                        Game.CurrentGame.Player.Lives += add;
                    };
                    break;

                case "GravityFlip":
                    bool flip = node.GetValue<bool>();
                    effect = entity => { entity.Container.IsGravityFlipped = flip; };
                    break;

                case "Func":
                    effect = entity => { };
                    string[] statements = node.Value.Split(';');
                    foreach (string st in statements.Where(st => !string.IsNullOrEmpty(st.Trim())))
                    {
                        LambdaExpression lambda = System.Linq.Dynamic.DynamicExpression.ParseLambda(
                            new[] { posParam, moveParam, sprParam, inputParam, collParam, ladderParam, timerParam, healthParam, stateParam, weaponParam, playerParam },
                            typeof(SplitEffect),
                            null,
                            st,
                            dirDict);
                        effect += CloseEffect((SplitEffect)lambda.Compile());
                    }
                    break;

                case "Trigger":
                    string conditionString;
                    if (node.Attribute("condition") != null) conditionString = node.RequireAttribute("condition").Value;
                    else conditionString = node.Element("Condition").Value;

                    Condition condition = ParseCondition(conditionString);
                    Effect triggerEffect = LoadTriggerEffect(node.Element("Effect"));
                    effect += (e) =>
                    {
                        if (condition(e)) triggerEffect(e);
                    };
                    break;

                case "Pause":
                    effect = entity => { entity.Paused = true; };
                    break;

                case "Unpause":
                    effect = entity => { entity.Paused = false; };
                    break;

                case "Next":
                    var transfer = GameXmlReader.LoadHandlerTransfer(node);
                    effect = e => { Game.CurrentGame.ProcessHandler(transfer); };
                    break;

                case "Palette":
                    var paletteName = node.RequireAttribute("name").Value;
                    var paletteIndex = node.GetAttribute<int>("index");
                    effect = e =>
                    {
                        var palette = PaletteSystem.Get(paletteName);
                        if (palette != null)
                        {
                            palette.CurrentIndex = paletteIndex;
                        }
                    };
                    break;

                case "Delay":
                    var delayFrames = node.GetAttribute<int>("frames");
                    var delayEffect = LoadEffect(node);
                    effect = e =>
                    {
                        Engine.Instance.DelayedCall(() => delayEffect(e), null, delayFrames);
                    };
                    break;

                case "SetVar":
                    var varname = node.RequireAttribute("name").Value;
                    var value = node.RequireAttribute("value").Value;
                    effect = e =>
                    {
                        Game.CurrentGame.Player.SetVar(varname, value);
                    };
                    break;

                default:
                    effect = GameEntity.ParseComponentEffect(node);
                    break;
            }
            return effect;
        }
示例#30
0
        private ScreenInfo LoadScreenXml(XElement node, FilePath stagePath, Tileset tileset)
        {
            string id = node.RequireAttribute("id").Value;

            var screen = new ScreenInfo(id, tileset);

            screen.Layers.Add(LoadScreenLayer(node, stagePath.Absolute, id, tileset, 0, 0, false));

            foreach (var overlay in node.Elements("Overlay"))
            {
                var name = overlay.RequireAttribute("name").Value;
                var x = overlay.TryAttribute<int>("x");
                var y = overlay.TryAttribute<int>("y");
                bool foreground = overlay.TryAttribute<bool>("foreground");
                bool parallax = overlay.TryAttribute<bool>("parallax");

                var layer = LoadScreenLayer(overlay, stagePath.Absolute, name, tileset, x, y, foreground);
                layer.Parallax = parallax;

                screen.Layers.Add(layer);
            }

            foreach (XElement teleport in node.Elements("Teleport"))
            {
                TeleportInfo info;
                int from_x = teleport.TryAttribute<int>("from_x");
                int from_y = teleport.TryAttribute<int>("from_y");
                int to_x = teleport.TryAttribute<int>("to_x");
                int to_y = teleport.TryAttribute<int>("to_y");
                info.From = new Point(from_x, from_y);
                info.To = new Point(to_x, to_y);
                info.TargetScreen = teleport.Attribute("to_screen").Value;

                screen.Teleports.Add(info);
            }

            var blocks = new List<BlockPatternInfo>();

            foreach (XElement blockNode in node.Elements("Blocks"))
            {
                BlockPatternInfo pattern = _blockReader.FromXml(blockNode);
                screen.BlockPatterns.Add(pattern);
            }

            screen.Commands = HandlerXmlReader.LoadCommands(node, stagePath.BasePath);

            return screen;
        }