如何根据击键更改图像

我正在为学校项目创建一个程序。 这是一个基于粉丝的神奇宝贝程序,我在理解如何根据击键更改图像时遇到一些麻烦。

这是到目前为止Character类的代码

import java.awt.Image; import java.awt.event.KeyEvent; import java.io.*; //the File class import java.util.*; //the Scanner class import javax.swing.ImageIcon; import javax.swing.JPanel; import java.awt.image.*; import javax.swing.ImageIcon; public class MainCharacter { private Image up, up1, up2, down, down1, down2, left, left1, left2, right, right1, right2; private void loadImages() { up = new ImageIcon("Up.png").getImage(); up1 = new ImageIcon("Up1.png").getImage(); up2 = new ImageIcon("Up2.png").getImage(); down = new ImageIcon("Down.png").getImage(); down1 = new ImageIcon("Down1.png").getImage(); down2= new ImageIcon("Down2.png").getImage(); left = new ImageIcon("Left.png").getImage(); left1 = new ImageIcon("Left1.png").getImage(); left2 = new ImageIcon("Left2.png").getImage(); right = new ImageIcon("Right.png").getImage(); right1 = new ImageIcon("Right1.png").getImage(); right2 = new ImageIcon("Right2.png").getImage(); } /*public Image getImage() { //dont know what to return here } */ public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_LEFT) { //dont know what to do } if (key == KeyEvent.VK_RIGHT) { //dont know what to do } if (key == KeyEvent.VK_UP) { //dont know what to do } if (key == KeyEvent.VK_DOWN) { //dont know what to do } } public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_LEFT) { //dont know what to do } if (key == KeyEvent.VK_RIGHT) { //dont know what to do } if (key == KeyEvent.VK_UP) { //dont know what to do } if (key == KeyEvent.VK_DOWN) { //dont know what to do } } } 

以下是与地图一起移动的类:

 import java.awt.Color; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import javax.swing.JPanel; import javax.swing.Timer; public class MapMovement extends JPanel implements ActionListener { private Timer timer; private Map map; private MainCharacter mainCharacter; public MapMovement() { addKeyListener(new TAdapter()); setFocusable(true); setBackground(Color.BLACK); setDoubleBuffered(true); map = new Map(); timer = new Timer(5, this); timer.start(); } public void paint(Graphics g) { super.paint(g); Graphics2D g2d = (Graphics2D)g; g2d.drawImage(map.getImage(), map.getX(), map.getY(), 1000, 1500, this); Toolkit.getDefaultToolkit().sync(); g.dispose(); } public void actionPerformed(ActionEvent e) { map.move(); repaint(); } private class TAdapter extends KeyAdapter { public void keyReleased(KeyEvent e) { map.keyReleased(e); //mainCharacter.keyReleased(e); } public void keyPressed(KeyEvent e) { map.keyPressed(e); //mainCharacter.keyPressed(e); } } 

}

更新:

这是Map类

 import java.awt.Image; import java.awt.event.KeyEvent; import javax.swing.ImageIcon; public class Map { private String map = "Map-1stCity.png"; private int dx; private int dy; private int x; private int y; private Image image; public Map() { ImageIcon ii = new ImageIcon(this.getClass().getResource(map)); image = ii.getImage(); x = -100; y = -100; } public void move() { x += dx; y += dy; } public int getX() { return x; } public int getY() { return y; } public Image getImage() { return image; } public void keyPressed(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_LEFT) { dx = 1; } if (key == KeyEvent.VK_RIGHT) { dx = -1; } if (key == KeyEvent.VK_UP) { dy = 1; } if (key == KeyEvent.VK_DOWN) { dy = -1; } } public void keyReleased(KeyEvent e) { int key = e.getKeyCode(); if (key == KeyEvent.VK_LEFT) { dx = 0; } if (key == KeyEvent.VK_RIGHT) { dx = 0; } if (key == KeyEvent.VK_UP) { dy = 0; } if (key == KeyEvent.VK_DOWN) { dy = 0; } } } 

提前感谢您的帮助!

概观

基本上,您将需要知道当前的键状态和当前帧(基于每个位置有两个图像的事实)。

有了这些信息,您就可以确定应该显示哪个角色图像。

这个例子非常简单,它演示了使用KeyListener的键绑定API ,因为它解决了处理焦点的问题。 它还演示了通过单个基本Action修改当前状态是多么容易

示例的MainCharacter有一个单独的方法(感兴趣),用于根据当前KeyState (本例中的enum )和当前frame确定应显示哪个图像。

getCharacter方法每10帧切换一次图像,以便在当前位置之间提供动画…

步行

 import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.imageio.ImageIO; 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 Character { public static void main(String[] args) { new Character(); } public Character() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new GamePane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class GamePane extends JPanel { private MainCharacter mc; private KeyState keyState; private int frame; public GamePane() { mc = new MainCharacter(); Timer timer = new Timer(40, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { frame++; if (frame > 100) { frame = 0; } repaint(); } }); timer.start(); InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0), "Up"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0), "Down"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "Left"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "Right"); ActionMap am = getActionMap(); am.put("Up", new KeyStateAction(KeyState.UP)); am.put("Down", new KeyStateAction(KeyState.DOWN)); am.put("Left", new KeyStateAction(KeyState.LEFT)); am.put("Right", new KeyStateAction(KeyState.RIGHT)); } @Override public Dimension getPreferredSize() { return new Dimension(200, 200); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); Image img = mc.getCharacter(keyState, frame); int x = (getWidth() - img.getWidth(this)) / 2; int y = (getHeight() - img.getHeight(this)) / 2; g2d.drawImage(img, x, y, this); g2d.dispose(); } public class KeyStateAction extends AbstractAction { private KeyState state; public KeyStateAction(KeyState state) { this.state = state; } @Override public void actionPerformed(ActionEvent e) { keyState = state; } } } public enum KeyState { UP, DOWN, LEFT, RIGHT; } public class MainCharacter { private Map> mapImage; public MainCharacter() { mapImage = new HashMap<>(25); try { mapImage.put(KeyState.UP, loadImages("Up")); mapImage.put(KeyState.DOWN, loadImages("Down")); mapImage.put(KeyState.LEFT, loadImages("Left")); mapImage.put(KeyState.RIGHT, loadImages("Right")); } catch (IOException exp) { exp.printStackTrace(); } } protected List loadImages(String name) throws IOException { List images = new ArrayList<>(25); images.add(ImageIO.read(new File(name + "1.png"))); images.add(ImageIO.read(new File(name + "2.png"))); return images; } public Image getCharacter(KeyState keyState, int frame) { Image img = null; List images = mapImage.get(keyState); if (images == null) { images = mapImage.get(KeyState.DOWN); } int index = (frame / 10) % 2 == 0 ? 0 : 1; img = images.get(index); return img; } } } 

正如我在评论中所说,不要在你没有创建的Graphics上下文中调用dispose ,因为这不仅会影响你正在绘制的内容,还会影响你之后绘制的内容。