public void TestAngledImpacts() { // Try all four rotations around the origin foreach(int xSign in new []{-1, 1}) { foreach (int ySign in new[] { -1, 1 }) { GeometryCollection geometry = new GeometryCollection(); Line line = new Line(new Vector2(0, 0), new Vector2(xSign, ySign)); geometry.Add(line); // position just 0.5 above the line Particle p = new Particle(new Vector2(0.5f * xSign, (ySign + 1) / 2), new Vector2(0, -1), new Vector2(0, -0.1f)); BoundParticle impact = geometry.FirstCollision(p); Assert.AreEqual<Line>(line, impact.boundTo); AssertExtra.AreApproximate(0.5, impact.g); AssertExtra.AreApproximate(-ySign * 0.5, impact.gv); AssertExtra.AreApproximate(-ySign * 0.5 / 10, impact.ga); } } }
internal void Update() { mouseListener.Update(); var keystate = Keyboard.GetState(); if(keystate.IsKeyDown(Keys.Z) && !playback && isBound) // TODO: we can improve this to work even when unbound { var target = geometry.SnapToClosePoint(mouseListener.Transform(Mouse.GetState())); recording = PathFinding.PathTo(player2, target, geometry, ACCEL, GRAVITY); if (recording != null) { timeInRecording = 0; recordingPointer = new Particle(recording.absolutePosAt(0), Vector2.Zero, Vector2.Zero); playback = true; } } if (!playback) { if (!isBound) { var collision = geometry.FirstCollision(player); if (collision != null) { isBound = true; player2 = collision; } } if (isBound) { bool upsideDown = (((Vector2)player2.boundTo).X < 0) != player2.onCW; if (upsideDown) { isBound = false; player.position = player2.boundTo.p1 + Vector2.Multiply(player2.boundTo, (float)player2.g); player.velocity = Vector2.Multiply(player2.boundTo, (float)player2.gv) + player.gravity; player.position += player.velocity; player.velocity += player.gravity; } else { player2.g += player2.gv; player2.gv += player2.ga; if (keystate.IsKeyDown(Keys.A)) { player2.gv += ACCEL * ((player2.onCW) ? 1 : -1) / ((Vector2)player2.boundTo).Length(); } if (keystate.IsKeyDown(Keys.D)) { player2.gv -= ACCEL * ((player2.onCW) ? 1 : -1) / ((Vector2)player2.boundTo).Length(); } if (player2.g > 1 || player2.g < 0) { var exitingPoint = (player2.g < 0) ? player2.boundTo.p1 : player2.boundTo.p2; var nextList = geometry.LinesAttachedTo(exitingPoint).Where(l => l != player2.boundTo); nextList = nextList.Where(l => (((((Vector2)player2.boundTo).CrossProduct(l) < 0) != player2.onCW) != (player2.boundTo.p1 == exitingPoint)) != ((exitingPoint == l.p1) == (exitingPoint == player2.boundTo.p1))); if (nextList.Count() > 0) { var next = nextList.OrderBy(l => Math.Abs(((Vector2)player2.boundTo).CrossProduct(l)) / ((Vector2)l).Length()).Last(); var multiplier = Vector2.Dot(next, player2.boundTo) / (((Vector2)next).Length() * ((Vector2)player2.boundTo).Length()) * ((Vector2)player2.boundTo).Length() / ((Vector2)next).Length(); if ((exitingPoint == next.p1) == (exitingPoint == player2.boundTo.p1)) { player2.onCW = !player2.onCW; } player2.boundTo = next; player2.g = (next.p1 == exitingPoint) ? 0 : 1; player2.gv *= multiplier; player2.ga = Vector2.Dot(player.gravity, (Vector2)next) / (((Vector2)next).LengthSquared()); } else { isBound = false; player.position = player2.boundTo.p1 + Vector2.Multiply(player2.boundTo, (float)player2.g); player.velocity = Vector2.Multiply(player2.boundTo, (float)player2.gv); } } } } else { // order of this matters player.position += player.velocity; player.velocity += player.gravity; } } }