/**
*
*/
package com.szuppe.jakub.model;
import com.szuppe.jakub.common.Acceleration2D;
import com.szuppe.jakub.common.Coordinates2D;
import com.szuppe.jakub.common.Ray2D;
import com.szuppe.jakub.common.SpeedVector2D;
import com.szuppe.jakub.config.model.BallConfig;
/**
* Klasa opisująca piłkę.
*
* @author Jakub Szuppe <j.szuppe at gmail.com>
*
*/
class Ball
{
/** Współrzędne środka piłki. */
private Coordinates2D coordinates;
/** Wektor prędkości. */
private SpeedVector2D speed;
/** Wektor przyspieszenia. */
private Acceleration2D acceleration;
/** Promień. */
private final int radius;
/** Stan. */
private BallState ballState;
/** Konfiguracja piłki. */
private final BallConfig ballConfig;
/**
* Tworzy piłkę na podstawie podanej konfiguracji.
*
* @param ballConfig - konfiguracja piłki.
*/
public Ball(BallConfig ballConfig)
{
this.ballConfig = ballConfig;
this.ballState = BallState.GLUED_TO_PADDLE;
this.coordinates = ballConfig.getStartCoordinates();
this.radius = ballConfig.getRadius();
this.speed = new SpeedVector2D(0, 0);
this.acceleration = new Acceleration2D(0, 0);
}
/**
* Ustala stan piłki (współrzędne środka, prędkość,
* przyspieszenie) po czasie.
*
* @param timeInterval - czas, który upłynął.
*/
public void move(long timeInterval)
{
if (speed.getSpeedValue() == 0)
{
return;
}
else if (!isReleased())
{
// Przyklejona do platformy -> ma przyspieszenie
// d = v*t + 0.5*a*t^2
final long timeWhenBallWillStop = (long) Math.abs(speed.getXSpeed()
/ acceleration.getxAcc());
long movementTime = Math.min(timeInterval, timeWhenBallWillStop);
moveAlongVector(movementTime);
countNewSpeedAndAcc(timeInterval, timeWhenBallWillStop);
}
else
{
// Wolna, stała prędkość
// d = v*t
moveAlongVector(timeInterval);
}
}
/**
* Przywraca piłkę to stanu startowego, tj.
* pozycji startowej, prędkości, przyspieszenia.
* Przykleja piłkę do platformy.
*/
public void resetToStartSituation()
{
ballState = BallState.GLUED_TO_PADDLE;
coordinates = ballConfig.getStartCoordinates();
speed.zero();
acceleration.zero();
}
/**
* Wypuszcza piłkę (odkleja się od platformy).
*/
public void release()
{
if(ballState != BallState.RELEASED)
{
acceleration.zero();
ballState = BallState.RELEASED;
speed = ballConfig.getSpeedAfterRelease();
}
}
/**
* @return Prawdę, jeżeli piłka jest odklejona od platformy; fałsz wpp.
*/
public boolean isReleased()
{
return ballState == BallState.RELEASED;
}
/**
* Zatrzymuje piłkę w miejscu. Zeruje prędkośc i przyspieszenie.
*/
public void stop()
{
speed.zero();
acceleration.zero();
}
/**
* Odwraca poziomą składową przyspieszenia.
*/
public void reverseXAcc()
{
acceleration.reverseXAcc();
}
/**
* Odwraca poziomą składową prędkości.
*/
public void reverseXSpeed()
{
speed.reverseXSpeed();
}
/**
* Odwraca pionową składową prędkości.
*/
public void reverseYSpeed()
{
speed.reverseYSpeed();
}
/**
* Rotuje wektor prędkości zgodnie z podanym kątem.
*
* @param alpha
*/
public void rotateSpeedVector(double alpha)
{
speed.rotateVector(alpha);
}
/**
* @return Półprostą przedstawiającą tor ruchu piłki.
*/
public Ray2D getMovementRay()
{
Coordinates2D start = new Coordinates2D(coordinates);
Coordinates2D end = coordinates.moveAlongVector(speed.countDisplacement(1000));
return new Ray2D(start, end);
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
final String sPosition = "Position: " + coordinates;
final String sSpeed = "Speed: " + speed;
final String sRadius = "Radius: " + radius;
return sPosition + " " + sSpeed + " " + sRadius;
}
/**
* @return Współrzędne środka piłki.
*/
public Coordinates2D getCoordinates()
{
return new Coordinates2D(coordinates);
}
/**
* @return Poziomą współrzędną środka piłki.
*/
public float getX()
{
return coordinates.getX();
}
/**
* @return Pionową współrzędną środka piłki.
*/
public float getY()
{
return coordinates.getY();
}
/**
* @return Wektor prędkości piłki.
*/
public SpeedVector2D getSpeed()
{
return speed;
}
/**
* Ustawia prędkość piłki na podaną.
*
* @param speed - nowa prędkości piłki.
*/
public void setSpeed(SpeedVector2D speed)
{
this.speed = speed;
}
/**
* @return Wektor przyspieszenia piłki.
*/
public Acceleration2D getAcceleration()
{
return acceleration;
}
/**
* Ustawia przyspieszenie piłki.
*
* @param acceleration - nowe przyspieszenie.
*/
public void setAcceleration(Acceleration2D acceleration)
{
this.acceleration = acceleration;
}
/**
* @return Promień.
*/
public int getRadius()
{
return radius;
}
/**
* @return Poziomą składową prędkości piłki.
*/
public float getXSpeed()
{
return speed.getXSpeed();
}
/**
* @return Pionową składową prędkości piłki.
*/
public float getYSpeed()
{
return speed.getYSpeed();
}
/**
* Oblicza prędkość po zadanym czasie.
*
* @param timeInterval - czas.
* @param timeWhenBallWillStop - czas, po którym piłka się zatrzyma.
*/
private void countNewSpeedAndAcc(long timeInterval, long timeWhenBallWillStop)
{
if (timeInterval >= timeWhenBallWillStop)
{
speed.zero();
acceleration.zero();
}
else
{
long movementTime = Math.min(timeInterval, timeWhenBallWillStop);
speed.add(acceleration.countSpeedChange(movementTime));
}
}
/**
* Przemieszcza piłkę po zadanym czasie.
*
* @param movementTime - czas.
*/
private void moveAlongVector(long movementTime)
{
Coordinates2D displacementFromVelocity = speed.countDisplacement(movementTime);
Coordinates2D displacementFromAcc = acceleration.countDisplacement(movementTime);
Coordinates2D displacement = displacementFromVelocity
.moveAlongVector(displacementFromAcc);
coordinates.add(displacement);
}
}
enum BallState
{
RELEASED, GLUED_TO_PADDLE;
}