Привет, спасибо, что посмотрели мой пост. Летом я работал над интересным проектом, и эта проблема возникла. Во-первых, это может считаться повторяющимся вопросом, но я просматривал этот сайт и Oracle в поисках исправления и не смог его найти, или, что более вероятно, я просто не понимаю код, с которым работаю. Одним из основных помощников является одно судно на воздушной подушке, полное угрей, в ответ на такие вопросы, как этот .
Я хочу получить ящик JPanel
, чтобы перемещаться по JFrame
, ну и еще JPanel
, с помощью клавиш w
, a
, s
, d
. Сначала я создал свою собственную панель, расширив JPanel
. Оттуда мне удалось заставить работать движение, но есть заикание из-за того, как работают привязки клавиш, и я читал, что добавление таймера качания улучшит заикание. Первоначально я предполагаю, что я что-то реализую неправильно или недостаточно знаю о том, что делаю, чтобы увидеть свою ошибку. Я также пробовал свои силы в установке флага, чтобы помочь непрерывному движению. Сообщений об ошибках нет, и мне еще нужно кое-что реализовать, например, предотвратить выход за границы. Вот что у меня есть:
public class PlayerPanel extends JPanel {
private static final int width = 100;
private static final int height = 200;
private int xPos, yPos;
private boolean movingUp, movingDown, movingLeft, movingRight;
private static final int SPIN_TIMER_PERIOD = 20;
private Timer timer;
public PlayerPanel() {
xPos = this.getX();
yPos = this.getY();
movingUp = movingDown = movingLeft = movingRight = false;
timer = new Timer(SPIN_TIMER_PERIOD, new SpinTimerListener());
timer.setInitialDelay(0);
timer.start();
setPreferredSize(new Dimension(width, height));
setBackground(Color.cyan);
setUpKeyBindings();
}
private void setUpKeyBindings() {
int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
InputMap inMap = this.getInputMap(condition);
ActionMap actMap = this.getActionMap();
inMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "moveUp");
actMap.put("moveUp", new KeyAction("up"));
inMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "moveDown");
actMap.put("moveDown", new KeyAction("down"));
inMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "moveLeft");
actMap.put("moveLeft", new KeyAction("left"));
inMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "moveRight");
actMap.put("moveRight", new KeyAction("right"));
}
public class KeyAction extends AbstractAction {
private String direction;
private int delta = 2;
public KeyAction(String direction) {
this.direction = direction;
}
@Override
public void actionPerformed(ActionEvent e) {
switch(direction) {
case "up":
movingUp = true;
yPos -= delta;
break;
case "down":
movingDown = true;
yPos += delta;
break;
case "right":
movingRight = true;
xPos += delta;
break;
case "left":
movingLeft = true;
xPos -= delta;
break;
default:
break;
}
}
}
private class SpinTimerListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
int delta = 5;
if(movingUp) {
yPos -= delta;
movingUp = false;
}
else if(movingDown) {
yPos += delta;
movingDown = false;
}
else if(movingLeft) {
xPos -= delta;
movingLeft = false;
}
else if(movingRight) {
xPos += delta;
movingRight = false;
}
setLocation(xPos, yPos);
}
}
}
Я старался, чтобы мой код был минимальным, и это то, что я создал.
Да, есть более эффективные способы кодирования этого, например использование enum для настройки привязок клавиш, но моя философия кодирования такова:
- выяснить, что я хочу сделать, заставить его работать (обычно с тем, что я называю кодом грубой силы)
- понять, почему это работает
- сделать его лучше и красивее.
Я нахожусь в фазе понимания. Еще один очень важный момент: почему я не использую Graphics, как в Graphics g.draw (бла). ТБХ Понятия не имею. Мне не удалось заставить его работать, и мне нужно потратить больше времени на него, прежде чем я задам вопрос, связанный с ним, поскольку просить кого-нибудь научить меня, как использовать графику, здесь не кажется уместным. как и должно быть, как мне лучше реализовать привязку клавиш и таймер качания. Я думал, что использование setLocation
может быть проблемой вместо использования graphics.repaint или чего-то еще, но setLocation
вызывает перерисовку, поэтому я не думаю, что это основная проблема, но, вероятно, тем не менее. Я прошу прощения за стену с текстом, но я хочу попытаться быть внимательным, поэтому ...
TL: DR; Я делаю обычай JPanel
перемещаться с привязкой клавиш и таймером поворота. Движение заикается, и я бы тоже этого не хотел. После публикации и некоторого отдыха я объединю четыре движущихся логических значения в одно, поскольку это тоже может не помочь, и добавлю переменную состояния для направления и попытаюсь разложить свой код. Спасибо, что посмотрели мой код, и любая помощь приветствуется. Мне нравится учиться программировать и читать любое количество ссылок, которые, по вашему мнению, мне было лень искать.
Также вот мой основной код, если вы хотите запустить именно то, что я запускаю, PlayerPanel
и Класс Driver
с основным методом - это мои единственные два файла, с которыми я работаю.
public class Driver {
public static void main(String args[]) {
JFrame frame = new JFrame();
frame.setSize(1000, 500);
JPanel background = new JPanel();
background.setBackground(Color.BLACK);
PlayerPanel player = new PlayerPanel();
background.add(player);
frame.add(background);
frame.setVisible(true);
}
}