2016-09-09 2 views
0

Ich mache FlappyBirds in Java, alles funktioniert gut für jetzt. Aber ich stecke mit einem Problem fest.KeyListener verzögert

Ich habe eine ganzzahlige Variable mit dem Namen 'status'. Wenn status ist 0, das Spiel läuft, wenn die status ist 1, dann wird das Fenster sagen "game over, press s to begin". Mein KeyListener funktioniert gut für das Spiel.

Aber nachdem ich das Spiel verloren und status wird 1, wenn ich die Taste s erneut drücken, muss ich die Taste für einige Zeit halten. Es reagiert nicht schnell. Während des Starts ist status1. Wenn ich während dieser Zeit die s drücke, kommt es schnell, aber wenn ich verliere und der Status wieder 1 wird, tritt das Problem auf.

package flappybirds; 

import java.awt.Color; 
import java.awt.Font; 
import java.awt.Graphics; 
import java.awt.Rectangle; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.util.ArrayList; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import java.util.Random; 
import java.util.logging.Level; 
import java.util.logging.Logger; 


public class FlappyBirds extends JPanel implements  ActionListener,KeyListener { 
    public int WIDTH=800,HEIGHT=800,x=WIDTH/2-10,y=HEIGHT/2-10 , gravity=0,  ticks=0,status=1; 
    public static FlappyBirds flappy; 
    public boolean jump; 
    public boolean gameOver=true ; 
    public ArrayList<Rectangle>walls; 
    public Rectangle bird; 

    public Random generator; 
    public FlappyBirds(){ 
     Timer t=new Timer(10,this); 
     JFrame window=new JFrame("Flappy Birds"); 
     window.setSize(WIDTH ,HEIGHT); 
     window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     window.add(this); 
     window.setVisible(true); 
     window.addKeyListener(this); 
     walls=new ArrayList<Rectangle>(); 
     generator=new Random(); 
     t.start(); 
    } 

    public static void main(String[] args) { 
     flappy=new FlappyBirds(); 
    } 

    @Override 
    public void paintComponent(Graphics g){ 
     super.paintComponent(g); 
     bird=new Rectangle(x,y,15,15); 
     g.setColor(new Color(0,200,255)); 
     g.fillRect(0,0,WIDTH,HEIGHT); 
     g.setColor(Color.ORANGE); 
     g.fillRect(0, HEIGHT-100, WIDTH,100); 
     g.setColor(Color.GREEN); 
     g.fillRect(0,HEIGHT-110,WIDTH,10); 
     g.setColor(Color.red); 
     g.fillRect(bird.x,bird.y,bird.width,bird.height); 
     g.drawString(Integer.toString(status),200,200); 
     g.setColor(new Color(200,200,40)); 

     if(status==0){ 
      for(Rectangle rect:walls){ 
       paintWall(rect,g); 
      } 
     } 

     if(status==1){ 
      g.setFont(new Font("Arial",50,50)); 
      g.setColor(Color.RED); 
      g.drawString("Press 'S' to begin",400,400); 
     } 

     g.setColor(Color.RED); 
    } 

    @Override 
    public void actionPerformed(ActionEvent e) { 

     repaint(); 
     if(status==0){ 
      addWall(true); 
      addWall(true); 

      ticks ++; 
      if(jump){ 
       if(ticks%8==0){ 
        gravity=-10; 
       } 

      } 
      else if(ticks%8==0 && gravity<15 && jump==false){ 
       gravity+=2; 

      } 
      if(ticks==1000){ 
       ticks=0; 
      } 
      y += gravity; 

      for(Rectangle rect:walls){ 
       rect.x -=10; 
      } 

      for(int i=0;i<walls.size();i++){ 
       Rectangle r=walls.get(i); 

       if(r.x+r.width<0){ 

        addWall(false); 
       } 
      } 


      for(Rectangle column:walls){ 
       if(column.intersects(bird) || bird.y>=HEIGHT-120 ||  bird.y<=3){ 
        gameOver=true; 
        status=1; 
        if(!jump){ 
         if(y>=HEIGHT-120){ 
          y=HEIGHT-120; 
         } 
         if(column.intersects(bird)){ 
          y=HEIGHT/2-10; 
         } 
         if(bird.y<=3){ 
          y=HEIGHT/2-10; 
         } 
        }else if(jump){ 
         y=HEIGHT/2-10; 
        } 
       }else{ 
        gameOver=false; 
       } 
      } 
      collide(); 

     } 
    } 


    @Override 
    public void keyTyped(KeyEvent e) {} 

    @Override 
    public void keyPressed(KeyEvent e) { 
     int c=e.getKeyCode(); 
     if(status==0){ 
      if(c==KeyEvent.VK_SPACE){ 
       jump=true; 
      } 
     } 
     if(status==1){ 
      if(c==KeyEvent.VK_S){ 

       status=0; 
      } 
     } 
    } 
    public void collide(){ 
     if(status==0){ 
      if(gameOver){ 
       walls.clear(); 
       addWall(true); 
       addWall(true); 
       gameOver=false; 

      } 
     } 
    } 

