2

所以嘿,我正在尝试根据 Tron 的光周期制作一个简单的游戏。它有3个类:带有main方法的驱动程序(LightCycleRunner),一个LightCycle类,存储每个光循环的坐标和方向,以及绘制和处理绘制背景后的运动的类。一切都很好,只是关键听众直到比赛结束后才会听。我试图通过创建一个新线程来运行游戏来解决这个问题,这样关键的监听器仍然会监听,但现在我的图形无法被识别。你有什么意见?

这是 LightCycleRunner.java

import java.awt.Event;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JFrame;

public class LightCycleRunner extends JFrame{

    /**
     *@param WIDTH the width of the window.
     *@param HEIGHT the height of the window.
     */
    private static final int WIDTH = 617;
    private static final int HEIGHT = 639;


    public LightCycleRunner()
    {
        super("Light Cycles");
        addKeyListener(this);
        setSize(WIDTH,HEIGHT);
        Grid obj = new Grid();
        getContentPane().add(obj);
        obj.giveCycles(cycle1, cycle2);
        setFocusable(true);
        setVisible(true);
    }

    public static void main( String args[] )
    {
        run();
    }
    public void run() {
            LightCycleRunner run = new LightCycleRunner();
            window = this.getGraphics();
        }

    public boolean handleEvent(Event e) {
        if (e.id == Event.KEY_PRESS) {
            System.out.println("pressed!!!!!!!!!!");
        } else if (e.id == Event.KEY_RELEASE) {
            System.out.println("pressed!!!!!!!!!!");
        }
        return false;
    }
}

这是 Grid.java

import java.awt.*;
import javax.swing.JFrame;
import java.awt.event.*;

public class Grid extends Canvas implements KeyListener, Runnable{

    final int FRAME_WIDTH = 600;
    final int FRAME_HEIGHT = 600;
    final int SQUARE_WIDTH = 20;
    final int SQUARE_HEIGHT = 20;
    final long WAITING_TIME = 300;
    Grid griddy = new Grid();
    Graphics window = griddy.getGraphics();
    griddy.paint(Graphics griddy);

    //to determine if the lightcycle will crash or not
    private boolean[][] instanceGrid = new boolean[30][30];
    //the two light players will control these light cycles
    LightCycle redCycle = new LightCycle(0,0,15);
    LightCycle blueCycle = new LightCycle(2,29,15);

    public void Grid(){
        setSize(FRAME_WIDTH,FRAME_HEIGHT);
        setBackground(Color.black);
        addKeyListener(this);
        setVisible(true);
        setFocusable(true);
    }

    public void giveCycles(LightCycle c1, LightCycle c2){
        redCycle = c1;
        blueCycle = c2;
    }

    public void run(){
        paint(this.getGraphics());
    }

