/// <summary> /// Checks for overlaps between the provided object and any tiles above the collision index. /// </summary> /// <param name="Core">The <code>FlxObject</code> you want to check against.</param> /// <returns>True if overlap occurs, otherwise False</returns> override public bool overlaps(FlxObject Core) { int d; int dd; List <BlockPoint> blocks = new List <BlockPoint>(); //First make a list of all the blocks we'll use for collision int ix = (int)FlxU.floor((Core.x - x) / _tileWidth); int iy = (int)FlxU.floor((Core.y - y) / _tileHeight); int iw = (int)FlxU.ceil((float)Core.width / (float)_tileWidth) + 1; int ih = (int)FlxU.ceil((float)Core.height / (float)_tileHeight) + 1; int r = 0; int c; while (r < ih) { if (r >= heightInTiles) { break; } d = (iy + r) * widthInTiles + ix; c = 0; while (c < iw) { if (c >= widthInTiles) { break; } dd = _data[d + c]; if (dd >= collideMin && dd >= collideMax) { blocks.Add(new BlockPoint((int)(x + (ix + c) * _tileWidth), (int)(y + (iy + r) * _tileHeight), dd)); } c++; } r++; } //Then check for overlaps int bl = blocks.Count; int i = 0; while (i < bl) { _block.x = blocks[i].x; _block.y = blocks[i++].y; if (_block.overlaps(Core)) { return(true); } } return(false); }
/// <summary> /// <code>FlxU.collide()</code> (and thus <code>FlxObject.collide()</code>) call /// this function each time two objects are compared to see if they collide. /// It doesn't necessarily mean these objects WILL collide, however. /// </summary> /// <param name="Object">The <code>FlxObject</code> you're about to run into.</param> override public void preCollide(FlxObject Object) { //Collision fix, in case updateMotion() is called colHullX.x = 0; colHullX.y = 0; colHullY.x = 0; colHullY.y = 0; int r; int c; int rs; int ix = (int)FlxU.floor((Object.x - x) / _tileWidth); int iy = (int)FlxU.floor((Object.y - y) / _tileHeight); int iw = ix + (int)FlxU.ceil((float)Object.width / (float)_tileWidth) + 1; int ih = iy + (int)FlxU.ceil((float)Object.height / (float)_tileHeight) + 1; if (ix < 0) { ix = 0; } if (iy < 0) { iy = 0; } if (iw > widthInTiles) { iw = widthInTiles; } if (ih > heightInTiles) { ih = heightInTiles; } rs = iy * widthInTiles; r = iy; colOffsets.Clear(); while (r < ih) { c = ix; while (c < iw) { if (_data[rs + c] >= collideMin && _data[rs + c] <= collideMax) { colOffsets.Add(new Vector2(x + c * _tileWidth, y + r * _tileHeight)); } c++; } rs += widthInTiles; r++; } }
/// <summary> /// Shoots a ray from the start point to the end point. /// If/when it passes through a tile, it stores and returns that point. /// </summary> /// <param name="StartX">The X component of the ray's start.</param> /// <param name="StartY">The Y component of the ray's start.</param> /// <param name="EndX">The X component of the ray's end.</param> /// <param name="EndY">The Y component of the ray's end.</param> /// <param name="Result">A <code>Point</code> object containing the first wall impact.</param> /// <param name="Resolution">Defaults to 1, meaning check every tile or so. Higher means more checks!</param> /// <returns>Whether or not there was a collision between the ray and a colliding tile.</returns> public bool ray(int StartX, int StartY, int EndX, int EndY, Vector2 Result, int Resolution) { int step = _tileWidth; if (_tileHeight < _tileWidth) { step = _tileHeight; } step /= Resolution; int dx = EndX - StartX; //if (dx == 0) return false; int dy = EndY - StartY; //if (dy == 0) return false; float distance = (float)Math.Sqrt(dx * dx + dy * dy); int steps = (int)FlxU.ceil(distance / step); int stepX = dx / steps; int stepY = dy / steps; int curX = StartX - stepX; int curY = StartY - stepY; int tx; int ty; int i = 0; while (i < steps) { curX += stepX; curY += stepY; if ((curX < 0) || (curX > width) || (curY < 0) || (curY > height)) { i++; continue; } tx = curX / _tileWidth; ty = curY / _tileHeight; if (_data[ty * widthInTiles + tx] >= collideMin && _data[ty * widthInTiles + tx] <= collideMax) { //Some basic helper stuff tx *= _tileWidth; ty *= _tileHeight; int rx = 0; int ry = 0; int q; int lx = curX - stepX; int ly = curY - stepY; //Figure out if it crosses the X boundary q = tx; if (dx < 0) { q += _tileWidth; } rx = q; ry = ly + stepY * ((q - lx) / stepX); if ((ry > ty) && (ry < ty + _tileHeight)) { Console.WriteLine("X Result: {0} {1}", rx, ry); Result.X = rx; Result.Y = ry; return(true); } //Else, figure out if it crosses the Y boundary q = ty; if (dy < 0) { q += _tileHeight; } rx = lx + stepX * ((q - ly) / stepY); ry = q; if ((rx > tx) && (rx < tx + _tileWidth)) { Console.WriteLine("Y Result: {0} {1}", rx, ry); Result.X = rx; Result.Y = ry; return(true); } return(false); } i++; } return(false); }
/// <summary> /// Load the tilemap with string data and a tile graphic. /// </summary> /// <param name="MapData">A string of comma and line-return delineated indices indicating what order the tiles should go in. <para>If you want to use 0,1,0,1... use FlxTilemap.OFF, FlxTilemap.AUTO or FlxTilemap.ALT</para><para>If you are using tile ids such as 0,23,12,4,1... use FlxTilemap.STRING</para></param> /// <param name="TileGraphic">All the tiles you want to use, arranged in a strip corresponding to the numbers in MapData.</param> /// <param name="TileWidth">The width of your tiles (e.g. 8) - defaults to height of the tile graphic if unspecified.</param> /// <param name="TileHeight">The height of your tiles (e.g. 8) - defaults to width if unspecified.</param> /// <returns>A pointer this instance of FlxTilemap, for chaining as usual :)</returns> public FlxTilemap loadMap(string MapData, Texture2D TileGraphic, int TileWidth, int TileHeight) { refresh = true; _tileBitmap = TileGraphic; //Figure out the map dimensions based on the data string string[] cols; string[] rows = MapData.Split('\n'); //int xxx = 0; //foreach (var item in rows) //{ // Console.WriteLine(xxx + " " + item); // xxx++; //} heightInTiles = rows.Length; int r = 0; int c; cols = rows[r].Split(','); _data = new int[rows.Length * cols.Length]; //Console.WriteLine(rows.Length + " " + cols.Length); //foreach (var item in _data) // Console.Write(item.ToString() + ","); //Console.WriteLine("\n"); while (r < heightInTiles) { cols = rows[r++].Split(','); if (cols.Length <= 1) { heightInTiles = heightInTiles - 1; continue; } if (widthInTiles == 0) { widthInTiles = cols.Length; } c = 0; //Console.WriteLine(widthInTiles + " " + heightInTiles); while (c < widthInTiles) { //int ff = ((r - 1) * widthInTiles) + c; //Console.WriteLine(r + " " + c + " " + ff); _data[((r - 1) * widthInTiles) + c] = int.Parse(cols[c++]); //.push(uint(cols[c++])); } } //now that height and width have been determined, find how many extra //"filler tiles" are at the end of your map. int standardLength = TileHeight * TileWidth; int graphicWidth = _tileBitmap.Width; _extraMiddleTiles = (graphicWidth - standardLength) / TileWidth; //Pre-process the map data if it's auto-tiled int i; totalTiles = widthInTiles * heightInTiles; if (auto == AUTO || auto == ALT) { collideMin = collideIndex = startingIndex = drawIndex = 1; i = 0; while (i < totalTiles) { autoTile(i++); } } if (auto == RANDOM) { collideMin = collideIndex = startingIndex = drawIndex = 1; i = 0; while (i < totalTiles) { randomTile(i++); } } if (auto == STRING) { collideMin = collideIndex = startingIndex = drawIndex = 1; i = 0; while (i < totalTiles) { stringTile(i++); } } if (auto == REMAPAUTO || auto == REMAPALT) { collideMin = collideIndex = startingIndex = drawIndex = 1; i = 0; while (i < totalTiles) { autoTileWithRemap(i++); } } //Figure out the size of the tiles _tileWidth = TileWidth; if (_tileWidth == 0) { _tileWidth = TileGraphic.Height; } _tileHeight = TileHeight; if (_tileHeight == 0) { _tileHeight = _tileWidth; } _block.width = _tileWidth; _block.height = _tileHeight; //Then go through and create the actual map width = widthInTiles * _tileWidth; height = heightInTiles * _tileHeight; _rects = new List <Rectangle>(); i = 0; while (i < totalTiles) { _rects.Add(Rectangle.Empty); updateTile(i++); } //Pre-set some helper variables for later _screenRows = (int)FlxU.ceil((float)FlxG.height / (float)_tileHeight) + 1; if (_screenRows > heightInTiles) { _screenRows = heightInTiles; } _screenCols = (int)FlxU.ceil((float)FlxG.width / (float)_tileWidth) + 1; if (_screenCols > widthInTiles) { _screenCols = widthInTiles; } generateBoundingTiles(); refreshHulls(); _flashRect.X = 0; _flashRect.Y = 0; _flashRect.Width = (int)(FlxU.ceil((float)FlxG.width / (float)_tileWidth) + 1) * _tileWidth;; _flashRect.Height = (int)(FlxU.ceil((float)FlxG.height / (float)_tileHeight) + 1) * _tileHeight; //foreach (var item in _data) // Console.Write(item.ToString() + ","); //Console.WriteLine("\n"); return(this); }
public FlxTilemap loadMap(string MapData, Texture2D TileGraphic, int TileWidth, int TileHeight) { refresh = true; _tileBitmap = TileGraphic; //Figure out the map dimensions based on the data string string[] cols; string[] rows = MapData.Split('\n'); heightInTiles = rows.Length; int r = 0; int c; cols = rows[r].Split(','); _data = new int[rows.Length * cols.Length]; while (r < heightInTiles) { cols = rows[r++].Split(','); if (cols.Length <= 1) { heightInTiles = heightInTiles - 1; continue; } if (widthInTiles == 0) { widthInTiles = cols.Length; } c = 0; while (c < widthInTiles) { _data[((r - 1) * widthInTiles) + c] = int.Parse(cols[c++]); //.push(uint(cols[c++])); } } //Pre-process the map data if it's auto-tiled int i; totalTiles = widthInTiles * heightInTiles; if (auto > OFF) { collideIndex = startingIndex = drawIndex = 1; i = 0; while (i < totalTiles) { autoTile(i++); } } //Figure out the size of the tiles _tileWidth = TileWidth; if (_tileWidth == 0) { _tileWidth = TileGraphic.Height; } _tileHeight = TileHeight; if (_tileHeight == 0) { _tileHeight = _tileWidth; } _block.width = _tileWidth; _block.height = _tileHeight; //Then go through and create the actual map width = widthInTiles * _tileWidth; height = heightInTiles * _tileHeight; _rects = new List <Rectangle>(); i = 0; while (i < totalTiles) { _rects.Add(Rectangle.Empty); updateTile(i++); } //Pre-set some helper variables for later _screenRows = (int)FlxU.ceil((float)FlxG.height / (float)_tileHeight) + 1; if (_screenRows > heightInTiles) { _screenRows = heightInTiles; } _screenCols = (int)FlxU.ceil((float)FlxG.width / (float)_tileWidth) + 1; if (_screenCols > widthInTiles) { _screenCols = widthInTiles; } generateBoundingTiles(); refreshHulls(); _flashRect.X = 0; _flashRect.Y = 0; _flashRect.Width = (int)(FlxU.ceil((float)FlxG.width / (float)_tileWidth) + 1) * _tileWidth;; _flashRect.Height = (int)(FlxU.ceil((float)FlxG.height / (float)_tileHeight) + 1) * _tileHeight; return(this); }