package com.szuppe.jakub.view;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.BlockingQueue;
import javax.swing.AbstractAction;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.OverlayLayout;
import com.szuppe.jakub.common.Direction;
import com.szuppe.jakub.config.view.GamePanelConfig;
import com.szuppe.jakub.events.*;
import com.szuppe.jakub.mockups.*;
class GamePanel extends JPanel
{
private static final long serialVersionUID = 4387937676434893831L;
/** Piłka, którą widać. */
private Ball ball;
/** Platforma, którą widać. */
private Paddle paddle;
/** Wymiary planszy. */
@SuppressWarnings("unused")
private Dimension levelDimension;
/** Klocki. */
private Bricks bricks;
/** Timer służący do animacji obiektów. */
private Timer screenTimer;
/** Zadanie animacji obiektów. */
private TimerTask screenTimerTask;
/** Kolejka blokująca zdarzeń. Potrzebna przy keybindings. */
@SuppressWarnings("unused")
private final BlockingQueue<AppEvent> eventsBlockingQueue;
/** Konfiguracja. */
private final GamePanelConfig gamePanelConfig;
/** Informacje o graczu (życia) */
private final PlayerInfo playerInfo;
/**
* Tworzy {@link GamePanel}, czyli plansze gry
* na podstawie podanej konfiguracji oraz makiety
* stanu gry.
*
* @param gamePanelConfig - konfiguracja.
* @param eventsBlockingQueue - kolejka blokująca potrzebna przy keybindings
* @param gameMockup - makieta stanu gry.
*/
public GamePanel(GamePanelConfig gamePanelConfig,
BlockingQueue<AppEvent> eventsBlockingQueue, GameMockup gameMockup)
{
this.gamePanelConfig = gamePanelConfig;
setPreferredSize(gameMockup.getLevelMockup().getDimension());
setBackground(gamePanelConfig.getBgColor());
setLayout(new OverlayLayout(this));
setDoubleBuffered(true);
this.eventsBlockingQueue = eventsBlockingQueue;
this.screenTimer = new Timer();
this.levelDimension = gameMockup.getLevelMockup().getDimension();
this.ball = new Ball(gamePanelConfig.getBallConfig(), gameMockup.getBallMockup());
this.paddle = new Paddle(gamePanelConfig.getPaddleConfig(),
gameMockup.getPaddleMockup());
this.bricks = new Bricks(gamePanelConfig.getBricksConfig(),
gameMockup.getBricksMockup(), this);
this.playerInfo = new PlayerInfo(gameMockup.getPlayerMockup(), gameMockup
.getLevelMockup().getDimension());
add(playerInfo);
add(ball);
add(paddle);
initTimerTasks();
initActions(eventsBlockingQueue);
}
/**
* Uruchamia animacje/odświeżane.
*/
public void start()
{
screenTimer.schedule(screenTimerTask, 0, gamePanelConfig.getRefreshRatio());
}
/**
* Zatrzymuje animacje.
*/
public void stop()
{
screenTimer.purge();
}
/**
* Ustawia piłkę zgodnie z makietą.
*
* @param ballMockup - makieta stanu piłki.
*/
public void setBall(BallMockup ballMockup)
{
ball.setFromMockup(ballMockup);
}
/**
* Ustawie platformę zgodnie z makietą.
*
* @param paddleMockup - makieta stanu platformy.
*/
public void setPaddle(final PaddleMockup paddleMockup)
{
paddle.setFromMockup(paddleMockup);
}
/**
* Ustawia klocki zgodnie z makietą.
*
* @param bricksMockups - makieta stanu klocków.
*/
public void setBricks(BricksMockup bricksMockups)
{
bricks.setFromMockup(bricksMockups);
}
/**
* @param playerMockup - makieta stanu gracza.
*/
public void setPlayerInfo(PlayerMockup playerMockup)
{
playerInfo.setLifesLeft(playerMockup.getLivesLeft());
}
/**
* Inicjalizuje zadanie animacji.
*/
private void initTimerTasks()
{
this.screenTimerTask = new TimerTask()
{
@Override
public void run()
{
ball.move();
paddle.move();
ball.repaint();
paddle.repaint();
bricks.repaint();
}
};
}
/**
* Inicjalizuje skróty klawiszowe (keybindings), przypisuje
* do nich odpowiednie akcje.
*
* @param eventsBlockingQueue
*/
@SuppressWarnings("serial")
private void initActions(final BlockingQueue<AppEvent> eventsBlockingQueue)
{
getInputMap().put(KeyStroke.getKeyStroke("pressed SPACE"), "releaseBall");
getInputMap().put(KeyStroke.getKeyStroke("pressed LEFT"), "movePaddleLeft");
getInputMap().put(KeyStroke.getKeyStroke("pressed RIGHT"), "movePaddleRight");
getActionMap().put("releaseBall", new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
try
{
eventsBlockingQueue.put(new BallReleaseEvent());
} catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
});
getActionMap().put("movePaddleLeft", new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
try
{
eventsBlockingQueue.put(new MovePaddleEvent(Direction.LEFT));
} catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
});
getActionMap().put("movePaddleRight", new AbstractAction()
{
@Override
public void actionPerformed(ActionEvent e)
{
try
{
eventsBlockingQueue.put(new MovePaddleEvent(Direction.RIGHT));
} catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
});
}
}