    public void paint(Graphics window){
        /*
         *Draws Grid
         */
        window.setColor(Color.black);
        window.fillRect(0,0,600,600);
        //vertical lines
        window.setColor(Color.gray);
        for(int x = 0; x <= FRAME_WIDTH; x+=SQUARE_WIDTH){  
            window.drawLine(x,0,x,600);
        }
        //horizontal lines
        for(int y = 0; y <= FRAME_HEIGHT; y+=SQUARE_HEIGHT){
            window.drawLine(0,y,600,y);
        }

        //starting positions
        //red Cycle
        instanceGrid[redCycle.getY()][redCycle.getX()] = true;
        //blue Cycle
        instanceGrid[blueCycle.getY()][blueCycle.getX()] = true;

        public static void main(String[]args)
    {

        JFrame jp1 = new JFrame();
        Grid a=new Grid ();
        jp1.getContentPane().add(a, BorderLayout.CENTER);
        jp1.setSize(new Dimension(500,500));
        jp1.setVisible(true);

    }

        /*
         *Process pieces
         */
        new Thread() {
            public void run(){
                while(redCycle.isAlive()&&blueCycle.isAlive()){
                    //waiting period
                    System.out.println("***cycle started***");
                    this.getGraphics() = window;

                    try{
                        Thread.sleep(WAITING_TIME);
                    }
                    catch(InterruptedException e){
                        e.printStackTrace();
                    }
                    //testing instanceGrid[][] for bugs
                    for(int row = 0; row < instanceGrid[0].length; row++){
                        for(int column = 0; column < instanceGrid.length; column++){
                            if(instanceGrid[row][column])
                                System.out.print("-");
                            else System.out.print("0");
                        }
                        System.out.println();
                    }
                    //red checks for obstructions
                    boolean redObstructed = false;
                    try{
                        switch(redCycle.getDirection()){
                            case 0: if(instanceGrid[redCycle.getY()][redCycle.getX()+1] == true)
                                //System.out.println(redCycle.getX()+1+","+redCycle.getY());
                                redObstructed = true; break;
                            case 1: if(instanceGrid[redCycle.getY()-1][redCycle.getX()] == true)
                                //System.out.println(redCycle.getX()+","+(redCycle.getY()-1));
                                redObstructed = true; break;
                            case 2: if(instanceGrid[redCycle.getY()][redCycle.getX()-1] == true)
                                //System.out.println(redCycle.getX()-1+","+redCycle.getY());
                                redObstructed = true; break;
                            case 3: if(instanceGrid[redCycle.getY()+1][redCycle.getX()] == true)
                                //System.out.println(redCycle.getX()+","+redCycle.getY()+1);
                                redObstructed = true; break;
                        }
                    }
                    catch(IndexOutOfBoundsException e){
                        redObstructed = true;
                    }


                    //kill red if crashed
                    if (redObstructed == true)
                        redCycle.kill();

                    //move and draw trails
                    if(redCycle.isAlive()){
                        //move
                        window.setColor(Color.red);
                        int x = redCycle.getX()*20+1;
                        int y = redCycle.getY()*20+1;
                        window.fillRect(x,y,SQUARE_WIDTH-1,SQUARE_HEIGHT-1);
                        redCycle.move();
                        instanceGrid[redCycle.getY()][redCycle.getX()] = true;
                        //window.drawLine(x1,y1,x2,y2);
                        x = redCycle.getX()*20+1;
                        y = redCycle.getY()*20+1;   

                        switch(redCycle.getDirection()){
                            case 0:
                                //update instanceGrid[][]
                                //draw triangle pointing right
                                //window.drawString("0",35,35);
                                window.drawLine(x,y,x,y+18);
                                window.drawLine(x,y,x+18,y+9);
                                window.drawLine(x,y+18,x+18,y+9);
                            break;
                            case 1:
                                //draw triangle pointing up
                                //window.drawString("1",35,35);
                                window.drawLine(x+9,y,x,y+18);
                                window.drawLine(x,y+18,x+18,y+18);
                                window.drawLine(x+9,y,x+18,y+18);
                            break;
                            case 2:
                                //draw triangle pointing left
                                //window.drawString("2",35,35);
                                window.drawLine(x+18,y,x+18,y+18);
                                window.drawLine(x,y+9,x+18,y);
                                window.drawLine(x,y+9,x+18,y+18);
                            break;
                            case 3:
                                //draw triangle pointing down
                                //window.drawString("3",35,35);
                                window.drawLine(x,y,x+18,y);
                                window.drawLine(x,y,x+9,y+18);
                                window.drawLine(x+18,y,x+9,y+18);
                            break;
                        }
                            //draw trails
                    }

                    boolean blueObstructed = false;
                    try{
                        switch(blueCycle.getDirection()){
                            case 0: if(instanceGrid[blueCycle.getY()][blueCycle.getX()+1] == true)
                                blueObstructed = true; break;
                            case 1: if(instanceGrid[blueCycle.getY()-1][blueCycle.getX()] == true)
                                blueObstructed = true; break;
                            case 2: if(instanceGrid[blueCycle.getY()][blueCycle.getX()-1] == true)
                                blueObstructed = true; break;
                            case 3: if(instanceGrid[blueCycle.getY()+1][blueCycle.getX()] == true)
                                blueObstructed = true; break;
                        }
                    }
                    catch(IndexOutOfBoundsException e){
                        blueObstructed = true;
                    }
                    if(blueObstructed == true)
                        blueCycle.kill();
                    if(blueCycle.isAlive()){
                        //move
                        window.setColor(Color.blue);
                        int x = blueCycle.getX()*20+1;
                        int y = blueCycle.getY()*20+1;
                        window.fillRect(x,y,SQUARE_WIDTH-1,SQUARE_HEIGHT-1);
                        blueCycle.move();
                        instanceGrid[blueCycle.getY()][blueCycle.getX()] = true;
                        //window.drawLine(x1,y1,x2,y2);
                        x = blueCycle.getX()*20+1;
                        y = blueCycle.getY()*20+1;

                        switch(blueCycle.getDirection()){
                            case 0:
                                //update instanceGrid[][]
                                //draw triangle pointing right
                                //window.drawString("0",35,35);
                                window.drawLine(x,y,x,y+18);
                                window.drawLine(x,y,x+18,y+9);
                                window.drawLine(x,y+18,x+18,y+9);
                            break;
                            case 1:
                                //draw triangle pointing up
                                //window.drawString("1",35,35);
                                window.drawLine(x+9,y,x,y+18);
                                window.drawLine(x,y+18,x+18,y+18);
                                window.drawLine(x+9,y,x+18,y+18);
                            break;
                            case 2:
                                //draw triangle pointing left
                                //window.drawString("2",35,35);
                                window.drawLine(x+18,y,x+18,y+18);
                                window.drawLine(x,y+9,x+18,y);
                                window.drawLine(x,y+9,x+18,y+18);
                            break;
                            case 3:
                                //draw triangle pointing down
                                //window.drawString("3",35,35);
                                window.drawLine(x,y,x+18,y);
                                window.drawLine(x,y,x+9,y+18);
                                window.drawLine(x+18,y,x+9,y+18);
                            break;
                        }
                            //draw trails
                    }
                    if(!(blueCycle.isAlive()||redCycle.isAlive())){
                        window.setColor(Color.white);
                        window.drawString("TIE",200,300);
                        System.out.println("TIE!");
                    }
                    else if(!blueCycle.isAlive()){
                        window.setColor(Color.white);
                        window.drawString("RED WINS!",200,300);
                        System.out.println("RED WINS!");
                    }
                    else{
                        window.setColor(Color.white);
                        window.drawString("BLUE WINS!",300,300);
                        System.out.println("BLUE WINS!");
                    }
                }
            }
        }.start();
    }
     /**
     *changes the direction of the light cycles according to which key was pressed
     */  
    public void keyPressed(KeyEvent e) {
        //System.out.println("KEY PRESSED");
        if(e.getKeyCode() == KeyEvent.VK_W)
        {redCycle.setDirection(1);
        System.out.println("RED UP");}
        else if(e.getKeyCode() == KeyEvent.VK_A)
        {redCycle.setDirection(2);
        System.out.println("RED LEFT");}
        else if(e.getKeyCode() == KeyEvent.VK_S)
        {redCycle.setDirection(3);
        System.out.println("RED DOWN");}
        else if(e.getKeyCode() == KeyEvent.VK_D)
        {redCycle.setDirection(0);
        System.out.println("RED RIGHT");}
        else if(e.getKeyCode() == KeyEvent.VK_UP)
        {blueCycle.setDirection(1);
        System.out.println("BLUE UP");}
        else if(e.getKeyCode() == KeyEvent.VK_LEFT)
        {blueCycle.setDirection(2);
        System.out.println("BLUE LEFT");}
        else if(e.getKeyCode() == KeyEvent.VK_DOWN)
        {blueCycle.setDirection(3);
        System.out.println("BLUE DOWN");}
        else if(e.getKeyCode() == KeyEvent.VK_RIGHT)
        {blueCycle.setDirection(0);
        System.out.println("BLUE RIGHT");}
    }

