2016-07-29 14 views
7

저는 개발중인 작은 게임에 기본 텍스트 거품을 구현하려고했습니다. 너무 화려한 가고 싶지 않다, 나는 몇 가지 텍스트를 포함하는 테두리가 기본 모서리가 둥근 직사각형 시작 :
Basic Text BubbleBufferedImage에서 불투명도가있는 둥근 사각형을 그립니다.

그럼, 그 텍스트 거품가 사전 설정된 시간 후 페이드 아웃해야했다. 그리고 이것은 내가 우연히 발견 한 문제입니다 : 테스트 창에 거품을 표시하려고 할 때 모든 것이 잘 작동했지만, 게임에 표시 할 때 거품이 사라지면 왜곡이 발생했습니다. 필자는 좀 더 테스트하고 디버깅 한 결과 두 가지 경우의 유일한 차이점은 테스트 윈도우에서 paintComponent 메서드의 Graphics로 버블을 그린 반면 게임에서는 BufferedImages를 사용하여 레이어를 시뮬레이션하고 image.createGraphics의 그래픽을 사용한다는 점입니다. 그때 성공적으로 버그를 복제 할 수 있습니다 : 여기
Gif displaying the bug

을, 당신은 왼쪽에 거품이 퇴색 할 때, 그 둥근 모서리 오른쪽의 둥근 모서리하지 변화에 거품 반면, 페이딩 이전에 비해 모양을 변경 볼 . 실제로 왼쪽 버블은 BufferedImage에 그려지며,이 버블 이미지는 패널에 그려지며 오른쪽 버블은 패널에 직접 그려집니다. 여기

public static void main(String[] args) { 

    JFrame frame = new JFrame("Test"); 
    frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
    frame.setLocationRelativeTo(null); 
    frame.setSize(400, 400); 

    JPanel panel = new JPanel() { 

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

      BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); 
      Graphics graphics = image.createGraphics(); 

      paintExampleBubble(graphics, 50, 50); 

      g.drawImage(image, 0, 0, this); 

      paintExampleBubble(g, 250, 50); 
     } 
    }; 

    frame.getContentPane().add(panel); 
    frame.setVisible(true); 
} 

private static final Color background = new Color(1f, 1f, 1f, 0.5f); 
private static final Color foreground = new Color(0f, 0f, 0f, 0.5f); 
private static final int borderRadius = 16; 
private static final int width = 100; 
private static final int height = 50; 

private static void paintExampleBubble(Graphics g, int x, int y) { 

    g.setColor(background); 
    g.fillRoundRect(x, y, width, height, borderRadius, borderRadius); 
    g.setColor(foreground); 
    g.drawRoundRect(x, y, width, height, borderRadius, borderRadius); 
} 

위의 코드가 생성하는 결과 :
나는이 문제를 재현하는 데 필요한 코드를 격리했다 어쨌든
Minimal code bug reproduction image

을이이 BufferedImage의 드로잉하는 원인이 무엇임을 보여줍니다 그러나 문제는 BufferedImages를 놓아 둘 수있는 옵션이 아닙니다.

이 차이를 일으킬 수있는 코드를 디버그하려고했는데 그래픽 개체가 투명성이 관련되었을 때 그릴 때 다른 구성 요소를 사용한다는 사실을 눈치 챘을지라도 내 문제를 해결하는 데 도움이되지는 않습니다. 그래픽이 내가 원하는 것을하도록 강요하는 것이 가능했다. 가능한 경우 해킹을 피했다.

누구든지 비교적 간단하고 효율적인 방법으로이 문제를 해결하거나 해결할 수 있습니까?

어쨌든,이 글을 읽을 시간을내어 주셔서 감사합니다

PS는 :) : 이것이 내가 질문을 처음으로, 나는 몇 가지 물건을 놓칠 수있다, 그래서이 경우 말해 주시기 케이스! 대단히 감사하겠습니다.

편집 : 의견에서 말했듯이 게임은 픽셀 아트 기반이므로 앤티 앨리어싱을 사용하지 않고 둥근 사각형의 기본 픽셀 화 모양을 유지합니다.

+0

정확하게 확실하지가 아니라하는 AlphaComposite 투명성 (foretground 색상 관리의 투명성) 왼쪽에 왜곡을 볼 수 있지만 켜려고 앤티 엘리 어싱'g.setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)'여기서'g'는'Graphics2D'의 인스턴스입니다 – copeg

+0

빠른 응답 감사합니다! 지금 당장 시도해 보았습니다. (투명도가 떨어질 때 국경이 더 이상 바뀌지 않기 때문에) 작동합니다. 그러나 필자가 여기서 언급하지는 않았지만, 필자가 작업하고있는 게임은 픽셀 아트 그래픽과 자동 앤티 앨리어싱 만이 너무 뛰어나고 해상도가 낮아 매우 흐리게 보입니다. – Niss36

+0

