带 Swing 的 keyListener 和带 Swing/keyListener 和 Thread 的游戏关卡系统

keyListener with Swing and game level system with Swing/keyListener and Thread

我是一名新手编码员,大约 10 年前有一点点 C++ 经验,现在正在学习 java(大约 4-5 个月)。我有一个小的协作项目正在进行,我有一些事情要弄清楚。

代码如下:

import java.awt.event.*;
import java.awt.*;

import javax.swing.JFrame;

import java.util.Scanner;
import java.util.Random;

public class Game extends JFrame {


    GamePanel panel;
    int[][] grid;
    int size;

    //...and some other variables

    public Game(String title) {

        super(title);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        panel = new GamePanel(grid,size);
        this.add(panel);

        Button button = new Button("WHAT");
        button.setBounds(-100, -100, 70, 70);
        this.add(button);
        button.addKeyListener(new KeyHandler());

    }

    class KeyHandler extends KeyAdapter {

        public void keyPressed(KeyEvent e) {

            int keycode = e.getKeyCode();

            switch(keycode) {

                //arrow keys input and stuff

            }

            if(checkForWin())  //checkForWin() returns a boolean value for win/loss
                //won the game, thus end the thread here

            if(checkForLoss()) // similar stuff as checkForLoss()
                //lost the game, thus end the thread here

            //...update the panel
            panel.repaint();

        }

    }

    public static void main(String [] args) {

        Game me = new Game("GAME");

        me.setVisible(true);

    }

}

这就是整个游戏的样子。

我有问题:

  1. 我正在使用一个按钮并将其放在负位置以使其不可见并将其用作 KeyListener 的手段。还有其他方法可以添加关键监听器吗?例如)到面板或其他东西?

  2. 我想改成每个"level"一个线程,弄成这样

    public static void main(String [] args) {
    
        int level = 1;
    
        do {
    
            GameThread gt = new GameThread("Game");
    
            // run() will have the game constructor inside
    
            gt.setLevel(level);
            gt.start();
            gt.join();       //wait until the game "level" is finished
    
            if(won)
                level++;
    
            if(lost)
                level = 1;
    
        } while(!checkIfDonePlaying())
    
    }
    

有点像这样。我无法让线程继续 运行 直到游戏关卡真正完成。我该怎么做?

  1. 我想添加一个 JLabel 来在框架上显示分数。但是当我这样做时,当我重绘()它时,分数不会更新。我该怎么做?

提前致谢!

这是第一个问题的解决方案:

panel.setFocusable(true);
panel.addKeyListener(this);

那么您应该就可以执行通常的关键侦听器方法了。一定要实现 KeyListener! 其他问题的解决方案正在路上。 (实际上采纳@TNT 的建议并使用键绑定,我更喜欢听众,但对于游戏我通常使用 lwjgl 或 slick2d)

2.

我觉得 运行 宁你的程序水平可能有点低效(可能只是我)我建议在 运行 方法中有一个线程并具有以下内容:

Public void reset(int level)
 {
   //reset all variables based on local variable level...

}

这样称呼它:

Reset(++currentLevel)); //use ++ before currentLevel so it adds to it and then resets

如果需要,您可以轻松地使用 switch case 来做一些特殊的事情

Switch(level){
case 1: //...
}

等等。 (我正在手机上打字,抱歉出现了奇怪的大写字母)

几件事:

  1. 是的,有一种方法可以将 KeyListener 添加到面板,那就是使用 key bindings。例如:

    javax.swing.InputMap im = panel.getInputMap(panel.WHEN_IN_FOCUSED_WINDOW);
    javax.swing.ActionMap am = panel.getActionMap();
    
    im.put(javax.swing.KeyStroke.getKeyStroke("pressed UP"), "up");
    am.put("up", new javax.swing.AbstractAction() {
        @Override
        public void actionPerformed(ActionEvent ev) {
            // handle up arrow key action here
        }
    });
    
  2. Swing是一个事件驱动的环境,所以不应该使用do-while循环。相反,请使用 Swing 计时器定期检查您的关卡是否已完成。

  3. 因为你没有在你的 JLabel 上做任何自定义绘画,你不应该使用 repaint。相反,使用它的 setText 方法。