public void BlockIntersectFromOutside() { // X-Achse links zu weit weg (keine Bewegung) Axis? collisionAxis; float?distance = block.Intersect( new Index3(10, 20, 30), new BoundingBox(new Vector3(5, 20, 30), new Vector3(6, 21, 31)), new Vector3(), out collisionAxis); Assert.AreEqual(null, collisionAxis); Assert.AreEqual(null, distance); // X-Achse links zu weit weg (bewegung nach links) distance = block.Intersect( new Index3(10, 20, 30), new BoundingBox(new Vector3(5, 20, 30), new Vector3(6, 21, 31)), new Vector3(-4, 0, 0), out collisionAxis); Assert.AreEqual(null, collisionAxis); Assert.AreEqual(null, distance); // X-Achse links zu weit weg (bewegung nach rechts) distance = block.Intersect(new Index3(10, 20, 30), new BoundingBox(new Vector3(5, 20, 30), new Vector3(6, 21, 31)), new Vector3(4, 0, 0), out collisionAxis); Assert.AreEqual(null, collisionAxis); Assert.AreEqual(null, distance); }
private void Move() { bool collision = false; int loop = 0; do { BoundingBox playerBox = new BoundingBox( new Vector3( player.GlobalPosition.X - playerRadius, player.GlobalPosition.Y - playerRadius, player.GlobalPosition.Z), new Vector3( player.GlobalPosition.X + playerRadius, player.GlobalPosition.Y + playerRadius, player.GlobalPosition.Z + playerHeight)); collision = false; float min = 1f; Axis minAxis = Axis.None; foreach (var pos in blocks.Keys) { BlockDefinition block = blocks[pos]; if (block == null) { continue; } Axis? localAxis; float?moveFactor = block.Intersect(pos, playerBox, move, out localAxis); if (moveFactor.HasValue && moveFactor.Value < min) { collision = true; min = moveFactor.Value; minAxis = localAxis.Value; } } player += (move * min); move *= (1f - min); switch (minAxis) { case Axis.X: player += new Vector3(move.X > 0 ? -gap : gap, 0, 0); move.X = 0f; break; case Axis.Y: player += new Vector3(0, move.Y > 0 ? -gap : gap, 0); move.Y = 0f; break; case Axis.Z: player += new Vector3(0, 0, move.Z > 0 ? -gap : gap); move.Z = 0f; break; } // Koordinate normalisieren (Rundwelt) // player.NormalizeChunkIndexXY(planet.Size); loop++; }while (collision && loop < 3); }
public void SlidingWall() { // ### // 3# // 2# // 1 Dictionary <Index3, BlockDefinition> blocks = new Dictionary <Index3, BlockDefinition>(); blocks.Add(new Index3(2, 2, 1), new TestBlock()); blocks.Add(new Index3(3, 2, 1), new TestBlock()); blocks.Add(new Index3(4, 2, 1), new TestBlock()); blocks.Add(new Index3(4, 3, 1), new TestBlock()); blocks.Add(new Index3(4, 4, 1), new TestBlock()); BoundingBox player = new BoundingBox(new Vector3(2, 5, 1), new Vector3(3, 6, 1)); Vector3 move = new Vector3(0.75f, -0.75f, 0); Axis? collisionAxis; float? distance; // Step 1 (2/5 -> 2.75/4.25 (keine Kollision) foreach (var pos in blocks.Keys) { BlockDefinition block = blocks[pos]; distance = block.Intersect(pos, player, move, out collisionAxis); Assert.IsNull(collisionAxis); Assert.IsNull(distance); } // Step 2 (2.75/4.25 -> 3.5/3.5 (kollision X) -> 3.0/3.5 player = new BoundingBox(player.Min + move, player.Max + move); foreach (var pos in blocks.Keys) { BlockDefinition block = blocks[pos]; distance = block.Intersect(pos, player, move, out collisionAxis); if (pos == new Index3(4, 3, 1) || pos == new Index3(4, 4, 1)) { Assert.AreEqual(Axis.X, collisionAxis); Assert.AreEqual(1f / 3f, distance); } else { Assert.IsNull(collisionAxis); Assert.IsNull(distance); } } // Step 3 (3.0/3.5 -> 3.75/2.75 (Kollision X & Y) -> 3/3 player = new BoundingBox(new Vector3(3, 3.5f, 1), new Vector3(4, 4.5f, 1)); foreach (var pos in blocks.Keys) { BlockDefinition block = blocks[pos]; distance = block.Intersect(pos, player, move, out collisionAxis); if (pos == new Index3(4, 3, 1) || pos == new Index3(4, 4, 1)) { Assert.AreEqual(Axis.X, collisionAxis); Assert.AreEqual(0f, distance); } else if (pos == new Index3(2, 2, 1) || pos == new Index3(3, 2, 1) || pos == new Index3(4, 2, 1)) { Assert.AreEqual(Axis.Y, collisionAxis); Assert.AreEqual(2f / 3f, distance); } else { Assert.IsNull(collisionAxis); Assert.IsNull(distance); } } // Step 4 (freeze) 3/3 -> 3.75/2.25 (Kollision X & Y) -> 3/3 player = new BoundingBox(new Vector3(3, 3, 1), new Vector3(4, 3, 1)); foreach (var pos in blocks.Keys) { BlockDefinition block = blocks[pos]; distance = block.Intersect(pos, player, move, out collisionAxis); if (pos == new Index3(4, 2, 1) || pos == new Index3(4, 3, 1)) { Assert.AreEqual(Axis.X, collisionAxis); Assert.AreEqual(0f, distance); } else if (pos == new Index3(2, 2, 1) || pos == new Index3(3, 2, 1)) { Assert.AreEqual(Axis.Y, collisionAxis); Assert.AreEqual(0, distance); } else { Assert.IsNull(collisionAxis); Assert.IsNull(distance); } } }