Subversion Repositories sokoban

Rev

Blame | Last modification | View Log | RSS feed

  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. }
  743.