2013-05-31 2 views
2

Итак, я пытаюсь создать простую игру, основанную на световых циклах от Tron. Он имеет 3 класса: драйвер с основным методом (LightCycleRunner), класс LightCycle, который хранит координаты и направление каждого светового цикла, и класс, который рисует и обрабатывает движения после рисования фона. Все работало отлично, за исключением того, что слушатели ключевых слов не слушали, пока игра не закончилась. Я попытался решить эту проблему, создав новый поток для запуска игры, в то время как слушатель клавиш все равно будет слушать, но теперь моя графика не распознается. Каковы ваши мнения?Key Listener и Graphics не согласны

Это 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; 
    } 

} 
+0

Есть много вещей, которые я рекомендую вам изменить. Ваша графика ошибочна: вы почти никогда не должны получать графику через 'getGraphics()' на компоненте, вам следует избегать KeyListeners и использовать Key Bindings, поскольку они являются конструкцией более высокого уровня и более просты в отношении фокуса. Вам не следует смешивать компоненты Swing и AWT, вы почти никогда не должны называть 'paint (...)' непосредственно, ... Вам действительно нужно прочитать некоторые из руководств, прежде чем пытаться это сделать, поскольку угадать, что он редко работает хорошо. –

ответ

2

Чтобы оформить мои рекомендации в мой комментарий:

  • Не следует смешивать компоненты AWT с компонентами Swing, т.к в
    • вы будете смешивания тяжелых и легких компонентов вес в одном графическом интерфейсе, которые, если не сделано правильно, может привести к побочным эффектам
    • вы потеряете преимущество Свинг двойная буферизация по умолчанию.
  • ли ваш чертеж в JComponent-й или paintComponent(...) метода JPanel в, не paint(...) метода. Опять же, это даст вам преимущество двойной буферизации по умолчанию Swing.
  • Не получайте свой объект Graphics, вызвав getGraphics() на компонент, так как это вернет затухающий объект, который вскоре станет нулевым, что приведет к нестабильным изображениям. '
    • Намного лучше рисовать фоновые изображения в BufferedImage, но обратите внимание, что это нормально, чтобы вызвать getGraphics(), чтобы получить объект Graphics для BufferedImage, но не забывайте его утилизировать по завершении.
    • Затем нарисуйте BufferedImage в переопределении paintComponent(...), вызвав drawImage(...) на объекте Graphics, который JVM переходит в параметр метода paintComponent (Graphics g).
  • Нарисуйте любые краткосрочные или движущиеся изображения в методе paintComponent(...), снова используя объект Graphics, предоставленный вам JVM.
  • Не удаляйте объект Graphics, предоставленный JVM.
  • Вы почти никогда звоните paint(...) или paintComponent(...) напрямую. Я сделал это самостоятельно только при печати компонента или когда мне нужно сделать очень причудливую графику, как показано в книге Filthy Rich Clients.
  • Избегайте использования KeyListeners, поскольку они представляют собой низкоуровневые конструкции и требуют, чтобы компонент имел фокус.
    • Лучше использовать привязки клавиш - ознакомьтесь с учебником, чтобы узнать больше об этом.
    • Если вы должны использовать KeyListeners, вы должны быть уверены, что прослушали компонент в фокусе.
  • Отъезд Swing Graphics Tutorials
  • , а также Painting in AWT and Swing статья.
Смежные вопросы