2013-05-05 6 views
1

편집 : 이것은 내 문제를 설명하는 SSCCE입니다.JPanel은 이중 버퍼를 사용하더라도 찢어 지나요?

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.Point; 
import java.awt.event.ActionEvent; 
import java.awt.image.BufferedImage; 
import java.awt.Graphics2D; 
import javax.swing.AbstractAction; 
import javax.swing.ActionMap; 
import javax.swing.InputMap; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.KeyStroke; 

public class Main { 
    public static BufferedImage map, tileSand, tileSea; 
    public static void main(String[] args) { 
     map = new BufferedImage(50, 50, BufferedImage.TYPE_INT_ARGB); 
     for(int x = 0; x < 50 ; x++){ 
      for(int y = 0; y < 50 ; y++){ 
       boolean colour = Math.random() < 0.5; 
       if (colour){ 
        map.setRGB(x, y, -256); 
       } else { 
        map.setRGB(x, y, -16776961); 
       } 
      } 
     } 
     tileSand = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); 
     Graphics g = tileSand.getGraphics(); 
     g.setColor(Color.YELLOW); 
     g.fillRect(0, 0, 32, 32); 
     tileSea = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); 
     g.setColor(Color.BLUE); 
     g = tileSea.getGraphics(); 
     g.fillRect(0, 0, 32, 32); 
     Island test = new Main.Island(); 
     test.start(); 
     long start, sleep; 
     while(true) { 
      start = System.currentTimeMillis(); 
      test.getCanvas().requestFocus(); 
      test.getCanvas().repaint(); 
      sleep = 15-(System.currentTimeMillis()-start); 
      try { 
       Thread.sleep(sleep > 0 ? sleep : 0); 
      } catch (InterruptedException e) { 
      } 
     } 
    } 

    static class Island implements Runnable { 

     private Tile[][] tiles; 
     private JFrame frame; 
     private JPanel panel; 
     private Thread logicThread; 
     private boolean running = false; 
     private boolean paused = false; 
     private Image image; 
     private Player player; 

     public Island() { 
      image = new BufferedImage(1027, 768, BufferedImage.TYPE_INT_ARGB); 
      player = new Player(); 
      tiles = new Tile[map.getWidth()][map.getHeight()]; 
      int rgb; 
      for(int x = 0; x < map.getWidth(); x++) { 
       for(int y = 0; y < map.getHeight(); y++) { 
        rgb = map.getRGB(x, y); 
        switch (rgb) { 
         case -16776961: tiles[x][y] = new Tile("sea"); 
             break; 
         case -256: tiles[x][y] = new Tile("sand"); 
            break; 
        } 
       } 
      } 
      makeMap(); 
      makeFrame(); 
      addBindings(); 
      logicThread = new Thread(this); 
     } 

     public JPanel getCanvas() { 
      return panel; 
     } 

     public void start() { 
      running = true; 
      paused = false; 
      logicThread.start(); 
     } 

     public void run() { 
      long sleep, before; 
      while(running){ 
       before = System.currentTimeMillis(); 
       player.move(); 
       try { 
        sleep = 15-(System.currentTimeMillis()-before); 
        Thread.sleep(sleep > 0 ? sleep : 0); 
       } catch (InterruptedException ex) { 
       } 
       while(running && paused); 
      } 
      paused = false; 
     } 

     private void makeFrame() { 
      frame = new JFrame("Island"); 
      panel = new JPanel(){ 
       @Override 
       public void paintComponent(Graphics g) { 
        super.paintComponent(g); 
        Graphics2D g2d = (Graphics2D) image.getGraphics(); 
        g2d.setColor(Color.BLACK); 
        g2d.fillRect(0, 0, 1024, 768); 
        long xl, yl; 
        xl = player.getLocation().x-512; 
        yl = player.getLocation().y-384; 
        int x2, y2; 
        x2 = (int) Math.floor(xl/32); 
        y2 = (int) Math.floor(yl/32); 
        int xoffset, yoffset; 
        xoffset = (int) (xl % 32); 
        yoffset = (int) (yl % 32); 
        for(int x = x2; x < x2+40; x++) { 
         for(int y = y2; y < y2+40; y++) { 
          if (x < tiles.length && x > 0 && y < tiles[0].length && y > 0) { 
           g2d.drawImage(tiles[x][y].getContent(), (x-x2)*32 - xoffset, (y-y2)*32 - yoffset, null); 
          } 
         } 
        } 
        g.drawImage(image, 0, 0, null); 
       } 
      }; 
      panel.setPreferredSize(new Dimension(1024, 768)); 
      panel.setIgnoreRepaint(true); 
      frame.add(panel); 
      frame.pack(); 
      frame.setVisible(true); 
     } 

     private void addBindings() { 
      InputMap inputMap = panel.getInputMap(); 
      ActionMap actionMap = panel.getActionMap(); 
      inputMap.put(KeyStroke.getKeyStroke("Q"),"hold-sprint"); 
      actionMap.put("hold-sprint", new AbstractAction() { 
       public void actionPerformed(ActionEvent e) { 
        player.sprint(true); 
       } 
      }); 
      inputMap.put(KeyStroke.getKeyStroke("released Q"),"release-sprint"); 
      actionMap.put("release-sprint", new AbstractAction() { 
       public void actionPerformed(ActionEvent e) { 
        player.sprint(false); 
       } 
      }); 
      inputMap.put(KeyStroke.getKeyStroke("RIGHT"),"hold-right"); 
      actionMap.put("hold-right", new AbstractAction() { 
       public void actionPerformed(ActionEvent e) { 
        player.right(true); 
       } 
      }); 
      inputMap.put(KeyStroke.getKeyStroke("released RIGHT"),"release-right"); 
      actionMap.put("release-right", new AbstractAction() { 
       public void actionPerformed(ActionEvent e) { 
        player.right(false); 
       } 
      }); 
      inputMap.put(KeyStroke.getKeyStroke("DOWN"),"hold-down"); 
      actionMap.put("hold-down", new AbstractAction() { 
       public void actionPerformed(ActionEvent e) { 
        player.down(true); 
       } 
      }); 
      inputMap.put(KeyStroke.getKeyStroke("released DOWN"),"release-down"); 
      actionMap.put("release-down", new AbstractAction() { 
       public void actionPerformed(ActionEvent e) { 
        player.down(false); 
       } 
      }); 
      inputMap.put(KeyStroke.getKeyStroke("LEFT"),"hold-left"); 
      actionMap.put("hold-left", new AbstractAction() { 
       public void actionPerformed(ActionEvent e) { 
        player.left(true); 
       } 
      }); 
      inputMap.put(KeyStroke.getKeyStroke("released LEFT"),"release-left"); 
      actionMap.put("release-left", new AbstractAction() { 
       public void actionPerformed(ActionEvent e) { 
        player.left(false); 
       } 
      }); 
      inputMap.put(KeyStroke.getKeyStroke("UP"),"hold-up"); 
      actionMap.put("hold-up", new AbstractAction() { 
       public void actionPerformed(ActionEvent e) { 
        player.up(true); 
       } 
      }); 
      inputMap.put(KeyStroke.getKeyStroke("released UP"),"release-up"); 
      actionMap.put("release-up", new AbstractAction() { 
       public void actionPerformed(ActionEvent e) { 
        player.up(false); 
       } 
      }); 
     } 

     private void makeMap() { 
      for(int x = 0; x < tiles.length; x++) { 
       for(int y = 0; y < tiles[0].length; y++) { 
        switch (tiles[x][y].getType()) { 
         case "sea": tiles[x][y].setContent(tileSea); 
            break; 
         case "sand": tiles[x][y].setContent(tileSand); 
             break; 
        } 
       } 
      } 
     } 
    } 

    static class Player{ 
     private Point location; 
     private int xspeed, yspeed; 
     private boolean left, up, right, down, sprint; 

     public Player() { 
      location = new Point(0, 0); 
      left = false; 
      up = false; 
      right = false; 
      down = false; 
      sprint = false; 
      xspeed = yspeed = 0; 
     } 
     public void left(boolean state){ 
      left = state; 
     } 

     public void up(boolean state){ 
      up = state; 
     } 

     public void right(boolean state){ 
      right = state; 
     } 

     public void down(boolean state){ 
      down = state; 
     } 

     public void sprint(boolean state) { 
      sprint = state; 
     } 

     public void move() { 
      if (sprint) { 
       if (left) { 
        if(xspeed>-10) 
         xspeed--; 
       } if (right) { 
        if(xspeed<10) 
         xspeed++; 
       } if (up) { 
        if(yspeed>-10) 
         yspeed--; 
       } if (down) { 
        if(yspeed<10) 
         yspeed++; 
       } 
      } else { 
       if (left) { 
        if(xspeed>-5) 
         xspeed--; 
       } if (right) { 
        if(xspeed<5) 
         xspeed++; 
       } if (up) { 
        if(yspeed>-5) 
         yspeed--; 
       } if (down) { 
        if(yspeed<5) 
         yspeed++; 
       } 
      } 
      if (!sprint) { 
       if (xspeed > 5) { 
        xspeed--; 
       } if (xspeed < -5) { 
        xspeed++; 
       } if (yspeed > 5) { 
        yspeed--; 
       } if (yspeed < -5) { 
        yspeed++; 
       } 
      } 
      if (!left && !right) { 
       if (xspeed > 0) { 
        xspeed--; 
       } if (xspeed < 0) { 
        xspeed++; 
       } 
      } if (!up && !down) { 
       if (yspeed > 0) { 
        yspeed--; 
       } if (yspeed < 0) { 
        yspeed++; 
       } 
      } 
      location.x = location.x + xspeed; 
      location.y = location.y + yspeed; 
     } 

     public Point getLocation() { 
      return location; 
     } 
    } 

    static class Tile { 
     private String type; 
     private BufferedImage tile; 

     public Tile(String type) { 
      this.type = type; 
     } 

     public String getType() { 
      return type; 
     } 

     public void setContent(BufferedImage newTile) { 
      tile = newTile; 
     } 

     public BufferedImage getContent() { 
      return tile; 
     } 
    } 
} 

