Java постоянно перемещает спрайт во время нажатия клавиш
Я создал программу, которая создает квадрат и рисует его на JPanel. Существуют также сочетания клавиш, которые управляют движением квадрата (w вверх) (s вниз) (a слева) (d справа). Моя проблема в том, что когда я нажимаю клавиши, он перемещается на один экземпляр, колеблется, а затем продолжает двигаться. Есть ли способ предотвратить колебания движения.
import javax.swing.JFrame;
public class MovingBox extends JFrame{
Panel panel;
public static void main(String args[]){
MovingBox mb = new MovingBox();
}
public MovingBox(){
super("Moving Box");
setSize(800, 600);
setDefaultCloseOperation(EXIT_ON_CLOSE);
panel = new Panel();
add(panel);
setVisible(true);
}
}
Это мой групповой урок.
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
public class Panel extends JPanel{
Rectangle box;
public Panel(){
box = new Rectangle(100, 100, 50, 50);
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_D, 0), "move left");
getActionMap().put("move left", new MoveAction(3, 3));
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_A, 0), "move right");
getActionMap().put("move right", new MoveAction(1, 3));
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_W, 0), "move up");
getActionMap().put("move up", new MoveAction(0, 3));
getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_S, 0), "move down");
getActionMap().put("move down", new MoveAction(2, 3));
}
public void paintComponent(Graphics window){
super.paintComponent(window);
window.fillRect((int)box.getX(), (int)box.getY(), (int)box.getWidth(), (int)box.getHeight());
}
private class MoveAction extends AbstractAction{
int direction;
int speed;
public MoveAction(int direction, int speed){
this.direction = direction;
this.speed = speed;
}
public void actionPerformed(ActionEvent e){
if(direction == 0){
box.setLocation((int)box.getX(), (int)box.getY() - speed);
}else if(direction == 1){
box.setLocation((int)box.getX() - speed, (int)box.getY());
}else if(direction == 2){
box.setLocation((int)box.getX(), (int)box.getY() + speed);
}else if(direction == 3){
box.setLocation((int)box.getX() + speed, (int)box.getY());
}
repaint();
}
}
}
Любая помощь приветствуется. Благодарю вас.
2 ответа
Есть ли способ предотвратить колебания движения.
Вы можете использовать Swing Timer, чтобы запланировать анимацию. Проверьте движение с помощью клавиатуры для рабочего примера.
Чтобы получить плавное движение, вам нужно создать нить, которая обрабатывает движение.
Создайте логическую переменную для каждой клавиши (w, a, s, d) и установите ее значение true, когда клавиша нажата, и значение false, если клавиша отпущена. Просто ключевой слушатель. Не забудьте добавить слушателя в jframe и проверить, имеет ли jframe фокус.
private class InputListener implements KeyListener{
@Override
public void keyPressed(KeyEvent pressed) {
//arrow keys
if(pressed.getKeyCode() == 37){
arrowLeft = true;
}else if(pressed.getKeyCode() == 38){
arrowUp = true;
}else if(pressed.getKeyCode() == 39){
arrowRight = true;
}else if(pressed.getKeyCode() == 40){
arrowDown = true;
}
//System.out.println(pressed.getKeyCode());
}
@Override
public void keyReleased(KeyEvent released) {
if(released.getKeyCode() == 37){
arrowLeft = false;
}
if(released.getKeyCode() == 38){
arrowUp = false;
}
if(released.getKeyCode() == 39){
arrowRight = false;
}
if(released.getKeyCode() == 40){
arrowDown = false;
}
}
@Override
public void keyTyped(KeyEvent arg0) {}
}
Я использовал это для перемещения с помощью клавиш со стрелками, поэтому для перемещения wasd вам нужно изменить коды клавиш. Второе, что вам нужно, это фоновый поток, который перемещает квадрат, если нажата клавиша. Он рассчитывает движение на основе скорости и пройденного времени, поэтому он абсолютно плавный.
long currTime = 0;
long lastTime = 0;
new Thread() {
@Override
public void run() {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
while (true) {
currTime = System.currentTimeMillis();
long time = currTime - lastTime;
int movePixel = (int) (speed * time);
if (movePixel < 1 ) {
currPlayerTime -= time;
}else{
if(arrowLeft){
//move left by movePixel pixel
}else if(arrowRight){
//move right by movePixel pixel
}
if(arrowUp){
}else if(arrowDown){
}
}
lastTime = currTime;
}
}
}.start();
Возможно, это не самое простое и быстрое решение, но оно определенно лучшее:)