2011-12-14 76 views
3

我想做一个简单的java游戏 - 驾驶一辆汽车通过一个轨道。我受到老师的限制,使用矩形和类似的东西。我的问题是当我使用方法repaint(),我的框架闪烁。当汽车改变方向时,我试图重新绘制方法,但它没有任何好处。有什么建议么?我的JFrame闪烁

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.Rectangle; 
import java.awt.Toolkit; 
import java.awt.event.KeyEvent; 
import java.awt.event.KeyListener; 
import java.net.URL; 

import javax.swing.JFrame; 


@SuppressWarnings("serial") 
public class MAP extends JFrame 
{ 
    //the URL and Img designed for the images 
    URL cLeft,cRight,cUp; 
    Image img1,img2,img3; 

    //these will keep track of each player’s speed: 
    double p1Speed =.5, p2Speed =.5; 

    //constant for the screen size and used for the drawing the terrain 
    final int WIDTH = 900, HEIGHT = 650; 

    //these are ints that represent directions: 
    final int UP = 0, RIGHT = 1, DOWN = 2, LEFT = 3; 
    //these will keep track of the player’s directions (default = up) 
    int p1Direction = 0; 

    //this is the rectangle for player 1’s (outer) car: 
    Rectangle p1 = new Rectangle(WIDTH/9,HEIGHT/2, WIDTH/30,WIDTH/30); 

    //draw the terrain 
    Rectangle left = new Rectangle(0,0,WIDTH/9,HEIGHT); 
    Rectangle right = new Rectangle((WIDTH/9)*9,0,WIDTH/9,HEIGHT); 
    Rectangle top = new Rectangle(0,0,WIDTH, HEIGHT/9); 
    Rectangle bottom = new Rectangle(0,(HEIGHT/9)*9,WIDTH,HEIGHT/9); 
    Rectangle center = new Rectangle((int)((WIDTH/9)*2.5),(int)((HEIGHT/9)*2.5), (int)((WIDTH/9)*5),(HEIGHT/9)*4); 

    //these obstacles will obstruct the path and make navigating harder 
    Rectangle obstacle = new 
    Rectangle(WIDTH/2,(int)((HEIGHT/9)*7),WIDTH/10,HEIGHT/9); 
    Rectangle obstacle2 = new 
    Rectangle(WIDTH/3,(int)((HEIGHT/9)*5),WIDTH/10,HEIGHT/4); 
    Rectangle obstacle3 = new 
    Rectangle(2*(WIDTH/3),(int)((HEIGHT/9)*5),WIDTH/10,HEIGHT/4); 
    Rectangle obstacle4 = new Rectangle(WIDTH/3,HEIGHT/9,WIDTH/30,HEIGHT/9); 
    Rectangle obstacle5 = new Rectangle(WIDTH/2,(int)((HEIGHT/9)*1.5),WIDTH/30,HEIGHT/4); 
    Rectangle finish = new Rectangle(WIDTH/9,(HEIGHT/2)-HEIGHT/9,(int)((WIDTH/9)*1.5),HEIGHT/70); 
    Rectangle lineO=new Rectangle(WIDTH/9,HEIGHT/2,(int)((WIDTH/9)*1.5)/2,HEIGHT/140); 
    Rectangle lineI = new Rectangle(((WIDTH/9)+((int)((WIDTH/9)*1.5)/2)),(HEIGHT/2)+(HEIGHT/10),(int)((WIDTH/9)*1.5)/2, HEIGHT/140); 

    //the constructor: 
    public MAP() { 

     //the following code creates the JFrame 
     super("Radical Racing"); 
     setSize(WIDTH,HEIGHT); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     setVisible(true); 
     setResizable(false); 

     try { 
      cUp = this.getClass().getResource("carUp.jpg"); 
      cLeft = this.getClass().getResource("carLeft.jpg"); 
      cRight = this.getClass().getResource("carRight.jpg"); 
     } catch(Exception e) { 
     } 

     //attach the URLs to the images 
     img1 = Toolkit.getDefaultToolkit().getImage(cUp); 
     img2 = Toolkit.getDefaultToolkit().getImage(cLeft); 
     img3 = Toolkit.getDefaultToolkit().getImage(cRight); 

     repaint(); 
     Move1 m1 = new Move1(); 
     m1.start(); 
    } 

