/**
*
*/
package com.szuppe.jakub.view;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JComponent;
import com.szuppe.jakub.common.Acceleration2D;
import com.szuppe.jakub.common.Coordinates2D;
import com.szuppe.jakub.common.SpeedVector2D;
import com.szuppe.jakub.config.view.BallConfig;
import com.szuppe.jakub.mockups.BallMockup;
/**
* Klasa reprezentująca piłkę w widoku.
* Dziedziczy po {@link JComponent}.
* Zawiera pozycje, promień, przyspieszenie,
* prędkość piłki otrzymane z makiety.
*
* @author Jakub Szuppe <j.szuppe at gmail.com>
* @see JComponent
*/
class Ball extends JComponent
{
/**
*
*/
private static final long serialVersionUID = 3922642890603123111L;
/** Współrzędne lewego-górnego rogu kwadratu zawierającego piłkę. */
private Coordinates2D topLeftCoordinates;
/** Promień. */
private int radius;
/** Prędkość */
private SpeedVector2D speed;
/** Przyspieszenie */
private Acceleration2D acceleration;
/** Ostatni czas rysowania obiektu. */
private long lastRepaintTime;
/** Konfiguracja. */
private final BallConfig ballConfig;
/**
* Tworzy nowy obiekt {@link Ball} na podstawie
* podanej konfiguracji oraz makiety stanu piłki
* z modelu.
*
* @param ballConfig
* @param ballMockup
*/
public Ball(final BallConfig ballConfig, BallMockup ballMockup)
{
this.ballConfig = ballConfig;
setDoubleBuffered(ballConfig.isDoubleBuffered());
setVisible(true);
this.radius = ballMockup.getRadius();
this.topLeftCoordinates = ballMockup.getTopLeftCoordinates();
this.speed = ballMockup.getSpeed();
this.acceleration = ballMockup.getAcceleration();
this.lastRepaintTime = System.currentTimeMillis();
}
/**
* Rysuję piłkę, jako niebieski okrąg z ciemniejszym obwodem.
*
* @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
*/
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
final int leftUpperCornerX = topLeftCoordinates.getIntX();
final int leftUpperCornerY = topLeftCoordinates.getIntY();
final int diameter = 2 * radius;
// Could be image, but it would be the same.
g2.setColor(ballConfig.getOutsideColor()); // new Color(22, 119, 140);
g2.fillOval(leftUpperCornerX, leftUpperCornerY, diameter, diameter);
g2.setColor(ballConfig.getInsideColor()); // new Color(39, 217, 255);
g2.fillOval(leftUpperCornerX + 2, leftUpperCornerY + 2, diameter - 4, diameter - 4);
}
/**
* Zmienia stan na podstawie
* makiety stanu piłki z modelu.
*
* @param ballMockup
*/
public void setFromMockup(BallMockup ballMockup)
{
this.radius = ballMockup.getRadius();
this.topLeftCoordinates = new Coordinates2D(ballMockup.getTopLeftCoordinates());
this.speed = new SpeedVector2D(ballMockup.getSpeed());
this.acceleration = ballMockup.getAcceleration();
lastRepaintTime = System.currentTimeMillis();
}
/**
* Przemieszcza piłkę po czasie. Animuję.
*/
public void move()
{
long timeInterval = System.currentTimeMillis() - lastRepaintTime;
lastRepaintTime = System.currentTimeMillis();
Coordinates2D ballDisplacementVector;
// s = v * t + (a * t^2)/2
float xballDisplacement = (speed.getXSpeed() * timeInterval)
+ (0.5f * acceleration.getxAcc() * timeInterval * timeInterval);
float yballDisplacement = (speed.getYSpeed() * timeInterval)
+ (0.5f * acceleration.getyAcc() * timeInterval * timeInterval);
if (Math.abs(speed.getXSpeed()) < Math.abs(0.5f * acceleration.getxAcc() * timeInterval)
|| Math.abs(speed.getYSpeed()) < Math.abs(0.5f * acceleration.getyAcc() * timeInterval))
{
speed = new SpeedVector2D(0, 0);
acceleration = new Acceleration2D(0, 0);
ballDisplacementVector = new Coordinates2D(0, 0);
}
else
{
ballDisplacementVector = new Coordinates2D(xballDisplacement, yballDisplacement);
}
topLeftCoordinates = topLeftCoordinates.moveAlongVector(ballDisplacementVector);
SpeedVector2D speedChange = acceleration.countSpeedChange(timeInterval);
speed.add(speedChange);
}
}