    public void keyReleased(KeyEvent e) {
        //System.out.println("KEY RELEASED");
    }

    public void keyTyped(KeyEvent e) {
        //System.out.println("KEY TYPED");
    }

}

这是 LightCycle.java

import java.awt.event.*;

public class LightCycle{

    /* Cardinal directions
     * 0 = right
     * 1 = up
     * 2 = left
     * 3 = down 
     */
     /**
      *@param direction the cardinal direction the light cycle is facing (0=right, 1=up).
      *@param x the x coordinate from the left of the grid; 0 being the leftmost column.
      *@param y the y coordinate from the top of the grid; 0 being the top row.
      *@param alive whether or not the lightcycle has crashed or not
      */
    int direction;
    int x;
    int y;
    boolean alive = true;

    public LightCycle() {
        direction = 1;
        x = 0;
        y = 0;
    }

    /**
     *@param d the beginning direction the light cycle is facing
     *@param x1 the starting x coordinate.
     *@param y1 the starting y coordinate.
     */
    public LightCycle(int d, int x1, int y1) {
        direction = d;
        x = x1;
        y = y1;
    }


    /**
     *Changes the direction the light cycle is facing
     *@param d the new direction the light cycle will travel.
     */
    public void setDirection(int d){
        direction = d;
    }