    //this will draw the cars and the race track 
    public void paint(Graphics g) { 
     super.paint(g); 

     //draw the background for the racetrack 
     g.setColor(Color.DARK_GRAY); 
     g.fillRect(0,0,WIDTH,HEIGHT); 

     //when we draw, the border will be green 
     g.setColor(Color.GREEN); 

     //fill rectangle 
     g.fillRect(left.x,left.y,left.width,left.height); 
     g.fillRect(right.x,right.y,right.width,right.height); 
     g.fillRect(top.x,top.y,top.width,top.height); 
     g.fillRect(bottom.x,bottom.y,bottom.width,bottom.height); 
     g.fillRect(center.x,center.y,center.width,center.height); 
     g.fillRect(obstacle.x,obstacle.y,obstacle.width,obstacle.height); 
     g.fillRect(obstacle2.x,obstacle2.y,obstacle2.width,obstacle2.height); 
     g.fillRect(obstacle3.x,obstacle3.y,obstacle3.width,obstacle3.height); 
     g.fillRect(obstacle4.x,obstacle4.y,obstacle3.width,obstacle4.height); 
     g.fillRect(obstacle5.x,obstacle5.y,obstacle5.width,obstacle5.height); 

     //set the starting line color to white 
     g.setColor(Color.WHITE); 

     //now draw the starting line 
     g.fillRect(lineO.x,lineO.y,lineO.width,lineO.height); 
     g.fillRect(lineI.x,lineI.y,lineI.width,lineI.height); 

     //set the color of the finish line to yellow 
     g.setColor(Color.YELLOW); 

     //now draw the finish line 
     g.fillRect(finish.x,finish.y,finish.width,finish.height); 

     //set the color to blue for p1 
     g.setColor(Color.WHITE); 

     //now draw the actual player 
     g.fill3DRect(p1.x,p1.y,p1.width,p1.height,true); 

     //draw the images for the player 
     if(p1Direction==UP) 
     g.drawImage(img1,p1.x,p1.y,this); 
     if(p1Direction==LEFT) 
      g.drawImage(img2,p1.x,p1.y,this); 
     if(p1Direction==RIGHT) 
    g.drawImage(img3,p1.x,p1.y,this); 
    } 

    private class Move1 extends Thread implements KeyListener { 
     public void run() { 
      //now, this should all be in an infinite loop, so the process 
      //repeats 
      addKeyListener(this); 
      while(true) { 
       //now, put the code in a try block. This will let the 
       //program exit 
       //if there is an error. 

       try { 
        //first, refresh the screen: 
        repaint(); 
        //increase speed a bit 
        // if(p1Speed<=5) 
        // p1Speed+=.2; 
        //p1.y-=(int) p1Speed; 
        if(p1.intersects(left) || p1.intersects(right) || p1.intersects(top) || p1.intersects(bottom) || p1.intersects(obstacle) || p1.intersects(obstacle2)|| p1.intersects(obstacle3) || p1.intersects(obstacle4) || p1.intersects(obstacle5)) { 
         p1Speed = -5; 
        } 
        //if the car hits the center, do the same as above 
        //but make the speed -2.5. 
        if(p1.intersects(center)) { 
         p1Speed = -5; 
        } 
        //increase speed a bit 
        if(p1Speed<=5) 
         p1Speed+=.2; 
        //these will move the player based on direction 
        if(p1Direction==UP) { 
         p1.y-=(int)p1Speed; 
         //repaint(); 
        } 
        if(p1Direction==DOWN) { 
         p1.y+=(int)p1Speed; 
         //repaint(); 
        } 
        if(p1Direction==LEFT) { 
         p1.x-=(int)p1Speed; 
         //repaint(); 
        } 
        if(p1Direction==RIGHT) { 
         p1.x+=(int)p1Speed; 
         //repaint(); 
        } 
        //this delays the refresh rate: 
        Thread.sleep(200); 

       } catch(Exception e) { 
        //if there is an exception (an error), exit the loop. 
        break; 
       } 
      } 
     } 

     @Override 
     public void keyPressed(KeyEvent arg0) { 
      // TODO Auto-generated method stub 
     } 

     @Override 
     public void keyReleased(KeyEvent arg0) { 
      // TODO Auto-generated method stub 
     } 

     @Override 
     public void keyTyped(KeyEvent event) { 
      if(event.getKeyChar()=='a') { 
       p1Direction = LEFT; 
       repaint(); 
      } 
      if(event.getKeyChar()=='s') { 
       p1Direction = DOWN; 
       repaint(); 
      } 
      if(event.getKeyChar()=='d') { 
       p1Direction = RIGHT; 
       repaint(); 
      } 
      if(event.getKeyChar()=='w') { 
       p1Direction = UP; 
       repaint(); 
      } 
     } 
    } 
    //this starts the program by calling the constructor: 
    public static void main (String[ ] args) { 
     new MAP(); 
    } 
} 
+0

*“有什么建议吗?”*修正你的换档键,并在每个句子开头使用一次,以及任何使用单词'I'。 – 2011-12-14 17:05:59

回答

10

不要直接在绘图方法中绘制JFrame。取而代之的是在JPanel或JComponent中绘制,并覆盖它的paintComponent方法,因为Swing在默认情况下会执行双缓冲,这将允许您利用这一点。

+0

谢谢。你的评论是非常有益的。我已经尝试过它,它的工作 – Stormel 2011-12-14 22:43:49

2

通过使用双缓冲技术,可以避免图形界面上的闪烁。 Here是一个文章,给出了双缓冲的一个例子。 Java Tutorial的这部分内容还提供了进一步的建议和示例。

+0

感谢您的建议 – Stormel 2011-12-14 22:44:23