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
This commit is contained in:
= 2018-01-07 15:39:25 +01:00
parent 77b927cb1a
commit 4629419d3e
5 changed files with 187 additions and 52 deletions

View File

@ -89,5 +89,50 @@
</stars>
<energy x="17.053387" y="-0.8066667"/>
</level>
<level packId="2" id="2" goalX="3.0" startSpeed="0.5" endSpeed="0.5" terrainEdge="-0.6" ceilingEdge="1.0">
<terrainTiles class="java.util.ArrayList">
<tileData x="-2.75" width="0.5"/>
<tileData x="2.75" width="0.5"/>
</terrainTiles>
<ceilingTiles class="java.util.ArrayList">
<tileData x="0.0" width="6.0"/>
</ceilingTiles>
<obstacles class="java.util.ArrayList">
<obstacleData floating="true" moving="true" deadly="false" leftEdge="-1.1566665" rightEdge="-0.6566666" height="0.5" y="-0.99333346">
<moveComponent length="3.687" rotation="55.602" startOffset="0.0" direction="1.0" speed="0.0" hasPlayerXSpeed="true" triggerDistance="0.0"/>
</obstacleData>
</obstacles>
<stars class="java.util.ArrayList"/>
</level>
<level packId="2" id="3" goalX="3.0" startSpeed="0.5" endSpeed="0.5" terrainEdge="-0.6" ceilingEdge="1.0">
<terrainTiles class="java.util.ArrayList">
<tileData x="-2.75" width="0.5"/>
<tileData x="2.75" width="0.5"/>
</terrainTiles>
<ceilingTiles class="java.util.ArrayList">
<tileData x="0.0" width="6.0"/>
</ceilingTiles>
<obstacles class="java.util.ArrayList">
<obstacleData floating="true" moving="true" deadly="false" leftEdge="-1.1233333" rightEdge="-0.62333333" height="0.5" y="-0.96000004">
<moveComponent length="5.0" rotation="22.618" startOffset="0.0" direction="1.0" speed="0.0" hasPlayerXSpeed="true" triggerDistance="0.0"/>
</obstacleData>
</obstacles>
<stars class="java.util.ArrayList"/>
</level>
<level packId="2" id="4" goalX="3.0" startSpeed="0.5" endSpeed="0.5" terrainEdge="-0.6" ceilingEdge="1.0">
<terrainTiles class="java.util.ArrayList">
<tileData x="-2.75" width="0.5"/>
<tileData x="2.75" width="0.5"/>
</terrainTiles>
<ceilingTiles class="java.util.ArrayList">
<tileData x="0.0" width="6.0"/>
</ceilingTiles>
<obstacles class="java.util.ArrayList">
<obstacleData floating="true" moving="true" deadly="false" leftEdge="-1.1566666" rightEdge="-0.65666664" height="0.5" y="-0.92666656">
<moveComponent length="2.929" rotation="84.817" startOffset="0.0" direction="1.0" speed="0.0" hasPlayerXSpeed="true" triggerDistance="0.0"/>
</obstacleData>
</obstacles>
<stars class="java.util.ArrayList"/>
</level>
</levels>
</levelPack>

View File

@ -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;

View File

@ -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() {

View File

@ -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;
}

View File

@ -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);