public AreaTransitionTrigger(Area owner, Area target, Point tilePos, AreaSideEnum side, Point globalTarget, Point destTile) : this(owner, target, tilePos, side) { m_hasGlobalTarget = true; m_globalTarget = globalTarget; m_destTile = destTile; }
private AreaSideEnum m_side; // used to determine where to place the PC in the target Area #endregion Fields #region Constructors public AreaTransitionTrigger(Area owner, Area target, Point tilePos, AreaSideEnum side) : base(calculateBounds(owner, tilePos, side)) { this.m_owner = owner; this.m_target = target; this.m_tilePos = tilePos; this.m_side = side; }
public static void populateArea(Area a) { EnvironmentFillInfo efi = getCrateriaEnvironmentFillInfo(); // TODO data-drive this bad boy Dictionary<Point, GridUtils.TileConfigurer> tileConfigs = new Dictionary<Point, GridUtils.TileConfigurer>(); Dictionary<Point, bool> tilesToFix = new Dictionary<Point, bool>(); //Dictionary<Point, bool> fixedTiles = new Dictionary<Point,bool>(); // mark all cells hit by the fractals, and which sides they are hit on, using // grid intersection tests HashSet<Point> markedCellsSet = new HashSet<Point>(); // prevents duplicates // important because adding another fractal may change our interpretation // of a tile, so we do all fractals first then figure out the tiles foreach (LineFractalInfo lfi in a.fractals) { // mark cells hit by fractal List<Point> markedCells = GridUtils.getGridIntersects(lfi.fractal, 40, 40, tileConfigs); // and add them all to a total set of hit cells foreach (Point p in markedCells) { markedCellsSet.Add(p); } } // now that we know where all cells have been hit and where, we can figure out // what type of tile they are, and also flag their neighbors for correction if // necessary foreach (Point p in markedCellsSet) { if (p.X <= a.Tiles.GetUpperBound(0) && p.Y <= a.Tiles.GetUpperBound(1) && p.X >= 0 && p.Y >= 0) { switch (tileConfigs[p].getType()) { case GridUtils.TILE_TYPE.EMPTY: a.Tiles[p.X, p.Y] = efi.EMPTY; break; case GridUtils.TILE_TYPE.FILL: a.Tiles[p.X, p.Y] = efi.FILL; break; case GridUtils.TILE_TYPE.FILL_LEFT: a.Tiles[p.X, p.Y] = efi.FILL_LEFT; tilesToFix[new Point(p.X - 1, p.Y)] = false; break; case GridUtils.TILE_TYPE.FILL_RIGHT: a.Tiles[p.X, p.Y] = efi.FILL_RIGHT; tilesToFix[new Point(p.X + 1, p.Y)] = false; break; case GridUtils.TILE_TYPE.FILL_TOP: a.Tiles[p.X, p.Y] = efi.FILL_TOP; tilesToFix[new Point(p.X, p.Y - 1)] = false; break; case GridUtils.TILE_TYPE.FILL_BOTTOM: a.Tiles[p.X, p.Y] = efi.FILL_BOTTOM; tilesToFix[new Point(p.X, p.Y + 1)] = false; break; case GridUtils.TILE_TYPE.FILL_TOPLEFT: a.Tiles[p.X, p.Y] = efi.FILL_TOPLEFT; break; case GridUtils.TILE_TYPE.FILL_TOPRIGHT: a.Tiles[p.X, p.Y] = efi.FILL_TOPRIGHT; break; case GridUtils.TILE_TYPE.FILL_BOTTOMLEFT: a.Tiles[p.X, p.Y] = efi.FILL_BOTTOMLEFT; break; case GridUtils.TILE_TYPE.FILL_BOTTOMRIGHT: a.Tiles[p.X, p.Y] = efi.FILL_BOTTOMRIGHT; break; case GridUtils.TILE_TYPE.EMPTY_TOPLEFT: a.Tiles[p.X, p.Y] = efi.EMPTY_TOPLEFT; break; case GridUtils.TILE_TYPE.EMPTY_TOPRIGHT: a.Tiles[p.X, p.Y] = efi.EMPTY_TOPRIGHT; break; case GridUtils.TILE_TYPE.EMPTY_BOTTOMLEFT: a.Tiles[p.X, p.Y] = efi.EMPTY_BOTTOMLEFT; break; case GridUtils.TILE_TYPE.EMPTY_BOTTOMRIGHT: a.Tiles[p.X, p.Y] = efi.EMPTY_BOTTOMRIGHT; break; default: a.Tiles[p.X, p.Y] = efi.OTHER; break; } // if not empty, mark that we've set it - if empty it probably means // a tile which a fractal double backed on, so we don't want to make // any guarantees if (tileConfigs[p].getType() != GridUtils.TILE_TYPE.EMPTY) { tilesToFix[p] = true; } } } // copy list of tiles to fix into an array since we modify it // while we are traversing it, then use recursion to flood the changes Point[] points = new Point[tilesToFix.Count]; tilesToFix.Keys.CopyTo(points, 0); foreach (Point p in points) { fill(p, tilesToFix, a.Tiles, efi); } foreach (Point p in tilesToFix.Keys) { a.FixedTiles.Add(p); } a.initializeTileColliders(); }
/// <summary> /// Code to actually transfer PC to a new Area when touched; called by collision handler /// </summary> /// <param name="other">Collider which has impacted the trigger</param> public override void handleImpact(Collider other) { if (other.m_owner == GameplayManager.Samus) { // TODO // remove this code once maps are pre-generated and area transition triggers already contain references // to their targets -- or, we might decide its just easier this way Point targetGlobalLocation; switch (m_side) { case AreaSideEnum.Top: targetGlobalLocation = new Point(this.m_owner.GlobalLocation.X, this.m_owner.GlobalLocation.Y - 1); break; case AreaSideEnum.Bottom: targetGlobalLocation = new Point(this.m_owner.GlobalLocation.X, this.m_owner.GlobalLocation.Y + 1); break; case AreaSideEnum.Left: targetGlobalLocation = new Point(this.m_owner.GlobalLocation.X - 1, this.m_owner.GlobalLocation.Y); break; case AreaSideEnum.Right: targetGlobalLocation = new Point(this.m_owner.GlobalLocation.X + 1, this.m_owner.GlobalLocation.Y); break; case AreaSideEnum.Other: throw new Exception("AreaTransitions on non-edges not fully impled"); break; default: throw new Exception("Unknown value for AreaSideEnum"); } if (m_target == null) { // check if it was created but we just don't have it this.m_target = WorldManager.GetArea(targetGlobalLocation); // still not created, so make it if (m_target == null) { m_target = Area.makeTestArea(targetGlobalLocation); } } // This code stays Point targetTile; // tile on other map on which player should arrive switch (m_side) { case AreaSideEnum.Top: targetTile = new Point(this.m_tilePos.X, Area.HEIGHT_IN_TILES - 1); break; case AreaSideEnum.Bottom: targetTile = new Point(this.m_tilePos.X, 0); break; case AreaSideEnum.Left: targetTile = new Point(Area.WIDTH_IN_TILES - 1, this.m_tilePos.Y); break; case AreaSideEnum.Right: targetTile = new Point(0, this.m_tilePos.Y); break; case AreaSideEnum.Other: throw new Exception("AreaTransitions on non-edges not fully impled"); default: throw new Exception("Unknown value for AreaSideEnum"); } GameplayManager.changeActiveArea(this.m_target, targetTile); } }
/// <summary> /// Used during construction to get the shape of the collision box /// </summary> /// <returns></returns> private static Rectangle calculateBounds(Area owner, Point tilePos, AreaSideEnum side) { const int attSize = 10; int tileWidth = owner.TileSet.tileWidth; int tileHeight = owner.TileSet.tileHeight; switch (side) { case AreaSideEnum.Top: return new Rectangle( tileWidth * tilePos.X, -attSize, tileWidth, attSize); case AreaSideEnum.Bottom: return new Rectangle( tileWidth * tilePos.X, tileHeight * tilePos.Y + tileHeight, tileWidth, attSize); case AreaSideEnum.Left: return new Rectangle( -attSize, tileHeight * tilePos.Y, attSize, tileHeight); case AreaSideEnum.Right: return new Rectangle( tileWidth * tilePos.X + tileWidth, tileHeight * tilePos.Y, attSize, tileHeight); case AreaSideEnum.Other: return new Rectangle( tileWidth * tilePos.X, tileHeight * tilePos.Y, tileWidth, tileHeight); default: throw new Exception("Unknown value for AreaSideEnum"); } }
/// <summary> /// Puts area transition triggers around the edges of the Area, so that moving to the edges /// will transfer the player to the adjacent Area. /// </summary> /// <param name="north">Area to the north; i.e., to which Area the triggers on the top edge should lead</param> /// <param name="south"></param> /// <param name="east"></param> /// <param name="west"></param> public void initializeAreaTransitions(Area north, Area south, Area east, Area west) { // top for (int i = 0; i < WIDTH_IN_TILES; ++i) { this.addAreaTransitionTrigger(i, 0, north, AreaSideEnum.Top); } // bottom for (int i = 0; i < WIDTH_IN_TILES; ++i) { this.addAreaTransitionTrigger(i, HEIGHT_IN_TILES - 1, south, AreaSideEnum.Bottom); } // left for (int i = 0; i < HEIGHT_IN_TILES; ++i) { this.addAreaTransitionTrigger(0, i, west, AreaSideEnum.Left); } // right for (int i = 0; i < HEIGHT_IN_TILES; ++i) { this.addAreaTransitionTrigger(WIDTH_IN_TILES - 1, i, east, AreaSideEnum.Right); } }
/// <summary> /// Place a new area transition trigger in the Area; handles registering collision box /// </summary> /// <param name="tileX"></param> /// <param name="tileY"></param> /// <param name="target"></param> /// <param name="side"></param> public void addAreaTransitionTrigger(int tileX, int tileY, Area target, AreaSideEnum side) { AreaTransitionTrigger att = new AreaTransitionTrigger(this, target, new Point(tileX, tileY), side); add(att); }
/// <summary> /// Creates an empty area using a specified tileset at the specified global coordinate /// </summary> /// <param name="tileSetpath"></param> /// <param name="location"></param> /// <returns></returns> public static Area makeEmptyArea(string tileSetpath, Point location) { Area a = new Area(tileSetpath, location); // default area for (int i = 0; i < WIDTH_IN_TILES; ++i) for (int j = 0; j < HEIGHT_IN_TILES; ++j) { a.Tiles[i, j] = 3; //if (j == HEIGHT_IN_TILES - 1) //{ // a.Tiles[i, j] = 4; //} } a.initializeTileColliders(); a.initializeAreaTransitions(null, null, null, null); return a; }
public static void RegisterArea(Point p, Area area) { if (!WorldMap.ContainsKey(p)) { // throw new Exception("Area at p already registered"); WorldMap[p] = area; } }
private static Area makeAreaFromMapScreen(int row, int col, MapScreen mapScreen) { Area a = new Area(@"Sprites/TileSet1", new Point(row,col)); CS8803AGA.story.map.MapScreen.TileType tt; for (int r = 0; r < HEIGHT_IN_TILES; r++) { for (int c = 0; c < WIDTH_IN_TILES; c++) { tt = mapScreen.getFloorTile(r, c); a.Tiles[c, r] = (tt == MapScreen.TileType.WALL) ? 4 : (tt == MapScreen.TileType.ROCK) ? 6 : (tt == MapScreen.TileType.DESK_BOTTOM) ? 15 : (tt == MapScreen.TileType.DESK_LEFT) ? 16 : 3; } } foreach (CS8803AGA.story.map.MapScreen.CharacterRecord cr in mapScreen.Characters) { CharacterInfo ci = cr.character.getCharacterInfo(); Vector2 pos = new Vector2(a.getTileRectangle(cr.c, cr.r).X, a.getTileRectangle(cr.c, cr.r).Y); CharacterController cc = CharacterController.construct(ci, pos, cr.character.ID); GameplayManager.Game.Characters.Add(cr.character); a.add(cc); cc.AnimationController.requestAnimation("down", AnimationController.AnimationCommand.Play); } foreach (KeyCheck kc in mapScreen.Triggers) { a.add(kc); } return a; }
/// <summary> /// Creates an empty area using a specified tileset at the specified global coordinate /// </summary> /// <param name="tileSetpath"></param> /// <param name="location"></param> /// <returns></returns> public static Area makeEmptyArea(string tileSetpath, Point location) { Area a = new Area(tileSetpath, location); // default area /*for (int i = 0; i < WIDTH_IN_TILES; ++i) for (int j = 0; j < HEIGHT_IN_TILES; ++j) { a.Tiles[i, j] = 3; }*/ // whoever came up with this map format was drunk, // it's stored rotated counter-clockwise 90 degrees AND THEN horizontally flipped // what the shit, right? a.Tiles = AreaDefinitions.areaAt(location); a.initializeTileColliders(); a.initializeAreaTransitions(null, null, null, null); return a; }