package de.gurkenlabs.litiengine.physics;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import org.junit.jupiter.api.Test;

import de.gurkenlabs.litiengine.GameLoop;
import de.gurkenlabs.litiengine.entities.ICombatEntity;
import de.gurkenlabs.litiengine.entities.IMovableCombatEntity;
import de.gurkenlabs.litiengine.entities.MovableCombatEntity;
import de.gurkenlabs.litiengine.graphics.RenderType;

public class PhysicsTests {

  @Test
  public void testBasicCollisionDetection() {
    try (GameLoop loop = new GameLoop(30)) {
      IMovableCombatEntity ent = new MovableCombatEntity();
      ent.setSize(16, 16);
      ent.setCollision(true);
      ent.setCollisionBoxWidth(16);
      ent.setCollisionBoxHeight(16);
      ent.setLocation(10, 10);

      IPhysicsEngine engine = new PhysicsEngine();
      engine.add(ent);

      loop.start();
      loop.attach(() -> {
        assertFalse(engine.collides(9, 9));
        assertFalse(engine.collides(27, 27));
        assertTrue(engine.collides(10.00001, 10.00001));
        assertTrue(engine.collides(25.99999, 25.99999));

        Rectangle2D rect1 = new Rectangle2D.Double(0, 0, 10, 10);
        Rectangle2D rect2 = new Rectangle2D.Double(10, 10, 0, 0);
        Rectangle2D rect3 = new Rectangle2D.Double(10, 10, 1, 1);
        Rectangle2D rect4 = new Rectangle2D.Double(8, 8, 3, 3);
        Rectangle2D rect5 = new Rectangle2D.Double(25.99999, 10, 10, 20);

        assertFalse(engine.collides(rect1));
        assertFalse(engine.collides(rect2));
        assertTrue(engine.collides(rect3));
        assertTrue(engine.collides(rect4));
        assertTrue(engine.collides(rect5));
      });
    }
  }

  @Test
  public void testPointCollides() {
    ICombatEntity ent = mock(ICombatEntity.class);
    when(ent.getCollisionBox()).thenReturn(new Rectangle2D.Double(0, 0, 10, 10));
    when(ent.hasCollision()).thenReturn(true);

    IPhysicsEngine engine = new PhysicsEngine();
    engine.add(ent);
    engine.update();

    assertTrue(engine.collides(5, 5));
    assertTrue(engine.collides(5, 5, CollisionType.ALL));
    assertTrue(engine.collides(5, 5, CollisionType.ENTITY));
    assertFalse(engine.collides(5, 5, CollisionType.STATIC));
    assertFalse(engine.collides(5, 5, CollisionType.NONE));

    engine.remove(ent);
    engine.update();

    assertFalse(engine.collides(5, 5));
  }

  @Test
  public void testRaycastCollides() {
    ICombatEntity ent = mock(ICombatEntity.class);
    when(ent.getCollisionBox()).thenReturn(new Rectangle2D.Double(0, 0, 10, 10));
    when(ent.hasCollision()).thenReturn(true);

    IPhysicsEngine engine = new PhysicsEngine();
    engine.add(ent);
    engine.update();

    assertNotNull(engine.collides(new Line2D.Double(0, 0, 5, 5)));
    assertNull(engine.collides(new Line2D.Double(10.1, 10.1, 15, 15)));
  }
}

@@ -3170,11 +3170,482 @@
 )));%0A  %7D
+%0A%0A  @Test%0A  public void testRectangleCollides() %7B%0A    ICombatEntity ent = mock(ICombatEntity.class);%0A    when(ent.getCollisionBox()).thenReturn(new Rectangle2D.Double(0, 0, 10, 10));%0A    when(ent.hasCollision()).thenReturn(true);%0A%0A    IPhysicsEngine engine = new PhysicsEngine();%0A    engine.add(ent);%0A    engine.update();%0A%0A    assertTrue(engine.collides(new Rectangle2D.Double(9, 9, 5, 5)));%0A    assertFalse(engine.collides(new Rectangle2D.Double(10.1, 10.1, 5, 5)));%0A  %7D
 %0A%7D%0A

Add rectangle collision test case.