2016-01-26 19 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的说法也是正确的。至少你应该用大写字母命名班级并清理缩进。