private static Behaviour BehaviourParser(Map context, string objname, string behaviour) { var actions = behaviour.Split(';'); if (actions.Length == 1) { //single action return(BehaviourHelper.Parse(context, objname, actions[0])); } else { //chained actionss return(BehaviourHelper.Parse(context, objname, actions)); } }
private static List <Line> ProcessInteractableObject(ref Map map, IEnumerable <Object> interactableObj) { List <Line> intLink = new List <Line>(); foreach (var obj in interactableObj) { if (!string.IsNullOrEmpty(obj.OnActivate)) { map.Objects[obj.Name].Activate = BehaviourParser(map, obj.Name, obj.OnActivate); foreach (var target in BehaviourHelper.GetAllTarget(map, obj.OnActivate.Split(';'))) { if (target is null) { continue; } var ps = HelperMethod.CutIntoAxisAlignVector2(obj.WorldPos.ToVector2(), target.WorldPos.ToVector2()).ToArray(); intLink.Add(new Line(Color.Cyan, ps)); } } if (!string.IsNullOrEmpty(obj.OnDeactivate)) { map.Objects[obj.Name].Deactivate = BehaviourParser(map, obj.Name, obj.OnDeactivate); foreach (var target in BehaviourHelper.GetAllTarget(map, obj.OnDeactivate.Split(';'))) { if (target is null) { continue; } var ps = HelperMethod.CutIntoAxisAlignVector2(obj.WorldPos.ToVector2(), target.WorldPos.ToVector2()).ToArray(); intLink.Add(new Line(Color.OrangeRed, ps)); } } } return(intLink); }
public static Map LoadTmxMap(string mapname) { //load the tiled map in var mappath = Path.Combine(CONTENT_MANAGER.LocalRootPath, "map", mapname + ".tmx"); if (!File.Exists(mappath)) { return(null); } var tmxmap = new TmxMap(mappath); var checksum = Convert.ToBase64String(HelperMethod.GetMD5CheckSum(mappath)); //define map dimesion var mapwidth = tmxmap.Width; var mapheight = tmxmap.Height; //declare map data array SpriteSheetRectName[,] f; SpriteSheetRectName[,] w; List <Object> o = new List <Object>(); List <Annotation> annotations = new List <Annotation>(); //serialize tiled map data to ingame map data f = HelperMethod.Make2DArray(tmxmap.Layers["floor"].Tiles.Select(x => (SpriteSheetRectName)(x.Gid - 1)).ToArray(), mapheight, mapwidth); w = HelperMethod.Make2DArray(tmxmap.Layers["wall"].Tiles.Select(x => (SpriteSheetRectName)(x.Gid - 1)).ToArray(), mapheight, mapwidth); var objects = tmxmap.ObjectGroups["object"].Objects; //generate collision bounding box var collision = new List <Humper.Base.RectangleF>(); int holecount = 0; for (int y = 0; y < mapheight; y++) { for (int x = 0; x < mapwidth; x++) { if (f[y, x] == SpriteSheetRectName.None) { var obj = new Object() { Name = "hole" + holecount++, WorldPos = new Vector3(x, y, 0), SpriteOrigin = Constant.SPRITE_ORIGIN, TileType = SpriteSheetRectName.None, BoundingBox = new Humper.Base.RectangleF(x - 0.3f, y - 0.3f, 1, 1), CollisionTag = CollisionTag.Hole }; o.Add(obj); } if (w[y, x].GetCollisionTag() != CollisionTag.None) { collision.Add(GetCollsionBox(new Vector2(x, y), w[y, x])); } } } //generate map border collision box collision.Add(new Humper.Base.RectangleF(0 - 0.3f, 0 - 0.3f, 0.3f, tmxmap.Height)); collision.Add(new Humper.Base.RectangleF(0 - 0.3f, 0 - 0.3f, mapwidth, 0.3f)); collision.Add(new Humper.Base.RectangleF(mapwidth - 0.3f, 0 - 0.3f, 0.3f, tmxmap.Height)); collision.Add(new Humper.Base.RectangleF(0 - 0.3f, mapheight - 0.3f, mapwidth, 0.3f)); //process objects List <Object> interactableObj = new List <Object>(); foreach (var oo in objects) { var objname = oo.Name; var x = (float)oo.X / tmxmap.TileHeight - 1; var y = (float)oo.Y / tmxmap.TileHeight - 1; if (oo.Tile is null) { if (objname.StartsWith("popup")) { //popup o.Add(new Object() { Name = objname, TileType = SpriteSheetRectName.Popup, MetaData = oo.Text.Value }); } else if (objname.StartsWith("trig")) { //trigger var obj = new Object() { Name = objname, WorldPos = new Vector3(x, y, 0), TileType = SpriteSheetRectName.Trigger, Activate = BehaviourHelper.NoAction(), OnActivate = string.Empty, Deactivate = BehaviourHelper.NoAction(), OnDeactivate = string.Empty, Memory = new Stack <string>() }; interactableObj.Add(obj); o.Add(obj); } else if (objname.StartsWith("start")) { var obj = new Object() { Name = objname, TileType = SpriteSheetRectName.Startup, Activate = BehaviourHelper.NoAction(), OnActivate = oo.Properties["OnActivate"], Deactivate = BehaviourHelper.NoAction(), OnDeactivate = string.Empty, Memory = new Stack <string>() }; interactableObj.Add(obj); o.Add(obj); } else { //map annotation var color = new Color(oo.Text.Color.R, oo.Text.Color.G, oo.Text.Color.B); var rotation = HelperFunction.DegreeToRadian((float)oo.Rotation); annotations.Add(new Annotation(x, y, oo.Text.Value, color, rotation)); } } else { //game object var objectiletype = (SpriteSheetRectName)(oo.Tile.Gid - 1); if (objectiletype != SpriteSheetRectName.None) { var obj = new Object() { Name = objname, WorldPos = new Vector3(x, y, 0), SpriteOrigin = Constant.SPRITE_ORIGIN, TileType = objectiletype, Activate = BehaviourHelper.NoAction(), OnActivate = string.Empty, Deactivate = BehaviourHelper.NoAction(), OnDeactivate = string.Empty, Memory = new Stack <string>() }; if (objectiletype.GetCollisionTag() != CollisionTag.None) { obj.BoundingBox = GetCollsionBox(new Vector2(x, y), objectiletype); obj.CollisionTag = objectiletype.GetCollisionTag(); } //if (oo.Name == "endpoint" && oo.Properties.ContainsKey("NextLevel")) { // nextlvl = oo.Properties["NextLevel"]; //} bool isObjInteractable = false; if (oo.Properties.ContainsKey("OnActivate")) { obj.OnActivate = oo.Properties["OnActivate"]; isObjInteractable = true; } if (oo.Properties.ContainsKey("OnDeactivate")) { obj.OnDeactivate = oo.Properties["OnDeactivate"]; isObjInteractable = true; } Humper.Base.RectangleF portalBase = obj.BoundingBox; switch (obj.TileType) { case SpriteSheetRectName.Portal_N: portalBase = new Humper.Base.RectangleF(obj.WorldPos.X - 0.3f, obj.WorldPos.Y - 0.3f, 1f, 0.2f); collision.Add(portalBase); break; case SpriteSheetRectName.Portal_W: portalBase = new Humper.Base.RectangleF(obj.WorldPos.X - 0.3f, obj.WorldPos.Y - 0.3f, 0.2f, 1f); collision.Add(portalBase); break; case SpriteSheetRectName.Portal_S: portalBase = new Humper.Base.RectangleF(obj.WorldPos.X - 0.3f, obj.WorldPos.Y + 0.5f, 1f, 0.2f); collision.Add(portalBase); break; case SpriteSheetRectName.Portal_E: portalBase = new Humper.Base.RectangleF(obj.WorldPos.X + 0.5f, obj.WorldPos.Y - 0.3f, 0.2f, 1f); collision.Add(portalBase); break; case SpriteSheetRectName.PortalOff_N: portalBase = new Humper.Base.RectangleF(obj.WorldPos.X - 0.3f, obj.WorldPos.Y - 0.3f, 1f, 0.2f); collision.Add(portalBase); break; case SpriteSheetRectName.PortalOff_W: portalBase = new Humper.Base.RectangleF(obj.WorldPos.X - 0.3f, obj.WorldPos.Y - 0.3f, 0.2f, 1f); collision.Add(portalBase); break; case SpriteSheetRectName.PortalOff_S: portalBase = new Humper.Base.RectangleF(obj.WorldPos.X - 0.3f, obj.WorldPos.Y + 0.5f, 1f, 0.2f); collision.Add(portalBase); break; case SpriteSheetRectName.PortalOff_E: portalBase = new Humper.Base.RectangleF(obj.WorldPos.X + 0.5f, obj.WorldPos.Y - 0.3f, 0.2f, 1f); collision.Add(portalBase); break; } if (isObjInteractable) { interactableObj.Add(obj); o.Add(obj); } else { o.Add(obj); } } } } //build a static map without interactable object var processedMap = new Map(mapwidth, mapheight, 3, f, w, o, collision.ToArray(), annotations); //todo separate line that have the same coord //var separator = new Vector2(1, 1); //foreach (var link in intLink) { // var sls = intLink.Where(x => x.Equals(link)).ToList(); // for (int i = 0; i < sls.Count; i++) { // sls[i].Point1 += separator * i; // sls[i].Point2 += separator * i; // } //} //parse and generate behaviour for interactable object processedMap.InteractLink = ProcessInteractableObject(ref processedMap, interactableObj); var startup = processedMap.FindObject(kvp => kvp.Key.StartsWith("start")); if (startup != null) { processedMap.Startup = startup.Activate; } mappath = Path.Combine(CONTENT_MANAGER.LocalRootPath, "map", mapname + ".lvl"); if (!File.Exists(mappath)) { var mapdata = string.Format("{0}|{1}", checksum, CompressHelper.Zip(JsonConvert.SerializeObject(processedMap))); File.WriteAllText(mappath, mapdata); } return(processedMap); }