2014-02-05 31 views
4

在此之後詢問新問題,發現here如何在同一時間滾動多個對象?

我是Java的新手,但我正在研究「Flappy Bird」的娛樂活動,以瞭解更多關於java和圖形顯示方式的信息。對我的任何問題的任何解決方案或建議非常感謝。謝謝!

現在,我的程序使得隨機管和滾動,但我並不需要它來保持滾動時x1-3 = -83這是當管會完全關閉屏幕,並且不再需要) 。

問題

我怎樣才能讓我的Game.class滾動Pipes.class多個實例,同時增加它們之間的預設距離?我可以找出他們之間的距離,但就展示不止一個,我不知道該怎麼做。最多3個管道必須同時顯示。

如何顯示主菜單的面板,然後在按下啓動按鈕後切換到管道面板?

Game.java

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 

public class Game { 

    Pipes panel = new Pipes(); 

    public Game() { 
     JFrame f = new JFrame(); 

     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.add(panel); 
     f.setTitle("Pipe Game"); 
     f.setResizable(false); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 

     Timer timer = new Timer(10, new ActionListener() { //pipe speed 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       panel.move(); 
      } 
     }); 
     timer.start(); 

     Timer refresh = new Timer(30, new ActionListener() { //refresh rate 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       panel.repaint(); 
      } 
     }); 
     refresh.start(); 


    } 

    public static void main(String args[]) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new Game(); 
      } 
     }); 
    } 
} 

Pipes.java

import java.awt.Dimension; 
import java.awt.Graphics; 
import javax.swing.JPanel; 

public class Pipes extends JPanel { 
    //Declare and initialiaze variables 
    int x1 = 754;    //xVal start 
    int x2 = 75;    //pipe width 
           //total width is 83 
    int y1 = -1;    //yVal start 
    int y2 = setHeightVal(); //pipe height 
    int gap = 130;    //gap height 

    @Override 
    public void paintComponent(Graphics g) { 
     super.paintComponent(g); 

     g.clearRect(0,0,750,500);      //Clear screen 
     g.drawRect(x1,y1,x2,y2);      //Draw part 1 
     g.drawRect(x1-3,y2-1,x2+6,25);     //Draw part 2 
     g.drawRect(x1-3,y2+25+gap,x2+6,25);    //Draw part 3 
     g.drawRect(x1,y2+25+gap+25,x2,500-y2-49-gap); //Draw part 4 
    } 

    public void move() { 
     x1--; 
    } 

    public int getMyX() { //To determine where the pipe is horizontally 
     return x1-3; 
    } 

    public int getMyY() { //To determine where the pipe is vertically 
     return y2+25; 
    } 

    public int setHeightVal() {  //Get a random number and select a preset height 
     int num = (int)(9*Math.random() + 1); 
     int val = 0; 
     if (num == 9) 
     { 
      val = 295; 
     } 
     else if (num == 8) 
     { 
      val = 246; 
     } 
     else if (num == 7) 
     { 
      val = 216; 
     } 
     else if (num == 6) 
     { 
      val = 185; 
     } 
     else if (num == 5) 
     { 
      val = 156; 
     } 
     else if (num == 4) 
     { 
      val = 125; 
     } 
     else if (num == 3) 
     { 
      val = 96; 
     } 
     else if (num == 2) 
     { 
      val = 66; 
     } 
     else 
     { 
      val = 25; 
     } 
     return val; 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(751, 501); 
    } 
} 
+0

