/// <summary> /// Determine point on ellipse where ray intersects /// </summary> /// <param name="v">Center point</param> /// <param name="size">Size</param> /// <param name="angle">Rotation angle (radians)</param> /// <param name="rayAngle">Angle to project ray (radians)</param> /// <returns>Point of intersection</returns> public static Vector EllipsePoint( Vector v, Vector size, double angle, double rayAngle ) { // Normalize the angle (remove the ellipse angle) double normalAngle = rayAngle - angle; // Determine intersection point, then rotate by the ellipse angle return new Vector( size.X / 2 * Math.Cos( normalAngle ), size.Y / 2 * Math.Sin( normalAngle ) ).Rotate( angle ).Plus( v ); }
public AngularConstraint( Particle p1, Particle p2, Particle p3 ) { pA = p1.Curr; pB = p2.Curr; pC = p3.Curr; lineA = new Line( pA, pB ); lineB = new Line( pB, pC ); // lineC is the reference line for getting the angle of the line segments pD = new Vector( pB.X + 0, pB.Y - 1 ); lineC = new Line( pB, pD ); // theta to constrain to -- domain is -Math.PI to Math.PI targetTheta = CalcTheta( pA, pB, pC ); // coefficient of stiffness stiffness = 1; }
/// <summary> /// Are ellipses colliding? /// </summary> /// <param name="v1">First ellipse center point</param> /// <param name="size1">First ellipse size</param> /// <param name="angle1">First ellipse angle</param> /// <param name="v2">Second ellipse center point</param> /// <param name="size2">Second ellipse size</param> /// <param name="angle2">Second ellipse angle</param> /// <param name="depth">Penetration depth (out)</param> /// <param name="point1">First ellipse intersection point</param> /// <param name="point2">Second ellipse intersection point</param> /// <returns>True if colliding</returns> public static bool IsEllipseCollision( Vector v1, Vector size1, double angle1, Vector v2, Vector size2, double angle2, out CollisionState state) { // Direction vector from first ellipse center to second ellipse center Vector direction = v2.MinusNew( v1 ); double angle = direction.Angle; // Point of collision on first ellipse state.Point1 = EllipsePoint( v1, size1, angle1, angle ); // Point of collision on second ellipse state.Point2 = EllipsePoint( v2, size2, angle2, angle + Math.PI ); // Penetration depth state.Depth = state.Point2.MinusNew( state.Point1 ); // If first ellipse radius (in direction of ray) + second ellipse radius is greater than the distance // between the two ellipses, we have a collision state.Colliding = ( v1.Distance( state.Point1 ) + v2.Distance( state.Point2 ) > v1.Distance( v2 ) ); return state.Colliding; }
public double Dot( Vector v ) { return x * v.x + y * v.y; }
public double Distance( Vector v ) { double dx = x - v.x; double dy = y - v.y; return Math.Sqrt( dx * dx + dy * dy ); }
public double Cross( Vector v ) { return x * v.y - y * v.x; }
public void Copy( Vector v ) { x = v.x; y = v.y; }
/** * projects this vector onto b */ public Vector Project( Vector b ) { double adotb = this.Dot( b ); double len = ( b.x * b.x + b.y * b.y ); Vector proj = new Vector( 0, 0 ); proj.x = ( adotb / len ) * b.x; proj.y = ( adotb / len ) * b.y; return proj; }
public Vector PlusNew( Vector v ) { return new Vector( x + v.x, y + v.y ); }
public Vector MinusNew( Vector v ) { return new Vector( x - v.x, y - v.y ); }
public Vector Minus( Vector v ) { x -= v.x; y -= v.y; return this; }
public void UpdateScrolling() { // update scroll pane if (editor.Active) { // editor handles scrolling editor.UpdateScrolling(); } else { // game handles scrolling Vector apos = level.actor.GetPos(); Vector dx = new Vector(apos.X - cameraX, apos.Y - cameraY); double mag = dx.Magnitude(); if (mag > 400) dx.Mult(400 / mag); cameraX += (int)(dx.X / 2); cameraY += (int)(dx.Y / 2); TranslateTransform tt = new TranslateTransform(); tt.X = -(cameraX - 500); tt.Y = -(cameraY - 400); scroller.RenderTransform = tt; } }
public void ProcessInputs(bool[] keys) { if (personHead.Curr.Y >= 1000) Kill(); double keySpeed = 0.1; if (IsDead()) { wheelA.RP.Decelerate(keySpeed); wheelB.RP.Decelerate(keySpeed); return; } bool keyLeft = keys[30]; // A bool keyRight = keys[33]; // D bool keyJump = keys[48]; // S bool keyStunt = keys[52]; // W if (keyLeft) { if (lastRight) { wheelA.RP.Decelerate(keySpeed); wheelB.RP.Decelerate(keySpeed); } wheelA.RP.VS -= keySpeed; wheelB.RP.VS -= keySpeed; } else if (keyRight) { if (!lastRight) { wheelA.RP.Decelerate(keySpeed); wheelB.RP.Decelerate(keySpeed); } wheelA.RP.VS += keySpeed; wheelB.RP.VS += keySpeed; } else { wheelA.RP.VS /= 2; wheelB.RP.VS /= 2; } Wheel primaryWheel = wheelA; Wheel secondaryWheel = wheelB; double deltaX = lastRight ? 1 : -1; double dirX = 1.0; if (deltaX < 0) { dirX = -1.0; primaryWheel = wheelB; secondaryWheel = wheelA; } Vector downNormal = new Vector(0, 0); if (primaryWheel.lastNormal!=null) { airTimeout = 0; if (keyStunt) { secondaryWheel.Curr.Y -= 2.0; secondaryWheel.Curr.X -= dirX * 0.5; personBody.Curr.X -= dirX; personHead.Curr.X += dirX; } downNormal = primaryWheel.lastNormal.Clone(); if (secondaryWheel.lastNormal != null) { downNormal.Plus(secondaryWheel.lastNormal); downNormal.Normalize(); } } else if (secondaryWheel.lastNormal!=null) { airTimeout = 0; if (keyStunt) { primaryWheel.Curr.Y -= 2.0; primaryWheel.Curr.X -= dirX / 2; personBody.Curr.X -= dirX; personHead.Curr.X += dirX; } downNormal = secondaryWheel.lastNormal; } else { // in air jumpCharge = 0; airTimeout++; if (airTimeout > 10) { Vector r = wheelB.Curr.MinusNew(wheelA.Curr); if (keyRight) { r = r.Rotate(((2 * Math.PI) / 360) * 10); r.Normalize(); r.Mult(5); wheelA.Curr.X -= r.X; wheelA.Curr.Y -= r.Y; wheelB.Curr.X += r.X; wheelB.Curr.Y += r.Y; //personBody.Curr.X += dirX; //personHead.Curr.X += 2; } if (keyLeft) { r = r.Rotate(-((2 * Math.PI) / 360) * 10); r.Normalize(); r.Mult(5); wheelA.Curr.X -= r.X; wheelA.Curr.Y -= r.Y; wheelB.Curr.X += r.X; wheelB.Curr.Y += r.Y; //personBody.Curr.X -= dirX; //personHead.Curr.X -= 2; } } } if (airTimeout == 0) { if (jumpCharge > 0 & !keyJump) { jumpImpulse.X = downNormal.X * jumpCharge; jumpImpulse.Y = downNormal.Y * jumpCharge; jumpCharge = 0; } if (keyJump) { if (jumpCharge == 0) jumpCharge = 8; // initial charge if (jumpCharge < 25) jumpCharge += 0.5; personBody.Curr.Y -= downNormal.Y * jumpCharge * 0.1; personHead.Curr.Y -= downNormal.Y * jumpCharge * 0.1; personBody.Curr.X -= downNormal.X * jumpCharge * 0.1; personHead.Curr.X -= downNormal.X * jumpCharge * 0.1; personHead.Curr.X += dirX; personBody.Curr.X -= dirX; primaryWheel.Curr.X += dirX * jumpCharge * 0.1; } } if (jumpImpulse.X != 0 || jumpImpulse.Y != 0) { primaryWheel.Curr.X += jumpImpulse.X; primaryWheel.Curr.Y += jumpImpulse.Y; secondaryWheel.Curr.X += jumpImpulse.X; secondaryWheel.Curr.Y += jumpImpulse.Y; jumpImpulse.X = jumpImpulse.X / 2; jumpImpulse.Y = jumpImpulse.Y / 2; if (Math.Abs(jumpImpulse.X) < 1) jumpImpulse.X = 0; if (Math.Abs(jumpImpulse.Y) < 1) jumpImpulse.Y = 0; } if (keyLeft) lastRight = false; if (keyRight) lastRight = true; primaryWheel.lastNormal = null; secondaryWheel.lastNormal = null; }
public void Init(double cx, double cy) { center = new Vector( cx, cy ); verts = new List<Vector>(); normal = new Vector( 0, 0 ); active = true; SetDirty(); }
public Vector Plus( Vector v ) { x += v.x; y += v.y; return this; }
public Line( Vector p1, Vector p2 ) { this.p1 = p1; this.p2 = p2; }
private double CalcTheta( Vector pa, Vector pb, Vector pc ) { Vector AB = new Vector( pb.X - pa.X, pb.Y - pa.Y ); Vector BC = new Vector( pc.X - pb.X, pc.Y - pb.Y ); double dotProd = AB.Dot( BC ); double crossProd = AB.Cross( BC ); return Math.Atan2( crossProd, dotProd ); }