2016-01-26 22 views
1

如何在每次使用wasd鍵時更新圖形?現在我的球員不能移動,並且我想在每次使用其中一個鍵移動時更新網格。每當按下箭頭鍵時,我如何實現和更新每次玩家。我創造了這個課程,但是隻要按下按鍵,它似乎都不會移動。如何在每次按下按鍵時實現移動並更新網格。我做了代碼,但球員似乎並沒有移動。任何人都可以告訴我我做錯了什麼?如何更新圖形

import java.awt.*; 
import javax.swing.*; 
import java.awt.event.*; // Needed for ActionListener 
import javax.swing.event.*; // Needed for ActionListener 
import java.awt.Graphics; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import javax.swing.Timer; 
import java.util.Scanner; 

class www extends JFrame 
{ 
    static Maze maze = new Maze(); 
    static Timer t; 

    //======================================================== constructor 
    public www() 
    { 
     // 1... Create/initialize components 
     // 2... Create content pane, set layout 
     JPanel panel = new JPanel(); 
     JPanel content = new JPanel();  // Create a content pane 
     content.setLayout (new BorderLayout()); // Use BorderLayout for panel 
     JPanel north = new JPanel(); 
     north.setLayout (new FlowLayout()); // Use FlowLayout for input area 

     DrawArea board = new DrawArea (500, 500); 
     // 3... Add the components to the input area. 

     content.add (north, "North"); // Input area 
     content.add (board, "South"); // Output area 

     // 4... Set this window's attributes. 
     setContentPane (content); 
     pack(); 
     setTitle ("MAZE"); 
     setSize (510, 570); 
     setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
     setLocationRelativeTo (null);   // Center window. 
    } 

    public static void main (String[] args) 
    { 

     www window = new www(); 
     window.setVisible (true); 

    } 


    class DrawArea extends JPanel 
    { 
     public DrawArea (int width, int height) 
     { 
      this.setPreferredSize (new Dimension (width, height)); // size 
     } 

     public void paintComponent (Graphics g) 
     { 
      maze.show (g); 
      // display current state of colony 
     } 
    } 
} 

class Maze 
{ 
    static Scanner sc; 
    private int maze [][]; 

    public Maze() 
    { 
     int [][] grid = 
      {{1,2,1,1,1,1,1,1,1,1,1,1,1}, 
       {1,0,1,0,1,0,1,0,0,0,0,0,1}, 
       {1,0,1,0,0,0,1,0,1,1,1,0,1}, 
       {1,0,0,0,1,1,1,0,0,0,0,0,1}, 
       {1,0,1,0,0,0,0,0,1,1,1,0,1}, 
       {1,0,1,0,1,1,1,0,1,0,0,0,1}, 
       {1,0,1,0,1,0,0,0,1,1,1,0,1}, 
       {1,0,1,0,1,1,1,0,1,0,1,0,1}, 
       {1,0,0,0,0,0,0,0,0,0,1,0,1}, 
       {1,1,1,1,1,1,1,1,1,1,1,0,1}}; 

     maze = grid; 

    } 


