2009-04-20 5 views
4

어제 14 번째 Ludum Dare 48 시간 게임에 대해 my entry을 끝 마치고 java2d를 사용하여 그래픽 작업을 수행하기로 결정했습니다.간단한 Java2D App에서의 놀라운 성능

저는 API에 익숙하지 않고 많은 그래픽 프로그래밍을하지는 않았지만 제 게임은 아주 작습니다 (단지 12 개 정도의 매우 작은 이동 오브젝트). 그래서 순진하게 프로그래밍 할 수 있다고 가정했습니다. 성능 문제는 여전히 발생하지 않습니다.

말할 것도없이, 틀 렸습니다. 게임은 대부분 시간을 잘 수행하지만 일단 너무 많은 '원수'가 화면을 돌아 다니거나 해상도가 너무 높아지면 눈에 띄게 느려집니다.

게임의 성능 병목 현상을 화면 그리기 기능으로 결정했습니다. 게임이 매우 빠르다고 설명 할 때 그렇습니다.

내가 여기서 잘못하고있는 사람이 누구일까요? (매우 짧은) 소스 코드는 here이고 대부분은 Main 클래스이며 inner game loop에서 호출되는 draw() 함수라는 일반적인 용의자가 있습니다.

이미 잘못 입력하지 않으면 화면을 업데이트하기 위해 이미 BufferStrategy을 사용하고 있으므로 문제가되지 않습니다.

미리 감사드립니다. 이도.

+0

+1이 주제에 대한 많은 관련 질문이있는 것으로 보이지만 이것이 새로운 정보를 생성하는지 확인하는 데 관심이 있습니다. –

답변

7

몇 가지 관찰은 있지만, 그 중 어느 것도 많이 도움이되지는 않을 것이라고 생각합니다.

가장 중요한 것은 AWT 스레드에서 벗어난 것입니다. paintComponent()를 오버라이드하고 객체에 대해 repaint()를 대신 호출하십시오. 그렇지 않으면 모든 종류의 문제가 발생할 수 있습니다.

모든 프레임마다 색을 다시 만듭니다. 이것은 캐싱하려는 것들 중 하나 일 수도 있고 아닐 수도 있습니다. 나는 당신의 색깔에 대해 상수를 갖는 것이 GCing을 망칠 가능성이 있지만 나중에 색상을 재사용하고자 할 때 직선으로 유지하기가 더 쉽다고 생각합니다.

프레임마다 모든 창을 다시 그립니다. 변경된 섹션을 다시 칠하기 만하면됩니다.

배경을 그릴 필요가 없습니다. 배경색을 설정하고 부모가 모든 것을 돌보게하십시오.

디자인의 일환으로 시신은 스스로 드로잉을 담당해야합니다. 그들의 주인은 그 (것)들을 그리기보다는 오히려 당겨질 필요가있다는 것을 그 (것)들에게 알려야한다.

본문은 매번 상태를 재생성합니다. 그들 사이에 그것을 저장하고 필요에 따라 돌연변이시키는 것을 고려하십시오. drawCircleBody()에서 trig 계산을 수행하는 데 많은 시간을 소비하고 있습니다.

while 루프에서 절전 모드를 사용하는 대신 타이머를 설정하는 것이 좋습니다. 이렇게하면보다 일관된 프레임 속도를 얻을 수 있지만, 실제로 의무를 이행 할 수 있는지 (또는 마감 기한이 지났을 때 여러 프레임을 하나로 합치면) 너무 많은 스레드가 생성 될 수 있습니다.

SwingWorker을 사용하여 계산을 수행 한 다음 done() 메소드에서 상태를 업데이트하고 repaint()를 호출하여 마무리하십시오.

다음은 몇 가지 예입니다. 실험을 통해 효과가 있고 효과가없는 것을 확인해야합니다. Java 그래픽 그리기를 한 지 오래되었습니다.

+0

답변입니다. +4를 갖고 싶습니다. –

+0

자세한 답변을 보내 주셔서 감사합니다. 첫 번째 사항에 대해서는 내가 연장해야한다는 의미입니까? JFrame 대신 JPanel을 사용하고 paintComponent()를 재정의 하시겠습니까? 왜냐하면 JFrame에는 내가 재정의 할 수있는 기능이 없기 때문입니다. 마지막으로, 내 앱 규모를 1 cpu/core 이상으로 만드는 보너스가 추가 될 것입니다. 맞습니까? 왜냐하면 대부분의 계산 작업은 GUI와는 별도의 스레드에서 발생하기 때문입니다. –

+0

예, 아마 JPanel이어야합니다. 실제 윈도우 동작을 변경해야 할 때만 JFrame을 확장해야합니다. 실제로는 내용 패널 (JPanel로 설정할 수 있음)을 그립니다. 스케일링의 경우, 작업의 일부는 순차적으로 수행되어야하기 때문에 스케일링에 대한 확장이 불가능할 수도 있습니다. 특히 각 프레임은 순차적으로 수행되어야합니다. 그러나 미래의 JVM은 실제로 당신을 위해 멀티 코어 최적화를 수행 할 수 있습니다. – James

6

단일 스레딩 규칙을 준수하지 귀하의 코드 :

http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html

나는 이것이 당신이보고있는 특정 성능 문제를 일으킬 수 있는지 확실하지 않습니다,하지만 큰 잠재적으로 눈에 띄는 문제, imo.

+0

예, 실제로는 스레드 수가 늘어나 기 때문에 성능과 기괴한 시각 효과에 큰 문제가 발생할 수 있으며 문제가 될 가능성이 큽니다. –

+0

제임스가 말한 것과 같은 GUI 스레드 외부의 그림 또는 다른 것을 의미합니까? –

6

글쎄, 당신의 draw() 함수를 간략하게 살펴보면, 당신은 많은 새로운 객체를 선언하고있는 것처럼 보입니다 (특히 drawPolygonBody에서). 매번 새로운 개체를 선언하는 대신 개체를 다시 사용하십시오.

EDIT : instanceof에 오버 헤드가 있습니다. 자신을 그리는 draw (Graphics g) 함수를 갖도록 Body를 확장하는 것이 더 좋습니다. 예 :

public class Circle extends Body 
{ 
    // override 
    public void draw(Graphics g) 
    { 
     ... 
    } 
} 

... 

void drawBody(Body body) 
{ 
    body.draw(); 
} 
4

은 당신이 병목이 도면 기능에 을 볼 수 프로파일 시도?

그냥 보면서 많은 것을 말하기는 어렵지만 왜 drawPolygonBody에서 다각형을 채우고 채우는 지 궁금합니다.
또한 drawBoxBody에서 drawRect()를 호출하는 대신 4 개의 선을 개별적으로 그립니다.

+0

당신이 옳다 고 생각합니다. 다각형을 채우면 그릴 필요도 없습니다. drawBoxBody에서 처음에는 그런 식으로했지만 몇 가지 문제가 발생하여 다시 되돌려 보았습니다.하지만 다시 살펴 보겠습니다. –

관련 문제