From 4629419d3eaa803cba8e25008ef9f6a29038c877 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sun, 7 Jan 2018 15:39:25 +0100 Subject: [PATCH] Changed circleQuadCollisionEdge function -> Now works perfectly also with moving obstacles Note: Just works for ball-obstacle-collision, when circle diameter is bigger than quad width or height, won't work anymore --- .../main/assets/levelpacks/Icy Mountains.xml | 45 +++++ .../de/frajul/endlessroll/data/Vector.java | 6 + .../frajul/endlessroll/entities/Obstacle.java | 8 +- .../entities/collision/CollisionDetector.java | 171 +++++++++++++----- .../endlessroll/levels/MoveComponent.java | 9 +- 5 files changed, 187 insertions(+), 52 deletions(-) diff --git a/app/src/main/assets/levelpacks/Icy Mountains.xml b/app/src/main/assets/levelpacks/Icy Mountains.xml index 6f9fd15..2a303dc 100644 --- a/app/src/main/assets/levelpacks/Icy Mountains.xml +++ b/app/src/main/assets/levelpacks/Icy Mountains.xml @@ -89,5 +89,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/de/frajul/endlessroll/data/Vector.java b/app/src/main/java/de/frajul/endlessroll/data/Vector.java index 1fbbdb9..316f21d 100644 --- a/app/src/main/java/de/frajul/endlessroll/data/Vector.java +++ b/app/src/main/java/de/frajul/endlessroll/data/Vector.java @@ -53,6 +53,12 @@ public class Vector { return this; } + public Vector abs(){ + this.x = Math.abs(x); + this.y = Math.abs(y); + return this; + } + public Vector mul(float z) { x *= z; y *= z; diff --git a/app/src/main/java/de/frajul/endlessroll/entities/Obstacle.java b/app/src/main/java/de/frajul/endlessroll/entities/Obstacle.java index af2fd86..fefa1ee 100644 --- a/app/src/main/java/de/frajul/endlessroll/entities/Obstacle.java +++ b/app/src/main/java/de/frajul/endlessroll/entities/Obstacle.java @@ -67,12 +67,10 @@ public class Obstacle extends Entity { moveProgress = 2 - moveProgress; moveDirection *= -1; } - Vector oldPosition = new Vector(super.getPosition()); + super.setPosition(moveComponent.getPositionForProgress(moveProgress)); - Vector newPosition = new Vector(super.getPosition()); - Vector move = newPosition.translate(oldPosition.negate()); - move.mul(1 / frameTime); - super.setMovement(move); + super.setMovement(moveComponent.getMovementVector(moveDirection)); + GameLog.i(super.getMovement().getX() + "; " + player.getMovement().getX()); } public boolean isMoving() { diff --git a/app/src/main/java/de/frajul/endlessroll/entities/collision/CollisionDetector.java b/app/src/main/java/de/frajul/endlessroll/entities/collision/CollisionDetector.java index d66102d..a94a01c 100644 --- a/app/src/main/java/de/frajul/endlessroll/entities/collision/CollisionDetector.java +++ b/app/src/main/java/de/frajul/endlessroll/entities/collision/CollisionDetector.java @@ -7,7 +7,6 @@ import de.frajul.endlessroll.entities.collision.collisionData.EntityCollisionDat import de.frajul.endlessroll.entities.collision.geometry.Circle; import de.frajul.endlessroll.entities.collision.geometry.Quad; import de.frajul.endlessroll.entities.collision.geometry.Triangle; -import de.frajul.endlessroll.main.GameLog; /** * Created by Julian on 01.12.2015. @@ -140,69 +139,153 @@ public class CollisionDetector { if (isCircleQuadCollision(circle, quad)) { Edge edge = circleQuadCollisionEdge(circle, player.getMovement(), quad, entity.getMovement()); - //Obstacles with MoveComponent do not have entity.getMovement() --> if player not moving, relativeMovement.x = 0 return new EntityCollisionData(entity, edge); } return new EntityCollisionData(null, null); } + private Edge circleQuadCollisionEdge(Circle circle, Vector circleMovement, Quad quad, Vector quadMovement) { + boolean circleFullyInsideQuad = false; + if (circle.getCenter().getX() + circle.getRadius() <= quad.getRightEdge() && circle + .getCenter().getX() - circle.getRadius() >= quad.getLeftEdge()) { + if (circle.getCenter().getY() + circle.getRadius() <= quad.getTopEdge() && circle + .getCenter().getY() - circle.getRadius() >= quad.getBottomEdge()) { + circleFullyInsideQuad = true; + } + } + if (circleFullyInsideQuad) + return circleCenterInQuadCollisionEdge(circle, circleMovement, quad, quadMovement); + return circlePartlyOutsideQuadCollisionEdge(circle, quad); + } + + private Edge circlePartlyOutsideQuadCollisionEdge(Circle circle, Quad quad) { + Edge edge = Edge.NONE; + if (circle.getCenter().getY() + circle.getRadius() >= quad.getTopEdge()) + edge = Edge.TOP; + else if (circle.getCenter().getY() - circle.getRadius() <= quad.getBottomEdge()) + edge = Edge.BOTTOM; + if (circle.getCenter().getX() - circle.getRadius() <= quad.getLeftEdge()) { + if (edge != Edge.NONE) { + if (edge == Edge.TOP) { + float m = -1; + float t = quad.getTopEdge() - m * quad.getLeftEdge(); + if (circle.getCenter().getY() >= m * circle.getCenter().getX() + t) + edge = Edge.TOP; + else + edge = Edge.LEFT; + } else if (edge == Edge.BOTTOM) { + float m = 1; + float t = quad.getBottomEdge() - m * quad.getLeftEdge(); + if (circle.getCenter().getY() <= m * circle.getCenter().getX() + t) + edge = Edge.BOTTOM; + else + edge = Edge.LEFT; + } + } else + edge = Edge.LEFT; + } else if (circle.getCenter().getX() + circle.getRadius() >= quad.getRightEdge()) { + if (edge != Edge.NONE) { + if (edge == Edge.TOP) { + float m = 1; + float t = quad.getTopEdge() - m * quad.getRightEdge(); + if (circle.getCenter().getY() >= m * circle.getCenter().getX() + t) + edge = Edge.TOP; + else + edge = Edge.RIGHT; + } else if (edge == Edge.BOTTOM) { + float m = -1; + float t = quad.getBottomEdge() - m * quad.getRightEdge(); + if (circle.getCenter().getY() <= m * circle.getCenter().getX() + t) + edge = Edge.BOTTOM; + else + edge = Edge.RIGHT; + } + } else + edge = Edge.RIGHT; + } + return edge; + } + + private Edge circleCenterInQuadCollisionEdge(Circle circle, Vector circleMovement, Quad quad, Vector quadMovement) { Vector relativeMovement = circleMovement.translate(quadMovement.negate()); - //LEFT || TOP || BOTTOM - if (relativeMovement.x > 0) { - //LEFT || BOTTOM - if (relativeMovement.y > 0) { - float toLeftDistance = quad.getLeftEdge() - circle.getCenter().x - circle.getRadius(); - float actualY = toLeftDistance * (relativeMovement.y / relativeMovement.x) + circle - .getCenter().y + circle.getRadius(); - if (actualY <= quad.getBottomEdge()) - return Edge.BOTTOM; - else - return Edge.LEFT; + float m = relativeMovement.getY() / relativeMovement.getX(); + float t = circle.getCenter().getY() - m * circle.getCenter().getX(); + + float yAtLeftEdge = m * quad.getLeftEdge() + t; + boolean touchingLeftEdge = yAtLeftEdge < quad.getTopEdge() && yAtLeftEdge > quad + .getBottomEdge(); + float yAtRightEdge = m * quad.getRightEdge() + t; + boolean touchingRightEdge = yAtRightEdge < quad.getTopEdge() && yAtRightEdge > quad + .getBottomEdge(); + + float xAtTopEdge = (quad.getTopEdge() - t) / m; + boolean touchingTopEdge = xAtTopEdge >= quad.getLeftEdge() && xAtTopEdge <= quad + .getRightEdge(); + float xAtBottomEdge = (quad.getBottomEdge() - t) / m; + boolean touchingBottomEdge = xAtBottomEdge >= quad.getLeftEdge() && xAtBottomEdge <= quad + .getRightEdge(); + + if (relativeMovement.getX() == 0) { + if (circle.getCenter().getX() - circle.getRadius() <= quad.getRightEdge() && circle + .getCenter().getX() + circle.getRadius() >= quad.getLeftEdge()) { + touchingTopEdge = true; + touchingBottomEdge = true; } - //LEFT || TOP - else if (relativeMovement.y < 0) { - float toLeftDistance = quad.getLeftEdge() - circle.getCenter().x - circle.getRadius(); - float actualY = toLeftDistance * (relativeMovement.y / relativeMovement.x) + circle - .getCenter().y - circle.getRadius(); - if (actualY > quad.getTopEdge()) - return Edge.TOP; - else + } + + // CORNERS BELONGING TO TOP / BOTTOM EDGES + if (touchingLeftEdge) { + if (touchingRightEdge) { + if (circle.getCenter().getX() <= quad.getPosition().getX()) return Edge.LEFT; + return Edge.RIGHT; + } else if (touchingTopEdge) { + // Normale through vertex + float mn = -1 / m; + float tn = quad.getTopEdge() - mn * quad.getLeftEdge(); + if (circle.getCenter().getY() < mn * circle.getCenter().getX() + tn) + return Edge.LEFT; + return Edge.TOP; + } else if (touchingBottomEdge) { + // Normale through vertex + float mn = -1 / m; + float tn = quad.getBottomEdge() - mn * quad.getLeftEdge(); + if (circle.getCenter().getY() > mn * circle.getCenter().getX() + tn) + return Edge.LEFT; + return Edge.BOTTOM; } else { return Edge.LEFT; } - } - //RIGHT || TOP || BOTTOM - else if (relativeMovement.x < 0) { - //RIGHT || BOTTOM - if (relativeMovement.y > 0) { - float toRightDistance = quad.getRightEdge() - circle.getCenter().x + circle.getRadius(); - float actualY = toRightDistance * (relativeMovement.y / relativeMovement.x) + circle - .getCenter().y + circle.getRadius(); - if (actualY <= quad.getBottomEdge()) - return Edge.BOTTOM; - else + } else if (touchingRightEdge) { + if (touchingTopEdge) { + // Normale through vertex + float mn = -1 / m; + float tn = quad.getTopEdge() - mn * quad.getRightEdge(); + if (circle.getCenter().getY() < mn * circle.getCenter().getX() + tn) return Edge.RIGHT; - } - //RIGHT || TOP - else if (relativeMovement.y < 0) { - float toRightDistance = quad.getRightEdge() - circle.getCenter().x + circle.getRadius(); - float actualY = toRightDistance * (relativeMovement.y / relativeMovement.x) + circle - .getCenter().y - circle.getRadius(); - if (actualY > quad.getTopEdge()) - return Edge.TOP; - else + return Edge.TOP; + } else if (touchingBottomEdge) { + // Normale through vertex + float mn = -1 / m; + float tn = quad.getBottomEdge() - mn * quad.getRightEdge(); + if (circle.getCenter().getY() > mn * circle.getCenter().getX() + tn) return Edge.RIGHT; + return Edge.BOTTOM; } else { return Edge.RIGHT; } - } else { - if (relativeMovement.y > 0) + } else if (touchingTopEdge) { + if (touchingBottomEdge) { + if (circle.getCenter().getY() >= quad.getPosition().getY()) + return Edge.TOP; return Edge.BOTTOM; - else if (relativeMovement.y < 0) + } else { return Edge.TOP; + } + } else if (touchingBottomEdge) { + return Edge.BOTTOM; } return Edge.NONE; } diff --git a/app/src/main/java/de/frajul/endlessroll/levels/MoveComponent.java b/app/src/main/java/de/frajul/endlessroll/levels/MoveComponent.java index 5fce6fd..90d9797 100644 --- a/app/src/main/java/de/frajul/endlessroll/levels/MoveComponent.java +++ b/app/src/main/java/de/frajul/endlessroll/levels/MoveComponent.java @@ -71,9 +71,7 @@ public class MoveComponent { public void calcSpeedForPlayerSpeed(Player player) { float xSpeed = player.getSpeed(); - double invertRotationRadians = Math.toRadians(90 - getRotation()); - float ySpeed = (float) (xSpeed * Math.sin(invertRotationRadians)); - speed = (float) Math.sqrt(xSpeed * xSpeed + ySpeed * ySpeed); + speed = xSpeed / new Vector(triangleWidth, triangleHeight).normalize().getX(); speed /= TRANSITION_VALUE; } @@ -81,6 +79,11 @@ public class MoveComponent { return triangleWidth >= 0 ? position.x : position.x + triangleWidth; } + public Vector getMovementVector(float moveDirection) { + return new Vector(triangleWidth, triangleHeight).normalize() + .mul(moveDirection * getSpeed() * TRANSITION_VALUE); + } + public Vector getPositionForProgress(float progress) { return new Vector(position.x + triangleWidth * progress, position.y + triangleHeight * progress);