    public void keyPressed(KeyEvent e, Graphics g) 
    { 
     int x = 0, y = 0,velX = 0, velY = 0; 
     int c = e.getKeyCode(); 
     if(c == KeyEvent.VK_LEFT || c == KeyEvent.VK_A) 
     { 
      velX = -1; 
      velY = 0; 
      for (int row = 0 ; row < maze.length ; row++) 
       for (int col = 0 ; col < maze [0].length ; col++) 
       { 
        if (maze [row] [col] == 1) // life 
        { 
         g.setColor (Color.black); 
        } 
        else if(maze [row][col] == 2) 
        { 

         g.setColor (Color.red); 
        } 
        else 
        { 
         g.setColor(Color.white); 
        } 
        g.fillRect (col * 20 + 20, row * 20 + 20, 50, 50); // draw life form 
      } 

     } 
     if(c == KeyEvent.VK_UP || c == KeyEvent.VK_W) 
     { 
      velX = 0; 
      velY = -1; 
      for (int row = 0 ; row < maze.length ; row++) 
       for (int col = 0 ; col < maze [0].length ; col++) 
       { 
        if (maze [row] [col] == 1) // life 
        { 
         g.setColor (Color.black); 
        } 
        else if(maze [row][col] == 2) 
        { 

         g.setColor (Color.red); 
        } 
        else 
        { 
         g.setColor(Color.white); 
        } 
        g.fillRect (col * 20 + 20, row * 20 + 20, 50, 50); // draw life form 
      } 
     } 
     if(c == KeyEvent.VK_RIGHT || c == KeyEvent.VK_D) 
     { 
      velX = 1; 
      velY = 0; 
      for (int row = 0 ; row < maze.length ; row++) 
       for (int col = 0 ; col < maze [0].length ; col++) 
       { 
        if (maze [row] [col] == 1) // life 
        { 
         g.setColor (Color.black); 
        } 
        else if(maze [row][col] == 2) 
        { 

         g.setColor (Color.red); 
        } 
        else 
        { 
         g.setColor(Color.white); 
        } 
        g.fillRect (col * 20 + 20, row * 20 + 20, 50, 50); // draw life form 
      } 

     } 
     if(c == KeyEvent.VK_DOWN || c == KeyEvent.VK_S) 
     { 
      velX = 0; 
      velY = 1; 
      for (int row = 0 ; row < maze.length ; row++) 
       for (int col = 0 ; col < maze [0].length ; col++) 
       { 
        if (maze [row] [col] == 1) // life 
        { 
         g.setColor (Color.black); 
        } 
        else if(maze [row][col] == 2) 
        { 

         g.setColor (Color.red); 
        } 
        else 
        { 
         g.setColor(Color.white); 
        } 
        g.fillRect (col * 20 + 20, row * 20 + 20, 50, 50); // draw life form 
      } 

     } 

    } 

    public void keyTyped(KeyEvent e){} 

    public void keyReleased(KeyEvent e){} 



    public void show (Graphics g) 
    { 
     for (int row = 0 ; row < maze.length ; row++) 
      for (int col = 0 ; col < maze [0].length ; col++) 
      { 
       if (maze [row] [col] == 1) // life 
       { 
        g.setColor (Color.black); 
       } 
       else if(maze [row][col] == 2) 
       { 

        g.setColor (Color.red); 
       } 
       else 
       { 
        g.setColor(Color.white); 
       } 
       g.fillRect (col * 20 + 20, row * 20 + 20, 50, 50); // draw life form 
     } 

    } 


    public class player extends JPanel implements ActionListener,KeyListener 
    { 

     Timer tm = new Timer(5,this); 
     int x = 0, y = 0,velX = 0, velY = 0; 
     public player() 
     { 
      tm.start();  
      addKeyListener(this); 
      setFocusable(true); 
      setFocusTraversalKeysEnabled(false); 
     } 

     public void paintComponent(Graphics g) 
     { 
      super.paintComponent(g); 
      g.setColor(Color.RED); 
      g.fillRect(x,y,50,30); 

     } 

     public void actionPerformed(ActionEvent e) 
     { 
      x = x+velX; 
      y = y +velY; 
      repaint(); 
     } 

     public void keyPressed(KeyEvent e) 
     { 
      int c = e.getKeyCode(); 
      if(c == KeyEvent.VK_LEFT || c == KeyEvent.VK_A) 
      { 
       velX = -1; 
       velY = 0; 

      } 
      if(c == KeyEvent.VK_UP || c == KeyEvent.VK_W) 
      { 
       velX = 0; 
       velY = -1; 
      } 
      if(c == KeyEvent.VK_RIGHT || c == KeyEvent.VK_D) 
      { 
       velX = 1; 
       velY = 0; 
      } 
      if(c == KeyEvent.VK_DOWN || c == KeyEvent.VK_S) 
      { 
       velX = 0; 
       velY = 1; 
     } 

    } 

