/* * private RectangleF GetRectangle(Coords positionTile) * { * return new RectangleF(positionTile.X * Constants.TileBitmapSize * this._zoom, positionTile.Y * Constants.TileBitmapSize * this._zoom, * (Constants.TileBitmapSize) * this._zoom, (Constants.TileBitmapSize) * this._zoom); * } */ #region Tile drawers // Draw tile bitmap private void TileDrawBitmap(Graphics g, Coords position, Bitmap image) { Point anchor = new Point((Int32)(position.X * _zoom), (Int32)(position.Y * _zoom)); g.DrawImageUnscaled(image, anchor); }
private void DrawEllipseAtPixel(Graphics g, Coords pixel, UInt16 radiusX, UInt16 radiusY) { g.DrawEllipse(new Pen(Constants.BoundingCircleColor), (pixel.X - radiusX) * this._zoom, (pixel.Y - radiusY) * this._zoom, radiusX * 2 * this._zoom, radiusY * 2 * this._zoom); }
public float GetMapValue(Coords number) { // Perhaps should throw exception return(this._map[number.X, number.Y]); }
public void ClippingBoxesRemoveFrom(Coords box, Footballer removeMe) { _clippingBoxes[box.X, box.Y].Remove(removeMe); }
public float DistanceTo(Coords c) { return((float)Math.Sqrt(Math.Pow((this.X - c.X), 2) + Math.Pow((this.Y - c.Y), 2))); }
/// <summary> /// Generates the influence map. /// Uses a silly recursive algorithm. /// Stopping conditions: Let's use two, to avoid stupid infinite loops. /// One is a distance threshold check. /// Second is a min influence threshold check. /// </summary> public float[,] GenerateInfluenceMap(UInt16 sizex, UInt16 sizey, Coords source, InfluenceSpreadFunction f) { float[,] influenceMap = new float[sizex, sizey]; // boolean array to keep note of which tiles have been processed BitArray[] takenCareOf = new BitArray[sizex]; for (int i = 0; i < sizex; ++i) { takenCareOf[i] = new BitArray(sizey); } takenCareOf[source.X][source.Y] = true; // sets up two queues - one for the current pass, one for the next one // distance increments by one at each pass // if too slow, the process should be broken up so it does a number of passes each tick Queue <Coords> currentQueue = new Queue <Coords>(); Queue <Coords> nextQueue = new Queue <Coords>(); currentQueue.Enqueue(source); UInt32 currentDistance = 0; // main loop // Stopping conditions: the two queues are exhausted, OR InfluenceMapMaxDistance is reached while ( ((currentQueue.Count > 0) & (nextQueue.Count > 0)) | (currentDistance < Constants.InfluenceMapMaxDistance) ) { // Checks if it's time to start the next pass if (currentQueue.Count == 0) { currentQueue = nextQueue; nextQueue = new Queue <Coords>(); currentDistance++; continue; } Coords currentCoords = currentQueue.Peek(); // Analyzes the neighbors of the current Tile for possible additions to nextQueue for (byte i = 0; i < 8; i++) { Direction currentDir = (Direction)i; Coords toCheck = StaticMathFunctions.CoordsNeighboringInDirection(currentCoords, currentDir); if (toCheck.X >= 0 && toCheck.X < sizex && toCheck.Y >= 0 && toCheck.Y < sizey) { if (!takenCareOf[toCheck.X][toCheck.Y]) { nextQueue.Enqueue(toCheck); takenCareOf[toCheck.X][toCheck.Y] = true; } } } float newVal = f(currentDistance); // Check to avert infnite / excessively deep loop if (newVal > Constants.InfluenceMapMinThreshold) { influenceMap[currentCoords.X, currentCoords.Y] = newVal; } currentQueue.Dequeue(); } return(influenceMap); }
private Coords VertexBottomLeft(Coords box) { return(new Coords(_pixelsPerBoxX * box.X, _pixelsPerBoxY * (box.Y + 1) - 1)); }
public Coords(Coords c) { _X = c.X; _Y = c.Y; }
// returns true if the two circles collide private bool CollisionCheckEllipses(Coords center1, UInt16 radius1X, UInt16 radius1Y, Coords center2, UInt16 radius2X, UInt16 radius2Y) { UInt16 radiusSumX = (UInt16)(radius1X + radius2X); UInt16 radiusSumY = (UInt16)(radius1Y + radius2Y); // IS this even correct? It is for circles. Should be for ellipses. return(CollisionCheckPixelInEllipse(center1, center2, radiusSumX, radiusSumY)); }
private Coords VertexTopRight(Coords box) { return(new Coords(_pixelsPerBoxX * (box.X + 1) - 1, _pixelsPerBoxY * box.Y)); }
private Coords VertexTopLeft(Coords box) { return(new Coords(_pixelsPerBoxX * box.X, _pixelsPerBoxY * box.Y)); }
/* * /// <summary> * /// Returns all footballers clipped by the agent; empty if none. * /// </summary> * public List<Footballer> CreatureClippingCheck(Footballer critter, Coords potentialPosition, bool creaturesClipCheck) * { * // obtain new entry tiles * LinkedList<Coords> newEntries = this.TilesCoveredByEllipse(potentialPosition, critter.RadiusX, critter.RadiusY); * * // if the flags demands it, check if there is a creature in the way * if (creaturesClipCheck) * { * if (this.PotentialCreatureToCreatureCollision(critter, potentialPosition)) * { * return CollisionType.Footballer; * } * } * * return CollisionType.None; * } */ public LinkedList <Coords> TilesCoveredByEllipse(Coords center, UInt16 radiusX, UInt16 radiusY) { if (PotentialOutOfBoundsEllipse(center, radiusX, radiusY)) { return(null); } LinkedList <Coords> returnValue = new LinkedList <Coords>(); Coords current = new Coords((Int32)(center.X / _pixelsPerBoxX), (Int32)(center.Y / _pixelsPerBoxY)); // add tile on which center-pixel lies (if it's passable) returnValue.AddLast(current); #region overlap to the right check if ((center.X + radiusX) / _pixelsPerBoxX > current.X) // overlap to the right { Coords tileRight = new Coords(current.X + 1, current.Y); returnValue.AddLast(tileRight); if ((center.Y + radiusY) / _pixelsPerBoxY > current.Y) // overlap also to the bottom { Coords tileBottom = new Coords(current.X, current.Y + 1); returnValue.AddLast(tileBottom); Coords tileBottomRight = new Coords(current.X + 1, current.Y + 1); // bottom-right inspection if (CollisionCheckPixelInEllipse(VertexTopLeft(tileBottomRight), center, radiusX, radiusY)) // we're inside! { returnValue.AddLast(tileBottomRight); } } else if ((center.Y - radiusY) / _pixelsPerBoxY < current.Y) // overlap also to the top { Coords tileTop = new Coords(current.X, current.Y - 1); returnValue.AddLast(tileTop); Coords tileTopRight = new Coords(current.X + 1, current.Y - 1); // top-right inspection if (CollisionCheckPixelInEllipse(VertexBottomLeft(tileTopRight), center, radiusX, radiusY)) // we're inside! { returnValue.AddLast(tileTopRight); } } } #endregion #region overlap to the left check else if ((center.X - radiusX) / _pixelsPerBoxX < current.X) // overlap to the left { Coords tileLeft = new Coords(current.X - 1, current.Y); returnValue.AddLast(tileLeft); if ((center.Y + radiusY) / _pixelsPerBoxY > current.Y) // overlap also to the bottom { Coords tileBottom = new Coords(current.X, current.Y + 1); returnValue.AddLast(tileBottom); Coords tileBottomLeft = new Coords(current.X - 1, current.Y + 1); // bottom-left inspection if (CollisionCheckPixelInEllipse(VertexTopRight(tileBottomLeft), center, radiusX, radiusY)) // we're inside! { returnValue.AddLast(tileBottomLeft); } } else if ((center.Y - radiusY) / _pixelsPerBoxY < current.Y) // overlap also to the top { Coords tileTop = new Coords(current.X, current.Y - 1); returnValue.AddLast(tileTop); Coords tileTopLeft = new Coords(current.X - 1, current.Y - 1); // top-left inspection if (CollisionCheckPixelInEllipse(VertexBottonRight(tileTopLeft), center, radiusX, radiusY)) // we're inside! { returnValue.AddLast(tileTopLeft); } } } #endregion #region in between else // still have to check Y { if ((center.Y + radiusY) / _pixelsPerBoxY > current.Y) // overlap also to the bottom { Coords tileBottom = new Coords(current.X, current.Y + 1); returnValue.AddLast(tileBottom); } else if ((center.Y - radiusY) / _pixelsPerBoxY < current.Y) // overlap also to the top { Coords tileTop = new Coords(current.X, current.Y - 1); returnValue.AddLast(tileTop); } } #endregion // clean-up foreach (Coords c in returnValue) { if (!CheckInBounds(c)) { returnValue.Remove(c); } } return(returnValue); }
/// <summary> /// Returns footballers overlapped by agent. /// </summary> public List <Footballer> PotentialFootballerToFootballerCollision(Footballer critter, Coords potentialPosition) { List <Footballer> returnVal = new List <Footballer>(); UInt16 critterRadiusX = critter.RadiusX; UInt16 critterRadiusY = critter.RadiusY; LinkedList <Coords> checkList = this.TilesCoveredByEllipse(potentialPosition, critterRadiusX, critterRadiusY); foreach (Coords checkme in checkList) { foreach (Footballer obstacle in _clippingBoxes[checkme.X, checkme.Y]) { // ignore self if (obstacle == critter) { continue; } if (CollisionCheckEllipses(potentialPosition, critterRadiusX, critterRadiusY, new Coords(obstacle.PositionDouble), obstacle.RadiusX, obstacle.RadiusY)) { returnVal.Add(obstacle); } } } return(returnVal); }
/* * public static Direction OppositeDirection(Direction d) * { * return (Direction)(((byte)d + 4) % 8); * } */ /* * public static Direction DirectionToTheRight(Direction d) * { * return (Direction)(((byte)d + 1) % 8); * } */ /* * public static Direction DirectionToTheLeft(Direction d) * { * return (Direction)(((byte)d + 7) % 8); * } */ /* * public static Coords CoordsAverage(Coords c1, Coords c2) * { * return new Coords((Int32)0.5 * (c1.X + c2.X), (Int32)0.5 * (c1.Y + c2.Y)); * } */ /* * public static bool CoordinateIsInBox(Coords c, Coords boxTopLeft, Coords boxBottomRight) * { * return (((c.X >= boxTopLeft.X) && (c.X <= boxBottomRight.X)) && ((c.Y >= boxTopLeft.Y) && (c.Y <= boxBottomRight.Y))); * } */ /// <summary> /// Returns the eucledean distance between two Coords /// </summary> public static float DistanceBetweenTwoCoordsEucledean(Coords c1, Coords c2) { return((float)Math.Sqrt(Math.Pow((c1.X - c2.X), 2) + Math.Pow((c1.Y - c2.Y), 2))); }
private Coords VertexBottonRight(Coords box) { return(new Coords(_pixelsPerBoxX * (box.X + 1) - 1, _pixelsPerBoxY * (box.Y + 1) - 1)); }
/// <summary> /// returns the distance between two Coords /// </summary> public static float DistanceBetweenTwoCoordss(Coords c1, Coords c2) { return(Math.Max(Math.Abs(c1.X - c2.X), Math.Abs(c1.Y - c2.Y))); }
private Tile(Map home, Coords position) { this.InhabitedMap = home; this.Position = position; }
public Vector2d(Coords c) { _X = c.X; _Y = c.Y; }
public Tile(Map home, Coords position, SpriteTile tileBitmap) : this(home, position) { this._myBitmap = tileBitmap; }
public InfluenceSourceMap(UInt16 sizex, UInt16 sizey, Coords source, UInt16 distance) : base(sizex, sizey) { _source = source; _effectiveDistance = distance; }
/// <summary> /// Coords the painting of the portion of the map between the two Coords parameters. /// </summary> public void Paint(Graphics g, Coords topLeft, Coords bottomRight) { // The algorithm is as follows: // 1) AT INIT: Imports and resizes the bitmaps. // 2) AT ZOOM: Resizes bitmaps. // 3) AT PAINT: The Form determines what portion of the map should be painted and calls Painter. // Painter goes through the Tiles and draws them, row by row, from left-to-right from // top-to-bottom. #region Tiles Int32 pixelsX = 0; // We assume the validity check for the two coords has been done in the caller class. for (Int32 i = 0; i < Constants.MapSizeX; ++i) { if (i > 0) { pixelsX += Constants.TileSizesX[i - 1]; } Int32 pixelsY = 0; for (Int32 j = 0; j < Constants.MapSizeY; ++j) { Coords currentCoords = new Coords(i, j); Tile currentTile = this._currentMap.GetTile(i, j); if (j > 0) { pixelsY += Constants.TileSizesY[j - 1]; } this.TileDrawBitmap(g, new Coords(pixelsX, pixelsY), this.Tiles[(sbyte)currentTile.MyBitmap]); foreach (Footballer critter in _currentMap.Roster.Values) { this.AddForPaintingFootballer(critter); } } } #endregion #region Props and Footballers // The tiles have informed the painter about the Footballers he's supposed to draw. foreach (Footballer critter in this._FootballersToDraw) { this.FillPlayerEllipse(g, critter.PositionDouble, 10, 8, critter.Team.TeamColor); this.DrawBitmapAtPixel(g, new Coords((Int32)critter.PositionDouble.X, (Int32)critter.PositionDouble.Y), this.Footballers[(sbyte)critter.MyBitmap]); Vector2d delta = critter.FacingDirection; delta.ScaleToLength(50); this.DrawLine(g, critter.PositionDouble, critter.PositionDouble + delta); } // Draw the labels foreach (Footballer critter in this._FootballersToDraw) { //FIX // draw labels if ((critter.LabelUpper != null) && (critter.LabelUpper.Length > 0)) { this.DrawLabel(g, critter.PositionDouble + new Vector2d(0, -200), critter.LabelUpper); } if ((critter.LabelLower != null) && (critter.LabelLower.Length > 0)) { //this.DrawLabel(g, new Coords(CoordsType.Pixel, critter.PositionPixel.X, critter.PositionPixel.Y + critter.RadiusY), critter.LabelLower); } } for (int i = 0; i < Props.Length; ++i) { DrawProp(g, Constants.PropLocations[i], Props[i]); } #endregion #region Nets, Ball, and Info // DrawGhostBall if option is enabled if (this._ghost != null) { //BallGhost ghost = new BallGhost(this._currentMap.BallReference); for (int i = 0; i < Constants.GhostBallTimeLength; ++i) { for (int j = 0; j < Constants.GhostBallDrawInterval; ++j) { _ghost.UpdateMotion3D(); } this.DrawGhostBall(g, _ghost); } } if (Constants.ShowTrajectory) { if (this._currentMap.BallReference.Projection.Count > 0) { foreach (Vector3d v in this._currentMap.BallReference.Projection) { BallGhost ghost = new BallGhost(this._currentMap.BallReference); //ghost.SpawnAt(v.ProjectionXY()); ghost.Stop(); ghost.Position3d = v; this.DrawGhostBall(g, ghost); } } } BallPosition ballPos = DetermineBallPosition(_currentMap.BallReference); // Nets if (ballPos == BallPosition.BehindGoal) { this.DrawSomeBall(g, _currentMap.BallReference, this.Balls[(sbyte)SpriteBall.Standard]); } DrawNetYAxis(g, Constants.NetsBackLeft); DrawNetYAxis(g, Constants.NetsBackRight); DrawNetXAxis(g, Constants.NetsBackLeft, Constants.GoalTop); DrawNetXAxis(g, Constants.GoalRight, Constants.GoalTop); if (ballPos == BallPosition.InsideGoal) { this.DrawSomeBall(g, _currentMap.BallReference, this.Balls[(sbyte)SpriteBall.Standard]); } DrawNetXAxis(g, Constants.NetsBackLeft, Constants.GoalBottom); DrawNetXAxis(g, Constants.GoalRight, Constants.GoalBottom); DrawNetZAxis(g, Constants.NetsBackLeft); DrawNetZAxis(g, Constants.GoalRight); DrawGoals(g); if (ballPos == BallPosition.Visible) { this.DrawSomeBall(g, _currentMap.BallReference, this.Balls[(sbyte)SpriteBall.Standard]); } DrawBallParameters(g, topLeft); DrawShotParameters(g, topLeft); this.DrawInfluenceMap(g, _currentMap.MatchOnMap.TeamLeft.TeamInfluenceMap, topLeft, _currentMap.MatchOnMap.TeamLeft.TeamColor, true); this.DrawInfluenceMap(g, _currentMap.MatchOnMap.TeamRight.TeamInfluenceMap, topLeft, _currentMap.MatchOnMap.TeamRight.TeamColor, false); #endregion // Clean up the ID list. this._FootballersToDraw.Clear(); }
/// <summary> /// The passed 'updater' is generic. It was added to the 'map' at oldsource. We want to substract it, and add it at /// newSource. /// </summary> public void UpdateMapViaSourceMap(InfluenceMap map, InfluenceSourceMap updater, Coords oldSource, Coords newSource) { if (oldSource == newSource) { return; } InfluenceSourceMap oldInfMap = ShiftInfluenceSourceMap(updater, oldSource); InfluenceSourceMap newInfMap = ShiftInfluenceSourceMap(updater, newSource); map.Substract(oldInfMap); map.Add(newInfMap); }
private void DrawProp(Graphics g, Coords topLeft, Bitmap image) { Point anchor = new Point((Int32)(topLeft.X * _zoom), (Int32)(topLeft.Y * _zoom)); g.DrawImageUnscaled(image, new Point(anchor.X, anchor.Y)); }
// Self-explanatory public void SetMapValue(Coords number, float newValue) { // Perhaps should throw exception this._map[number.X, number.Y] = newValue; }
public void ClippingBoxesAddTo(Coords box, Footballer newGuy) { _clippingBoxes[box.X, box.Y].Add(newGuy); }