public void ShowPath() { m_shootingBall = (Ball)m_aComingBalls[0]; EPointF loc = m_shootingBall.Loc; double dAngle = -Math.PI * Angle / 180; float fSpeed = 1000; EPointF pntVel = EPointF.FromLengthAndAngle(fSpeed, (float)dAngle); EPoint pntGridStick = null; EPointF pntBounce; int nMaxTests = 40; //if more bounces than this is calculated, then something has gone wrong as it's outside the system // EH.Put("Start at "+loc.ToString()); while (nMaxTests-- > 0) { if (m_playArea.m_pathCalc.GetFirstStickOrBounce(ref loc, ref pntVel, out pntGridStick, out pntBounce, true) == false) { // EH.Put("Test num:"+nMaxTests.ToString() + " loc"+loc.ToString()); // EH.Put("Bounce:" + loc.ToString()+" vel:"+pntVel.ToString()); // loc = pntBounce.Copy(); } else { // if (m_spTarget!=null) // m_spTarget.Loc = m_playArea.Grid.GetGfxLocFromGridLoc(pntGridStick); break; } } }
public override System.Collections.ArrayList GeneratePoints(EPoint ptStart) { //Calculate curve's control and end anchor points: //Control point is the start point + offset to control EPoint ptControl = ptStart + this._ptControl; //End point is control point + offset to anchor: EPoint ptAnchor = ptControl + this._ptAnchor; //now calculate two bezier handles for the curve (Flash uses quadratic beziers, GDI+ uses cubic). //The two handles are 2/3rds from each endpoint to the control point. EPointF diff = (ptControl - ptStart).ToEPointF(); EPointF ctrl1 = EPointF.FromLengthAndAngle(diff.Length * 2 / 3, diff.Angle) + ptStart.ToEPointF(); //EPointF ctrl1 = ptStart.ToEPointF() + diff/2f; //EPointF ctrl1 = new EPointF(ptStart.X + (1f * (ptControl.X - ptStart.X) / 2f), ptStart.Y + (1f * (ptControl.Y - ptStart.Y) / 2f)); diff = (ptControl - ptAnchor).ToEPointF(); EPointF ctrl2 = EPointF.FromLengthAndAngle(diff.Length * 2 / 3, diff.Angle) + ptAnchor.ToEPointF(); //diff = (ptAnchor-ptControl).ToEPointF(); //EPointF ctrl2 = ptControl.ToEPointF() + diff/2f; //ctrl2 = new EPointF(ptControl.X + (1f * (ptAnchor.X - ptControl.X) / 2f), ptControl.Y + (1f * (ptAnchor.Y - ptControl.Y) / 2f)); System.Collections.ArrayList pts = new System.Collections.ArrayList(); pts.Add(ptStart.ToEPointF()); pts.Add(ctrl1); pts.Add(ctrl2); pts.Add(ptAnchor.ToEPointF()); return(pts); }
public float CheckCollisionsWithBallFromTime(Ball a_ball, float a_fTime, ref PropsAtCollision[] propsAtCollisionList) { propsAtCollisionList[0].Ball = this; propsAtCollisionList[1].Ball = a_ball; float fCollisionTime; EPointF pntCircleAtCollisionLoc; EPointF pntTouchLoc; EPointF locThis = this.Loc + this.Velocity*a_fTime; EPointF velThis = this.Velocity*(1.0f-a_fTime); EPointF locOther = a_ball.Loc + a_ball.Velocity*a_fTime; EPointF velOther = a_ball.Velocity*(1.0f-a_fTime); if (Endogine.Collision.Collision.CalcFirstCircleCircleCollisions(locThis, locOther, velThis, velOther, this.Radius, a_ball.Radius, out pntCircleAtCollisionLoc, out fCollisionTime)) { propsAtCollisionList[0].Loc = locThis+velThis*fCollisionTime; propsAtCollisionList[1].Loc = locOther + velOther*fCollisionTime; propsAtCollisionList[0].Velocity = this.Velocity.Copy(); propsAtCollisionList[1].Velocity = a_ball.Velocity.Copy(); EPointF relativeVel = this.Velocity-a_ball.Velocity; EPointF pntTmp = EPointF.FromLengthAndAngle(this.Radius, (propsAtCollisionList[1].Loc-propsAtCollisionList[0].Loc).Angle); pntTouchLoc = propsAtCollisionList[0].Loc+pntTmp; EPointF debugLoc = propsAtCollisionList[1].Loc-propsAtCollisionList[0].Loc; //the amount of energy transferred to the other depends on the collision angle vs the C:\Documents and Settings\Jonas\Mina dokument\Visual Studio Projects\EndoTest01\Endogine\Sprite.csrelative velocity's angle float velAngle = relativeVel.Angle; EPointF pntX = propsAtCollisionList[0].Loc - pntTouchLoc; float angleOrientation = Endogine.Collision.Collision.GetOrientationAngle(pntX.Angle - velAngle); //if "wall" is same angle as relative move angle: no energy transferred. //if "wall" is 90 degrees off, all energy is transferred. float fTransferredEnergyFactor = Math.Abs((float)((angleOrientation-Math.PI/2)/(Math.PI/2))); //float fTransferredEnergyFactor = (float)(Math.Cos(angleOrientation*2)); EPointF pntDiff = propsAtCollisionList[1].Loc - pntTouchLoc; EPointF pntAddedVel = EPointF.FromLengthAndAngle(relativeVel.Length*fTransferredEnergyFactor, pntDiff.Angle); propsAtCollisionList[1].Velocity+=pntAddedVel; //total energy and angle must be the same, so adjust the other's velocity (must be an thought error somewhere?) propsAtCollisionList[0].Velocity = (this.Velocity+a_ball.Velocity) - propsAtCollisionList[1].Velocity; // propsAtCollisionList[0].Velocity = EPointF.FromLengthAndAngle( // (this.Velocity+a_ball.Velocity).Length - propsAtCollisionList[1].Velocity.Length, // (this.Velocity+a_ball.Velocity).Angle - propsAtCollisionList[1].Velocity.Angle); propsAtCollisionList[0].Velocity.Length = this.Velocity.Length+a_ball.Velocity.Length - propsAtCollisionList[1].Velocity.Length; return fCollisionTime * (1.0f-a_fTime) + a_fTime; } else return -1; }
private void DrawLineWithCaps(Graphics g, Pen pen, EPointF start, EPointF end, float capLength) { //pen caps aren't flexible enough... // pen.StartCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor; // pen.EndCap = System.Drawing.Drawing2D.LineCap.DiamondAnchor; EPointF pntDiff = end - start; g.DrawLine(pen, start.ToPointF(), end.ToPointF()); g.DrawLine(pen, start.ToPointF(), (start + EPointF.FromLengthAndAngle(capLength, pntDiff.Angle + (float)Math.PI / 4)).ToPointF()); g.DrawLine(pen, start.ToPointF(), (start + EPointF.FromLengthAndAngle(capLength, pntDiff.Angle - (float)Math.PI / 4)).ToPointF()); g.DrawLine(pen, end.ToPointF(), (end + EPointF.FromLengthAndAngle(capLength, pntDiff.Angle + (float)Math.PI + (float)Math.PI / 4)).ToPointF()); g.DrawLine(pen, end.ToPointF(), (end + EPointF.FromLengthAndAngle(capLength, pntDiff.Angle + (float)Math.PI - (float)Math.PI / 4)).ToPointF()); }
public override void EnterFrame() { this._frameNum++; float f = (float)Math.Sin((float)this._frameNum / 7f); EPointF ptNew = EPointF.FromLengthAndAngle(50, f * 0.5f); ptNew.Y *= 0.2f; if (this._ptOffset == null) { this._ptOffset = ptNew; } EPointF ptDiff = ptNew - this._ptOffset; this._ptOffset = ptNew; this.Parent.Loc += ptDiff; }
public float CheckCollisionsWithLinesFromTime(float a_fTime, ref PropsAtCollision propsAtCollision) { float fCollisionTime; EPointF pntCircleAtCollisionLoc; EPointF pntTouchLoc; EPointF locThis = this.Loc + this.Velocity*a_fTime; EPointF velThis = this.Velocity*(1.0f-a_fTime); float fFirstHitTime = 99; foreach (ERectangleF rctLine in GameMain.Instance.Table.Lines) { if (Endogine.Collision.Collision.CalcCircleLineCollision(locThis, this.Radius, velThis, rctLine, out pntTouchLoc, out pntCircleAtCollisionLoc)) { fCollisionTime = (pntCircleAtCollisionLoc-locThis).Length / velThis.Length; if (fCollisionTime < fFirstHitTime) { fFirstHitTime = fCollisionTime; float fNormal = (float)Endogine.Collision.Collision.GetNormalAngle(rctLine)+(float)Math.PI/2; //the line's direction, it shouldn't matter if it's up or down, or left or right - same bounce regardless fNormal = Endogine.Collision.Collision.GetOrientationAngle(fNormal); float fVelAngle = velThis.Angle; float fAngleDiff = fVelAngle-fNormal; float fAfterBounceAngle = fVelAngle-fAngleDiff*2; propsAtCollision.Loc = pntCircleAtCollisionLoc; propsAtCollision.Velocity = EPointF.FromLengthAndAngle(velThis.Length, fAfterBounceAngle); } } } propsAtCollision.Ball = this; if (fFirstHitTime <= 1) propsAtCollision.Time = fFirstHitTime * (1.0f-a_fTime) + a_fTime; return propsAtCollision.Time; }
/// <summary> /// /// </summary> /// <param name="a_loc">start loc</param> /// <param name="a_vel">find first collision/bounce while moving this amount</param> /// <param name="pntGridStick"></param> /// <returns>true if it hit something to stick to (another ball, or ceiling)</returns> public bool GetFirstStickOrBounce(ref EPointF a_loc, ref EPointF a_vel, out EPoint pntGridStick, out EPointF pntBounce, bool bMoveBallAfterCollision) { EPointF pntCollision = new EPointF(0, 0); EPointF pntCircleAtCollision; EPointF pntNormal = new EPointF(0, 0); bool bCollided = false; pntGridStick = null; //new EPoint(0,0); pntBounce = null; //new EPointF(0,0); float fFirstTime = 1000; ArrayList aBalls = m_playArea.Grid.GetAllBalls(); foreach (Ball ball in aBalls) { float fTime; EPointF pntThisCollision; if (Endogine.Collision.Collision.CalcFirstCircleCircleCollisions( a_loc, ball.Loc, a_vel, new EPointF(0, 0), m_playArea.Grid.BallDiameter / 2 - 1, m_playArea.Grid.BallDiameter / 2 - 1, //it's more like the original if we subtract 1 out pntThisCollision, out fTime)) { if (fTime < fFirstTime) { pntCollision = pntThisCollision; fFirstTime = fTime; } } } if (fFirstTime < 1000) { EPointF pntfGrid = m_playArea.Grid.GetGridLocFromGfxLoc(pntCollision); pntGridStick = m_playArea.Grid.RoundToClosestGridLoc(pntfGrid); a_loc = m_playArea.Grid.GetGfxLocFromGridLoc(pntGridStick); a_vel = new EPointF(0, 0); return(true); } //check wall bounces and ceiling stick for (int nLineNum = 0; nLineNum < m_playArea.m_aCollisionLines.Count; nLineNum++) { ERectangleF rctLine = (ERectangleF)m_playArea.m_aCollisionLines[nLineNum]; if (Endogine.Collision.Collision.CalcCircleLineCollision(a_loc, m_playArea.Grid.BallDiameter / 2, a_vel, rctLine, out pntCollision, out pntCircleAtCollision)) { if (nLineNum == 0) { //hit ceiling: make it stick! EPointF pntfGrid = m_playArea.Grid.GetGridLocFromGfxLoc(pntCollision); EndogineHub.Put(pntCollision.ToString() + " " + pntfGrid.ToString()); pntGridStick = m_playArea.Grid.RoundToClosestGridLoc(pntfGrid); a_loc = m_playArea.Grid.GetGfxLocFromGridLoc(pntGridStick); a_vel.X = 0; a_vel.Y = 0; return(true); } //TODO: check all lines, and use the one that is collided with first. //Then a new test should be done from the bounce point pntBounce = pntCollision; //bounce against a wall: which direction will it have afterwards double dNormal = Endogine.Collision.Collision.GetNormalAngle(rctLine); //the line's direction, it shouldn't matter if it's up or down, or left or right - same bounce regardless if (dNormal >= Math.PI) { dNormal -= Math.PI; } if (dNormal >= Math.PI / 2) { dNormal -= Math.PI / 2; } double dVelAngle = Math.Atan2(a_vel.X, -a_vel.Y); double dAfterBounceAngle = dNormal - (dVelAngle - dNormal); //just so it's easier to debug: if (dAfterBounceAngle > Math.PI) { dAfterBounceAngle -= Math.PI; } //how far can it move before hitting wall EPointF pntBefore = new EPointF(pntCircleAtCollision.X - a_loc.X, pntCircleAtCollision.Y - a_loc.Y); double dPartOfMove = Endogine.Collision.PointLine.PointIsWhereOnLine(pntBefore, new ERectangleF(0, 0, a_vel.X, a_vel.Y)); if (dPartOfMove > 0.99) { dPartOfMove = 0.99; } else if (dPartOfMove < 0 && dPartOfMove > -0.001) { dPartOfMove = 0; } //the rest of the movement will be in bounce direction a_vel = EPointF.FromLengthAndAngle(a_vel.Length, (float)dAfterBounceAngle); //EPointF velNew = EPointF.FromLengthAndAngle(a_vel.Length, (float)dAfterBounceAngle); //a_vel.X = velNew.X; //a_vel.Y = velNew.Y; //TODO: pntCircleAtCollision is not correctly calculated. a_loc = pntCircleAtCollision; if (bMoveBallAfterCollision) { a_loc.X += a_vel.X * (float)(1.0 - dPartOfMove); a_loc.Y += a_vel.Y * (float)(1.0 - dPartOfMove); } bCollided = true; break; } } if (!bCollided) { a_loc.X += a_vel.X; a_loc.Y += a_vel.Y; } return(false); }
private EPointF GetLocFromHue() { float angle = (this.HSB.H - 60) / 180 * (float)Math.PI; return(this.Center + EPointF.FromLengthAndAngle(0.72f * this._trianglePoints[1].X, angle)); }
public override void EnterFrame() { this.Interactor.Loc = this._locOrg + EPointF.FromLengthAndAngle(this.Interactor.PartLeftToNoteOn * 7, (float)(this.Interactor.PartLeftToNoteOn * Math.PI * 2 * 4)); }