    public void keyTyped(KeyEvent e){} 

    public void keyReleased(KeyEvent e){} 
+1

從[Swing中的併發]開始(http://docs.oracle.com/javase/tutorial/uiswing/concurrency/),[如何使用Swing定時器](http://docs.oracle.com/javase /tutorial/uiswing/misc/timer.html)和[如何使用密鑰綁定](http://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html)。然後看看[這個答案](http://stackoverflow.com/questions/35003520/program-not-painting-screen-properly/35004777#35004777)演示了一個基本遊戲的MVC實現,使用鍵盤輸入更新遊戲模型的狀態。我們給出的任何答案基本上與上面的一樣 – MadProgrammer

+0

@MadProgrammer:這必須是FN20,並且您已經給他這些鏈接。現在關於那座橋... –

+0

@HovercraftFullOfEels是的,我正在考慮只是做一個快捷方式來自動填寫評論的未來問題 – MadProgrammer

回答

4

好了,讓我們開始與一些問題...

class www extends JFrame 

首先,你應該避免覆蓋JFrame,你不添加任何新的功能類,把自己鎖整合到一個單一的使用案例中,並存在其他難以診斷的問題。

您的課程名稱應該以大寫字母開頭。通過Code Conventions for the Java TM Programming Language閱讀,它將使人們更容易閱讀你的代碼並閱讀其他人。

下一頁...

static Maze maze = new Maze(); 
static Timer t; 

static是一個不好的設計的一個好兆頭。你應該避免使用它們作爲跨通信機制,你失去了他們的引用是如何改變的控制,使其難以診斷可能出現的問題

下一頁...

class DrawArea extends JPanel 
{ 
    public DrawArea (int width, int height) 
    { 
     this.setPreferredSize (new Dimension (width, height)); // size 
    } 

    public void paintComponent (Graphics g) 
    { 
     maze.show (g); 
     // display current state of colony 
    } 
} 

首先,你打破了油漆鏈,這可能導致繪畫工件無法結束,您必須在執行任何自定義繪畫之前調用油漆方法super方法。詳情參見

而且Painting in AWT and SwingPerforming Custom Painting,它不是迷宮的責任油漆本身,它是由視圖來決定應如何最好地代表模型/迷宮

下一頁...

public class player extends JPanel implements ActionListener,KeyListener 
{ 
    //... 
} 

好的,這個班級根本就沒有用過,但它是唯一一次註冊KeyListener。你也過於複雜的過程,因爲DrawArea也應該負責繪製播放器和處理用戶輸入。

作爲一般的經驗法則,KeyListener不是合適的API,原因有很多。您最好使用Key Bindings API,它可以解決KeyListener的問題,並使其更易於更改和實現其他輸入設備。

你的代碼一般不會專注於孤立的責任,爲什麼player被允許改變玩家的位置?

OOP的一個關鍵方面是關於隔離責任,這使得更改事物更容易,而不會對系統的其他部分造成負面影響,這也支持Model-View-Controller範例。

其基本思想是,您的模型控制數據,維護狀態並定義可以更改它的規則(並可根據需要提供事件通知)。該視圖負責渲染模型的狀態。控制器是將它粘合在一起的膠水。

通常在MVC中,模型和視圖從不與每個MVC進行通信,控制器負責充當它們之間的管道。這可以通過使用Observer Pattern直接實現(直接對控制器進行調用),或者通常使用Observer Pattern來實現,其中視圖和模型生成控制器響應的事件。

,我們需要做的是定義每個元素,每一層是會暴露給其他方,例如信息和功能的基本功能的第一件事...

public interface GameModel { 
    public int[][] getMaze(); 
    public int[] getPlayerLocation(); 
    public void setPlayerLocation(int[] location); 
    public void update(Set<Direction> directions); 
} 

public interface GameController { 
    public int[][] getMaze(); 
    public int[] getPlayerLocation(); 
    public void setDirectionPressed(Direction direction, boolean pressed); 
    public void start(); 
} 

public interface GameView { 
    public void update(); 
    public void setController(GameController controller); 
    public GameController getController(); 
} 

這是開始的想法Composition over inheritance它允許你更好地解耦你的代碼,因爲你不依賴於類的物理實現,而只是他們的維護一個給定合同的結果。

接下來,我們定義的實現....

public class DefaultGameModel implements GameModel { 

    private int[][] maze 
      = {{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 
      {1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1}, 
      {1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1}, 
      {1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1}, 
      {1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1}, 
      {1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1}, 
      {1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1}, 
      {1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1}, 
      {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}, 
      {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}}; 

    private int[] playerLocation = new int[]{1, 0}; 

    @Override 
    public int[][] getMaze() { 
     return maze; 
    } 

    @Override 
    public int[] getPlayerLocation() { 
     return playerLocation; 
    } 

    @Override 
    public void setPlayerLocation(int[] playerLocation) { 
     this.playerLocation = playerLocation; 
    } 

    @Override 
    public void update(Set<Direction> directions) { 
     int[] location = getPlayerLocation(); 
     int[][] maze = getMaze(); 
     int x = location[0]; 
     int y = location[1]; 
     if (directions.contains(Direction.UP)) { 
      y--; 
     } else if (directions.contains(Direction.DOWN)) { 
      y++; 
     } 
     if (directions.contains(Direction.LEFT)) { 
      x--; 
     } else if (directions.contains(Direction.RIGHT)) { 
      x++; 
     } 
     if (x < 0) { 
      x = 0; 
     } else if (x >= maze[0].length) { 
      x = maze[0].length - 1; 
     } 
     if (y < 0) { 
      y = 0; 
     } else if (y >= maze.length) { 
      y = maze.length - 1; 
     } 

     if (maze[y][x] == 0) { 
      location = new int[]{x, y}; 
      setPlayerLocation(location); 
     } 

    } 

} 

public class DefaultGameController implements GameController { 

    private GameView view; 
    private GameModel model; 

    private Timer timer; 

    private Set<Direction> directions; 

    public DefaultGameController(GameView view, GameModel model) { 
     this.view = view; 
     this.model = model; 
     directions = new HashSet<>(4); 
     view.setController(this); 
    } 

    public GameView getView() { 
     return view; 
    } 

    public GameModel getModel() { 
     return model; 
    } 

    @Override 
    public int[][] getMaze() { 
     return getModel().getMaze(); 
    } 

    @Override 
    public int[] getPlayerLocation() { 
     return getModel().getPlayerLocation(); 
    } 

    @Override 
    public void setDirectionPressed(Direction direction, boolean pressed) { 
     if (pressed) { 
      directions.add(direction); 
     } else { 
      directions.remove(direction); 
     } 
    } 

    @Override 
    public void start() { 
     // This isn't really required for this type of simple example, but what 
     // does do is demonstrates at least one possible solution for simple 
     // game loop 
     // 
     // Because of the basic nature of the game, it would be possible to have 
     // setDirectionPressed call model.update and view.update 
     if (timer != null && timer.isRunning()) { 
      timer.stop(); 
     } 
     timer = new Timer(40, new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       getModel().update(Collections.unmodifiableSet(directions)); 
       getView().update(); 
      } 
     }); 
     timer.start(); 
    } 

} 

public class DefaultGameView extends JPanel implements GameView { 