   /**
    *changes either the x or y coordinates by 1 according to the direction 
    */
    public void move(){
        switch(direction){
            case 0: x++; break;
            case 1: y-- ; break;
            case 2: x--; break;
            case 3: y++; break;
        }
    } 
    /**
     *Sets alive to false.
     */
    public void kill(){
        alive = false;
    }

    /**
     *@return the direction the cycle is currently facing.
     */
    public int getDirection(){
        return direction;
    }

    /**
     *@return the current x coordinate.
     */
    public int getX(){
        return x;
    }

    /**
     *@return the current y coordinate.
     */
    public int getY(){
        return y;
    }

    /**
     *@return whether or not the lightcycle has crashed
     */
    public boolean isAlive(){
        return alive;
    }

}
4

1 回答 1

2

在我的评论中正式提出我的建议:

  • 不要将 AWT 组件与 Swing 组件不必要地混合为
    • 您将在一个 GUI 中混合使用重型和轻型组件,如果操作不当可能会导致副作用
    • 您将失去 Swing 默认双缓冲的优势。
  • 在 JComponent 或 JPanel 的paintComponent(...)方法中进行绘图,而不是paint(...)方法。同样,这将为您提供 Swing 的默认双缓冲的优势。
  • 不要通过调用getGraphics()组件来获取您的 Graphics 对象,因为这将返回一个短暂的对象,该对象将很快变为 null,从而导致图像不稳定。'
    • 将背景图像绘制到 BufferedImage 会更好,但请注意,调用getGraphics()来获取 BufferedImage 的 Graphics 对象是可以的,但不要忘记在完成后处理它。
    • 然后通过调用JVM 传递给 paintComponent(Graphics g) 方法参数的 Graphics 对象,在paintComponent(...)覆盖中绘制 BufferedImage 。drawImage(...)
  • paintComponent(...)再次使用 JVM 提供给您的 Graphics 对象,在该方法中绘制任何短暂的或移动的图像。
  • 不要处置 JVM 提供给您的 Graphics 对象。
  • 你几乎从不打电话paint(...)paintComponent(...)直接打电话。我只是在打印组件或需要制作一些非常精美的图形(如“肮脏的富客户端”一书中所示的图形)时自己完成此操作。
  • 避免使用 KeyListener,因为它们是低级结构,并且需要组件具有焦点。
    • 更好地使用键绑定——查看教程以获取更多信息。
    • 如果必须使用 KeyListeners,则必须确保将焦点放在被监听的组件上。
  • 查看Swing 图形教程
  • 以及AWT 和 Swing 中的绘画文章。
于 2013-05-31T21:22:01.647 回答