수정 된 paintComponent 메소드가있는 JPanel이 있습니다. 이 방법에서는 플레이어 위치를 기반으로 2 차원 어레이의 관련 타일을 화면에 그립니다. 모든 타일을 BufferedImage에 그려서 페인트 메서드의 끝에 화면에 적용합니다. 이론적으로 이것은 이중 버퍼링이므로 찢어지지 않아야합니다. 나는 찢어가 가능 플레이어의 위치는 타일되지 않음을 일으키는 원인이되는 페인트 방법의 기간에 걸쳐 변화에 의해 야기 될 수 있다고 생각

public void paintComponent(Graphics g) { 
     Graphics2D g2d = (Graphics2D) image.getGraphics(); 
     g2d.setColor(Color.BLACK); 
     g2d.fillRect(0, 0, 1024, 768); 
     long xl, yl; 
     xl = player.getLocation().x-512; 
     yl = player.getLocation().y-384; 
     int x2, y2; 
     x2 = (int) Math.floor(xl/32); 
     y2 = (int) Math.floor(yl/32); 
     int xoffset, yoffset; 
     xoffset = (int) (xl % 32); 
     yoffset = (int) (yl % 32); 
     for(int x = x2; x < x2+40; x++) { 
      for(int y = y2; y < y2+40; y++) { 
       if (x < tiles.length && x > 0 && y < tiles[0].length && y > 0) { 
        g2d.drawImage(tiles[x][y].getContent(), (x-x2)*32 - xoffset, (y-y2)*32 - yoffset, null); 
       } 
      } 
     } 
     g.drawImage(image, 0, 0, null); 
    } 

