2014-02-05 4 views
4

새로운 질문이이 후 질문되었습니다 here을 발견했습니다.동시에 두 개 이상의 객체를 스크롤하는 방법은 무엇입니까?

저는 Java에 익숙하지 않지만 "Flappy Bird"를 재 작성하여 Java 및 그래픽 표시 방법에 대해 자세히 배우고 있습니다. 모든 질문에 대한 해결책이나 제안은 대단히 감사하겠습니다. 감사!

지금, 내 프로그램이 임의의 파이프와 스크롤을 만드는,하지만 난 x1-3 = -83 ( 이것은 파이프가 완전히 화면 해제 할 때입니다 더 이상을 필요) 때 스크롤을 계속 할 필요가 없습니다

.

질문

가 어떻게 내 Game.class 스크롤 Pipes.class 개 이상의 인스턴스 사이에 미리 설정된 거리를 추가하는 동안 만들 수 있습니까? 나는 그 (것)들 사이두기 위하여 거리를 알아낼 수 있었다, 그러나 1 개 이상을 표시하기까지, 나는 그것을하는 방법을 모른다. 최대 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

타이머 타이머 = 새 타이머 (10, 새로운 ActionListener() {매우 짧은 지연 시간, 최소 새로 고침 빈도로 23-30을 사용해야 함, – mKorbel

+0

감사합니다. 그냥 궁금 해서요, 새로 고침 빈도가 중요한 이유는 무엇입니까? 그리고 최적의 것은 무엇이 될까요? 그래서 나는 깜빡 거리지 않고 파이프가 부드럽게 움직입니다. –

+0

또한이 숫자는 새로 고침 빈도가 아니며 파이프를 이동하기 전에 기다릴 시간을 결정하므로 파이프의 속도도 제어합니다. –

답변

4

는 "어떻게 Game.class이 파이프의 인스턴스를 두 개 이상 스크롤 할 수 있습니다. 클래스 사이에 미리 설정된 거리를 추가하는 중입니까? "

여기 간단한 논리가 있습니다. 데이터 구조를 사용하여 파이프을 보유하고 싶습니다. 이 데이터 구조는 x, y 좌표와 같이 그릴 때 필요한 데이터가 무엇이든지 유지합니다. 이 작업을 위해 나는 자신의 draw 메서드를 사용하여 새 클래스를 만드는 것을 선호합니다. paintComponent의 그래픽 컨텍스트를 전달합니다. 예를 들어

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); 
    } 
} 

지금이 그냥 예 클래스입니다. 위의 그림은 직사각형을 그리지 만, 이것은 여러분이해야 할 일을 보여주기위한 것입니다.

다음으로 배열과 같은 세 개의 Pipe 개체를 보유 할 데이터 구조가 있어야합니다. 나는 List을 선호한다. Pipes 클래스에 List을 입력하고 Pipe 개체를 3 개 추가하십시오. 당신은 일하기 위해 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을 통해 루프 바로 다음 repaint()을 모든 x 좌표를 변경합니다. 따라서 페인트 할 필요가있는 값을 사용하여 자신의 Pipe 클래스를 만들고 루프 내에서 그 둘을 이동할 수 있습니다. 속도의 변화에 ​​대한


, 대신 타이머 10 같은 하드 코딩 vakue를 사용하여, 당신은 버튼

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 
} 

의 클릭으로 같이 변경할 수 있습니다 변수 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

새 [question] (http://stackoverflow.com/questions/21592492/how-can-i-switch-between-jpanels?lq=1)의 코드를 업데이트하고 있습니다. @peeskillet –

+0

나는 이것을 추가하는 방법을보기 위해 Mario 프로그램을 테스트 할 것이다. –

관련 문제