public void TickCollisions(TickCollisionsEvent _) { // TODO: Do this via collision detection instead. // TODO: Clean this up. // Keeps sword rested on the ground. if (this.stateMachine_.IsOnGround) { var bladeFromGroundY = -(this.playerRigidbody_.CenterY - this.playerRigidbody_.BottomY); bladeFromGroundY -= MathF.Abs( TrigMath.LenDegY(this.handDis_, this.handDeg_)); var minAngle = MathF.Acos(bladeFromGroundY / this.bladeLength_) / MathF.PI * 180; var diffToGround = TrigMath.DifferenceInDegrees(this.swordDeg_, 270); if (FloatMath.Abs(diffToGround) <= minAngle) { this.swordDeg_ = 270 + FloatMath.Sign(diffToGround) * minAngle; if (FloatMath.Abs(this.swordDevVel_) > 2) { this.swordDevVel_ *= -.5f; } else { this.swordDevVel_ = 0; } } } }
/// <summary> /// Returns the intersection point of the given lines. /// Returns Empty if the lines do not intersect. /// Source: http://mathworld.wolfram.com/Line-LineIntersection.html /// https://stackoverflow.com/a/385828/1761622 /// </summary> public static bool LineIntersection(FPoint v1, FPoint v2, FPoint v3, FPoint v4, out FPoint intersec) { float a = Det2(v1.X - v2.X, v1.Y - v2.Y, v3.X - v4.X, v3.Y - v4.Y); if (FloatMath.Abs(a) < FloatMath.EPSILON) { intersec = FPoint.Zero; return(false); } // Lines are parallel float d1 = Det2(v1.X, v1.Y, v2.X, v2.Y); float d2 = Det2(v3.X, v3.Y, v4.X, v4.Y); float x = Det2(d1, v1.X - v2.X, d2, v3.X - v4.X) / a; float y = Det2(d1, v1.Y - v2.Y, d2, v3.Y - v4.Y) / a; intersec = new FPoint(x, y); if (x < FloatMath.Min(v1.X, v2.X) - FloatMath.EPSILON || x > FloatMath.Max(v1.X, v2.X) + FloatMath.EPSILON) { return(false); } if (y < FloatMath.Min(v1.Y, v2.Y) - FloatMath.EPSILON || y > FloatMath.Max(v1.Y, v2.Y) + FloatMath.EPSILON) { return(false); } if (x < FloatMath.Min(v3.X, v4.X) - FloatMath.EPSILON || x > FloatMath.Max(v3.X, v4.X) + FloatMath.EPSILON) { return(false); } if (y < FloatMath.Min(v3.Y, v4.Y) - FloatMath.EPSILON || y > FloatMath.Max(v3.Y, v4.Y) + FloatMath.EPSILON) { return(false); } return(true); }
private void TickCollisions_(TickCollisionsEvent _) { var initXSpd = FloatMath.Abs(this.playerRigidbody_.XVelocity); var collidedTypes = this.collider_.TickCollisions(); if ((collidedTypes & LevelTileTypes.LEFT_WALL) != 0 || (collidedTypes & LevelTileTypes.RIGHT_WALL) != 0) { if (initXSpd > 1) { this.playerSounds_.PlayBumpWallSound(); } } // If falling while meant to be on the ground, then switch to falling state. if (this.stateMachine_.IsOnGround && this.rigidbody_.YVelocity > 0) { this.stateMachine_.State = PlayerState.INITIALLY_FALLING_OFF_LEDGE; this.initiallyFallingTimer_ = 3; } if (this.stateMachine_.State == PlayerState.WALL_SLIDING && this.rigidbody_.YVelocity > 0) { this.playerRigidbody_.YAcceleration = PlayerConstants.WALL_SLIDING_GRAVITY; } else { this.playerRigidbody_.YAcceleration = PlayerConstants.GRAVITY; } }
public static bool LineIntersectionExt(FPoint v1s, FPoint v1e, FPoint v2s, FPoint v2e, float epsilon, out FPoint intersec, out float u1, out float u2) { float a = Det2(v1s.X - v1e.X, v1s.Y - v1e.Y, v2s.X - v2e.X, v2s.Y - v2e.Y); if (FloatMath.Abs(a) < FloatMath.EPSILON) { intersec = FPoint.Zero; u1 = u2 = Single.NaN; return(false); } // Lines are parallel float d1 = Det2(v1s.X, v1s.Y, v1e.X, v1e.Y); float d2 = Det2(v2s.X, v2s.Y, v2e.X, v2e.Y); float x = Det2(d1, v1s.X - v1e.X, d2, v2s.X - v2e.X) / a; float y = Det2(d1, v1s.Y - v1e.Y, d2, v2s.Y - v2e.Y) / a; intersec = new FPoint(x, y); var v1len = (v1e - v1s).Length(); var v2len = (v2e - v2s).Length(); u1 = ((x - v1s.X) * (v1e.X - v1s.X) + (y - v1s.Y) * (v1e.Y - v1s.Y)) / ((v1e.X - v1s.X) * (v1e.X - v1s.X) + (v1e.Y - v1s.Y) * (v1e.Y - v1s.Y)); u2 = ((x - v2s.X) * (v2e.X - v2s.X) + (y - v2s.Y) * (v2e.Y - v2s.Y)) / ((v2e.X - v2s.X) * (v2e.X - v2s.X) + (v2e.Y - v2s.Y) * (v2e.Y - v2s.Y)); if (u1 < (0 - (epsilon / v1len)) || u1 > (1 + (epsilon / v1len))) { return(false); } if (u2 < (0 - (epsilon / v2len)) || u2 > (1 + (epsilon / v2len))) { return(false); } return(true); }
private IGamepad?FindFirstTouchedGamepad_() { foreach (var gamepad in this.gamepads_) { foreach (var analogStick in gamepad.AnalogSticks) { var rawAxes = analogStick.RawAxes; if (FloatMath.Abs(rawAxes.X) > GamepadConstants.DEADZONE || FloatMath.Abs(rawAxes.Y) > GamepadConstants.DEADZONE) { return(gamepad); } } foreach (var button in gamepad.Buttons) { if (button.IsDown) { return(gamepad); } } } return(null); }
private void UpdateDrag(SAMTime gameTime, InputState istate) { if (dragMode == DragMode.Node) { var delta = (istate.GamePointerPositionOnMap.X - mouseStartPos); isActiveDragging |= FloatMath.Abs(delta) > MIN_DRAG; if (!isActiveDragging) { return; } _values[dragAnchor].SetDirect(offsetStart + delta); for (int i = dragAnchor - 1; i >= 0; i--) { _values[i].Set(_values[i + 1].TargetValue - DIST_X); _values[i].ValueMin = float.MinValue; _values[i].ValueMax = _values[i + 1].Value - MIN_DIST_X; } for (int i = dragAnchor + 1; i < _nodes.Length; i++) { _values[i].Set(_values[i - 1].TargetValue + DIST_X); _values[i].ValueMin = _values[i - 1].Value + MIN_DIST_X; _values[i].ValueMax = float.MaxValue; } if (gameTime.TotalElapsedSeconds - dragStartTime > CLICK_CANCEL_TIME || FloatMath.Abs(delta) > CLICK_CANCEL_DIST) { _nodes[dragAnchor].CancelClick(); } dragStartTime = gameTime.TotalElapsedSeconds; } else if (dragMode == DragMode.Global) { var delta = (istate.GamePointerPositionOnMap.X - mouseStartPos); isActiveDragging |= FloatMath.Abs(delta) > MIN_DRAG; if (!isActiveDragging) { return; } for (int i = 0; i < _nodes.Length; i++) { _values[i].Set(offsetStart + delta + i * DIST_X); _values[i].ValueMin = (i == 0) ? float.MinValue : _values[i - 1].Value + MIN_DIST_X; _values[i].ValueMax = (i + 1 == _nodes.Length) ? float.MaxValue : _values[i + 1].Value - MIN_DIST_X; } } UpdateOffsets(gameTime, istate); _sleep = false; }
public virtual void TakeLaserDamage(Fraction source, LaserRay ray, float dmg) { #if DEBUG if (DebugSettings.Get("ImmortalCannons")) { _attackingRaysCollector.Add(ray); return; } #endif if (source.IsNeutral) { if (dmg > 0f) { ResetChargeAndBooster(); } } else if (Fraction.IsNeutral) { if (dmg > 0f) { counterAttackingLasersFriends++; _attackingRaysCollector.Add(ray); SetFraction(source); CannonHealth.Set(dmg / Scale); CannonHealth.Limit(0f, 1f); } } else { if (dmg > 0) { counterAttackingLasersEnemy++; } _attackingRaysCollector.Add(ray); CannonHealth.Dec(dmg / Scale); if (FloatMath.IsZero(CannonHealth.TargetValue)) { // Never tell me the odds SetFraction(Fraction.GetNeutral()); } else if (CannonHealth.TargetValue < 0) { SetFraction(source); CannonHealth.Set(FloatMath.Abs(CannonHealth.TargetValue)); } CannonHealth.Limit(0f, 1f); } }
public void ProcessInputs(ProcessInputsEvent _) { var secondaryAnalogStick = this.gamepad_[AnalogStickType.SECONDARY]; var secStickX = secondaryAnalogStick.RawAxes.X; var secStickY = secondaryAnalogStick.RawAxes.Y; var secStickMag = TrigMath.DistanceBetween(0, 0, secStickX, secStickY); if (secStickMag < GamepadConstants.DEADZONE) { secStickMag = 0; } var wasShieldOut = this.isShieldOut_; this.isShieldOut_ = secStickMag > 0; if (this.isShieldOut_) { var secStickDeg = TrigMath.DegreesBetween(0, 0, secStickX, secStickY); var toHandDeg = secStickDeg; var maxHorizontalHandDis = this.playerRigidbody_.Width / 2 + 2; var maxVerticalHandDis = this.playerRigidbody_.Height / 2 + 2; var maxHandDis = FloatMath.Abs( TrigMath.LenDegX(maxHorizontalHandDis, secStickDeg)) + FloatMath.Abs( TrigMath.LenDegY(maxVerticalHandDis, secStickDeg)); var toHandDis = maxHandDis * secStickMag; if (!wasShieldOut) { this.handDis_ = toHandDis; this.handDeg_ = toHandDeg; } else { var accFactor = 3; this.handDis_ += (toHandDis - this.handDis_) / accFactor; this.handDeg_ += TrigMath.DifferenceInDegrees(toHandDeg, this.handDeg_) / accFactor; } } }
private void TickAnimations_(TickAnimationEvent _) { if (this.stateMachine_.IsMovingUprightOnGround || this.stateMachine_.IsMovingDuckedOnGround) { this.distanceToNextFootstep_ -= FloatMath.Abs(this.rigidbody_.XVelocity); } if (this.distanceToNextFootstep_ <= 0) { var isUpright = this.stateMachine_.IsMovingUprightOnGround; this.PlayAtRandomPitch_(isUpright ? this.footstepHeavy_ : this.footstepLight_); this.distanceToNextFootstep_ += this.distanceBetweenFootsteps_; } }
public virtual void TakeDamage(Fraction source, float sourceScale) { #if DEBUG if (DebugSettings.Get("ImmortalCannons")) { return; } #endif if (source.IsNeutral) { ResetChargeAndBooster(); } else if (Fraction.IsNeutral) { SetFraction(source); CannonHealth.Set((sourceScale * HEALTH_HIT_GEN) / Scale); CannonHealth.Limit(0f, 1f); } else { CannonHealth.Dec((sourceScale * HEALTH_HIT_DROP) / Scale); if (FloatMath.IsZero(CannonHealth.TargetValue)) { // Never tell me the odds SetFraction(Fraction.GetNeutral()); } else if (CannonHealth.TargetValue < 0) { SetFraction(source); CannonHealth.Set(FloatMath.Abs(CannonHealth.TargetValue)); } CannonHealth.Limit(0f, 1f); } }
private void RemoveUntrusted(List <Tuple <BulletPathBlueprint, float> >[] rayClock) { List <Tuple <int, Tuple <BulletPathBlueprint, float> > > rems = new List <Tuple <int, Tuple <BulletPathBlueprint, float> > >(); for (int ideg = 0; ideg < RESOLUTION; ideg++) { var ddeg = (ideg * 1f / RESOLUTION) * 360; foreach (var ray in rayClock[ideg]) { bool fault = false; for (int ideg2 = 0; ideg2 < RESOLUTION; ideg2++) { var ddeg2 = (ideg2 * 1f / RESOLUTION) * 360; if (ideg2 == ideg || FloatMath.Abs(FloatMath.DiffModulo(ddeg, ddeg2, 360)) > TRUSTANGLE) { continue; } if (rayClock[ideg2].All(r => r.Item1.TargetCannonID != ray.Item1.TargetCannonID)) { fault = true; } } if (fault) { rems.Add(Tuple.Create(ideg, ray)); } } } foreach (var rem in rems) { rayClock[rem.Item1].Remove(rem.Item2); } }
private List <Tuple <BulletPathBlueprint, float> > FindLaserPaths(LevelBlueprint lvl, World wBase, World wCollision, int sourceID, FPoint rcStart, List <Tuple <Vector2, Vector2> > sourcerays, float startRadians, float cannonRadians, int remainingRecasts, bool inGlassBlock, object objIgnore) { var none = new List <Tuple <BulletPathBlueprint, float> >(); if (remainingRecasts <= 0) { return(none); } var rays = sourcerays.ToList(); var rcEnd = rcStart + new Vector2(2048, 0).Rotate(startRadians); var traceResult = RayCastLaser(wBase, rcStart, rcEnd, objIgnore); var traceResult2 = RayCastLaser(wCollision, rcStart, rcEnd, objIgnore); if (traceResult2 != null && traceResult != null && traceResult2.Item1.UserData != traceResult.Item1.UserData) { // Dirty hit return(none); } if (traceResult == null) { return(none); } foreach (var r in rays) { if (Math2D.LineIntersectionExt(rcStart, traceResult.Item2, r.Item1.ToFPoint(), r.Item2.ToFPoint(), -0.1f, out _, out _, out _)) { return(none); } } var fCannon = traceResult.Item1.UserData as ICannonBlueprint; if (fCannon != null) { if (fCannon.CannonID == sourceID) { return(none); } var quality = Math2D.LinePointDistance(rcStart, traceResult.Item2, new FPoint(fCannon.X, fCannon.Y)); rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D())); var path = new BulletPathBlueprint(fCannon.CannonID, cannonRadians, rays.ToArray()); return(new List <Tuple <BulletPathBlueprint, float> > { Tuple.Create(path, quality) }); } var fGlassBlock = traceResult.Item1.UserData as MarkerRefractionEdge; if (fGlassBlock != null) { rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D())); var pNewStart = traceResult.Item2; var normal = traceResult.Item3; var aIn = (rcStart - rcEnd).ToAngle() - normal.ToAngle(); // sin(aIn) / sin(aOut) = currRefractIdx / Glass.RefractIdx var n = inGlassBlock ? (GlassBlockBlueprint.REFRACTION_INDEX / 1f) : (1f / GlassBlockBlueprint.REFRACTION_INDEX); var sinaOut = FloatMath.Sin(aIn) * n; var dat = new List <Tuple <BulletPathBlueprint, float> >(); var isRefracting = sinaOut <1 && sinaOut> -1; var isReflecting = FloatMath.Abs(aIn) > LaserNetwork.MIN_REFRACT_ANGLE && (!inGlassBlock || (inGlassBlock && !isRefracting)); if (isRefracting) // refraction { // refraction var aOut = FloatMath.Asin(sinaOut); var pRefractAngle = (-normal).ToAngle() + aOut; var sub = FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pRefractAngle, cannonRadians, remainingRecasts - 1, !inGlassBlock, fGlassBlock); dat.AddRange(sub); } if (isReflecting) { // reflection var pReflectVec = Vector2.Reflect(rcEnd - rcStart, traceResult.Item3); var sub = FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pReflectVec.ToAngle(), cannonRadians, remainingRecasts - 1, !inGlassBlock, fGlassBlock); dat.AddRange(sub); } return(dat); } var fGlassBlockCorner = traceResult.Item1.UserData as MarkerRefractionCorner; if (fGlassBlockCorner != null) { if (NO_LASER_CORNER_HITS) { return(none); } rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D())); var pNewStart = traceResult.Item2; var dat = new List <Tuple <BulletPathBlueprint, float> >(); if (!inGlassBlock) { // reflection var pReflectVec = Vector2.Reflect(rcEnd - rcStart, traceResult.Item3); var sub = FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pReflectVec.ToAngle(), cannonRadians, remainingRecasts - 1, !inGlassBlock, fGlassBlockCorner); dat.AddRange(sub); } return(dat); } var fMirrorBlock = traceResult.Item1.UserData as MirrorBlockBlueprint; if (fMirrorBlock != null) { rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D())); var pNewStart = traceResult.Item2; var pVec = Vector2.Reflect(rcEnd - rcStart, traceResult.Item3); return(FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1, inGlassBlock, fMirrorBlock)); } var fMirrorCircle = traceResult.Item1.UserData as MirrorCircleBlueprint; if (fMirrorCircle != null) { rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D())); var pNewStart = traceResult.Item2; var pVec = Vector2.Reflect(rcEnd - rcStart, traceResult.Item3); return(FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1, inGlassBlock, fMirrorCircle)); } var fVoidWall = traceResult.Item1.UserData as VoidWallBlueprint; if (fVoidWall != null) { return(none); } var fVoidCircle = traceResult.Item1.UserData as VoidCircleBlueprint; if (fVoidCircle != null) { return(none); } var fPortal = traceResult.Item1.UserData as PortalBlueprint; if (fPortal != null) { bool hit = FloatMath.DiffRadiansAbs(traceResult.Item3.ToAngle(), FloatMath.ToRadians(fPortal.Normal)) < FloatMath.RAD_POS_005; if (!hit) { return(none); } rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D())); var dat = new List <Tuple <BulletPathBlueprint, float> >(); foreach (var outportal in lvl.BlueprintPortals.Where(p => p.Side != fPortal.Side && p.Group == fPortal.Group)) { var cIn = new FPoint(fPortal.X, fPortal.Y); var cOut = new FPoint(outportal.X, outportal.Y); var rot = FloatMath.ToRadians(outportal.Normal - fPortal.Normal + 180); var stretch = outportal.Length / fPortal.Length; var newAngle = FloatMath.NormalizeAngle(startRadians + rot); var newStart = cOut + stretch * (traceResult.Item2 - cIn).Rotate(rot); newStart = newStart.MirrorAtNormal(cOut, Vector2.UnitX.Rotate(FloatMath.ToRadians(outportal.Normal))); var sub = FindLaserPaths(lvl, wBase, wCollision, sourceID, newStart, rays, newAngle, cannonRadians, remainingRecasts - 1, inGlassBlock, outportal); dat.AddRange(sub); } return(dat); } var fBorder = traceResult.Item1.UserData as MarkerCollisionBorder; if (fBorder != null) { if (lvl.WrapMode == LevelBlueprint.WRAPMODE_DONUT) { rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D())); var pNewStartX = traceResult.Item2.X; var pNewStartY = traceResult.Item2.Y; switch (fBorder.Side) { case FlatAlign4.NN: pNewStartY += lvl.LevelHeight; break; case FlatAlign4.EE: pNewStartX -= lvl.LevelWidth; break; case FlatAlign4.SS: pNewStartY -= lvl.LevelHeight; break; case FlatAlign4.WW: pNewStartX += lvl.LevelWidth; break; default: throw new ArgumentOutOfRangeException(); } var pVec = rcEnd - rcStart; var pNewStart = new FPoint(pNewStartX, pNewStartY); return(FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1, inGlassBlock, fBorder)); } else if (lvl.WrapMode == LevelBlueprint.WRAPMODE_SOLID) { rays.Add(Tuple.Create(rcStart.ToVec2D(), traceResult.Item2.ToVec2D())); var pNewStart = traceResult.Item2; var pVec = Vector2.Reflect(rcEnd - rcStart, traceResult.Item3); return(FindLaserPaths(lvl, wBase, wCollision, sourceID, pNewStart, rays, pVec.ToAngle(), cannonRadians, remainingRecasts - 1, inGlassBlock, fBorder)); } throw new Exception("Unsupported WrapMode: " + lvl.WrapMode); } throw new Exception("Unknown rayTrace resturn ficture: " + traceResult.Item1.UserData); }
private void RecalcFromRay(LaserSource src, FPoint istart, FPoint iend, int idepth, bool iinglass, object iignore, LaserRay isrc, float idist, bool nofault) { Stack <Tuple <FPoint, FPoint, int, bool, object, LaserRay, float> > remaining = new Stack <Tuple <FPoint, FPoint, int, bool, object, LaserRay, float> >(); remaining.Push(Tuple.Create(istart, iend, idepth, iinglass, iignore, isrc, idist)); while (remaining.Any()) { var pop = remaining.Pop(); var start = pop.Item1; var end = pop.Item2; var depth = pop.Item3; var inglass = pop.Item4; var ignore = pop.Item5; var source = pop.Item6; var startdist = pop.Item7; if (src.Lasers.Count + 1 >= MAX_LASER_PER_SOURCE) { continue; } if (depth >= MAX_LASER_RAYCOUNT) { continue; } if (!start.IsValid) { continue; } if (!end.IsValid) { continue; } if (start.EpsilonEquals(end, FloatMath.EPSILON6)) { continue; } var result = RayCast(start, end, ignore); #region OOB if (result == null) { var ray = new LaserRay(start, end, source, LaserRayTerminator.OOB, depth, inglass, ignore, null, startdist, null, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } continue; } #endregion #region Cannon var resultCannon = result.Item1.UserData as Cannon; if (resultCannon != null) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Target, depth, inglass, ignore, resultCannon, startdist, resultCannon, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } continue; } #endregion #region GlassBlockRefraction var resultGlassBlockRefrac = result.Item1.UserData as MarkerRefractionEdge; if (resultGlassBlockRefrac != null) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Glass, depth, inglass, ignore, resultGlassBlockRefrac, startdist, null, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } // sin(aIn) / sin(aOut) = currRefractIdx / Glass.RefractIdx var aIn = (start - end).ToAngle() - result.Item3.ToAngle(); var n = inglass ? (GlassBlock.REFRACTION_INDEX / 1f) : (1f / GlassBlock.REFRACTION_INDEX); var sinaOut = FloatMath.Sin(aIn) * n; var isRefracting = sinaOut <1 && sinaOut> -1; var isReflecting = FloatMath.Abs(aIn) > MIN_REFRACT_ANGLE && (!inglass || (inglass && !isRefracting)); if (isRefracting) // refraction { var aOut = FloatMath.Asin(sinaOut); var pRefractAngle = (-result.Item3).ToAngle() + aOut; remaining.Push(Tuple.Create(result.Item2, result.Item2 + new Vector2(_rayLength, 0).Rotate(pRefractAngle), depth + 1, !inglass, (object)resultGlassBlockRefrac, ray, startdist + ray.Length)); } if (isReflecting) { var reflect_end = result.Item2 + Vector2.Reflect(end - start, result.Item3).WithLength(_rayLength); remaining.Push(Tuple.Create(result.Item2, reflect_end, depth + 1, inglass, (object)resultGlassBlockRefrac, ray, startdist + ray.Length)); } continue; } #endregion #region GlassBlockRefraction (Corner) var resultGlassCornerRefrac = result.Item1.UserData as MarkerRefractionCorner; if (resultGlassCornerRefrac != null) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.VoidObject, depth, inglass, ignore, resultGlassCornerRefrac, startdist, null, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } // sin(aIn) / sin(aOut) = currRefractIdx / Glass.RefractIdx var aIn = (start - end).ToAngle() - result.Item3.ToAngle(); var n = inglass ? (GlassBlock.REFRACTION_INDEX / 1f) : (1f / GlassBlock.REFRACTION_INDEX); var sinaOut = FloatMath.Sin(aIn) * n; var isRefracting = sinaOut <1 && sinaOut> -1; if (isRefracting) // refraction { // No refrac in corner } if (!inglass) { var reflect_end = result.Item2 + Vector2.Reflect(end - start, result.Item3).WithLength(_rayLength); remaining.Push(Tuple.Create(result.Item2, reflect_end, depth + 1, inglass, (object)resultGlassCornerRefrac, ray, startdist + ray.Length)); continue; } else { // No funtime in corner continue; } } #endregion #region MirrorBlock var resultMirrorBlock = result.Item1.UserData as MirrorBlock; if (resultMirrorBlock != null) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Mirror, depth, inglass, ignore, resultMirrorBlock, startdist, null, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } var reflect_end = result.Item2 + Vector2.Reflect(end - start, result.Item3).WithLength(_rayLength); remaining.Push(Tuple.Create(result.Item2, reflect_end, depth + 1, inglass, (object)resultMirrorBlock, ray, startdist + ray.Length)); continue; } #endregion #region MirrorCircle var resultMirrorCircle = result.Item1.UserData as MirrorCircle; if (resultMirrorCircle != null) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Mirror, depth, inglass, ignore, resultMirrorCircle, startdist, null, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } var reflect_end = result.Item2 + Vector2.Reflect(end - start, result.Item3).WithLength(_rayLength); remaining.Push(Tuple.Create(result.Item2, reflect_end, depth + 1, inglass, (object)resultMirrorCircle, ray, startdist + ray.Length)); continue; } #endregion #region VoidWall var resultVoidWall = result.Item1.UserData as VoidWall; if (resultVoidWall != null) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.VoidObject, depth, inglass, ignore, resultVoidWall, startdist, null, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } continue; } #endregion #region VoidCircle var resultVoidCircle = result.Item1.UserData as VoidCircle; if (resultVoidCircle != null) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.VoidObject, depth, inglass, ignore, resultVoidCircle, startdist, null, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } continue; } #endregion #region Shield var resultShield = result.Item1.UserData as ShieldCollisionMarker; if (resultShield != null) { if (resultShield.Active) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Target, depth, inglass, ignore, resultShield, startdist, resultShield.Source, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } continue; } else if (src.Type == RayType.Shield && src.LaserFraction == resultShield.Source.Fraction) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Target, depth, inglass, ignore, resultShield, startdist, resultShield.Source, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } continue; } else { continue; } } #endregion #region Portal var resultPortal = result.Item1.UserData as Portal; if (resultPortal != null) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Portal, depth, inglass, ignore, resultPortal, startdist, null, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } var inPortal = resultPortal; var normal = result.Item3; bool hit = FloatMath.DiffRadiansAbs(normal.ToAngle(), inPortal.Normal) < FloatMath.RAD_POS_001; if (!hit) { continue; // back-side hit } if (inPortal.Links.Count == 0) { continue; // void portal } foreach (var outportal in inPortal.Links) { var rot = outportal.Normal - inPortal.Normal + FloatMath.RAD_POS_180; var projec = result.Item2.ProjectOntoLine(inPortal.Position, inPortal.VecDirection); var newVelocity = (end - start).Rotate(rot); var newStart = outportal.Position + outportal.VecDirection * (-projec) + outportal.VecNormal * (Portal.WIDTH / 2f); var newEnd = newStart + newVelocity.WithLength(_rayLength); remaining.Push(Tuple.Create(newStart, newEnd, depth + 1, false, (object)outportal, ray, startdist + ray.Length)); } continue; } #endregion #region Border var resultBorderMarker = result.Item1.UserData as MarkerCollisionBorder; if (resultBorderMarker != null) { if (_wrapMode == GameWrapMode.Reflect) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Mirror, depth, inglass, ignore, resultBorderMarker, startdist, null, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } var reflect_end = result.Item2 + Vector2.Reflect(end - start, result.Item3).WithLength(_rayLength); remaining.Push(Tuple.Create(result.Item2, reflect_end, depth + 1, inglass, (object)resultBorderMarker, ray, startdist + ray.Length)); continue; } else if (_wrapMode == GameWrapMode.Donut) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.Portal, depth, inglass, ignore, resultBorderMarker, startdist, null, src.Type); src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } var pNewStartX = result.Item2.X; var pNewStartY = result.Item2.Y; switch (resultBorderMarker.Side) { case FlatAlign4.NN: pNewStartY += _screen.Blueprint.LevelHeight; break; case FlatAlign4.EE: pNewStartX -= _screen.Blueprint.LevelWidth; break; case FlatAlign4.SS: pNewStartY -= _screen.Blueprint.LevelHeight; break; case FlatAlign4.WW: pNewStartX += _screen.Blueprint.LevelWidth; break; default: SAMLog.Error("LASER::EnumSwitch_RFR", "value: " + resultBorderMarker.Side); break; } var newStart = new FPoint(pNewStartX, pNewStartY); var newEnd = newStart + (end - start); remaining.Push(Tuple.Create(newStart, newEnd, depth + 1, inglass, (object)null, ray, startdist + ray.Length)); continue; } else { SAMLog.Error("LASER::UnknownWrap", "Unknown wrapmode: " + _wrapMode); } continue; } #endregion #region Bullet var resultBullet = result.Item1.UserData as Bullet; if (resultBullet != null) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.BulletTerm, depth, inglass, ignore, resultBullet, startdist, null, src.Type); ray.TerminatorBullet = resultBullet; src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } continue; } #endregion #region RemoteBullet var resultRemoteBullet = result.Item1.UserData as RemoteBullet; if (resultRemoteBullet != null) { var ray = new LaserRay(start, result.Item2, source, LaserRayTerminator.BulletTerm, depth, inglass, ignore, resultRemoteBullet, startdist, null, src.Type); ray.TerminatorBullet = resultRemoteBullet; src.Lasers.Add(ray); if (TestForLaserCollision(src, ray, nofault)) { continue; } continue; } #endregion // wud ??? SAMLog.Error("LASER::UnknownFixture", string.Format("Ray collided with unkown fixture: {0}", result?.Item1?.UserData ?? "<NULL>")); } }
private void ProcessScheduledHorizontalMovement_() { var heldXAxis = this.HeldXAxis; var isRunning = this.IsRunning; var isTryingToRun = FloatMath.Abs(heldXAxis) > .5f; var heldXAxisSign = FinMath.Sign(heldXAxis); float?targetXVelocity = null; float xAcceleration = 0; if (this.StateMachine.CanMoveUprightOnGround) { var maxGroundXVelocity = isRunning ? PlayerConstants.UPRIGHT_MAX_FAST_XSPD : PlayerConstants.UPRIGHT_MAX_SLOW_XSPD; var groundAcceleration = isTryingToRun ? PlayerConstants.GROUND_UPRIGHT_FAST_XACC : PlayerConstants.GROUND_UPRIGHT_SLOW_XACC; var reactionFraction = heldXAxisSign == -FinMath.Sign(this.Rigidbody.XVelocity) ? PlayerConstants.GROUND_REACTION_FRAC : 1; targetXVelocity = maxGroundXVelocity * heldXAxis; xAcceleration = groundAcceleration * reactionFraction * heldXAxisSign; // If holding a direction on the ground, we're either turning, running, or walking. if (heldXAxisSign != 0) { this.StateMachine.State = reactionFraction != 1 ? PlayerState.TURNING : isTryingToRun ? PlayerState.RUNNING : PlayerState.WALKING; } // If not holding a direction on the ground but velocity is not zero, we're stopping. else if (FinMath.Abs(this.Rigidbody.XVelocity) > .001) { this.StateMachine.State = PlayerState.STOPPING; } } else if (this.StateMachine.CanMoveDuckedOnGround) { var maxGroundXVelocity = isRunning ? PlayerConstants.DUCKED_MAX_FAST_XSPD : PlayerConstants.DUCKED_MAX_SLOW_XSPD; var groundAcceleration = isTryingToRun ? PlayerConstants.GROUND_DUCKED_FAST_XACC : PlayerConstants.GROUND_DUCKED_SLOW_XACC; targetXVelocity = maxGroundXVelocity * heldXAxis; xAcceleration = groundAcceleration * heldXAxisSign; // If holding a direction on the ground, we're either turning, running, or walking. if (heldXAxisSign != 0) { this.StateMachine.State = PlayerState.DUCKWALKING; } } else if (this.StateMachine.CanMoveInAir) { var maxAirXVelocity = isRunning ? PlayerConstants.UPRIGHT_MAX_FAST_XSPD : PlayerConstants.UPRIGHT_MAX_SLOW_XSPD; var airAcceleration = isTryingToRun ? PlayerConstants.AIR_FAST_XACC : PlayerConstants.AIR_SLOW_XACC; targetXVelocity = maxAirXVelocity * heldXAxis; xAcceleration = airAcceleration * heldXAxisSign; } this.Rigidbody.TargetXVelocity = targetXVelocity; this.Rigidbody.XAcceleration = xAcceleration; }
public static FSize Diff(FPoint a, FPoint b) { return(new FSize(FloatMath.Abs(a.X - b.X), FloatMath.Abs(a.Y - b.Y))); }
public static float LinePointDistance(FPoint p1, FPoint p2, FPoint point) { return(FloatMath.Abs(CrossProduct(p1, p2, point) / (p2 - p1).Length())); }
public static float ManhattenLength(this Vector2 v) { return(FloatMath.Abs(v.X) + FloatMath.Abs(v.Y)); }
public static FSize ToAbsFSize(this Vector2 p) { return(new FSize(FloatMath.Abs(p.X), FloatMath.Abs(p.Y))); }
private void TickAnimation_(TickAnimationEvent _) { var xVel = this.playerRigidbody_.XVelocity; var xVelSign = MathF.Sign(xVel); if (xVelSign != 0) { this.xDir_ = xVelSign; } var isStanding = this.stateMachine_.State == PlayerState.STANDING; var isWalking = this.stateMachine_.State == PlayerState.WALKING; var isRealRunning = this.stateMachine_.State == PlayerState.RUNNING; if (isStanding) { this.frameFraction_.Value += .01f; } if (isWalking) { var walkFraction = FloatMath.Abs(this.playerRigidbody_.XVelocity) / PlayerConstants.UPRIGHT_MAX_SLOW_XSPD; var animationSpeed = FloatMath.Max(.01f, .02f * walkFraction); this.frameFraction_.Value += animationSpeed; } if (isRealRunning) { var runFraction = FloatMath.Abs(this.playerRigidbody_.XVelocity) / PlayerConstants.UPRIGHT_MAX_FAST_XSPD; var animationSpeed = FloatMath.Max(.01f, .04f * runFraction); this.frameFraction_.Value += animationSpeed; } var frameFraction = this.frameFraction_.Value; var frameAngle = this.frameFraction_.Value * 360; var hipWidth = PlayerConstants.HSIZE * .6f; var backHipWidth = .4f * hipWidth; var frontHipWidth = hipWidth - backHipWidth; if (isStanding) { this.hipCenter_.Transform.RelativeDeg = 0; this.hipLeft_.Transform.Length = frontHipWidth; this.hipRight_.Transform.Length = backHipWidth; var leanAngle = this.OscillateAround_(15, 15, frameAngle); this.upperLegLeft_.Transform.RelativeDeg = 90 + leanAngle; this.upperLegRight_.Transform.RelativeDeg = -90 + leanAngle; this.lowerLegLeft_.Transform.RelativeDeg = -leanAngle; this.lowerLegRight_.Transform.RelativeDeg = -leanAngle; } if (isWalking) { var hipAngle = TrigMath.LenDegX(15, -20 + frameAngle); this.hipCenter_.Transform.RelativeDeg = hipAngle; this.hipLeft_.Transform.Length = frontHipWidth * this.OscillateAround_(1, .5f, hipAngle + 180); this.hipRight_.Transform.Length = backHipWidth * this.OscillateAround_(1, .5f, hipAngle); var upperLegRange = 20; this.upperLegLeft_.Transform.RelativeDeg = 90 + TrigMath.LenDegX(upperLegRange / 2, frameAngle); this.upperLegRight_.Transform.RelativeDeg = -90 + TrigMath.LenDegX(upperLegRange / 2, frameAngle + 180); var lowerLegAngle = -15 + frameAngle; var lowerLegRange = 30; this.lowerLegLeft_.Transform.RelativeDeg = -lowerLegRange / 2 + TrigMath.LenDegX(lowerLegRange / 2, lowerLegAngle); this.lowerLegRight_.Transform.RelativeDeg = -lowerLegRange / 2 + TrigMath.LenDegX(lowerLegRange / 2, lowerLegAngle + 180); } if (isRealRunning) { var hipAngle = TrigMath.LenDegX(15, -45 + frameAngle); this.hipCenter_.Transform.RelativeDeg = hipAngle; this.hipLeft_.Transform.Length = frontHipWidth * this.OscillateAround_(1, .5f, hipAngle + 180); this.hipRight_.Transform.Length = backHipWidth * this.OscillateAround_(1, .5f, hipAngle); this.upperLegLeft_.Transform.RelativeDeg = 180 + this.CalcUpperBoneAngle_(frameFraction, false); this.upperLegRight_.Transform.RelativeDeg = this.CalcUpperBoneAngle_(frameFraction, true); this.lowerLegLeft_.Transform.RelativeDeg = this.CalcLowerBoneAngle_(frameFraction, false); this.lowerLegRight_.Transform.RelativeDeg = this.CalcLowerBoneAngle_(frameFraction, true); } // TODO: Should this happen automatically? this.ForEachBone_(bone => bone.UpdateMatrices()); var leftHeight = FloatMath.Abs(TrigMath.LenDegY(this.upperLegLeft_.Transform.Length, this.upperLegLeft_.Transform .GlobalDeg)) + FloatMath.Abs(TrigMath.LenDegY(this.lowerLegLeft_.Transform.Length, this.lowerLegLeft_.Transform .GlobalDeg)); var rightHeight = FloatMath.Abs(TrigMath.LenDegY(this.upperLegRight_.Transform.Length, this.upperLegRight_.Transform .GlobalDeg)) + FloatMath.Abs(TrigMath.LenDegY(this.lowerLegRight_.Transform.Length, this.lowerLegRight_.Transform .GlobalDeg)); this.legHeight_ = FloatMath.Max(leftHeight, rightHeight); }
public bool EpsilonEquals(FPoint other, float eps = FloatMath.EPSILON) { return(FloatMath.Abs(X - other.X) <= eps && FloatMath.Abs(Y - other.Y) <= eps); }
public static bool EpsilonEquals(this Vector2 vector2, Vector2 other, float eps = 0.00001f) { return(FloatMath.Abs(vector2.X - other.X) <= eps && FloatMath.Abs(vector2.Y - other.Y) <= eps); }
private void ProcessManualInputs_() { var secondaryAnalogStick = this.gamepad_[AnalogStickType.SECONDARY]; var secStickX = secondaryAnalogStick.RawAxes.X; var secStickY = secondaryAnalogStick.RawAxes.Y; var secStickMag = TrigMath.DistanceBetween(0, 0, secStickX, secStickY); if (secStickMag < GamepadConstants.DEADZONE) { secStickMag = 0; } var secStickDeg = TrigMath.DegreesBetween(0, 0, secStickX, secStickY); var isResting = secStickMag == 0; // TODO: Detect arcs? /*if (isResting) { * var xVel = this.playerRigidbody_.XVelocity; * if (xVel != 0) { * var sign = FloatMath.Sign(xVel); * * this.handDis_ = this.maxHandDis_; * * if (this.stateMachine_.State == PlayerState.WALKING) { * this.handDeg_ = 90 - sign * (90 + 45); * this.swordDeg_ = 90 - sign * 45; * } else if (this.stateMachine_.State == PlayerState.RUNNING) { * this.handDeg_ = 90 + sign * (90 + 22); * this.swordDeg_ = 90 + sign * (90 + 22); * } * } * return; * }*/ // Stick moves hands to lift sword. Angle needs to be closer to have // more of an effect. var diffToHeld = TrigMath.DifferenceInDegrees(secStickDeg, this.handDeg_); var normalizedDiffToHeld = MathF.Abs(diffToHeld / 180); var moveFactor = 1 - normalizedDiffToHeld; var diffToTop = TrigMath.DifferenceInDegrees(90, this.handDeg_); var isLifting = FloatMath.Sign(diffToTop) == FloatMath.Sign(diffToHeld); var moveForce = 0f; var liftFactor = secStickMag * MathF.Pow(moveFactor, 5); // 4, 6, 7 if (isLifting) { var liftForce = .6f * diffToHeld * liftFactor; // .5f moveForce = liftForce; } else { var dropFactor = secStickMag; var dropForce = .8f * diffToHeld * dropFactor; moveForce = dropForce; } var initDiffToGround = TrigMath.DifferenceInDegrees(270, this.handDeg_); var gravitationalForce = 3 * FloatMath.Sign(initDiffToGround); var forceOnHands = moveForce + gravitationalForce; // TODO: Use euler method? this.handDegVel_ += forceOnHands; this.handDeg_ += this.handDegVel_; var minAngle = 45; var finalDiffToGround = TrigMath.DifferenceInDegrees(this.handDeg_, 270); if (FloatMath.Abs(finalDiffToGround) < minAngle) { this.handDeg_ = 270 + FloatMath.Sign(finalDiffToGround) * minAngle; if (FloatMath.Abs(this.handDegVel_) > 2) { this.handDegVel_ *= -.5f; } else { this.handDegVel_ = 0; } } // TODO: This line should theoretically not be here?? //this.handDeg_ += diffToHeld * liftFactor; this.handDeg_ %= 360; // TODO: Keep this value when the player lets go of the stick this.handDis_ = 16 * secStickMag; // TODO: Should be based on velocity instead. // If lifting sword, sword angle lags behind. //this.swordDeg_ = this.handDeg_; var swordDegAccFac = 1 / (1 + MathF.Abs(this.handDegVel_)); this.swordDeg_ += TrigMath.DifferenceInDegrees(this.handDeg_, this.swordDeg_) * swordDegAccFac; }
public LineSegment(FPoint start, FPoint end) { startPoint = start; endPoint = end; direction = (end - start).Normalized(); Length = (end - start).Length(); Boundings = new FRectangle(FloatMath.Min(startPoint.X, endPoint.X), FloatMath.Min(startPoint.Y, endPoint.Y), FloatMath.Abs(startPoint.X - endPoint.X), FloatMath.Abs(startPoint.Y - endPoint.Y)); }