    private GameController controller; 

    public DefaultGameView() { 
     addKeyBinding("left.pressed", KeyEvent.VK_LEFT, true, new MoveAction(Direction.LEFT, true)); 
     addKeyBinding("left.released", KeyEvent.VK_LEFT, false, new MoveAction(Direction.LEFT, false)); 
     addKeyBinding("right.pressed", KeyEvent.VK_RIGHT, true, new MoveAction(Direction.RIGHT, true)); 
     addKeyBinding("right.released", KeyEvent.VK_RIGHT, false, new MoveAction(Direction.RIGHT, false)); 
     addKeyBinding("up.pressed", KeyEvent.VK_UP, true, new MoveAction(Direction.UP, true)); 
     addKeyBinding("up.released", KeyEvent.VK_UP, false, new MoveAction(Direction.UP, false)); 
     addKeyBinding("down.pressed", KeyEvent.VK_DOWN, true, new MoveAction(Direction.DOWN, true)); 
     addKeyBinding("down.released", KeyEvent.VK_DOWN, false, new MoveAction(Direction.DOWN, false)); 
    } 

    @Override 
    public void update() { 
     repaint(); 
    } 

    @Override 
    public void setController(GameController controller) { 
     this.controller = controller; 
     revalidate(); 
     repaint(); 
    } 

