1 package nl.tudelft.jpacman.ui;
2
3 import java.awt.BorderLayout;
4 import java.awt.Container;
5 import java.util.Map;
6 import java.util.concurrent.Executors;
7 import java.util.concurrent.ScheduledExecutorService;
8 import java.util.concurrent.TimeUnit;
9
10 import javax.swing.JFrame;
11 import javax.swing.JPanel;
12 import javax.swing.WindowConstants;
13
14 import nl.tudelft.jpacman.game.Game;
15 import nl.tudelft.jpacman.ui.ScorePanel.ScoreFormatter;
16
17 /**
18 * The default JPacMan UI frame. The PacManUI consists of the following
19 * elements:
20 *
21 * <ul>
22 * <li>A score panel at the top, displaying the score of the player(s).
23 * <li>A board panel, displaying the current level, i.e. the board and all units
24 * on it.
25 * <li>A button panel, containing all buttons provided upon creation.
26 * </ul>
27 *
28 * @author Jeroen Roosen
29 *
30 */
31 public class PacManUI extends JFrame {
32
33 /**
34 * Default serialisation UID.
35 */
36 private static final long serialVersionUID = 1L;
37
38 /**
39 * The desired frame rate interval for the graphics in milliseconds, 40
40 * being 25 fps.
41 */
42 private static final int FRAME_INTERVAL = 40;
43
44 /**
45 * The panel displaying the player scores.
46 */
47 private final ScorePanel scorePanel;
48
49 /**
50 * The panel displaying the game.
51 */
52 private final BoardPanel boardPanel;
53
54 /**
55 * Creates a new UI for a JPacman game.
56 *
57 * @param game
58 * The game to play.
59 * @param buttons
60 * The map of caption-to-action entries that will appear as
61 * buttons on the interface.
62 * @param keyMappings
63 * The map of keyCode-to-action entries that will be added as key
64 * listeners to the interface.
65 * @param scoreFormatter
66 * The formatter used to display the current score.
67 */
68 public PacManUI(final Game game, final Map<String, Action> buttons,
69 final Map<Integer, Action> keyMappings,
70 ScoreFormatter scoreFormatter) {
71 super("JPacman");
72 assert game != null;
73 assert buttons != null;
74 assert keyMappings != null;
75
76 setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
77
78 PacKeyListener keys = new PacKeyListener(keyMappings);
79 addKeyListener(keys);
80
81 JPanel buttonPanel = new ButtonPanel(buttons, this);
82
83 scorePanel = new ScorePanel(game.getPlayers());
84 if (scoreFormatter != null) {
85 scorePanel.setScoreFormatter(scoreFormatter);
86 }
87
88 boardPanel = new BoardPanel(game);
89
90 Container contentPanel = getContentPane();
91 contentPanel.setLayout(new BorderLayout());
92 contentPanel.add(buttonPanel, BorderLayout.SOUTH);
93 contentPanel.add(scorePanel, BorderLayout.NORTH);
94 contentPanel.add(boardPanel, BorderLayout.CENTER);
95
96 pack();
97 }
98
99 /**
100 * Starts the "engine", the thread that redraws the interface at set
101 * intervals.
102 */
103 public void start() {
104 setVisible(true);
105 ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
106 service.scheduleAtFixedRate(this::nextFrame, 0, FRAME_INTERVAL, TimeUnit.MILLISECONDS);
107 }
108
109 /**
110 * Draws the next frame, i.e. refreshes the scores and game.
111 */
112 private void nextFrame() {
113 boardPanel.repaint();
114 scorePanel.refresh();
115 }
116 }