이 정확히 무엇을 하려는지 정확히 알지 못하도록 내 질문을 업데이트 하겠지만 다음은 게시자가 다른 방법을 사용할 수도있는 게시글입니다. http://stackoverflow.com/ 질문/15025092/border-with-rounded-corners-transparency – camickr

답변

3

왼쪽의 거품이 희미 해지면 둥근 모서리가 변색되기 전과 비교하여 모양이 바뀌는 반면 오른쪽의 둥근 모서리에있는 거품은 변경되지 않습니다. 실제로 왼쪽 버블은 BufferedImage에 그려지며,이 버블 이미지는 패널에 그려지며 오른쪽 버블은 패널에 직접 그려집니다.

이미지를 다른 알파 값으로 매번 다시 그리는 것이 아니라 한 번 생성하고 AlphaComposite을 사용하여 투명도를 관리하십시오.

다음은 3 개의 '거품'을 사용하여 예제를 적용한 것입니다. 왼쪽은 전경색을 변경할 때마다 이미지를 그립니다. 오른쪽의 두 가지는 한 번만 생성 된 이미지를 사용하여 가운데를 사용합니다. JPanel 그래픽 직접). 내 시스템에서

public class Test { 

    public static void main(String[] args) { 

     JFrame frame = new JFrame("Test"); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     frame.setLocationRelativeTo(null); 
     frame.setSize(600, 200); 
     final BufferedImage image = new BufferedImage(600, 200, BufferedImage.TYPE_INT_ARGB); 
     Graphics2D graphics = image.createGraphics(); 
     paintExampleBubble(graphics, 250, 50, foreground); 
     graphics.dispose(); 
     final JPanel panel = new JPanel() { 

      @Override 
      protected void paintComponent(Graphics g) { 
       super.paintComponent(g); 
       Graphics2D g2d = (Graphics2D)g; 

       final BufferedImage i2 = new BufferedImage(600, 200, BufferedImage.TYPE_INT_ARGB); 
       Graphics2D graphics = i2.createGraphics(); 
       paintExampleBubble(graphics, 50, 50, alphaForeground); 
       graphics.dispose(); 
       g.drawImage(i2, 0, 0, this); 
       //use Alpha Composite for transparency 
       Composite comp = AlphaComposite.getInstance(AlphaComposite.SRC_OVER , alpha); 
       g2d.setComposite(comp); 
       g2d.drawImage(image, 0, 0, this); 

       paintExampleBubble(g2d, 450, 50, foreground); 
      } 
     }; 
     javax.swing.Timer timer = new javax.swing.Timer(100, new ActionListener(){ 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       alpha -= 0.05; 

       if (alpha < 0){ 
        alpha = 1.0f; 
       } 
       alphaForeground = new Color(0f, 0f, 0f, alpha); 
       panel.repaint(); 
      } 

     }); 
     timer.start(); 
     frame.getContentPane().add(panel); 
     frame.setVisible(true); 
    } 

    private static float alpha = 1.0f; 
    private static final Color background = new Color(1f, 1f, 1f, 1f); 
    private static final Color foreground = new Color(0f, 0f, 0f, 1f); 
    private static Color alphaForeground = new Color(0f, 0f, 0f, alpha); 
    private static final int borderRadius = 16; 
    private static final int width = 100; 
    private static final int height = 50; 

    private static void paintExampleBubble(Graphics g, int x, int y, Color color) { 
     g.setColor(background); 
     g.fillRoundRect(x, y, width, height, borderRadius, borderRadius); 
     g.setColor(color); 
     g.drawRoundRect(x, y, width, height, borderRadius, borderRadius); 
    } 
} 

나는 내가 정확하게 당신이 설명하는 것을보고 있어요 경우까지

+1

감사합니다! 내 특정 사례 (실제로 게시 한 코드와 많이 다른)에 대한 답변을 포팅하여 작동하게했습니다. 그러나 텍스트 거품 당 하나의 BufferedImage를 생성하므로 표시 할 거품이 많은 경우 성능 문제가 발생할 수 있지만 현재로서는 우려 할 사항이 아니며 사용자가 답변을 표시 할 때까지 답변을 표시합니다. 추가 BufferedImages가 필요없는 솔루션입니다. – Niss36

+0

모든 텍스트 거품에 대해 하나의 중간 버퍼를 사용할 수 있습니다. 당신은 그것을 매번 지울 수 있으며, 거품을 완전히 불투명하게 그려서 구성 요소에 알파 합성합니다. 다음 버블은 같은 중간 버퍼를 사용할 수 있습니다. – Falco

+0

조금 더 자세하게 설명해 주시겠습니까? 나는 네가 의미하는 바를 잘 모르겠다. 내가 생각하기에 텍스트 버블이 그려지는 장면의 크기와 같은 정적 BufferedImage와 같아서 이미지가 화면에 알파로 그려지면 지워지고 다음 버블에 대해 반복됩니다. – Niss36