    @Override 
    public void keyReleased(KeyEvent e) { 
     jump=false; 
    } 
    public void paintWall(Rectangle rect,Graphics g){ 
     g.fillRect(rect.x, rect.y, rect.width, rect.height); 
    } 
    public void paintSpace(Rectangle rect,Graphics g){ 
     g.setColor(new Color(0,200,225)); 
     g.fillRect(rect.x,rect.y,rect.width,rect.height); 
    } 
    public void addWall(boolean oldwall){ 
     int width=100; 
     final int height=350; 
     int yloc=100+generator.nextInt(150); 
     int space=100; 
     if(oldwall){ 
      if(generator.nextBoolean()){ 
       walls.add(new Rectangle(WIDTH+width+ (walls.size()*200),HEIGHT- height-yloc,width,height)); 
       walls.add(new Rectangle(WIDTH+width+(walls.size()-1)*200,- yloc, width,height- space)); 
      }else{ 
       walls.add(new Rectangle(WIDTH+width+ (walls.size()*200),HEIGHT-height+yloc,width,height)); 
       walls.add(new Rectangle(WIDTH+width+ (walls.size()-1)*200,+yloc, width,height- space)); 
      } 
     }else{ 
      if(generator.nextBoolean()){ 
       walls.add(new  Rectangle(walls.get(walls.size()-1).x+600,HEIGHT-height- yloc,width,height+space)); 
       walls.add(new Rectangle(walls.get(walls.size()-2).x+600,- yloc,width,height-space)); 
      }else{ 
       walls.add(new  Rectangle(walls.get(walls.size()-1).x+600,HEIGHT- height+yloc,width,height+space)); 
       walls.add(new  Rectangle(walls.get(walls.size()-2).x+600,yloc,width,height-space)); 
      } 
     } 
    } 
} 
+0

Es gibt nicht wirklich genug Informationen, um Ihre Frage zu beantworten. Es ist nichts falsch mit dem Code, den Sie gezeigt haben, was bedeutet, dass das Problem von woanders kommt. Vielleicht nimmt Ihre Spielschleife beim zweiten Mal zu viel Speicher in Anspruch oder Ihr Code, der zum Spiel selbst wechselt, wird erst nach einer gewissen Verzögerung erreicht oder Ihr Key Listener wird nach einiger Zeit entfernt und neu zugewiesen, ich könnte beliebig weitermachen Möglichkeiten, aber mit so wenig Informationen, ich denke nicht, dass es helfen wird. – Mark

+0

Kann ich den gesamten Quellcode posten? –

+0

Ich denke, Sie könnten, obwohl das wahrscheinlich eine Menge Code zu lesen ist und nicht viele Leute finden die Zeit dafür: D Es wäre wahrscheinlich besser, wenn Sie versuchen könnten, ein wenig zu debuggen, so dass Sie grob herausfinden können wo in deinem Code deine Probleme liegen und dann nur diese Teile posten. Benutzen Sie einfach den Debugger Ihrer IDE oder geben Sie eine Testausgabe ein (denken Sie daran, sie danach wieder zu entfernen). Ich würde wahrscheinlich damit beginnen, zu sehen, ob die keyPressed-Methode zu spät aufgerufen wird oder das Stück Code, das ausgeführt werden muss, sobald der Status 0 ist. – Mark

Antwort

0

Definitiv die Ursache der Verzögerung ist der Zeitgeber:

Der Timer kontinuierlich läuft, startet Ereignisse alle 10 ms (d.h. actionPerformed Aufruf). Auch nachdem das Spiel zu Ende ist, läuft es, so dass die ActionEvent-Ereignisse in der Ereigniswarteschlange angesammelt werden und das 'S', das du drückst, erleidet eine große Verzögerung, bis es an der Reihe ist, verarbeitet zu werden.

Ich empfehle Ihnen:

  1. den Timer zu stoppen, sobald das Spiel vorbei ist.
  2. Sobald das Spiel neu gestartet wird, initialisieren Sie alle Instanzvariablen auf ihren ursprünglichen Zustand. Zum Beispiel, implementieren Sie eine private Methode namens init und nehmen Sie dort die Initialisierung von x, y, gravity, , walls, und natürlich, den Anruf an timer.start().
  3. Rufen Sie init am Ende des Konstruktors und auch innerhalb keyPressed, nachdem Sie status=0.
+0

Sollte ich den Timer im Konstruktor stoppen? Ich frage das, denn wenn ich das tue, funktioniert es nicht. –

+0

Nein. Der Timer muss im Konstruktor gestartet und gestoppt werden, wenn Sie 'gameOver = true' zuweisen. –