这是我第一次用Java编写游戏。我正在制作一款RPG游戏。我已经成功地移动了我的角色与使用KeyListener功能的箭头键。然而,当鼠标在窗口点击时,我一直试图将我的角色移向鼠标。我已经弄清楚它可以使用mouseclick函数,但我似乎不能在我的代码中实现它。我一直在试图理解正确的方法来布置它,但互联网上所有不同的代码让我越来越困惑。我上传我的播放器类与小代码我对鼠标适配器。任何帮助与实施它将不胜感激。
import java.awt.Graphics;
import java.awt.event.KeyListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseAdapter;
public class Player implements KeyListener {
private int x,y;
private SpriteSheet ss;
private boolean up = false, down = false, left= false, right = false;
public boolean mouseActive = false; // mouse
public Point mouse; // mouse
private final int SPEED = 3;
public Player( int x, int y, SpriteSheet ss) {
this.x = x;
this.y = y;
this.ss = ss;
}
public void tick() {
if(up) {
y-=SPEED;
}
if (down) {
y+=SPEED;
}
if (left){
x-=SPEED;
}
if (right) {
x+=SPEED;
}
}
public void render( Graphics g) {
g.drawImage(ss.crop(0,0,16,16), x, y, 16* Game.SCALE, 16* Game.SCALE, null);
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
up = true;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
down = true;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
left = true;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
right = true;
}
if (e.getKeyCode() == KeyEvent.VK_M) { // mouse
mouseActive = true;
}
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
up = false;
}
if (e.getKeyCode() == KeyEvent.VK_DOWN) {
down = false;
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
left = false;
}
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
right = false;
}
if (e.getKeyCode() == KeyEvent.VK_M) {
mouseActive = false;
}
}
// this is where I have been trying to add mouseClicked function to my code
addMouseListener( new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
mouse = new Point(e.getX(), e.getY() - 25);
if(e.getButton() == MouseEvent.BUTTON1 && !mouseActive) {
x = mouse.x;
y = mouse.y;
}
}
});
}
编译错误:发现5个错误:
文件:/Users/welcome/Documents/Player.java [line: 11]错误:/Users/welcome/Documents/Player.java:11: Player不是抽象的,没有覆盖java.awt.event.KeyListener中的抽象方法keyTyped(java.awt.event.KeyEvent)
文件:/Users/welcome/Documents/Player.java [line: 18]错误:/Users/welcome/Documents/Player.java:18: cannot find symbol符号:classlocation: class Player
文件:/Users/welcome/Documents/Player.java [line: 112]错误:/Users/welcome/Documents/Player.java:112: cannot find symbol类MouseEventlocation: class Player
文件:/Users/welcome/Documents/Player.java [line: 113]错误:/Users/welcome/Documents/Player.java:113: cannot find symbol符号:classlocation: class Player
文件:/Users/welcome/Documents/Player.java [line: 115]错误:/Users/welcome/Documents/Player.java:115:找不到符号变量MouseEventlocation: class Player
这是概念的证明。这个想法是,角色将总是试图移动到一个给定的点(在本例中是target
)。
键盘控制元素被设计成在按下目标时将目标从当前玩家位置移动指定距离。
鼠标控制元素简单地将目标移动到鼠标单击的位置。
主引擎只是试图驱动字符到达那个点。
在这个例子中,键盘操作覆盖鼠标操作
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
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 MoveMe {
public static void main(String[] args) {
new MoveMe();
}
public MoveMe() {
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 Surface());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public enum KeyControl {
UP, DOWN, LEFT, RIGHT
}
public class Surface extends JPanel {
private Character character;
private Point target;
private int xDelta = 2;
private int yDelta = 2;
private Set<KeyControl> keyControls;
public Surface() {
keyControls = new HashSet<>(4);
character = new Character(new Rectangle(95, 95, 10, 10));
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
processKeyCommands();
if (target != null) {
Rectangle bounds = character.getBounds();
Point cp = new Point(bounds.getLocation());
cp.x += bounds.width / 2;
cp.y += bounds.height / 2;
if (!cp.equals(target)) {
if (cp.x != target.x) {
if (target.x < cp.x) {
cp.x -= xDelta;
if (cp.x < target.x) {
cp.x = target.x;
}
} else {
cp.x += xDelta;
if (cp.x > target.x) {
cp.x = target.x;
}
}
}
if (target.y != cp.y) {
if (target.y < cp.y) {
cp.y -= yDelta;
if (cp.y < target.y) {
cp.y = target.y;
}
} else {
cp.y += yDelta;
if (cp.y > target.y) {
cp.y = target.y;
}
}
}
bounds.x = cp.x - bounds.width / 2;
bounds.y = cp.y - bounds.height / 2;
if (bounds.x < 0) {
bounds.x = 0;
} else if (bounds.x + bounds.width > getWidth()) {
bounds.x = getWidth() - bounds.width;
}
if (bounds.y < 0) {
bounds.y = 0;
} else if (bounds.y + bounds.height > getHeight()) {
bounds.y = getHeight() - bounds.height;
}
} else {
target = null;
}
}
repaint();
}
});
timer.start();
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
target = e.getPoint();
}
});
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "pressUp");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "pressDown");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "pressLeft");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "pressRight");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "releaseUp");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "releaseDown");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "releaseLeft");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "releaseRight");
ActionMap am = getActionMap();
am.put("pressUp", new KeyStateAction(keyControls, KeyControl.UP, true));
am.put("pressDown", new KeyStateAction(keyControls, KeyControl.DOWN, true));
am.put("pressLeft", new KeyStateAction(keyControls, KeyControl.LEFT, true));
am.put("pressRight", new KeyStateAction(keyControls, KeyControl.RIGHT, true));
am.put("releaseUp", new KeyStateAction(keyControls, KeyControl.UP, false));
am.put("releaseDown", new KeyStateAction(keyControls, KeyControl.DOWN, false));
am.put("releaseLeft", new KeyStateAction(keyControls, KeyControl.LEFT, false));
am.put("releaseRight", new KeyStateAction(keyControls, KeyControl.RIGHT, false));
}
protected Point createTargetBasedOnCharacter() {
target = new Point();
Rectangle bounds = character.getBounds();
target.x = bounds.x + bounds.width / 2;
target.y = bounds.y + bounds.height / 2;
return target;
}
protected void processKeyCommands() {
if (keyControls.contains(KeyControl.UP)) {
Point target = createTargetBasedOnCharacter();
target.y -= xDelta;
} else if (keyControls.contains(KeyControl.DOWN)) {
Point target = createTargetBasedOnCharacter();
target.y += xDelta;
}
if (keyControls.contains(KeyControl.LEFT)) {
Point target = createTargetBasedOnCharacter();
target.x -= xDelta;
} else if (keyControls.contains(KeyControl.RIGHT)) {
Point target = createTargetBasedOnCharacter();
target.x += xDelta;
}
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (target != null) {
g2d.setColor(Color.RED);
g2d.fillOval(target.x - 5, target.y - 5, 10, 10);
}
character.render(g2d);
g2d.dispose();
}
}
public class Character {
private Rectangle bounds;
public Character(Rectangle bounds) {
this.bounds = bounds;
}
public Rectangle getBounds() {
return bounds;
}
public void render(Graphics2D g) {
g.setColor(Color.BLUE);
g.fill(getBounds());
}
}
public class KeyStateAction extends AbstractAction {
private final Set<KeyControl> keyControls;
private final KeyControl keyControl;
private final boolean pressed;
private KeyStateAction(Set<KeyControl> keyControls, KeyControl keyControl, boolean pressed) {
this.keyControls = keyControls;
this.keyControl = keyControl;
this.pressed = pressed;
}
@Override
public void actionPerformed(ActionEvent e) {
if (pressed) {
keyControls.add(keyControl);
} else {
keyControls.remove(keyControl);
}
}
}
}
这个例子使用了键绑定API,它可以更好地控制触发键事件所需的焦点级别。
我还将实体(Character
)与控件解耦。这是,键盘和鼠标控制和管理的Surface
,作为,恕我直言,玩家实体应该不知道。这集中了控制,意味着字符可以通过你想添加的任何输入来移动。