2013-04-20 2 views
2

내 게임 (프레임 워크)이 전체 화면에서 초당 30 프레임 (업데이트 호출간에 약 33ms)보다 빠르게 진행될 수 없습니다. 나는 루프를 위해 타이머를 사용한다. 실제로 지연이 점진적으로 줄어들면 측정 호출 간 시간이 길어지기 때문에 실제로는 좀 더 복잡해집니다. 그것은 설정된 지연을 예상 값의 두 배 이상으로 점프합니다. 임계 값은 30ms 인 것 같습니다. 불일치가 4ms 임계 값에서 나타나기 시작하는 창 모드에서는 문제가 없습니다. 두 가지 모드는 일반적으로 더 높은 지연에서 작동합니다. 다음은 내가 생각하는 코드의 일부입니다.전체 화면 프레임 속도 제한 conundrum

fps = 30;  
timer = new Timer(1000/fps, new ActionListener() {   
@Override 
public void actionPerformed(ActionEvent arg0) { 
    tick();    
} 

위의 내용은 타이머 설정입니다. 나머지는 다음과 같습니다.

private void tick(){ 
    update(gameTime); 
    draw(gameTime);  
} 

다음은 내 그래픽 (2D) 및 BufferedImage입니다.

public DrawBatch(DeviceManager deviceManager) { 
    this.deviceManager = deviceManager; 
    color = Color.MAGENTA; 
    bufferedImage = deviceManager.getBufferedImage();  
    bufferedGraphics = (Graphics2D)bufferedImage.getGraphics();bufferedGraphics = (Graphics2D)bufferedImage.getGraphics(); 
    bufferedGraphics.setBackground(color); 
    bufferedGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
    bufferedGraphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
    bufferedGraphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); 
} 

추첨 (GameTime gameTime) 방법은이 방법으로 시작 :

public void begin(){ 
    bufferedGraphics.clearRect(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight()); 
} 

이제 우리는 bufferedGraphics를 사용하여 그릴 수 있습니다. 그릴 (GT의 GT)이 끝나는. (XNA 영감)
public void end(){ 
    if(deviceManager.isFullScreen())deviceManager.getGraphics().drawImage(bufferedImage, 0,0, null); 
    else deviceManager.getGraphics().drawImage(bufferedImage, 3,25, null);  
    deviceManager.getGraphics().dispose();  
    bufferedImage.flush(); 
} 

난 (그래픽 객체와 함께) 새로운 제조 보낸 같은 BufferedImage를 재활용 메모리 누수 하나 대체했다. .dispose()/new Graphics 대신에 같은 Graphics 객체를 사용하는지 모릅니다.

윈도우 모드에서 BufferedImage는 jFrame.getGraphics() 및 graphicDevice.getFullScreenWindow(). getGraphics()에서 fulls-creen에 그려집니다.

다음은 전체 화면 설정입니다.

public void setFS(){ 
    jFrame.setVisible(false); 
    jFrame.dispose(); 
    jFrame.setIgnoreRepaint(true); 
    jFrame.setResizable(false); 
    jFrame.setUndecorated(true); 
    graphicDevice.setFullScreenWindow(jFrame); 
    graphicDevice.getFullScreenWindow().setIgnoreRepaint(true); 
    graphicDevice.setDisplayMode(new DisplayMode(width, height, 32, 60)); 
    jFrame.setVisible(true);   
    fullScreen = true;  
} 

그리고 창 설정.

왜 모드의 다른 동작이 있습니까? (프레임 속도와 일부 잠재적 인 메모리 누수를 제외하고는 프로그램이 원활하게 실행됩니다.)

+0

스윙 이벤트 발송 스레드가 타이머가 제어 할 수없는 자체 스레드이기 때문에 귀하의 틱이 더 빨리/더 느리게 호출됩니다. 특정 시간대의 통화 수를 다른 방식으로 제한해야합니다. – arynaq

+1

많은 것들이 마음에 들지만, 이해가가는 것처럼 보이는 것은 EDT가 압도적으로되고 타이머가 단순히 이벤트를 스태킹하고 있다는 것입니다. Timer는 [setCoalesce] (http://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html#setCoalesce (boolean))라는 메서드를 사용하여 여러 개의 짧은 요청을 단일 EDT에 요청하십시오 – MadProgrammer

+0

예. EDT는 매주기마다'graphicDevice.getFullScreenWindow(). getGraphics()'에 질식합니다. EDT는 게임 루프에 좋은 아이디어였습니까? 하나의 단점은 내가 SwingUtilities의 일부를 사용할 수 없다는 것입니다. 다른 것을 아십니까? –

답변

1

이론적으로 타이머 기간은 한 프레임을 렌더링하는 데 걸리는 시간보다 짧을 수 있습니다. 실제로는 더 길거나 타이머의 공유 스레드를 즉시 포화 상태로 만들 수 있습니다. 확인하려면 profile해야합니다. drawImage()으로의 전화는 일반적으로 스케일링없이 지배적입니다. 이 AnimationTest은 지난 몇 시간 동안 렌더링 시간의 이동 평균을 표시합니다. FRAMES. 이 접근법을 사용하여 가장 느린 허용 목표 플랫폼에 맞게 구현을 조정할 수 있습니다.

+0

부야!프로파일 제안 덕분에 전체 화면 창에서 새로운 Graphics 객체를 얻는 데 많은 시간이 걸렸습니다. 이제 모드 (전체 화면/창) 변경시 Graphics 객체를 만듭니다. 프레임 속도는 고정되어 있습니다. 모드간에 전환하는 것과 그래픽 객체를 잃는 것에 대한 새로운 문제가 있지만 쉽게 고칠 수 있다고 확신합니다. 고맙다 trashgod. –

+0

@ 사샤 - 산 : 다행스럽게 도와 줬어. 'getGraphics()'의 그래픽 문맥은 일시적입니다. 'BufferedImage'에서는 괜찮 았지만'DeviceManager'에서 어떻게 얻는 지 조심하세요. – trashgod

+0

다음 질문입니다. Jframe.getGraphics()는 해당 프레임의 Grpahics 객체를 가져 오거나 (참조) 새 프레임을 만듭니다. 저것에 너무 명확하지 않음. –