Я играю в тетрис, и она почти завершена. У меня проблема с KeyEvents и таймером.
My Timer вызывает actionPerformed
каждые 400 мсек, которые выпадают из блока тетриса. Проблема в том, что если я нажимаю что-то с клавиатуры (вниз, влево, вправо и т. Д.), Эти команды записываются также каждые 400 миллисекунд. Как я могу сделать вызов таймера actionPerformed
каждые 400 мс, но чтобы я мог нажимать всякий раз, когда и сколько раз я хочу что-то от клавиатуры, и это мгновенно распознается / реагирует на?
РЕДАКТИРОВАТЬ: Вот код, который люди просили
public class Game extends JPanel implements ActionListener {
public static final HashMap<Character, Color> colors = new HashMap<Character,Color>();
Timer timer;
Block kpl;
Grid gameBoard;
char[][] grid;
boolean paused = false;
public Game() {
colors.put('P', Color.blue); colors.put('S', Color.green);
colors.put('D', Color.pink); colors.put('L', Color.red);
colors.put('Z', Color.orange); colors.put('A', Color.cyan);
colors.put('T', Color.magenta);
kpl = new Block();
gameBoard = new Grid(21,10); // 21x10 sized gameboard
grid = gameBoard.getGrid();
addKeyListener(new KeyListening());
setDoubleBuffered(true);
setFocusable(true);
timer = new Timer(100, this);
timer.start();
}
@Override
public void paint(Graphics g) { // draws the current game situation
super.paint(g);
int height = getHeight()/grid.length;
int width = getWidth()/grid[0].length/2;
for (int row = 0; row < grid.length; ++row) {
for (int column = 0; column < grid[row].length; ++column) {
if (grid[row][column] == '.') { // if empty, paint white
g.setColor(Color.white);
g.fillRect(column*width, row*height , width, height);
g.setColor(Color.LIGHT_GRAY);
g.drawRect(column*width, row*height , width, height);
}
else if (grid[row][column] != '.') { // if not empty, paint with the color of the block
g.setColor(colors.get(grid[row][column]));
g.fillRect(column*width, row*height , width, height);
g.setColor(Color.BLACK);
g.drawRect(column*width, row*height , width, height);
}
}
}
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
public void actionPerformed(ActionEvent e) {
if (!gameBoard.isFallingBlock())
gameBoard.drop(kpl); // if not any falling blocks, drops a new block
gameBoard.updateView(); // moves the block down
repaint();
}
private class KeyListening extends KeyAdapter {
@Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_LEFT:
gameBoard.move("v"); // moves block left
break;
case KeyEvent.VK_RIGHT:
gameBoard.move("o"); // moves block right
break;
case KeyEvent.VK_DOWN:
gameBoard.updateView(); // moves block down
break;
case KeyEvent.VK_SPACE:
gameBoard.move("p"); // drops the block to the bottom
break;
case KeyEvent.VK_UP: // rotates block
gameBoard.move("k");
break;
case KeyEvent.VK_P: // makes the game pause
if (paused) {
timer.start();
paused = false;
return;
}
timer.stop();
paused = true;
break;
}
}
}
}
Пришлось немного перевести переменные, так как я назвал их своим языком. GUI также довольно прост, так как я сначала создал текстовую версию своего Tetris, поэтому он в основном запускает текстовую версию в фоновом режиме и просто рисует ситуацию в игре.
Сама текстовая версия представляет собой матрицу с типом символов, куда я перемещаю блоки, например:
..P..
..ppp
.....
.....
РЕШИТЬ:
Проблема решена! В public void keyPressed () после каждой команды, поступающей с клавиатуры, я просто вызывал repaint () - метод снова похож на
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
switch (key) {
case KeyEvent.VK_LEFT:
gameBoard.move("v");
repaint();
break;
Первоначально моя игра мгновенно реагировала на команды клавиатуры, но отображала текущее состояние игры каждые 400 мс в actionPerformed (), где вызывался repaint (). Теперь мои блоки можно перемещать в любое время, когда я захочу, без «задержки», и они по-прежнему стабильно падают каждые 400 мс:)