2010-05-18 4 views
9

Java에서 간단한 2D 게임을 만들려고합니다.UI 스레드를 멈추지 않고 게임 루프를 구현하는 가장 좋은 방법

지금까지, 메뉴 모음 및 JPanel을 확장하는 클래스가 있고 paint 메서드를 재정의했습니다. 이제 게임 루프를 만들어야합니다. 여기서 이미지의 위치를 ​​업데이트 할 것입니다. 그러나, 나는 이것을 달성하는 최선의 방법에 갇혀있다. 다중 스레드를 사용해야합니까? 왜냐하면 확실하게 메인 스레드에 무한 루프를 넣으면 UI (따라서 내 메뉴 표시 줄)가 멈 춥니 다.

여기 내 코드는 지금까지의 :

import java.awt.Color; 
import java.awt.Graphics; 

import javax.swing.JPanel; 

@SuppressWarnings("serial") 
public class GameCanvas extends JPanel { 

    public void paint(Graphics g) { 
     while (true) { 
      g.setColor(Color.DARK_GRAY); 
      try { 
       Thread.sleep(100); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

import javax.swing.JFrame; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 

@SuppressWarnings("serial") 
public class Main extends JFrame { 

    GameCanvas canvas = new GameCanvas(); 
    final int FRAME_HEIGHT = 400; 
    final int FRAME_WIDTH = 400; 

    public static void main(String args[]) { 
     new Main(); 
    } 

    public Main() { 
     super("Game"); 

     JMenuBar menuBar = new JMenuBar(); 
     JMenu fileMenu = new JMenu("File"); 
     JMenuItem startMenuItem = new JMenuItem("Pause"); 
     menuBar.add(fileMenu); 
     fileMenu.add(startMenuItem); 

     super.add(canvas); 
     super.setVisible(true); 
     super.setSize(FRAME_WIDTH, FRAME_WIDTH); 
     super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     super.setJMenuBar(menuBar); 
    } 
} 

모든 포인터 또는 팁? 내 루프는 어디에 두어야합니까? 내 메인 클래스 또는 GameCanvas 클래스에서?

답변

5

게임 루프는 하나의 스레드가 필요하고 마우스 클릭이나 키 누르기와 같은 Swing UI 이벤트를 처리하는 하나의 스레드가 필요합니다.

스윙 API를 사용하면 이벤트 발송 스레드라는 UI 용 스레드가 자동으로 추가로 제공됩니다. 콜백은 주 스레드가 아닌이 스레드에서 실행됩니다.

프로그램이 실행될 때 자동으로 게임을 시작하려면 게임 루프에 기본 스레드가 적합합니다. Swing GUI로 게임을 시작하고 중지하려면 메인 스레드에서 GUI를 시작한 다음 GUI를 사용하여 게임을 시작하려는 경우 GUI에서 게임 루프를위한 새로운 스레드를 만들 수 있습니다.

아니요, 게임 루프를 주 스레드에 넣으면 메뉴 막대가 멈추지 않습니다. Swing 콜백이 완료되는 데 오랜 시간이 걸리면 메뉴 막대가 멈 춥니 다.

스레드간에 공유되는 데이터는 잠금으로 보호해야합니다.

스윙 코드를 자체 클래스에 포함시키고 게임 루프를 기본 클래스에만 넣는 것이 좋습니다. 게임 루프에 주 스레드를 사용하는 경우이를 설계하는 방법에 대한 대략적인 아이디어입니다.

import javax.swing.JFrame; 
import javax.swing.JMenu; 
import javax.swing.JMenuBar; 
import javax.swing.JMenuItem; 

class GUI extends JFrame { 
    GameCanvas canvas = new GameCanvas(); 
    final int FRAME_HEIGHT = 400; 
    final int FRAME_WIDTH = 400; 


    public GUI() { 
     // build and display your GUI 
     super("Game"); 

     JMenuBar menuBar = new JMenuBar(); 
     JMenu fileMenu = new JMenu("File"); 
     JMenuItem startMenuItem = new JMenuItem("Pause"); 
     menuBar.add(fileMenu); 
     fileMenu.add(startMenuItem); 

     super.add(canvas); 
     super.setVisible(true); 
     super.setSize(FRAME_WIDTH, FRAME_WIDTH); 
     super.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     super.setJMenuBar(menuBar); 
    } 
} 

public class Main { 

    public static void main(String args[]) { 
     GUI ui = new GUI(); // create and display GUI   

     gameLoop(); // start the game loop 
    } 

    static void gameLoop() { 
     // game loop  
    } 
} 
11

게임 루프 (모델)는 GUI 클래스 (보기) 근처에 있으면 안됩니다. GUI 클래스를 사용하지만 중개자 (컨트롤러)를 통해 할 수도 있습니다. 올바른 방법은 모델에 "include javax.swing. ???"이 하나도 없는지 확인하는 것입니다.

당신이 할 수있는 최선의 일은 게임 루프를 자신의 스레드에 유지하는 것입니다. GUI에서 변경을 원할 때마다 SwingWorker를 사용하거나 어린 아이들이 지금 사용하고있는 것을 사용하여 하나의 작업 만 GUI 스레드에 강제로 적용하십시오.

실제로 GUI 작업 (컨트롤러를 구성 할 것입니다)에 대해 생각하게하기 때문에 실제로는 멋지기도합니다. 예를 들어, 이동 뒤에 GUI 로직이있는 "이동"이라는 클래스가있을 수 있습니다. 게임 루프는 올바른 값 (이동하려는 항목, 최종 위치)으로 "이동"을 인스턴스화하고 처리를 위해 GUI 루프로 전달할 수 있습니다.

일단이 점에 도달하면 각 GUI 작업에 간단하게 "실행 취소"를 추가하면 모든 작업을 쉽게 취소 할 수 있습니다. Swing GUI를 웹 GUI로 대체하는 것이 더 쉽습니다 ...

4

자바는 event-driven programming에 실제로 적합합니다. 기본적으로 타이머 이벤트를 설정하고 청취하십시오. 각 '틱 - 퍽 (tick-tock)'에서 게임 논리를 업데이트합니다. 각 GUI 이벤트에서 게임 로직 메소드가 읽을 데이터 구조를 업데이트합니다.

관련 문제