/// <summary> /// Generates an Obstacle at the given location with a random number of points created using a random radius. /// </summary> /// <param name="pLocation"></param> /// <param name="MinPoints"></param> /// <param name="MaxPoints"></param> /// <param name="MinRadius"></param> /// <param name="MaxRadius"></param> /// <param name="pDrawBrush"></param> /// <param name="pDrawPen"></param> public PolygonObstacle(PointF pLocation,int MinPoints,int MaxPoints,float MinRadius,float MaxRadius,PolygonBlockDrawMethod drawMethod) : base(pLocation,null,0) { _Location = pLocation; _Poly = new Polygon(BCBlockGameState.GenPoly(MinRadius,MaxRadius,MinPoints,MaxPoints)); _Poly.Offset(pLocation); _DrawMethod = drawMethod; //base.Size = _Poly.GetBounds().Size; }
public PolygonObstacle(IEnumerable<PointF> Points,Brush pDrawBrush,Pen pDrawPen) : base(CenterPoint(Points),null,0) { _DrawMethod = new FilledPolyDrawMethod(pDrawPen, pDrawBrush); _Poly = new Polygon(Points.ToArray()); //base.Size = _Poly.GetBounds().Size; }
public override bool PerformFrame(BCBlockGameState gamestate) { if (_Abilities.Any()) { List<GameCharacterAbility> addabilities = new List<GameCharacterAbility>(); List<GameCharacterAbility> removeabilities = new List<GameCharacterAbility>(); foreach (GameCharacterAbility gma in _Abilities) { if (gma.PerformFrame(this, gamestate)) removeabilities.Add(gma); } foreach (var removeit in removeabilities) { Abilities.Remove(removeit); } foreach (var addit in addabilities) { Abilities.Add(addit); } } bool nobasecall = false; if (!flInit) { flInit = true; //hook the GameClient events... gamestate.ClientObject.ButtonDown += ClientObject_ButtonDown; gamestate.ClientObject.ButtonUp += ClientObject_ButtonUp; } if (EnemyAction == "DEATH") return base.PerformFrame(gamestate); if (EnemyAction == "DYING") { if (DateTime.Now - DeadTime.Value > new TimeSpan(0, 0, 0, 1)) { EnemyAction = "DEATH"; BCBlockGameState.Soundman.PlaySound("MARDEATH2"); Velocity = new PointF(0, -4); _GravityEffect = new PointF(0, 8f); Nocollisions = true; nobasecall = true; } return base.PerformFrame(gamestate); } /* case Keys.W: return ButtonConstants.Button_E; case Keys.A: return ButtonConstants.Button_F; case Keys.S: return ButtonConstants.Button_G; case Keys.D: return ButtonConstants.Button_H;*/ if (EnemyAction == "IDLELEFT" || EnemyAction == "IDLERIGHT") { if (Buttonspressed[ButtonConstants.Button_F]) { EnemyAction = "WALKLEFT"; } else if (Buttonspressed[ButtonConstants.Button_H]) { EnemyAction = "WALKRIGHT"; } } switch (EnemyAction) { case "IDLELEFT": if (!isonground) EnemyAction = "JUMPLEFT"; break; case "IDLERIGHT": if (!isonground) EnemyAction = "JUMPRIGHT"; break; case "JUMPLEFT": if (isonground) EnemyAction = "WALKLEFT"; Decelerate(); break; case "JUMPRIGHT": if (isonground) EnemyAction = "WALKRIGHT"; Decelerate(); break; case "WALKLEFT": Decelerate(); if (Math.Abs(Velocity.X) < 0.1) EnemyAction = "IDLELEFT"; if (!isonground) EnemyAction = "JUMPLEFT"; break; case "WALKRIGHT": Decelerate(); if (Math.Abs(Velocity.X) < 0.1) EnemyAction = "IDLERIGHT"; if (!isonground) EnemyAction = "JUMPRIGHT"; break; } //check for ball collisions. foreach (var loopball in gamestate.Balls) { Polygon ppoly = loopball.GetBallPoly(); Polygon boundbox = new Polygon(this.GetRectangleF()); var result = GeometryHelper.PolygonCollision(ppoly, boundbox, new Vector(0, 0)); if (result.Intersect) { Die(gamestate); break; } } if (!nobasecall) return base.PerformFrame(gamestate); else return false; }
public override bool PerformFrame(BCBlockGameState gamestate) { if (Frozen) return false; PointF usedoffset=PointF.Empty; BCBlockGameState.IncrementLocation(gamestate, ref _Location, _Velocity,ref usedoffset); _Poly.Offset(usedoffset); if (!(new Polygon(gamestate.GameArea).Contains(_Poly))) { //reflect var result = GeometryHelper.PolygonCollision(new Polygon(gamestate.GameArea), _Poly, Velocity); var copied = new PointF(-result.MinimumTranslationVector.X, -result.MinimumTranslationVector.Y); if (Math.Abs(result.MinimumTranslationVector.X) > Math.Abs(result.MinimumTranslationVector.Y)) { //mirror X speed. Velocity = new PointF(-Velocity.X, Velocity.Y); } else { Velocity = new PointF(Velocity.X, -Velocity.Y); } } _Velocity = _VelocityDecayFunction(this, _Velocity); CurrAngle += AngleSpeed; _AngleSpeed = _AngleSpeedDecayFunction(this, _AngleSpeed); //check for ball collisions. foreach (cBall checkball in gamestate.Balls) { Polygon ballpoly = checkball.GetBallPoly(); if (_Poly.IntersectsWith(ballpoly) && !InvokeBeforeObstacleHit(gamestate,checkball,this)) { //only if it intersects. Vector Adjustment; GeometryHelper.PolygonCollisionResult pcr = GeometryHelper.PolygonCollision(_Poly, ballpoly, new Vector(checkball.Velocity.X+Velocity.X, checkball.Velocity.Y+Velocity.Y)); Adjustment = pcr.MinimumTranslationVector; checkball.Velocity = checkball.Velocity.Mirror(pcr.MinimumTranslationVector); checkball.Velocity = new PointF(checkball.Velocity.X, checkball.Velocity.Y); checkball.Location = new PointF(checkball.Location.X - Adjustment.X, checkball.Location.Y - Adjustment.Y); BCBlockGameState.Soundman.PlaySound("bounce"); //determine percentage of "knockback" to us based on the ratio between the ball radius and our average radius. float ourAverage = _Poly.AverageRadius(); float ballradii = checkball.Radius; float ratio = ballradii / ourAverage; PointF mCenter = GetRectangle().CenterPoint(); Velocity = new PointF(Velocity.X + pcr.MinimumTranslationVector.X * ratio, Velocity.Y + pcr.MinimumTranslationVector.Y * ratio); //get angle between the ball's previous location (assumed from the velocity) and it's current pos, //with our center point as the pivot. PointF PrevPosition = checkball.PrevLocation; PointF CurrLocation = checkball.Location; var PrevAngle = BCBlockGameState.GetAngle(mCenter, PrevPosition); var CurrentAngle = BCBlockGameState.GetAngle(mCenter, CurrLocation); AngleSpeed = CurrentAngle - PrevAngle; //reduce our size, as well. _Poly = _Poly.Scale(0.9f); if (_Poly.Area() < MinimumSize && !InvokeObstacleHit(gamestate,checkball,this)) { //Fire the OnDestroy event if(!InvokeObstacleDestroy(gamestate,checkball,this)) return true; //tweak: make it explode or something, too. } } } if (_fShoot) { if (delayoffset++ == _ShootDelay) { delayoffset = 0; //shoot lightning. Because lightning is da' shit. //choose a random point on this polygon. PointF selectedpoint = BCBlockGameState.Choose(Poly.Points); //get angle between that point and the paddle. //if there is no paddle, use a random value. double fireangle = gamestate.PlayerPaddle != null ? BCBlockGameState.GetAngle(selectedpoint, gamestate.PlayerPaddle.CenterPoint()) : BCBlockGameState.rgen.NextDouble() * Math.PI * 2; PointF createdvel = BCBlockGameState.VaryVelocity(new PointF((float)Math.Cos(fireangle), (float)Math.Sin(fireangle)), Math.PI / 12); LightningShot ls = new LightningShot(selectedpoint, createdvel) { DamageBlocks = false, DamagePaddle = true }; gamestate.Defer(() => gamestate.GameObjects.AddLast(ls)); } } return !gamestate.GameArea.IntersectsWith(_Poly.GetBounds().ToRectangle()); }
private void regenpoints() { PolyPoints = new List<PointF>(); double currangle = 0, angleincrement = Math.PI / (NumPolyPoints * 2); for (int i = 0; i < NumPolyPoints; i++) { PolyPoints.Add(new PointF((float)(Math.Cos(currangle)*Radius),(float)(Math.Sin(currangle)*Radius))); currangle+=angleincrement; } BallPoly = new Polygon(PolyPoints.ToArray()); //done... }
public override void Draw(object source, Polygon pb, Graphics g) { var Grabpoints = pb.getPoints().ToArray(); g.FillPolygon(_FillBrush, Grabpoints); //g.DrawPolygon(_LinePen, Grabpoints); foreach (var iterateA in Grabpoints) { foreach (var iterateB in Grabpoints) { if (iterateA != iterateB) { //draw a line. g.DrawLine(LinePen, iterateA, iterateB); } } } }
// Calculate the projection of a polygon on an axis and returns it as a [min, max] interval public static void ProjectPolygon(Vector axis, Polygon polygon, ref float min, ref float max) { // To project a point on an axis use the dot product float d = axis.DotProduct(polygon.Points[0]); min = d; max = d; for (int i = 0; i < polygon.Points.Count; i++) { d = polygon.Points[i].DotProduct(axis); if (d < min) { min = d; } else { if (d > max) { max = d; } } } }
// Check if polygon A is going to collide with polygon B for the given velocity public static PolygonCollisionResult PolygonCollision(Polygon polygonA, Polygon polygonB, Vector velocity) { if (polygonA == null || polygonB == null) { Debug.Print("balls"); } PolygonCollisionResult result = new PolygonCollisionResult(); result.Intersect = true; result.WillIntersect = true; int edgeCountA = polygonA.Edges.Count; int edgeCountB = polygonB.Edges.Count; float minIntervalDistance = float.PositiveInfinity; Vector translationAxis = new Vector(); Vector edge; // Loop through all the edges of both polygons for (int edgeIndex = 0; edgeIndex < edgeCountA + edgeCountB; edgeIndex++) { if (edgeIndex < edgeCountA) { edge = polygonA.Edges[edgeIndex]; } else { edge = polygonB.Edges[edgeIndex - edgeCountA]; } // ===== 1. Find if the polygons are currently intersecting ===== // Find the axis perpendicular to the current edge Vector axis = new Vector(-edge.Y, edge.X); axis.Normalize(); // Find the projection of the polygon on the current axis float minA = 0; float minB = 0; float maxA = 0; float maxB = 0; ProjectPolygon(axis, polygonA, ref minA, ref maxA); ProjectPolygon(axis, polygonB, ref minB, ref maxB); // Check if the polygon projections are currentlty intersecting if (IntervalDistance(minA, maxA, minB, maxB) > 0) result.Intersect = false; // ===== 2. Now find if the polygons *will* intersect ===== // Project the velocity on the current axis float velocityProjection = axis.DotProduct(velocity); // Get the projection of polygon A during the movement if (velocityProjection < 0) { minA += velocityProjection; } else { maxA += velocityProjection; } // Do the same test as above for the new projection float intervalDistance = IntervalDistance(minA, maxA, minB, maxB); if (intervalDistance > 0) result.WillIntersect = false; // If the polygons are not intersecting and won't intersect, exit the loop if (!result.Intersect && !result.WillIntersect) break; // Check if the current interval distance is the minimum one. If so store // the interval distance and the current distance. // This will be used to calculate the minimum translation vector intervalDistance = Math.Abs(intervalDistance); if (intervalDistance < minIntervalDistance) { minIntervalDistance = intervalDistance; translationAxis = axis; Vector d = polygonA.Center - polygonB.Center; if (d.DotProduct(translationAxis) < 0) translationAxis = -translationAxis; } } // The minimum translation vector can be used to push the polygons appart. // First moves the polygons by their velocity // then move polygonA by MinimumTranslationVector. if (result.WillIntersect) result.MinimumTranslationVector = translationAxis * minIntervalDistance; return result; }
//splits this polygon into triangular sectors, each of which is returned as a new polygon in the return array. public Polygon[] Split() { Polygon[] returnpoly = new Polygon[Points.Count]; for (int i = 0; i < Points.Count - 1;i++ ) { //First, second, Center will be the polygon order. Polygon pg = new Polygon(new PointF[] { Points[i], Points[i + 1], Center }); returnpoly[i] = pg; } // add last poly. Last-First-Center returnpoly[returnpoly.Length - 1] = new Polygon(new PointF[] { Points.Last(), Points.First(), Center }); return returnpoly; }
public bool IntersectsWith(Polygon otherpoly) { return (GeometryHelper.PolygonCollision(this, otherpoly, new Vector(0, 0)).Intersect); }
public bool Contains(Polygon Otherpoly) { return Otherpoly.Points.All(this.Contains); }