如何更新图形
How to update the graphics
How do you update graphics everytime you use wasd keys? Right now my player cant move and i want to update the grid everytime the player moves using one of those keys. How do i implement and update each time player when ever the arrow keys are being pressed. I have made the class but it doesnt seem to move whenever the keys are pressed.How can i implement movement and update the grid each time a key is being pressed. I did the code but the player doesnt seem to move.Can anyone tell me what i am doing wrong?
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){}
好吧,让我们从一些问题开始吧...
class www extends JFrame
首先,您应该避免覆盖 JFrame
,您没有向 class 添加任何新功能,将自己锁定在一个用例中,运行 其他的风险难以诊断的问题。
您的 class 名字确实应该以大写字母开头。通读 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 Swing and Performing Custom Painting
此外,绘制自身不是迷宫的责任,由视图决定如何最好地表示 model/maze
下一个...
public class player extends JPanel implements ActionListener,KeyListener
{
//...
}
好吧,这个class根本没用过,但这是你唯一一次注册一个KeyListener
。您还使过程过于复杂,因为 DrawArea
还应该负责绘制播放器和处理用户输入。
根据一般经验,KeyListener
不是合适的 API,原因有很多。您最好使用 Key Bindings API,它解决了 KeyListener
的问题,并且可以更轻松地更改和实施其他输入设备。
你的代码通常不关注孤立的责任,为什么 player
允许改变玩家的位置?
OOP 的一个关键方面是关于隔离责任,这使得更改事物更容易而不会对系统的其余部分产生不利影响,Model-View-Controller 范例也支持这一点。
基本思想是,您的模型控制数据、维护状态并定义可以更改数据的规则(并可以根据需要提供事件通知)。视图负责呈现模型的状态。控制器是将它们粘合在一起的粘合剂。
通常在 MVC 中,模型和视图从不相互通信,充当它们之间的管道是控制器的责任。这可以直接实现(直接调用控制器)或更常见地通过使用 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 想法的开始,它允许您更好地解耦代码,因为您不依赖于 classes 的物理实现,而只是它们的协议维持给定的合同。
接下来,我们定义实现....
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);
}
}
}
}
好吧,这样一个简单的问题可能看起来有点奇怪,但要知道想象一下你想要添加更多的迷宫,这就像改变模型一样简单。
最后,我们需要把它放在一起...
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 和博弈论
要处理键盘事件,您应该创建一个实现 KeyListener
接口的 class 实例(或者像其他人明智地建议的那样使用 key bindings )并使用 addKeyListener
方法。
当你构造你的 main window 时,你创建了一个 Maze
和一个 DrawArea
,但你没有创建一个 player
,并且没有关键监听器是已注册。
Maze
class包含keyPressed
等方法,但没有实现KeyListener
接口,所以没有调用这些方法
您有两个 class,DrawArea
和 player
,它们都扩展了 JPanel 并渲染了一些东西。一起使用这些 class 有什么想法?我看到 DrawArea
(使用 Maze
)也可以呈现红色方块。 player
中的渲染代码真的需要吗?
要检查特定方法是否被调用,您可以使用调试器(在您感兴趣的每个方法中添加断点),或者您可以使用 System.out.println
.[=25= 将消息打印到控制台]
MadProgrammer 所说的 OOP 和 MVC 也都是正确的。至少你应该用大写字母命名 classes 并清理缩进。
How do you update graphics everytime you use wasd keys? Right now my player cant move and i want to update the grid everytime the player moves using one of those keys. How do i implement and update each time player when ever the arrow keys are being pressed. I have made the class but it doesnt seem to move whenever the keys are pressed.How can i implement movement and update the grid each time a key is being pressed. I did the code but the player doesnt seem to move.Can anyone tell me what i am doing wrong?
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){}
好吧,让我们从一些问题开始吧...
class www extends JFrame
首先,您应该避免覆盖 JFrame
,您没有向 class 添加任何新功能,将自己锁定在一个用例中,运行 其他的风险难以诊断的问题。
您的 class 名字确实应该以大写字母开头。通读 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 Swing and Performing Custom Painting
此外,绘制自身不是迷宫的责任,由视图决定如何最好地表示 model/maze
下一个...
public class player extends JPanel implements ActionListener,KeyListener
{
//...
}
好吧,这个class根本没用过,但这是你唯一一次注册一个KeyListener
。您还使过程过于复杂,因为 DrawArea
还应该负责绘制播放器和处理用户输入。
根据一般经验,KeyListener
不是合适的 API,原因有很多。您最好使用 Key Bindings API,它解决了 KeyListener
的问题,并且可以更轻松地更改和实施其他输入设备。
你的代码通常不关注孤立的责任,为什么 player
允许改变玩家的位置?
OOP 的一个关键方面是关于隔离责任,这使得更改事物更容易而不会对系统的其余部分产生不利影响,Model-View-Controller 范例也支持这一点。
基本思想是,您的模型控制数据、维护状态并定义可以更改数据的规则(并可以根据需要提供事件通知)。视图负责呈现模型的状态。控制器是将它们粘合在一起的粘合剂。
通常在 MVC 中,模型和视图从不相互通信,充当它们之间的管道是控制器的责任。这可以直接实现(直接调用控制器)或更常见地通过使用 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 想法的开始,它允许您更好地解耦代码,因为您不依赖于 classes 的物理实现,而只是它们的协议维持给定的合同。
接下来,我们定义实现....
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);
}
}
}
}
好吧,这样一个简单的问题可能看起来有点奇怪,但要知道想象一下你想要添加更多的迷宫,这就像改变模型一样简单。
最后,我们需要把它放在一起...
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 和博弈论
要处理键盘事件,您应该创建一个实现 KeyListener
接口的 class 实例(或者像其他人明智地建议的那样使用 key bindings )并使用 addKeyListener
方法。
当你构造你的 main window 时,你创建了一个 Maze
和一个 DrawArea
,但你没有创建一个 player
,并且没有关键监听器是已注册。
Maze
class包含keyPressed
等方法,但没有实现KeyListener
接口,所以没有调用这些方法
您有两个 class,DrawArea
和 player
,它们都扩展了 JPanel 并渲染了一些东西。一起使用这些 class 有什么想法?我看到 DrawArea
(使用 Maze
)也可以呈现红色方块。 player
中的渲染代码真的需要吗?
要检查特定方法是否被调用,您可以使用调试器(在您感兴趣的每个方法中添加断点),或者您可以使用 System.out.println
.[=25= 将消息打印到控制台]
MadProgrammer 所说的 OOP 和 MVC 也都是正确的。至少你应该用大写字母命名 classes 并清理缩进。