Subversion Repositories sokoban

Rev

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
}