2016-02-28 250 views
0

我想用Java創建一個簡單的遊戲。我使用BlueJ的IDE和我的代碼,目前如下:用Java Applet實現鍵盤監聽器

import java.util.*; 
import java.awt.*; 
import javax.swing.*;  

public class GameGraphic extends JApplet 
{ 

    // Variable initialization 
    private Board board; 
    private Dice dice; 
    private ArrayList<Player> players; 
    private Player currentPlayer; 

    // etc.. 

    public void init() 
    { 
     setSize(600,800); 

     // Code to initialize game, load images 
     // etc.. 

    } 

    // Game method etc.. 

    public void paint(Graphics g) 
    { 
     // Drawing game board etc.. 

     turn++; 
     int diceRoll = dice.roll(); 


     advancePlayer(currentPlayer, steps); 
     changeCoins(currentPlayer, diceRoll); 

     whoseTurn = (whoseTurn+1)%players.size(); 

     while(command=="w") { 
     } 

     try { 
     Thread.sleep(3000); 
     } catch(InterruptedException ex) { 
     Thread.currentThread().interrupt(); 
     } 

     revalidate(); 
     repaint(); 
    } 
} 

所以,現在,它被用來模擬,一切運作良好,並進入下一個轉彎每次3秒。我想要做的就是使用鍵盤輸入進行下一回合。我希望它基本上可以繪製板子,等到輸入一個字符,如果字符是「n」然後前進一圈(基本上運行paint()一次迭代並再次等待)。 實施這個的最佳方式是什麼?我嘗試過使用KeyListener,但它看起來不適用於AWT。非常感謝你:)

+1

[棄用Java插件的支持(http://www.gizmodo.com .au/2016/01/rest-in-hell-java-plug-in /)和[移至無插件網頁](https://blogs.oracle。com/java-platform-group/entry/moving_to_a_plugin_free) – MadProgrammer

+0

因爲我知道有些人會提出這個建議,所以通常不會推薦'KeyListener',你應該看看[Key Bindings API](http://docs.oracle.com /javase/tutorial/uiswing/misc/keybinding.html),它旨在解決許多與'KeyListener'相關的問題API – MadProgrammer

+0

不要在'paint'方法中調用'Thread.sleep',這不是應該完成動畫,看看[併發中的Swing](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/)和[如何使用Swing定時器](http://docs.oracle.com .com/javase/tutorial/uiswing/misc/timer.html)以獲取更多詳細信息 – MadProgrammer

回答

2

讓我們開始無線小應用程序正式是一種死硬的技術,我不會浪費時間讓它們工作,相反,我會把你的努力集中在API的其他領域。有關更多詳細信息,請參閱Java Plugin support deprecatedMoving to a Plugin-Free Web

您不應該在事件分派線程的上下文內(或者執行任何其他長時間運行或阻塞操作)並且尤其不能從paint方法的上下文中調用Thread.sleep。有關更多詳細信息,請參閱Concurrency in Java

您不應該調用任何可能直接或間接生成重繪的方法,繪畫僅用於繪畫而不用其他任何東西,否則可能會導致EDT不穩定並導致程序無響應。

在Swing中製作動畫的一個簡單解決方案是使用Swing Timer,它不會阻止EDT,但會在EDT的內容中觸發它的更新,從而更安全地從內部更新UI。

有關更多詳細信息,請參見How to use Swing Timers

我也建議你看看Painting in AWT and SwingPerforming Custom Painting因爲如果你打算做任何類型的自定義繪畫,你應該有一些瞭解如何繪畫過程的作品。

KeyListener是一個低級別的API,它從鍵盤焦點問題受到影響(如果它註冊到組件沒有鍵盤焦點,也不會產生事件),相反,你應該使用Key Bindings API來代替。

在下面的例子中,有兩件事發生。該是Timer這是更新「運行時間」值,當你按下ñ關鍵,它更新一個turn變量

import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.FontMetrics; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import javax.swing.AbstractAction; 
import javax.swing.ActionMap; 
import javax.swing.InputMap; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class GameGraphic { 

    public static void main(String[] args) { 
     new GameGraphic(); 
    } 

    public GameGraphic() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new GamePane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class GamePane extends JPanel { 
     private int turn = 0; 
     private long runtime; 

     public GamePane() { 
      InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW); 
      ActionMap actionMap = getActionMap(); 

      inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_N, 0), "next"); 
      actionMap.put("next", new AbstractAction() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        System.out.println("..."); 
        turn++; 
        repaint(); 
       } 
      }); 

      long startTime = System.currentTimeMillis(); 
      Timer timer = new Timer(40, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        runtime = System.currentTimeMillis() - startTime; 
        repaint(); 
       } 
      }); 
      timer.start(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      int width = getWidth(); 
      int height = getHeight(); 
      FontMetrics fm = g2d.getFontMetrics(); 
      String text = Integer.toString(turn); 
      int x = (width - fm.stringWidth(text))/2; 
      int y = ((height - fm.getHeight())/2) + fm.getAscent(); 
      g2d.drawString(text, x, y); 

      text = Long.toString(runtime); 
      x = width - fm.stringWidth(text); 
      y = height - fm.getHeight() + fm.getAscent(); 
      g2d.drawString(text, x, y); 
      g2d.dispose(); 
     } 


    } 
} 
0

在java中有這個名爲的KeyListener的接口(接口意在面向對象編程的概念)

你的KeyListener添加到對象,下面是一個例子:

https://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html

這裏是用java遊戲的例子http://www.edu4java.com/en/game/game4.html網站(非常好... ...)

+0

[如何使用鍵綁定](http://docs.oracle.co m/javase/tutorial/uiswing/misc/keybinding.html) – MadProgrammer

+0

嗨MadProgrammer,你給的例子使用JComponent。它仍然適用於我擁有的JApplet嗎?因爲JApplet似乎根本不接受這個接口! –

+1

@WassimGr這可以歸結爲第二點,你應該避免重寫頂層容器的paint,而是使用applet作爲核心組件的容器(例如,從'JComponent'或'JPanel'擴展),這樣,你不要將自己鎖定在一個用例中(你可以將你的核心組件添加到你喜歡的任何容器中) – MadProgrammer