    @Override 
    public GameController getController() { 
     return controller; 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     Dimension size = new Dimension(13 * 20, 10 * 20); 
     GameController controller = getController(); 
     if (controller != null) { 
      int[][] maze = controller.getMaze(); 
      size.height = maze.length * 20; 
      size.width = maze[0].length * 20; 
     } 
     return size; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     GameController controller = getController(); 
     if (controller != null) { 
      Graphics2D g2d = (Graphics2D) g.create(); 
      Dimension size = getPreferredSize(); 
      int x = (getWidth() - size.width)/2; 
      int y = (getHeight() - size.height)/2; 

      int[][] maze = controller.getMaze(); 
      for (int row = 0; row < maze.length; row++) { 
       int yPos = y + (row * 20); 
       for (int col = 0; col < maze[row].length; col++) { 
        int xPos = x + (col * 20); 
        switch (maze[row][col]) { 
         case 1: 
          g2d.setColor(Color.BLACK); 
          break; 
         default: 
          g2d.setColor(Color.WHITE); 
          break; 
        } 
        g2d.fillRect(xPos, yPos, 20, 20); 
       } 
      } 
      int[] playerLocation = controller.getPlayerLocation(); 
      int xPos = x + (playerLocation[0] * 20); 
      int yPos = y + (playerLocation[1] * 20); 
      g2d.setColor(Color.RED); 
      g2d.fillRect(xPos, yPos, 20, 20); 
      g2d.dispose(); 
     } 
    } 

    protected void addKeyBinding(String name, int virtualKey, boolean pressed, MoveAction action) { 
     addKeyBinding(name, KeyStroke.getKeyStroke(virtualKey, 0, !pressed), action); 
    } 

    protected void addKeyBinding(String name, KeyStroke keyStroke, MoveAction action) { 
     InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW); 
     ActionMap actionMap = getActionMap(); 

     inputMap.put(keyStroke, name); 
     actionMap.put(name, action); 
    } 

    public class MoveAction extends AbstractAction { 
     private Direction direction; 
     private boolean pressed; 

