Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | daniel-mar | 1 | package gdi1sokoban.gui; |
2 | |||
3 | import java.awt.BorderLayout; |
||
4 | import java.awt.Dimension; |
||
5 | import java.awt.Font; |
||
6 | import java.awt.GridLayout; |
||
7 | import java.awt.Toolkit; |
||
8 | import java.awt.event.ActionEvent; |
||
9 | import java.awt.event.ActionListener; |
||
10 | import java.awt.event.KeyEvent; |
||
11 | import java.io.File; |
||
12 | import java.io.IOException; |
||
13 | import java.net.URI; |
||
14 | import java.net.URISyntaxException; |
||
15 | import java.text.SimpleDateFormat; |
||
16 | import java.util.Date; |
||
17 | import java.util.regex.Matcher; |
||
18 | import java.util.regex.Pattern; |
||
19 | |||
20 | import javax.swing.ButtonGroup; |
||
21 | import javax.swing.JButton; |
||
22 | import javax.swing.JComboBox; |
||
23 | import javax.swing.JDialog; |
||
24 | import javax.swing.JFileChooser; |
||
25 | import javax.swing.JLabel; |
||
26 | import javax.swing.JMenu; |
||
27 | import javax.swing.JMenuBar; |
||
28 | import javax.swing.JMenuItem; |
||
29 | import javax.swing.JOptionPane; |
||
30 | import javax.swing.JPanel; |
||
31 | import javax.swing.JRadioButtonMenuItem; |
||
32 | import javax.swing.JScrollPane; |
||
33 | import javax.swing.JTable; |
||
34 | import javax.swing.border.BevelBorder; |
||
35 | |||
36 | import gdi1sokoban.exceptions.InternalFailureException; |
||
37 | import gdi1sokoban.exceptions.LevelHistoryEntryNotFoundException; |
||
38 | import gdi1sokoban.exceptions.ParameterOutOfRangeException; |
||
39 | import gdi1sokoban.exceptions.ParseException; |
||
40 | import gdi1sokoban.game.GameEngine; |
||
41 | import gdi1sokoban.globals.SokobanFileExtFilter; |
||
42 | import gdi1sokoban.sound.SoundEngine; |
||
43 | |||
44 | /** |
||
45 | * SokobanWindow class |
||
46 | * |
||
47 | * extends the GameWindow class and provides |
||
48 | * basic functions for controlling the game |
||
49 | */ |
||
50 | public class SokobanWindow extends GameWindow { |
||
51 | |||
52 | private static final long serialVersionUID = -3022370482307739059L; |
||
53 | private GameEngine owner; |
||
54 | private final SoundEngine sndEngine = new SoundEngine(); |
||
55 | // labels for status bar |
||
56 | private final JPanel statusBar = new JPanel(); |
||
57 | private final JLabel coords = new JLabel(""); |
||
58 | private final JLabel time = new JLabel(""); |
||
59 | private final JLabel steps = new JLabel(""); |
||
60 | private final JLabel infos = new JLabel(""); |
||
61 | private String infoText = ""; |
||
62 | public SokobanWindow(final String windowTitle) |
||
63 | throws InternalFailureException { |
||
64 | super(windowTitle); |
||
65 | setMenu(); |
||
66 | setStatusBar(); |
||
67 | } |
||
68 | |||
69 | /** |
||
70 | * sets the owner for the Gui-Object |
||
71 | * @param owner the GameEngine that owns this gui-object |
||
72 | */ |
||
73 | public void setOwner(final GameEngine owner){ |
||
74 | this.owner = owner; |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * creates the menu for the Game |
||
79 | */ |
||
80 | private void setMenu(){ |
||
81 | // Create Menu Bar |
||
82 | final JMenuBar menuBar = new JMenuBar(); |
||
83 | // Create Game Menu |
||
84 | final JMenu gameMenu = new JMenu("Spiel"); |
||
85 | // Create History Menu |
||
86 | final JMenu historyMenu = new JMenu("Extras"); |
||
87 | // Create Skin Menu |
||
88 | final JMenu skinMenu = new JMenu("Skin"); |
||
89 | // Group for JRadioButtonMenuItem |
||
90 | final ButtonGroup skinGroup = new ButtonGroup(); |
||
91 | // Create Help Menu |
||
92 | final JMenu helpMenu = new JMenu("?"); |
||
93 | // Add menus to Menubar |
||
94 | menuBar.add(gameMenu); |
||
95 | menuBar.add(historyMenu); |
||
96 | menuBar.add(helpMenu); |
||
97 | |||
98 | // Create New Game Item |
||
99 | final JMenuItem newGameItem = new JMenuItem("Neues Spiel"); |
||
100 | // set shortcut key |
||
101 | newGameItem.setMnemonic('N'); |
||
102 | // Add action to New Game |
||
103 | newGameItem.addActionListener(new ActionListener() { |
||
104 | // Action performed when clicked |
||
105 | public void actionPerformed(final ActionEvent e){ |
||
106 | keyNewGamePressed(); |
||
107 | } |
||
108 | }); |
||
109 | |||
110 | // Create Load Game Item |
||
111 | final JMenuItem loadGameItem = new JMenuItem("Spielstand laden..."); |
||
112 | // set shortcut key |
||
113 | loadGameItem.setMnemonic('L'); |
||
114 | // Add action to Save Game |
||
115 | loadGameItem.addActionListener(new ActionListener() { |
||
116 | // Action performed when clicked |
||
117 | public void actionPerformed(final ActionEvent e){ |
||
118 | keyLoadGamePressed(); |
||
119 | } |
||
120 | }); |
||
121 | |||
122 | // Create Save Game Item |
||
123 | final JMenuItem saveGameItem = new JMenuItem("Spielstand speichern..."); |
||
124 | // set shortcut key |
||
125 | saveGameItem.setMnemonic('S'); |
||
126 | // Add action to Save Game |
||
127 | saveGameItem.addActionListener(new ActionListener() { |
||
128 | // Action performed when clicked |
||
129 | public void actionPerformed(final ActionEvent e){ |
||
130 | keySaveGamePressed(); |
||
131 | } |
||
132 | }); |
||
133 | |||
134 | // Create Quit Game Item |
||
135 | final JMenuItem quitGameItem = new JMenuItem("Beenden"); |
||
136 | // set shortcut key |
||
137 | quitGameItem.setMnemonic('Q'); |
||
138 | // Add action to Quit |
||
139 | quitGameItem.addActionListener(new ActionListener() { |
||
140 | // Action performed when clicked |
||
141 | public void actionPerformed(final ActionEvent e){ |
||
142 | System.exit(0); |
||
143 | } |
||
144 | }); |
||
145 | // Create Undo Item |
||
146 | final JMenuItem undoItem = new JMenuItem("Rückgängig"); |
||
147 | // set shortcut key |
||
148 | //aboutItem.setMnemonic('A'); |
||
149 | // Add action to Undo |
||
150 | undoItem.addActionListener(new ActionListener() { |
||
151 | // Action performed when clicked |
||
152 | public void actionPerformed(final ActionEvent e){ |
||
153 | keyUndoPressed(); |
||
154 | } |
||
155 | }); |
||
156 | |||
157 | // Create Redo Item |
||
158 | final JMenuItem redoItem = new JMenuItem("Wiederholen"); |
||
159 | // set shortcut key |
||
160 | //aboutItem.setMnemonic('A'); |
||
161 | // Add action to Redo |
||
162 | redoItem.addActionListener(new ActionListener() { |
||
163 | // Action performed when clicked |
||
164 | public void actionPerformed(final ActionEvent e){ |
||
165 | keyRedoPressed(); |
||
166 | } |
||
167 | }); |
||
168 | |||
169 | // Create Show Highscore Item |
||
170 | final JMenuItem highscoreItem = new JMenuItem("Highscoreliste..."); |
||
171 | // set shortcut key |
||
172 | highscoreItem.setMnemonic('H'); |
||
173 | // Add action to Show Highscore |
||
174 | highscoreItem.addActionListener(new ActionListener() { |
||
175 | // Action performed when clicked |
||
176 | public void actionPerformed(final ActionEvent e){ |
||
177 | showHighscores(); |
||
178 | } |
||
179 | }); |
||
180 | // Create About Item |
||
181 | final JMenuItem aboutItem = new JMenuItem("Über..."); |
||
182 | // set shortcut key |
||
183 | aboutItem.setMnemonic('A'); |
||
184 | // Add action to Show Highscore |
||
185 | aboutItem.addActionListener(new ActionListener() { |
||
186 | // Action performed when clicked |
||
187 | public void actionPerformed(final ActionEvent e){ |
||
188 | showAbout(); |
||
189 | } |
||
190 | }); |
||
191 | |||
192 | // Entries for skin-submenu |
||
193 | final JRadioButtonMenuItem standardSkinItem = new JRadioButtonMenuItem("Standard"); |
||
194 | final JRadioButtonMenuItem bigSkinItem = new JRadioButtonMenuItem("Standard Big"); |
||
195 | final JRadioButtonMenuItem doomSkinItem = new JRadioButtonMenuItem("doomSkin"); |
||
196 | final JRadioButtonMenuItem crazyPaulSkinItem = new JRadioButtonMenuItem("crazyPaulSkin"); |
||
197 | // When Game is started Big Skin is selected |
||
198 | bigSkinItem.setSelected(true); |
||
199 | // Add action to switch skin |
||
200 | standardSkinItem.addActionListener(new ActionListener() { |
||
201 | // Action performed when clicked |
||
202 | public void actionPerformed(final ActionEvent e){ |
||
203 | loadSkin(0); |
||
204 | } |
||
205 | }); |
||
206 | bigSkinItem.addActionListener(new ActionListener() { |
||
207 | // Action performed when clicked |
||
208 | public void actionPerformed(final ActionEvent e){ |
||
209 | loadSkin(1); |
||
210 | } |
||
211 | }); |
||
212 | doomSkinItem.addActionListener(new ActionListener() { |
||
213 | // Action performed when clicked |
||
214 | public void actionPerformed(final ActionEvent e){ |
||
215 | loadSkin(2); |
||
216 | } |
||
217 | }); |
||
218 | crazyPaulSkinItem.addActionListener(new ActionListener() { |
||
219 | // Action performed when clicked |
||
220 | public void actionPerformed(final ActionEvent e){ |
||
221 | loadSkin(3); |
||
222 | } |
||
223 | }); |
||
224 | |||
225 | // Add entries to group |
||
226 | skinGroup.add(standardSkinItem); |
||
227 | skinGroup.add(bigSkinItem); |
||
228 | skinGroup.add(doomSkinItem); |
||
229 | skinGroup.add(crazyPaulSkinItem); |
||
230 | |||
231 | // Add Items to Menu |
||
232 | gameMenu.add(newGameItem); |
||
233 | gameMenu.add(loadGameItem); |
||
234 | gameMenu.add(saveGameItem); |
||
235 | gameMenu.add(skinMenu); |
||
236 | gameMenu.add(quitGameItem); |
||
237 | historyMenu.add(undoItem); |
||
238 | historyMenu.add(redoItem); |
||
239 | historyMenu.add(highscoreItem); |
||
240 | helpMenu.add(aboutItem); |
||
241 | // Add Items to Skin-Submenu |
||
242 | skinMenu.add(standardSkinItem); |
||
243 | skinMenu.add(bigSkinItem); |
||
244 | skinMenu.add(doomSkinItem); |
||
245 | skinMenu.add(crazyPaulSkinItem); |
||
246 | // Add Menu Bar to Window |
||
247 | this.setJMenuBar(menuBar); |
||
248 | |||
249 | } |
||
250 | |||
251 | /** |
||
252 | * adds a statusbar to the gameWindow |
||
253 | */ |
||
254 | public void setStatusBar(){ |
||
255 | statusBar.setLayout(new GridLayout(1,4)); |
||
256 | coords.setBorder(new BevelBorder(BevelBorder.LOWERED)); |
||
257 | coords.setFont(new Font("Arial", Font.BOLD, 10)); |
||
258 | coords.setHorizontalAlignment(JLabel.CENTER); |
||
259 | // time label |
||
260 | time.setBorder(new BevelBorder(BevelBorder.LOWERED)); |
||
261 | time.setFont(new Font("Arial", Font.BOLD, 10)); |
||
262 | time.setHorizontalAlignment(JLabel.CENTER); |
||
263 | // step-counter label |
||
264 | steps.setBorder(new BevelBorder(BevelBorder.LOWERED)); |
||
265 | steps.setFont(new Font("Arial", Font.BOLD, 10)); |
||
266 | steps.setHorizontalAlignment(JLabel.CENTER); |
||
267 | // infos label |
||
268 | infos.setBorder(new BevelBorder(BevelBorder.LOWERED)); |
||
269 | infos.setFont(new Font("Arial", Font.BOLD, 10)); |
||
270 | infos.setHorizontalAlignment(JLabel.CENTER); |
||
271 | // add labels to statusbar |
||
272 | statusBar.add(time); |
||
273 | statusBar.add(coords); |
||
274 | statusBar.add(steps); |
||
275 | statusBar.add(infos); |
||
276 | statusBar.setPreferredSize(new Dimension(getWidth(), 20)); |
||
277 | // add statusbar to gamewindow |
||
278 | getContentPane().add(statusBar, BorderLayout.SOUTH); |
||
279 | } |
||
280 | |||
281 | /** |
||
282 | * sets the info field in the Statusbar |
||
283 | * @param info text that shall be shown in the statusbar |
||
284 | */ |
||
285 | public void setStatusBarInfo(final String info){ |
||
286 | infoText = info; |
||
287 | updateStatusBar(); |
||
288 | } |
||
289 | |||
290 | @Override |
||
291 | protected SokobanPanel createGamePanel() { |
||
292 | final SokobanPanel panel = new SokobanPanel(this); |
||
293 | add(panel); |
||
294 | return panel; |
||
295 | } |
||
296 | |||
297 | @Override |
||
298 | /** |
||
299 | * Events for other keys |
||
300 | */ |
||
301 | protected void keyOtherPressed(final KeyEvent key) { |
||
302 | try { |
||
303 | owner.checkCheat(key.getKeyChar()); |
||
304 | } catch (final ParameterOutOfRangeException e) { |
||
305 | System.err.println("Fehler: Ungültige Levelkoordinaten!"); |
||
306 | } |
||
307 | } |
||
308 | |||
309 | /** |
||
310 | * Redo actions |
||
311 | */ |
||
312 | @Override |
||
313 | protected void keyRedoPressed() { |
||
314 | try { |
||
315 | sndEngine.playSound("redoSound", "sounds/redo.mp3", SoundEngine.SND_ASYNC); |
||
316 | } catch (final InternalFailureException e1) { |
||
317 | System.err.println("Interner Fehler: Fehler beim Abspielen eines Sounds"); |
||
318 | } |
||
319 | try { |
||
320 | owner.redo(); |
||
321 | owner.roundEnd(true); |
||
322 | } catch (final LevelHistoryEntryNotFoundException e) { |
||
323 | System.err.println("Redo nicht möglich: Keine gültigen Schritte verfügbar"); |
||
324 | } catch (final ParameterOutOfRangeException e) { |
||
325 | System.err.println("Fehler: Ungültige Levelkoordinaten!"); |
||
326 | } |
||
327 | } |
||
328 | |||
329 | /** |
||
330 | * Plays a sound when a player is perfoming a move |
||
331 | * @param validStep was this move a valid step? |
||
332 | */ |
||
333 | private void playMoveSound(final boolean validStep) { |
||
334 | if (validStep) |
||
335 | try { |
||
336 | sndEngine.playSound("moveSound", "sounds/walk.mp3", SoundEngine.SND_ASYNC); |
||
337 | } catch (final InternalFailureException e1) { |
||
338 | System.err.println("Interner Fehler: Fehler beim Abspielen eines Sounds"); |
||
339 | } |
||
340 | else |
||
341 | try { |
||
342 | sndEngine.playSound("wallSound", "sounds/wall.mp3", SoundEngine.SND_ASYNC); |
||
343 | } catch (final InternalFailureException e1) { |
||
344 | System.err.println("Interner Fehler: Fehler beim Abspielen eines Sounds"); |
||
345 | } |
||
346 | } |
||
347 | |||
348 | /** |
||
349 | * plays a sound when user types in a cheat |
||
350 | */ |
||
351 | public void playCheatSound() { |
||
352 | try { |
||
353 | sndEngine.playSound("cheatSound", "sounds/cheat.mp3", SoundEngine.SND_ASYNC); |
||
354 | } catch (final InternalFailureException e1) { |
||
355 | System.err.println("Interner Fehler: Fehler beim Abspielen eines Sounds"); |
||
356 | } |
||
357 | } |
||
358 | |||
359 | /** |
||
360 | * shows a warning when a deadlock state is reached |
||
361 | */ |
||
362 | public void showDeadlockMessage() { |
||
363 | JOptionPane.showMessageDialog(null, "Das Level befindet sich in einem Deadlockzustand.\n\nBenutzen Sie die Undo-Funktion, um die Schritte,\ndie zu diesem Zustand geführt haben, rückgängig zu machen.", "Deadlock-Zustand", JOptionPane.WARNING_MESSAGE); |
||
364 | setStatusBarInfo("Deadlock"); |
||
365 | } |
||
366 | |||
367 | /** |
||
368 | * shows an error message when level syntax is incorrect |
||
369 | */ |
||
370 | public void showParseError() { |
||
371 | JOptionPane.showMessageDialog(null, "Das Level konnte nicht geladen werden.\nDie Datei ist fehlerhaft.", "Leveldatei fehlerhaft", JOptionPane.ERROR_MESSAGE); |
||
372 | setStatusBarInfo("Error"); |
||
373 | } |
||
374 | |||
375 | /** |
||
376 | * Plays a sound when there is a deadlock situation |
||
377 | */ |
||
378 | public void playDeadlockSound() { |
||
379 | try { |
||
380 | sndEngine.stopSound("backgroundSound"); |
||
381 | sndEngine.playSound("deadlock", "sounds/stuck.mp3", SoundEngine.SND_ASYNC + SoundEngine.SND_LOOP); |
||
382 | } catch (final InternalFailureException e1) { |
||
383 | System.err.println("Interner Fehler: Fehler beim Abspielen eines Sounds"); |
||
384 | } |
||
385 | } |
||
386 | |||
387 | /** |
||
388 | * Plays the background sound |
||
389 | */ |
||
390 | public void playBackgroundSound() { |
||
391 | try { |
||
392 | setStatusBarInfo(""); |
||
393 | sndEngine.stopSound("deadlock"); |
||
394 | sndEngine.playSound("backgroundSound", "sounds/bg.mp3", SoundEngine.SND_ASYNC + SoundEngine.SND_LOOP); |
||
395 | } catch (final InternalFailureException e1) { |
||
396 | System.err.println("Interner Fehler: Fehler beim Abspielen eines Sounds"); |
||
397 | } |
||
398 | } |
||
399 | |||
400 | /** |
||
401 | * Moves the player |
||
402 | * @param dir directory |
||
403 | */ |
||
404 | private void movePlayer(final char dir) { |
||
405 | boolean validMove; |
||
406 | try { |
||
407 | validMove = owner.movePlayer(dir); |
||
408 | playMoveSound(validMove); |
||
409 | owner.roundEnd(validMove); |
||
410 | } catch (final ParameterOutOfRangeException e) { |
||
411 | System.err.println("Fehler: Ungültige Levelkoordinaten!"); |
||
412 | } |
||
413 | } |
||
414 | |||
415 | /** |
||
416 | * updates information on the status panel |
||
417 | */ |
||
418 | private final void updateStatusBar() { |
||
419 | if((owner != null) && (owner.getGameLevel() != null)) { |
||
420 | try { |
||
421 | coords.setText("Lvl: " + owner.getCurrentLevelNr() + " [" + owner.getGameLevel().getPlayerPos().left + ", " + owner.getGameLevel().getPlayerPos().top + "]"); |
||
422 | } catch (final ParameterOutOfRangeException e) { |
||
423 | System.err.println("Fehler: Ungültige Levelkoordinaten!"); |
||
424 | } // show player coordinates |
||
425 | steps.setText("Schritte: " + owner.getGameLevel().getSteps()); // show number of made steps |
||
426 | time.setText("Zeit: " + owner.getPlayingTime(0) + " Sek."); |
||
427 | infos.setText(infoText); // show info |
||
428 | } |
||
429 | } |
||
430 | |||
431 | @Override |
||
432 | protected void keyDownPressed() { |
||
433 | movePlayer('D'); |
||
434 | } |
||
435 | |||
436 | @Override |
||
437 | protected void keyLeftPressed() { |
||
438 | movePlayer('L'); |
||
439 | } |
||
440 | |||
441 | @Override |
||
442 | protected void keyRightPressed() { |
||
443 | movePlayer('R'); |
||
444 | } |
||
445 | |||
446 | @Override |
||
447 | protected void keyUpPressed() { |
||
448 | movePlayer('U'); |
||
449 | } |
||
450 | |||
451 | /** |
||
452 | * Undo event |
||
453 | */ |
||
454 | @Override |
||
455 | protected void keyUndoPressed() { |
||
456 | try { |
||
457 | sndEngine.playSound("undoSound", "sounds/undo.mp3", SoundEngine.SND_ASYNC); |
||
458 | } catch (final InternalFailureException e1) { |
||
459 | System.err.println("Interner Fehler: Fehler beim Abspielen eines Sounds"); |
||
460 | } |
||
461 | try { |
||
462 | owner.undo(); |
||
463 | owner.roundEnd(true); |
||
464 | } catch (final LevelHistoryEntryNotFoundException e) { |
||
465 | System.err.println("Undo nicht möglich: Keine vorherigen Schritte verfügbar."); |
||
466 | } catch (final ParameterOutOfRangeException e) { |
||
467 | System.err.println("Fehler: Ungültige Levelkoordinaten!"); |
||
468 | } |
||
469 | } |
||
470 | |||
471 | /** |
||
472 | * Method is called when panel is resized. |
||
473 | * Updates the size of the Window |
||
474 | */ |
||
475 | public void panelResized(){ |
||
476 | // Set Window's size to size of panel |
||
477 | setSize(getWidth(),getHeight()); |
||
478 | setVisible( true ); |
||
479 | } |
||
480 | |||
481 | /** |
||
482 | * Shows the highscore list |
||
483 | */ |
||
484 | public void showHighscores() { |
||
485 | showHighscores(owner.getCurrentLevelNr()); |
||
486 | } |
||
487 | |||
488 | public void showHighscores(final int levelNo) { |
||
489 | final JDialog hsForm = new JDialog(); |
||
490 | hsForm.setBounds(0, 0, 600, 370); |
||
491 | final JLabel hsLevelLabel = new JLabel("Level:"); |
||
492 | final String [] hsTableHeader = {"Platz", "Spielername", "Benötigte Schritte", "Benötigte Zeit (in Sek.)" }; |
||
493 | final JTable hsTable = new JTable(owner.getHighscores().toStringArray(levelNo), hsTableHeader); |
||
494 | final String [] hsLevels = owner.getHighscores().getLevels(); |
||
495 | final JComboBox hsLevelList = new JComboBox(hsLevels); |
||
496 | hsLevelList.setSelectedItem(String.valueOf(levelNo)); |
||
497 | hsLevelList.addActionListener(new ActionListener() { |
||
498 | // Action performed when clicked |
||
499 | public void actionPerformed(final ActionEvent e){ |
||
500 | hsForm.setVisible(false); |
||
501 | showHighscores(Integer.valueOf((String)hsLevelList.getSelectedItem())); |
||
502 | } |
||
503 | }); |
||
504 | hsTable.setPreferredScrollableViewportSize(new Dimension(520, 220)); |
||
505 | hsTable.setFillsViewportHeight(true); |
||
506 | hsTable.setShowGrid(false); |
||
507 | hsTable.setShowHorizontalLines(true); |
||
508 | hsTable.setRowHeight(22); |
||
509 | hsTable.setFont(new Font(null, Font.PLAIN, 20)); |
||
510 | hsTable.setEnabled(false); |
||
511 | // Create the scroll pane and add the table to it. |
||
512 | final JScrollPane hsScrollPane = new JScrollPane(hsTable); |
||
513 | hsForm.setResizable(false); |
||
514 | hsForm.setTitle("Highscores - Level " + levelNo); |
||
515 | final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); |
||
516 | final int top = (screenSize.height - hsForm.getHeight()) / 2; |
||
517 | final int left = (screenSize.width - hsForm.getWidth()) / 2; |
||
518 | hsForm.setLocation(left, top); |
||
519 | final JButton hsResetButton = new JButton("Highscore Reset"); |
||
520 | hsResetButton.addActionListener(new ActionListener() { |
||
521 | // Action performed when clicked |
||
522 | public void actionPerformed(final ActionEvent e){ |
||
523 | if (JOptionPane.showConfirmDialog(null, "/!\\ GEFAHR /!\\\n\n=======================================\n\nALLE HIGHSCORES WERDEN UNWIDERBRINGLICH VERNICHTET.\n\n=======================================\n\nFortfahren?", "/!\\ GEFAHR /!\\", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.YES_OPTION) { |
||
524 | owner.getHighscores().resetHighscores(); |
||
525 | showHighscores(levelNo); |
||
526 | hsForm.setVisible(false); |
||
527 | } |
||
528 | } |
||
529 | }); |
||
530 | final JButton hsCloseButton = new JButton("Close"); |
||
531 | hsCloseButton.addActionListener(new ActionListener() { |
||
532 | // Action performed when clicked |
||
533 | public void actionPerformed(final ActionEvent e){ |
||
534 | hsForm.setVisible(false); |
||
535 | } |
||
536 | }); |
||
537 | final JPanel hsPanel = new JPanel(); |
||
538 | hsPanel.add(hsLevelLabel); |
||
539 | hsPanel.add(hsLevelList); |
||
540 | hsPanel.add(hsScrollPane); |
||
541 | hsPanel.add(hsResetButton); |
||
542 | hsPanel.add(hsCloseButton); |
||
543 | hsForm.add(hsPanel); |
||
544 | hsForm.getRootPane().setDefaultButton(hsCloseButton); |
||
545 | hsForm.setModal(true); |
||
546 | hsForm.setVisible(true); |
||
547 | } |
||
548 | |||
549 | /** |
||
550 | * Shows the about box |
||
551 | */ |
||
552 | public void showAbout(){ |
||
553 | JOptionPane.showMessageDialog(null, "<html>" + |
||
554 | "<h1><b><font color=\"#000099\">Sokoban</b></h1>" + |
||
555 | "<H3><I>developed by:</I> Yocto Software Solutions</H3>" + |
||
556 | "<ul><small>"+ |
||
557 | "Super Samuel Kniesz"+ |
||
558 | "<br>Victorious Victor-Philipp Negoescu"+ |
||
559 | "<br>Perfect Paul Ruchniewicz"+ |
||
560 | "<br>Heroic Holger Thies</small></ul>" + |
||
561 | "<H3><I>version:</I></H3>" + |
||
562 | "<ul><small>1.0</small></ul>" + |
||
563 | "<H3><I>special thanks to:</I></H3>" + |
||
564 | "<small><ul>the whole ics 1 team (for support)<br>our loved ones (for understanding)<br>the coffee-machine</small></ul>"+ |
||
565 | "</html>", "Über Sokoban", |
||
566 | JOptionPane.PLAIN_MESSAGE); |
||
567 | } |
||
568 | |||
569 | /** |
||
570 | * Loads a skin |
||
571 | * @param skinId predefined skin id |
||
572 | */ |
||
573 | public void loadSkin(final int skinId){ |
||
574 | getGamePanel().loadSkin(skinId); |
||
575 | try { |
||
576 | getGamePanel().redraw(); |
||
577 | } catch (final InternalFailureException e) { |
||
578 | System.err.println("Fehler: Fehler beim laden des Skin-Sets"); |
||
579 | } |
||
580 | } |
||
581 | |||
582 | /** |
||
583 | * New game event |
||
584 | */ |
||
585 | @Override |
||
586 | protected void keyNewGamePressed() { |
||
587 | try { |
||
588 | owner.newGame(owner.getCurrentLevelNr()); |
||
589 | } catch (final IOException e) { |
||
590 | System.err.println("Interner Fehler: I/O Fehler"); |
||
591 | e.printStackTrace(); |
||
592 | } catch (final ParameterOutOfRangeException e) { |
||
593 | System.err.println("Interner Fehler: Ungültiger Parameter!"); |
||
594 | e.printStackTrace(); |
||
595 | } catch (final InternalFailureException e) { |
||
596 | System.err.println("Interner Fehler: Es ist ein interner Fehler aufgetreten."); |
||
597 | e.printStackTrace(); |
||
598 | } catch (final URISyntaxException e) { |
||
599 | System.err.println("Fehler: Fehlerhafter Dateiname"); |
||
600 | } catch (ParseException e) { |
||
601 | System.err.println("Fehler: Leveldatei fehlerhaft"); |
||
602 | } |
||
603 | } |
||
604 | |||
605 | /** |
||
606 | * Load game event |
||
607 | */ |
||
608 | @Override |
||
609 | protected void keyLoadGamePressed() { |
||
610 | try { |
||
611 | // show File dialog |
||
612 | final JFileChooser chooser = new JFileChooser(); |
||
613 | final SokobanFileExtFilter filter = new SokobanFileExtFilter(); |
||
614 | chooser.setFileFilter(filter); |
||
615 | // setzt das Verzeichnis das angezeigt werden soll (also das LEVEL |
||
616 | // -Verzeichnis) |
||
617 | chooser.setCurrentDirectory(new File(new URI(owner.getLevelDir()))); |
||
618 | final int returnVal = chooser.showOpenDialog(chooser); |
||
619 | // Springt aus der funktion wenn abgebrochen wird |
||
620 | if (returnVal == JFileChooser.CANCEL_OPTION) |
||
621 | return; |
||
622 | File GamesSaveFile; |
||
623 | GamesSaveFile = new File(ClassLoader.getSystemClassLoader() |
||
624 | .getResource( |
||
625 | "levels" + File.separatorChar |
||
626 | + chooser.getSelectedFile().getName()) |
||
627 | .toURI()); |
||
628 | owner.loadGame(GamesSaveFile); |
||
629 | } catch (final URISyntaxException e) { |
||
630 | System.err.println("Fehler: Fehlerhafter Dateiname"); |
||
631 | } |
||
632 | } |
||
633 | |||
634 | |||
635 | /** |
||
636 | * Save game event |
||
637 | */ |
||
638 | @Override |
||
639 | protected void keySaveGamePressed() { |
||
640 | try { |
||
641 | String playerName = owner.getPlayerName(); |
||
642 | if (playerName.isEmpty()) |
||
643 | playerName = JOptionPane.showInputDialog("Bitte geben Sie Ihren Namen ein:"); |
||
644 | // Springt aus der funktion wenn abgebrochen wird |
||
645 | if (playerName == null) |
||
646 | return; |
||
647 | owner.setPlayerName(playerName); |
||
648 | // Filename is date and player name |
||
649 | final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss"); |
||
650 | final String dt = df.format(new Date()); |
||
651 | // replace illegal characters within the player name |
||
652 | final Pattern charPattern = Pattern.compile("[^a-zA-Z0-9äöüÄÖÜ]"); |
||
653 | final Matcher charMatcher = charPattern.matcher(playerName); |
||
654 | playerName = charMatcher.replaceAll("-"); // replace all illegal characters with "-" |
||
655 | // build filename and save the file |
||
656 | final String fileName = "Save_" + dt + "_" + playerName + ".sok"; |
||
657 | final File saveFile = new File(new URI(owner.getLevelDir() + fileName)); |
||
658 | if (owner.saveGame(saveFile)) |
||
659 | JOptionPane.showMessageDialog(null, "Spielstand erfolgreich gespeichert!\nDateiname: " + fileName, "Savegame gespeichert", JOptionPane.INFORMATION_MESSAGE); |
||
660 | } catch (final URISyntaxException e) { |
||
661 | System.err.println("Fehler: Datei konnte nicht gefunden werden!"); |
||
662 | } |
||
663 | } |
||
664 | |||
665 | /** |
||
666 | * Dialog for getting the max. time to solve this level |
||
667 | */ |
||
668 | public int showSolveTimeDialog(){ |
||
669 | int searchTime = 0; |
||
670 | try{ |
||
671 | searchTime = Integer.parseInt(JOptionPane.showInputDialog("Bitte geben Sie die maximale Suchdauer in Sekunden für die Lösung des Levels ein:")); |
||
672 | return searchTime; |
||
673 | } catch (final NumberFormatException e){ |
||
674 | return 0; |
||
675 | } |
||
676 | } |
||
677 | |||
678 | /** |
||
679 | * redraws the game panel when the round has ended |
||
680 | */ |
||
681 | public void roundEnd(final boolean hasMoved, final String playerName){ |
||
682 | // redraw game panel |
||
683 | try { |
||
684 | getGamePanel().redraw(); |
||
685 | } catch (final InternalFailureException e) { |
||
686 | System.err.println("Interner Fehler: Fehler beim Zeichnen des Spielfelds"); |
||
687 | } |
||
688 | } |
||
689 | |||
690 | /** |
||
691 | * level loader event |
||
692 | */ |
||
693 | @Override |
||
694 | public void notifyLevelLoaded(final int width, final int height) throws ParameterOutOfRangeException, InternalFailureException{ |
||
695 | super.notifyLevelLoaded(width, height); |
||
696 | playBackgroundSound(); // start playing background music |
||
697 | // start thread for updating StatusBar |
||
698 | infoText = ""; // reset info text |
||
699 | new Thread() { |
||
700 | public void run() { |
||
701 | while(!owner.getGameLevel().isSolved()){ |
||
702 | updateStatusBar(); // update status bar as long as level is not solved |
||
703 | try { |
||
704 | Thread.sleep(200); // update every 0.3 seconds |
||
705 | } catch (final InterruptedException e) { |
||
706 | System.err.println("Interner Fehler: Thread konnte nicht manipuliert werden, da er bereits beendet wurde."); |
||
707 | } |
||
708 | } |
||
709 | } |
||
710 | }.start(); |
||
711 | } |
||
712 | |||
713 | /** |
||
714 | * let the user type his name to insert a new highscore |
||
715 | * @param place winning place |
||
716 | */ |
||
717 | public void newHighscore(final int place) { |
||
718 | try { |
||
719 | sndEngine.stopSound("backgroundSound"); |
||
720 | sndEngine.playSound("levelCompleted", "sounds/finish.mp3", SoundEngine.SND_ASYNC); |
||
721 | // System.out.println("Herzlichen Glückwunsch! Ein neuer Highscore! Sie belegen Platz " + place); |
||
722 | if ((owner.getPlayerName() == null) || (owner.getPlayerName().isEmpty())) |
||
723 | owner.setPlayerName(JOptionPane.showInputDialog("Herzlichen Glückwunsch - ein neuer Highscore!\n\nSie haben Platz " + String.valueOf(place) + " der Highscoreliste belegt!\nBitte geben Sie Ihren Namen ein:")); |
||
724 | else |
||
725 | JOptionPane.showMessageDialog(null, "Herzlichen Glückwunsch - ein neuer Highscore!\n\n" + owner.getPlayerName() + ", Sie haben Platz " + String.valueOf(place) + " der Highscoreliste belegt!", "Ein neuer Highscore", JOptionPane.INFORMATION_MESSAGE); |
||
726 | } catch (final InternalFailureException e1) { |
||
727 | System.err.println("Interner Fehler: Fehler beim Eintragen des Highscores"); |
||
728 | } |
||
729 | } |
||
730 | |||
731 | /** |
||
732 | * resize the window when the panel is resized |
||
733 | * @param width new width of panel |
||
734 | * @param height new height of panel |
||
735 | */ |
||
736 | public void panelResized(final int width, int height){ |
||
737 | // Add height of menubar and statusbar to panel's size |
||
738 | height += this.getJMenuBar().getHeight() + statusBar.getHeight(); |
||
739 | // resize window |
||
740 | this.setSize(width, height); |
||
741 | } |
||
742 | } |