/**
*
*/
package com.szuppe.jakub.model;
import java.awt.Dimension;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;
import com.szuppe.jakub.common.Coordinates2D;
import com.szuppe.jakub.common.LineSegment2D;
import com.szuppe.jakub.common.DoesnotIntersectException;
import com.szuppe.jakub.common.Ray2D;
import com.szuppe.jakub.common.SpeedVector2D;
import com.szuppe.jakub.mockups.BrickType;
/**
* @author Jakub Szuppe <j.szuppe at gmail.com>
*
*/
class Brick
{
/** Współrzędne lewego-górnego rogu klocka. */
private final Coordinates2D topLeftCoordinates;
/** Wymiary klocka (szerokość x wysokość) */
private final Dimension dimension;
/**
* Tworzy klocek o podanych wymiarach i współrzędnych.
*
* @param topLeftCoordinates - współrzędne lewego-górnego rogu klocka.
* @param dimension - wymiary.
*/
public Brick(Coordinates2D topLeftCoordinates, Dimension dimension)
{
this.topLeftCoordinates = topLeftCoordinates;
this.dimension = dimension;
}
/**
* Tworzy nowy klocek na podstawie podanego.
*
* @param brick
*/
public Brick(Brick brick)
{
this(brick.getTopLeftCornerCoordinates(), brick.getDimension());
}
/**
* Sprawdza, czy i kiedy zajdą kolizje między klockiem, a piłką.
* Jeżeli tak zwraca odpowiedni kolekcję kolizji, które mogą wystąpić.
* Jeżeli nie zwraca pustą kolekcję.
*
* @param ball - piłka, z którą może zajść kolizja.
* @return Kolekcję kolizji.
*/
public Collection<Collision> checkCollisionsWithBall(Ball ball)
{
TreeSet<Collision> collisionList = new TreeSet<>();
List<LineSegment2D> brickLineSegments = getBrickWithCirleCollisionLineSegments(ball
.getRadius());
Side sides[] = { Side.BOTTOM, Side.RIGHT, Side.TOP, Side.LEFT, Side.CORNER,
Side.CORNER, Side.CORNER, Side.CORNER };
Ray2D ballMovementRay = ball.getMovementRay();
SpeedVector2D ballSpeed = ball.getSpeed();
Coordinates2D pointOfIntersection;
for (LineSegment2D brickLineSegment : brickLineSegments)
{
try
{
pointOfIntersection = brickLineSegment.intersectionPoint(ballMovementRay);
double distance = Math.sqrt(Math.pow(
pointOfIntersection.getX() - ball.getX(), 2)
+ Math.pow(pointOfIntersection.getY() - ball.getY(), 2));
long timeTillCollision = (long) (distance / ballSpeed.getSpeedValue());
Side side = sides[brickLineSegments.indexOf(brickLineSegment)];
collisionList.add(new BallWithBrickCollision(timeTillCollision, this, side));
} catch (DoesnotIntersectException e)
{
// Nie ma kolizji. To nie jest silent fail.
}
}
return collisionList;
}
/**
* @return Współrzędne lewego-górnego rogu.
*/
public Coordinates2D getTopLeftCornerCoordinates()
{
return new Coordinates2D(topLeftCoordinates);
}
/**
* @return Współrzędne prawego-górnego rogu.
*/
public Coordinates2D getTopRightCornerCoordinates()
{
return new Coordinates2D(
(float) (topLeftCoordinates.getX() + dimension.getWidth()),
topLeftCoordinates.getY());
}
/**
* @return Współrzędne prawego-dolnego rogu.
*/
public Coordinates2D getBottomRightCornerCoordinates()
{
return new Coordinates2D(
(float) (topLeftCoordinates.getX() + dimension.getWidth()),
(float) (topLeftCoordinates.getY() - dimension.getHeight()));
}
/**
* @return Współrzędne lewego-dolnego rogu.
*/
public Coordinates2D getBottomLeftCornerCoordinates()
{
return new Coordinates2D((float) (topLeftCoordinates.getX()),
(float) (topLeftCoordinates.getY() - dimension.getHeight()));
}
/**
* @return Współrzędne środka klocka.
*/
public Coordinates2D getCenterCoordiantes()
{
return new Coordinates2D(
(float) (topLeftCoordinates.getX() + dimension.getWidth() / 2),
(float) (topLeftCoordinates.getY() - dimension.getHeight() / 2));
}
/**
* @return Wymiary klocka.
*/
public Dimension getDimension()
{
return new Dimension(dimension);
}
/**
* @return Typ klocka.
*/
public BrickType getBrickType()
{
return BrickType.NormalBrick;
}
/**
* Zwraca listę odcinków, które reprezentują linie kolizji
* z okręgiem o podanym promieniu.
* Kolejność odcinków: spód, prawa ściana, wierzch, lewa ściana,
* lewy-dolny róg, prawy-dolny róg, prawy-góry róg, lewy-góry róg.
*
* @param radius - promień okręgu.
* @return Lista odcinków.
*/
private List<LineSegment2D> getBrickWithCirleCollisionLineSegments(final float radius)
{
List<LineSegment2D> brickLineSegments = new LinkedList<>();
// spód
Coordinates2D bottomStart = getBottomLeftCornerCoordinates().moveAlongVector(
new Coordinates2D(0, -radius));
Coordinates2D bottomEnd = getBottomRightCornerCoordinates().moveAlongVector(
new Coordinates2D(0, -radius));
brickLineSegments.add(new LineSegment2D(bottomStart, bottomEnd));
// prawa ściana
Coordinates2D rightSideStart = getBottomRightCornerCoordinates().moveAlongVector(
new Coordinates2D(radius, 0));
Coordinates2D rightSideEnd = getTopRightCornerCoordinates().moveAlongVector(
new Coordinates2D(radius, 0));
brickLineSegments.add(new LineSegment2D(rightSideStart, rightSideEnd));
// wierzch
Coordinates2D topStart = getTopRightCornerCoordinates().moveAlongVector(
new Coordinates2D(0, radius));
Coordinates2D topEnd = getTopLeftCornerCoordinates().moveAlongVector(
new Coordinates2D(0, radius));
brickLineSegments.add(new LineSegment2D(topStart, topEnd));
// Lewa ściana przesunięte o radius na zewnątrz.
Coordinates2D leftSideStart = getTopLeftCornerCoordinates().moveAlongVector(
new Coordinates2D(-radius, 0));
Coordinates2D leftSideEnd = getBottomLeftCornerCoordinates().moveAlongVector(
new Coordinates2D(-radius, 0));
brickLineSegments.add(new LineSegment2D(leftSideStart, leftSideEnd));
// lewy-dolny róg
brickLineSegments.add(new LineSegment2D(leftSideEnd, bottomStart));
// prawy-dolny róg
brickLineSegments.add(new LineSegment2D(bottomEnd, rightSideStart));
// prawy-górny róg
brickLineSegments.add(new LineSegment2D(rightSideEnd, topStart));
// lewy-górny róg
brickLineSegments.add(new LineSegment2D(topEnd, leftSideStart));
return brickLineSegments;
}
}