public override void AIControl(AIMode aiMode) { //if (aiMode == AIMode.) tempTurretTimer += OrbIt.Game.Time.ElapsedGameTime.Milliseconds; if (tempTurretTimer > TurretTimerSeconds * 1000) { float nearest = float.MaxValue; Node nearNode = null; foreach (Node n in room.Groups.Player.entities) { float dist = Vector2R.Distance(parent.body.pos, n.body.pos); if (dist < nearest) { nearNode = n; nearest = dist; } } if (nearNode != null) { Vector2R dir = nearNode.body.pos - parent.body.pos; VMath.NormalizeSafe(ref dir); dir.Y *= -1; FireNode(dir); tempTurretTimer = 0; } } }
public void AddToOutgoing(Node node) { if (node != parent && node.HasComp <Tether>()) { if (outgoing.Contains(node)) { outgoing.Remove(node); node.Comp <Tether>().incoming.Remove(parent); if (lockedAngle && confiningVects.ContainsKey(node)) { confiningVects.Remove(node); } if (lockedDistance && lockedVals.ContainsKey(node)) { lockedVals.Remove(node); } } else { outgoing.Add(node); node.Comp <Tether>().incoming.Add(parent); if (lockedAngle && !confiningVects.ContainsKey(node)) { Vector2R v = (node.body.pos - parent.body.pos); VMath.NormalizeSafe(ref v); confiningVects.Add(node, v); } if (lockedDistance && !lockedVals.ContainsKey(node)) { lockedVals.Add(node, (int)(node.body.pos - parent.body.pos).Length()); } } } }
public override void AffectOther(Node other) { if (!active) { return; } float dist = Vector2R.Distance(parent.body.pos, other.body.pos); //if (dist > radius) return; if (springMode == mode.PullOnly && dist < restdist) { return; } if (springMode == mode.PushOnly && dist > restdist) { return; } //if (dist > restdist * 2) return; if (deadzone.enabled && dist < deadzone.value) { dist = deadzone.value; } float stretch = dist - restdist; float strength = -stretch * multiplier / 10000f; Vector2R force = other.body.pos - parent.body.pos; VMath.NormalizeSafe(ref force); force *= strength; other.body.ApplyForce(force); }
public void scaleVelocity() { if (parent.body.velocity.X != 0 && parent.body.velocity.Y != 0) { VMath.NormalizeSafe(ref parent.body.velocity); parent.body.velocity *= randInitialVel; } }
public override void Draw() { float time = 0; if (parent.HasComp <Lifetime>()) { time = parent.Comp <Lifetime>().lifetime; } else { return; } yval = DelegateManager.SineComposite(time, amp, period, vshift, composite); Vector2R metapos = new Vector2R(parent.body.velocity.Y, -parent.body.velocity.X); VMath.NormalizeSafe(ref metapos); metapos *= yval; Vector2R metaposfinal = parent.body.pos + metapos; Vector2R reflectfinal = parent.body.pos - metapos; if (drawLines) { if (previousMetaPos != Vector2R.Zero) { room.Camera.DrawLinePermanent(previousMetaPos, metaposfinal, 2f, parent.body.color, Length); } previousMetaPos = metaposfinal; //previousRelectPos = metaposfinal; if (reflective) { if (previousRelectPos != Vector2R.Zero) { room.Camera.DrawLinePermanent(previousRelectPos, reflectfinal, 2f, parent.body.color, Length); if (drawSpin) { room.Camera.DrawLinePermanent(previousMetaPos, reflectfinal, 2f, parent.body.color, Length); room.Camera.DrawLinePermanent(previousRelectPos, metaposfinal, 2f, parent.body.color, Length); } } previousRelectPos = reflectfinal; //previousMetaPos = reflectfinal; //whoa make this a flag } } else { room.Camera.AddPermanentDraw(parent.texture, metaposfinal, parent.body.color, parent.body.scale * waveScale, 0, Length); if (reflective) { room.Camera.AddPermanentDraw(parent.texture, reflectfinal, parent.body.color, parent.body.scale * waveScale, 0, Length); } } }
public void RandomizeVelocity() { float x = ((float)Utils.random.NextDouble() * 100) - 50; float y = ((float)Utils.random.NextDouble() * 100) - 50; Vector2R vel = new Vector2R(x, y); VMath.NormalizeSafe(ref vel); //vel.Normalize(); vel = vel * randInitialVel; parent.body.velocity = vel; }
public override void Draw() { Color col; if (activated) { col = Color.Green; } else { col = Color.Red; } //spritebatch.Draw(parent.getTexture(), parent.body.pos * mapzoom, null, col, 0, parent.TextureCenter(), (parent.body.scale * mapzoom) * 1.2f, SpriteEffects.None, 0); room.Camera.Draw(parent.texture, parent.body.pos, parent.body.color, parent.body.scale * 1.2f, (int)Layers.Under2); foreach (Node receiver in outgoing) { /* * Color tempcol; * if (receiver.comps[comp.flow].gatetype == 2 && receiver.comps[comp.flow]) * { * //indexof wont work... * } */ room.Camera.DrawLine(parent.body.pos, receiver.body.pos, 2f, col, (int)Layers.Under3); Vector2R center = (receiver.body.pos + parent.body.pos) / 2; Vector2R perp = new Vector2R(center.Y, -center.X); VMath.NormalizeSafe(ref perp); perp *= 10; //center += perp; room.Camera.DrawLine(center + perp, receiver.body.pos, 2f, col, (int)Layers.Under3); room.Camera.DrawLine(center - perp, receiver.body.pos, 2f, col, (int)Layers.Under3); //count++; } string gatestring = ""; if ((int)gatetype > 0) { gatestring = gatetype.ToString(); } //spriteBatch.Begin(); //spritebatch.DrawString(room.game.font, gatestring, parent.body.pos * mapzoom, Color.White, 0f, new Vector2(0, 0), 0.5f, SpriteEffects.None, 0); room.Camera.DrawStringWorld(gatestring, parent.body.pos, parent.body.color, scale: 0.5f); }
public void Confine() { if (parent == null) { return; } confiningVects = new Dictionary <Node, Vector2R>(); foreach (Node other in outgoing.ToList()) { Vector2R len = other.body.pos - parent.body.pos; VMath.NormalizeSafe(ref len); confiningVects[other] = len; } }
public void moderateVelocity() { double velSquared = parent.body.velocity.X * parent.body.velocity.X + parent.body.velocity.Y * parent.body.velocity.Y; if (minVelocity.enabled && velSquared < minVelocity * minVelocity) { VMath.NormalizeSafe(ref parent.body.velocity); parent.body.velocity *= minVelocity; } if (maxVelocity.enabled && velSquared > maxVelocity * maxVelocity) { VMath.NormalizeSafe(ref parent.body.velocity); parent.body.velocity *= maxVelocity; } }
public void ComputeNormals() { // Compute face normals for (int i1 = 0; i1 < vertexCount; ++i1) { int i2 = i1 + 1 < vertexCount ? i1 + 1 : 0; Vector2R face = vertices[i2] - vertices[i1]; // Ensure no zero-length edges, because that's bad //Debug.Assert(face.LengthSquared() > GMath.EPSILON*GMath.EPSILON); // Calculate normal with 2D cross product between vector and scalar normals[i1] = new Vector2R(face.Y, -face.X); VMath.NormalizeSafe(ref normals[i1]); } }
public override void OnSpawn() { //Node.cloneNode(parent.Game1.ui.sidebar.ActiveDefaultNode, sword); //parent.body.texture = textures.orientedcircle; torchNode.dataStore["magictorchnodeparent"] = parent; torchNode.body.pos = parent.body.pos; torchNode.AffectExclusionCheck += (node) => node == parent; room.Groups.Items.IncludeEntity(torchNode); torchNode.OnSpawn(); torchNode.body.AddExclusionCheck(parent.body); torchNode.body.OnCollisionEnter += (p, o) => { Node otherparent = null; if (o.dataStore.ContainsKey("swordnodeparent")) { otherparent = o.dataStore["swordnodeparent"]; } else if (o.dataStore.ContainsKey("fistnodeparent")) { otherparent = o.dataStore["fistnodeparent"]; } else if (o.dataStore.ContainsKey("magictorchnodeparent")) { otherparent = o.dataStore["magictorchnodeparent"]; } if (otherparent != null) { Vector2R f = otherparent.body.pos - parent.body.pos; VMath.NormalizeSafe(ref f); f *= 10; otherparent.body.ApplyForce(f); } //if (o.player != null) //{ // //o.player.node.meta.CalculateDamage(parent, damageMultiplier); //} }; //sword.body.exclusionList.Add(parent.body); // //parent.body.exclusionList.Add(sword.body); }
public override void Draw() { Color col; if (activated) { col = Color.Blue; } else { col = Color.White; } room.Camera.Draw(parent.body.texture, parent.body.pos, col, parent.body.scale * 1.2f, (int)Layers.Under2); foreach (Node receiver in outgoing) { Vector2R diff = receiver.body.pos - parent.body.pos; Vector2R perp = new Vector2R(diff.Y, -diff.X); VMath.NormalizeSafe(ref perp); perp *= 2; room.Camera.DrawLine(parent.body.pos, receiver.body.pos, 2f, col, (int)Layers.Under3); room.Camera.DrawLine(parent.body.pos + perp, receiver.body.pos + perp, 2f, Color.Red, (int)Layers.Under3); room.Camera.DrawLine(parent.body.pos - perp, receiver.body.pos - perp, 2f, Color.Green, (int)Layers.Under3); perp *= 20; Vector2R center = (receiver.body.pos + parent.body.pos) / 2; Vector2R point = receiver.body.pos - (diff / 5); room.Camera.DrawLine(point + perp, receiver.body.pos, 2f, col, (int)Layers.Under3); room.Camera.DrawLine(point - perp, receiver.body.pos, 2f, col, (int)Layers.Under3); } }
public void ApplyImpulse() { if (GMath.Equal(a.invmass + b.invmass, 0)) { InfinitMassCorrection(); return; } for (int i = 0; i < contact_count; i++) { //calcuate radii from COM to contact Vector2R ra = contacts[i] - a.pos; Vector2R rb = contacts[i] - b.pos; //relative velocity Vector2R rv = b.velocity + VMath.Cross(b.angularVelocity, rb) - a.velocity - VMath.Cross(a.angularVelocity, ra); //relative velocity along the normal double contactVel = Vector2R.Dot(rv, normal); //do not resolve if velocities are seperating if (contactVel > 0) { return; } double raCrossN = VMath.Cross(ra, normal); double rbCrossN = VMath.Cross(rb, normal); double invMassSum = a.invmass + b.invmass + (raCrossN * raCrossN) * a.invinertia + (rbCrossN * rbCrossN) * b.invinertia; //calculate impulse scalar double j = -(1.0 + e) * contactVel; j /= invMassSum; j /= (double)contact_count; //apply impulse Vector2R impulse = VMath.MultVectDouble(normal, j); // normal * j; a.ApplyImpulse(-impulse, ra); b.ApplyImpulse(impulse, rb); //friction impulse rv = b.velocity + VMath.Cross(b.angularVelocity, rb) - a.velocity - VMath.Cross(a.angularVelocity, ra); Vector2R t = rv - (normal * Vector2R.Dot(rv, normal)); //t.Normalize(); VMath.NormalizeSafe(ref t); //j tangent magnitude double jt = -Vector2R.Dot(rv, t); jt /= invMassSum; jt /= (double)contact_count; //don't apply tiny friction impulses if (GMath.Equal(jt, 0.0)) { return; } //coulumbs law Vector2R tangentImpulse; if (Math.Abs(jt) < j * sf) { tangentImpulse = VMath.MultVectDouble(t, df); // t * df; } else { tangentImpulse = VMath.MultVectDouble(t, -j * df); // t * -j * df } //apply friction impulse a.ApplyImpulse(-tangentImpulse, ra); b.ApplyImpulse(tangentImpulse, rb); } }
public override void PlayerControl(Input input) { Vector2R newstickpos = input.GetRightStick(shovelReach, true).toV2R(); //input.GetRightStick(); Vector2R pos = newstickpos * shovelReach; Vector2R worldStickPos = parent.body.pos + pos; Vector2R diff = worldStickPos - shovelNode.body.pos; //float angle = Utils.VectorToAngle(shovelNode.body.pos - parent.body.pos) + VMath.PIbyTwo % VMath.twoPI; Vector2R shovelDir = shovelNode.body.pos - parent.body.pos; shovelDir = new Vector2R(shovelDir.Y, -shovelDir.X); shovelNode.body.SetOrientV2(shovelDir); if (modeShovelPosition == ModeShovelPosition.AbsoluteStickPos) { shovelNode.body.pos = worldStickPos; } else if (modeShovelPosition == ModeShovelPosition.PhysicsBased) { float len = diff.Length(); if (len < 1) { shovelNode.body.velocity = Vector2R.Zero; } else { float velLen = shovelNode.body.velocity.Length(); Vector2R diffcopy = diff; VMath.NormalizeSafe(ref diffcopy); Vector2R normalizedVel = shovelNode.body.velocity; VMath.NormalizeSafe(ref normalizedVel); float result = 0; Vector2R.Dot(ref diffcopy, ref normalizedVel, out result); diffcopy *= result; Vector2R force = (diff / physicsDivisor); if (shovelling && compoundedMass >= 1) { force /= compoundedMass * 1; } shovelNode.body.velocity = diffcopy + force; //shovelNode.body.ApplyForce(force); } } if (shovelling) { //if (fc.newGamePadState.Triggers.Right < deadzone && fc.oldGamePadState.Triggers.Right > deadzone) if (input.BtnReleased(InputButtons.RightTrigger_Mouse1)) { shovelling = false; foreach (Node n in shovelLink.targets.ToList()) { if (physicsThrow) { n.body.velocity = n.body.effvelocity; } else { Vector2R stickdirection = newstickpos; VMath.NormalizeSafe(ref stickdirection); n.body.velocity = stickdirection * throwSpeed; } n.collision.active = true; shovelLink.targets.Remove(n); n.body.ClearExclusionChecks(); n.body.color = n.body.permaColor; } shovelLink.formation.UpdateFormation(); shovelLink.active = false; shovelNode.room.AllActiveLinks.Remove(shovelLink); compoundedMass = 0f; } } else { if (input.BtnClicked(InputButtons.RightTrigger_Mouse1)) { shovelling = true; ObservableHashSet <Node> capturedNodes = new ObservableHashSet <Node>(); int count = 0; Action <Collider, Collider> del = delegate(Collider c1, Collider c2) { if (count >= maxShovelCapacity) { return; } if (c2.parent.dataStore.ContainsKey("shovelnodeparent")) { return; } if (c2.parent.HasComp <Diode>()) { return; } if (modePlayers != ModePlayers.GrabBoth && c2.parent.IsPlayer) { if (modePlayers == ModePlayers.GrabNone) { return; } if (modePlayers == ModePlayers.GrabSelf && c2.parent != parent) { return; } if (modePlayers == ModePlayers.GrabOtherPlayers && c2.parent == parent) { return; } } float dist = Vector2R.Distance(c1.pos, c2.pos); if (dist <= scoopReach) { count++; capturedNodes.Add(c2.parent); c2.parent.body.color = parent.body.color; } }; shovelNode.room.GridsystemAffect.retrieveOffsetArraysAffect(shovelNode.body, del, scoopReach * 2); shovelLink.targets = capturedNodes; shovelLink.formation.UpdateFormation(); shovelLink.active = true; shovelNode.room.AllActiveLinks.Add(shovelLink); compoundedMass = 0f; foreach (Node n in capturedNodes) { n.collision.active = false; compoundedMass += n.body.mass; } } } }
public static bool CircletoPolygon(Manifold m, Collider a, Collider b) { Circle A = (Circle)a.shape; Polygon B = (Polygon)b.shape; m.contact_count = 0; // Transform circle center to Polygon model space Vector2R center = a.pos; center = B.u.Transpose() * (center - b.pos); // Find edge with minimum penetration // Exact concept as using support points in Polygon vs Polygon double separation = -float.MaxValue; int faceNormal = 0; for (int i = 0; i < B.vertexCount; ++i) { double s = Vector2R.Dot(B.normals[i], center - B.vertices[i]); if (s > A.radius) { return(false); } if (s > separation) { separation = s; faceNormal = i; } } // Grab face's vertices Vector2R v1 = B.vertices[faceNormal]; int i2 = faceNormal + 1 < B.vertexCount ? faceNormal + 1 : 0; Vector2R v2 = B.vertices[i2]; // Check to see if center is within polygon if (separation < GMath.EPSILON) { m.contact_count = 1; m.normal = -(B.u * B.normals[faceNormal]); m.contacts[0] = VMath.MultVectDouble(m.normal, A.radius) + a.pos; m.penetration = A.radius; return(true); } // Determine which voronoi region of the edge center of circle lies within double dot1 = Vector2R.Dot(center - v1, v2 - v1); double dot2 = Vector2R.Dot(center - v2, v1 - v2); m.penetration = A.radius - separation; // Closest to v1 if (dot1 <= 0.0f) { if (Vector2R.DistanceSquared(center, v1) > A.radius * A.radius) { return(false); } m.contact_count = 1; Vector2R n = v1 - center; n = B.u * n; VMath.NormalizeSafe(ref n); m.normal = n; v1 = B.u * v1 + b.pos; m.contacts[0] = v1; } // Closest to v2 else if (dot2 <= 0.0f) { if (Vector2R.DistanceSquared(center, v2) > A.radius * A.radius) { return(false); } m.contact_count = 1; Vector2R n = v2 - center; v2 = B.u * v2 + b.pos; m.contacts[0] = v2; n = B.u * n; VMath.NormalizeSafe(ref n); m.normal = n; } // Closest to face else { Vector2R n = B.normals[faceNormal]; if (Vector2R.Dot(center - v1, n) > A.radius) { return(false); } n = B.u * n; m.normal = -n; m.contacts[0] = VMath.MultVectDouble(m.normal, A.radius) + a.pos; m.contact_count = 1; } return(true); }
public static bool PolygontoPolygonCheck(Collider a, Collider b) { Polygon A = (Polygon)a.shape; Polygon B = (Polygon)b.shape; //m.contact_count = 0; // Check for a separating axis with A's face planes int faceA = 0; double penetrationA = FindAxisLeastPenetration(ref faceA, A, B); if (penetrationA >= 0.0f) { return(false); } // Check for a separating axis with B's face planes int faceB = 0; double penetrationB = FindAxisLeastPenetration(ref faceB, B, A); if (penetrationB >= 0.0f) { return(false); } int referenceIndex; //bool flip; // Always point from a to b Polygon RefPoly; // Reference Polygon IncPoly; // Incident // Determine which shape contains reference face if (GMath.BiasGreaterThan(penetrationA, penetrationB)) { RefPoly = A; IncPoly = B; referenceIndex = faceA; //flip = false; } else { RefPoly = B; IncPoly = A; referenceIndex = faceB; //flip = true; } // World space incident face Vector2R[] incidentFace = new Vector2R[2]; FindIncidentFace(ref incidentFace, RefPoly, IncPoly, referenceIndex); // Setup reference face vertices Vector2R v1 = RefPoly.vertices[referenceIndex]; referenceIndex = referenceIndex + 1 == RefPoly.vertexCount ? 0 : referenceIndex + 1; Vector2R v2 = RefPoly.vertices[referenceIndex]; // Transform vertices to world space v1 = RefPoly.u * v1 + RefPoly.body.pos; v2 = RefPoly.u * v2 + RefPoly.body.pos; // Calculate reference face side normal in world space Vector2R sidePlaneNormal = (v2 - v1); VMath.NormalizeSafe(ref sidePlaneNormal); // Orthogonalize Vector2R refFaceNormal = new Vector2R(sidePlaneNormal.Y, -sidePlaneNormal.X); // ax + by = c // c is distance from origin double refC = Vector2R.Dot(refFaceNormal, v1); double negSide = -Vector2R.Dot(sidePlaneNormal, v1); double posSide = Vector2R.Dot(sidePlaneNormal, v2); // Clip incident face to reference face side planes if (Clip(-sidePlaneNormal, negSide, ref incidentFace) < 2) { return(false); // Due to floating point error, possible to not have required points } if (Clip(sidePlaneNormal, posSide, ref incidentFace) < 2) { return(false); // Due to floating point error, possible to not have required points } // Flip //m.normal = flip ? -refFaceNormal : refFaceNormal; // Keep points behind reference face int cp = 0; // clipped points behind reference face double separation = Vector2R.Dot(refFaceNormal, incidentFace[0]) - refC; if (separation <= 0.0f) { //m.contacts[cp] = incidentFace[0]; //m.penetration = -separation; ++cp; } //else // m.penetration = 0; separation = Vector2R.Dot(refFaceNormal, incidentFace[1]) - refC; if (separation <= 0.0f) { //m.contacts[cp] = incidentFace[1]; // //m.penetration += -separation; ++cp; // Average penetration //m.penetration /= (double)cp; } //m.contact_count = cp; return(cp > 0); }
public void FireNode(Vector2R dir) { if (maxAmmo.enabled) { ammo--; } if (!useStickVelocity) { VMath.NormalizeSafe(ref dir); } Node n = bulletNode.CreateClone(room); n.Comp <Lifetime>().timeUntilDeath.value = bulletLife; n.body.velocity = dir * speed; n.body.pos = parent.body.pos; n.body.AddExclusionCheck(parent.body); //n.body.AddExclusion(parent.body); if (parent.HasComp <Sword>()) { n.body.AddExclusionCheck(parent.Comp <Sword>().swordNode.body); //n.body.AddExclusion(parent.Comp<Sword>().sword.body); } if (parent.IsPlayer) { n.Comp <ColorChanger>().colormode = ColorChanger.ColorMode.none; n.SetColor(parent.player.pColor); } room.SpawnNode(n, g: room.Groups.Bullets); Action <Node, Node> bulletHit = (n1, n2) => { Node bullet, them; if (n1 == n) { bullet = n1; them = n2; } else if (n2 == n) { bullet = n2; them = n1; } else { return; } if (parent.meta.damageMode == Essential.Meta.DamageMode.OnlyPlayers) { if (!them.IsPlayer) { return; } } else if (parent.meta.damageMode == Essential.Meta.DamageMode.OnlyNonPlayers) { if (them.IsPlayer) { return; } } else if (parent.meta.damageMode == Essential.Meta.DamageMode.Nothing) { return; } them.meta.CalculateDamage(parent, damage); bullet.OnDeath(null); }; n.body.OnCollisionEnter += bulletHit; //n.body.isSolid = false; if (maxAmmo.enabled && ammo <= 0) { parent.RemoveComponent(typeof(Shooter)); } }