     public MoveAction(Direction direction, boolean pressed) { 
      this.direction = direction; 
      this.pressed = pressed; 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      GameController controller = getController(); 
      if (controller != null) { 
       controller.setDirectionPressed(direction, pressed); 
      } 
     } 

    } 

} 

好吧,這似乎有點怪異這樣一個簡單的問題,但知道想象你想添加更多的迷宮,這是一個簡單的改變該模型。

最後,我們需要把它放在一起......

Maze

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.util.Collections; 
import java.util.HashSet; 
import java.util.Set; 
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 Main { 

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

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

       GameModel model = new DefaultGameModel(); 
       DefaultGameView view = new DefaultGameView(); 
       GameController controller = new DefaultGameController(view, model); 

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

       controller.start(); 
      } 
     }); 
    } 

    public enum Direction { 
     UP, DOWN, LEFT, RIGHT; 
    } 

    public interface GameModel { 
     public int[][] getMaze(); 
     public int[] getPlayerLocation(); 
     public void setPlayerLocation(int[] location); 
     public void update(Set<Direction> directions); 
    } 

    public interface GameController { 
     public int[][] getMaze(); 
     public int[] getPlayerLocation(); 
     public void setDirectionPressed(Direction direction, boolean pressed); 
     public void start(); 
    } 

    public interface GameView { 
     public void update(); 
     public void setController(GameController controller); 
     public GameController getController(); 
    } 

    public class DefaultGameModel implements GameModel { 

     private int[][] maze 
       = {{1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, 
       {1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1}, 
       {1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1}, 
       {1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1}, 
       {1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1}, 
       {1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1}, 
       {1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1}, 
       {1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1}, 
       {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1}, 
       {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}}; 

     private int[] playerLocation = new int[]{1, 0}; 

     @Override 
     public int[][] getMaze() { 
      return maze; 
     } 

     @Override 
     public int[] getPlayerLocation() { 
      return playerLocation; 
     } 

     @Override 
     public void setPlayerLocation(int[] playerLocation) { 
      this.playerLocation = playerLocation; 
     } 

     @Override 
     public void update(Set<Direction> directions) { 
      int[] location = getPlayerLocation(); 
      int[][] maze = getMaze(); 
      int x = location[0]; 
      int y = location[1]; 
      if (directions.contains(Direction.UP)) { 
       y--; 
      } else if (directions.contains(Direction.DOWN)) { 
       y++; 
      } 
      if (directions.contains(Direction.LEFT)) { 
       x--; 
      } else if (directions.contains(Direction.RIGHT)) { 
       x++; 
      } 
      if (x < 0) { 
       x = 0; 
      } else if (x >= maze[0].length) { 
       x = maze[0].length - 1; 
      } 
      if (y < 0) { 
       y = 0; 
      } else if (y >= maze.length) { 
       y = maze.length - 1; 
      } 

      if (maze[y][x] == 0) { 
       location = new int[]{x, y}; 
       setPlayerLocation(location); 
      } 

     } 

    } 

    public class DefaultGameController implements GameController { 

     private GameView view; 
     private GameModel model; 

     private Timer timer; 

     private Set<Direction> directions; 

     public DefaultGameController(GameView view, GameModel model) { 
      this.view = view; 
      this.model = model; 
      directions = new HashSet<>(4); 
      view.setController(this); 
     } 

     public GameView getView() { 
      return view; 
     } 

     public GameModel getModel() { 
      return model; 
     } 

     @Override 
     public int[][] getMaze() { 
      return getModel().getMaze(); 
     } 

     @Override 
     public int[] getPlayerLocation() { 
      return getModel().getPlayerLocation(); 
     } 

     @Override 
     public void setDirectionPressed(Direction direction, boolean pressed) { 
      if (pressed) { 
       directions.add(direction); 
      } else { 
       directions.remove(direction); 
      } 
     } 

     @Override 
     public void start() { 
      // This isn't really required for this type of simple example, but what 
      // does do is demonstrates at least one possible solution for simple 
      // game loop 
      // 
      // Because of the basic nature of the game, it would be possible to have 
      // setDirectionPressed call model.update and view.update 
      if (timer != null && timer.isRunning()) { 
       timer.stop(); 
      } 
      timer = new Timer(40, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        getModel().update(Collections.unmodifiableSet(directions)); 
        getView().update(); 
       } 
      }); 
      timer.start(); 
     } 

    } 

    public class DefaultGameView extends JPanel implements GameView { 

     private GameController controller; 

     public DefaultGameView() { 
      addKeyBinding("left.pressed", KeyEvent.VK_LEFT, true, new MoveAction(Direction.LEFT, true)); 
      addKeyBinding("left.released", KeyEvent.VK_LEFT, false, new MoveAction(Direction.LEFT, false)); 
      addKeyBinding("right.pressed", KeyEvent.VK_RIGHT, true, new MoveAction(Direction.RIGHT, true)); 
      addKeyBinding("right.released", KeyEvent.VK_RIGHT, false, new MoveAction(Direction.RIGHT, false)); 
      addKeyBinding("up.pressed", KeyEvent.VK_UP, true, new MoveAction(Direction.UP, true)); 
      addKeyBinding("up.released", KeyEvent.VK_UP, false, new MoveAction(Direction.UP, false)); 
      addKeyBinding("down.pressed", KeyEvent.VK_DOWN, true, new MoveAction(Direction.DOWN, true)); 
      addKeyBinding("down.released", KeyEvent.VK_DOWN, false, new MoveAction(Direction.DOWN, false)); 
     } 

     @Override 
     public void update() { 
      repaint(); 
     } 

     @Override 
     public void setController(GameController controller) { 
      this.controller = controller; 
      revalidate(); 
      repaint(); 
     } 

     @Override 
     public GameController getController() { 
      return controller; 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      Dimension size = new Dimension(13 * 20, 10 * 20); 
      GameController controller = getController(); 
      if (controller != null) { 
       int[][] maze = controller.getMaze(); 
       size.height = maze.length * 20; 
       size.width = maze[0].length * 20; 
      } 
      return size; 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      GameController controller = getController(); 
      if (controller != null) { 
       Graphics2D g2d = (Graphics2D) g.create(); 
       Dimension size = getPreferredSize(); 
       int x = (getWidth() - size.width)/2; 
       int y = (getHeight() - size.height)/2; 

       int[][] maze = controller.getMaze(); 
       for (int row = 0; row < maze.length; row++) { 
        int yPos = y + (row * 20); 
        for (int col = 0; col < maze[row].length; col++) { 
         int xPos = x + (col * 20); 
         switch (maze[row][col]) { 
          case 1: 
           g2d.setColor(Color.BLACK); 
           break; 
          default: 
           g2d.setColor(Color.WHITE); 
           break; 
         } 
         g2d.fillRect(xPos, yPos, 20, 20); 
        } 
       } 
       int[] playerLocation = controller.getPlayerLocation(); 
       int xPos = x + (playerLocation[0] * 20); 
       int yPos = y + (playerLocation[1] * 20); 
       g2d.setColor(Color.RED); 
       g2d.fillRect(xPos, yPos, 20, 20); 
       g2d.dispose(); 
      } 
     } 

     protected void addKeyBinding(String name, int virtualKey, boolean pressed, MoveAction action) { 
      addKeyBinding(name, KeyStroke.getKeyStroke(virtualKey, 0, !pressed), action); 
     } 

     protected void addKeyBinding(String name, KeyStroke keyStroke, MoveAction action) { 
      InputMap inputMap = getInputMap(WHEN_IN_FOCUSED_WINDOW); 
      ActionMap actionMap = getActionMap(); 

      inputMap.put(keyStroke, name); 
      actionMap.put(name, action); 
     } 

     public class MoveAction extends AbstractAction { 
      private Direction direction; 
      private boolean pressed; 

      public MoveAction(Direction direction, boolean pressed) { 
       this.direction = direction; 
       this.pressed = pressed; 
      } 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       GameController controller = getController(); 
       if (controller != null) { 
        controller.setDirectionPressed(direction, pressed); 
       } 
      } 

     } 

    } 
} 

這是一般概念的一個基本的介紹,你應該考慮探索基本OOP和博弈論

0

要處理鍵盤事件,您應創建一個實現KeyListener接口的類的實例(或者使用key bindings作爲明智的建議),並使用註冊該實例方法。

當您構建主窗口時,將創建一個Maze和一個DrawArea,但不會創建一個player,並且不會註冊任何鍵監聽器。

Maze類包含的方法如keyPressed,但它不實現KeyListener接口,所以不調用這些方法。

您有兩個類,DrawAreaplayer,它們都擴展JPanel並呈現一些東西。什麼是一起使用這些類的想法?我看到DrawArea(使用Maze)也可以渲染紅色正方形。 player中的渲染代碼是否真的需要?

要檢查是否調用特定的方法,可以使用調試器(在您感興趣的每種方法中添加斷點),也可以使用System.out.println將消息打印到控制檯。

MadProgrammer關於OOP和MVC的說法也是正確的。至少你應該用大寫字母命名班級並清理縮進。