: 여기에 해당하는 코드는 이미지가 화면의 크기와 단지의 BufferedImage입니다입니다 일치하면 플레이어가 빠를수록 효과가 더 분명 해집니다. 그러나 나는 선수 위치를 얻고 두 개의 longs에서 그것을 저장합니다. 나는 longs가 값이 아닌 reference에 의해 전달되어 플레이어 위치가 메소드가 실행되는 동안 일정해야한다는 인상하에있었습니다.

더 많은 코드를 제공해 드릴 수있어서 기쁩니다. 미리 감사드립니다.

+0

더 나은 도움을 받으려면 [SSCCE] (http://sscce.org/)를 게시하십시오. –

+2

'public void paintComponent (Graphics g) {..''을'public void paintComponent (Graphics g) {super.paintComponent (g) ..'로 바꾼다. –

+0

그냥 테스트를 해봤지만 영향이 없다고 생각한다. 패널에서 스윙의 구성 요소를 드로잉하는 경우에만 그렇게해야한다는 인상을 주시겠습니까? 추가 할 또 다른 것은 JPanel으로 클래스를 확장하지 않습니다. 생성자에서 JPanel을 초기화 한 후에 paintComponent를 재정의합니다. 마찬가지로 : 패널 = 새 JPanel() { @Override 공개 무효 paintComponent (그래픽 g) {etc ... – Iain

답변

-1

사람들이 내 질문을 찾아서 "수정"하기 위해 한 일이 궁금하다면 프로젝트에 들어가기 전에 C++ 및 SDL 또는 다른 이미지 라이브러리로 전환해야합니다. 사물의.

+0

왜 내 대답에 투표하지 않습니까? 그것은 제가 찾을 수있는 유일한 해결책입니다. – Iain