Timer timer = new Timer(10,new ActionListener(){很短的延遲,必須使用23-30作爲最小刷新頻率, – mKorbel

+0

謝謝,我會改變這種情況。只是好奇,爲什麼我的刷新率是什麼?什麼是最佳的,這樣我就不會閃爍,管道平穩地移動? –

+0

另外,這個數字不僅僅是我的刷新率,它決定了在移動管道之前需要等待多長時間,所以它還可以控制管道的速度。 –

回答

4

「我怎樣才能讓我的Game.class滾動管道的多個實例。同時增加它們之間的預設距離?「

這裏有一些簡單的邏輯。你想使用一個數據結構來支持你管道。這個數據結構可以容納的是任何需要繪製的數據,比如x,y,座標。對於這個任務,我更喜歡用它自己的draw方法創建一個新類,以便將paintComponent的Graphics上下文傳遞給。例如

public class Pipe { 
    int x; 
    int y; 
    public class Pipe(int x, int y) { 
     this.x = x; 
     this.y = y; 
    } 

    public void drawPipe(Graphics g) { 
     g.fillRect(x, y, 50, 100); 
    } 
} 

現在,這只是一個示例類。上面只畫了一個矩形,但這只是爲了告訴你你應該做什麼。

所以接下來你想擁有數據結構來保存三個對象,如數組。我更喜歡使用List。您需要在Pipes類中使用List,並向其添加三個Pipe對象。您可以指定x是你喜歡的東西,讓他們同樣的距離相隔

public class Pipes extends JPanel { 
    List<Pipe> pipes = new ArrayList<Pipe>(); 

    public Pipes() { 
     pipes.add(new Pipe(50, 100)); 
     pipes.add(new Pipe(150, 100)); 
     pipes.add(new Pipe(250, 100)); 
    } 
} 

現在在paintComponent方法,所有你需要做的是循環遍歷它們,並使用其drawPipe方法

protected void paintComponent(Graphics g) { 
    super.paintComponent(g); 

    for (Pipe pipe : pipes){ 
     pipe.drawPipe(g); 
    } 
} 

現在你移動它們,你需要做的就是在計時器中移動x位置,並且撥打repaint。你也可能想檢查x,確保它不會脫離屏幕,或者如果你將它們移動到右邊,你可以把它們放在左邊然後乳清離開屏幕,就像傳送帶一樣。所以,你可以做這樣的事情

private static final int X_INC = 5; 
... 
Timer timer = new Timer(40, new ActionListener(){ 
    public void actionPerformed(ActionEvent e) { 
     for (Pipe pipe : pipes){ 
      if (pipe.x >= screenWidth) { 
       pipe.x = 0; 
      } else { 
       pipe.x += X_INC; 
      } 
     } 
     repaint(); 
    } 
}); 

正如你所看到的,我做的是通過List循環,只是改變他們所有的x座標,然後repaint()。所以你可以用你需要繪製的任何值創建你自己的Pipe類,然後在循環中移動它們。


對於速度的變化,而不是使用像10一個硬編碼vakue定時器,使用變量delay,你可以像一個按鈕

int delay = 100; 
JButton speedUp = new JButton("Speed UP"); 
JButton slowDown = new JButton("Slow Down"); 
Timer timer = null; 
public Pipes() { 
    timer = new Timer(delay, new ActionListener(){ 
     ... 
    }); 
    timer.start(); 

    speedUp.addActionListener(new ActionListener(){ 
     public void actionPerformed(ActionEvent e) { 
      if (!((delay - 20) < 0)) { 
       delay -=20; 
       timer.setDelay(delay); 
      } 
     } 
    }); 
    // do the same for slowDown, but decrease the delay 
} 

的點擊改變

測試了這一點

import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import java.net.URL; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.imageio.ImageIO; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 


public class Mario extends JPanel { 

    private static final int D_W = 800; 
    private static final int D_H = 300; 
    private static final int X_INC = 5; 

    BufferedImage bg; 
    BufferedImage pipeImg; 

    List<Pipe> pipes = new ArrayList<>(); 

    int delay = 50; 

    Timer timer = null; 

    public Mario() { 

     try { 
      bg = ImageIO.read(new URL("http://farm8.staticflickr.com/7341/12338164043_0f68c73fe4_o.png")); 
      pipeImg = ImageIO.read(new URL("http://farm3.staticflickr.com/2882/12338452484_7c72da0929_o.png")); 
     } catch (IOException ex) { 
      Logger.getLogger(Mario.class.getName()).log(Level.SEVERE, null, ex); 
     } 

     pipes.add(new Pipe(100, 150, pipeImg)); 
     pipes.add(new Pipe(400, 150, pipeImg)); 
     pipes.add(new Pipe(700, 150, pipeImg)); 

     timer = new Timer(delay, new ActionListener(){ 
      public void actionPerformed(ActionEvent e) { 
       for (Pipe pipe : pipes) { 
        if (pipe.x > D_W) { 
         pipe.x = 0; 
        } else { 
         pipe.x += X_INC; 
        } 
       } 
       repaint(); 
      } 
     }); 
     timer.start(); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     g.drawImage(bg, 0, 0, getWidth(), getHeight(), this); 
     for (Pipe pipe : pipes) { 
      pipe.drawPipe(g); 
     } 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(D_W, D_H); 
    } 

    public class Pipe { 

     int x; 
     int y; 
     Image pipe; 

     public Pipe(int x, int y, Image pipe) { 
      this.x = x; 
      this.y = y; 
      this.pipe = pipe; 
     } 

     public void drawPipe(Graphics g) { 
      g.drawImage(pipe, x, y, 75, 150, Mario.this); 
     } 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JFrame frame = new JFrame("Mario Pipes"); 
       frame.add(new Mario()); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 
} 

enter image description here

+0

由於我有兩個新的代碼部分要添加,我基本上必須重做我的大部分代碼,我不太確定如何添加此代碼。另外,我需要什麼進口? @peeskillet –

+0

我正在更新新的[問題]中的代碼(http://stackoverflow.com/questions/21592492/how-can-i-switch-between-jpanels?lq=1)。 @peeskillet –

+0

我會測試一下Mario程序,看看如何添加所有這些。 –

相關問題