2013-09-15 3 views
0

Прежде всего спасибо за то, что нашли время, чтобы прочитать мой вопрос! Я разрабатываю 2D-java-игру с картой на основе плитки. Когда мой персонаж перемещается, все в порядке, хотя, когда он перемещается влево, на экране появляются вертикальные белые линии, также известные как артефакт/разрывы. То же самое происходит, когда он движется вверх, хотя линии горизонтальны и намного меньше по ширине. Как ни странно, этого не происходит, когда я двигаюсь вправо или вниз. Я искал в Интернете, чтобы найти решение, хотя я не встречал ничего, что соответствовало моей проблеме.Разрыв/картирование на карте 2D-плитки

Вот код, хотя я сильно сократил и упростил его для тестирования. Поэтому его можно запускать без каких-либо изображений. Спасибо за любой ответ, который вы предоставляете!

package adriana; 

import java.awt.Color; 
import java.awt.Graphics; 
import java.awt.Image; 
import java.awt.Rectangle; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent; 
import java.awt.image.BufferedImage; 
import javax.swing.JFrame; 

/** 
* 
* @author Christophe 
*/ 
public class Main extends JFrame implements Runnable{ 

    public Image dbImage; 
    public Graphics dbGraphics; 

    //Image + Array size 
    final static int listWidth = 500, listHeight = 500; 


    //Move Variables 
    int playerX = 320, playerY = 240, xDirection, yDirection; 

    //Sprites 
    BufferedImage spriteSheet; 

    //Lists for sprite sheet: 1 = STILL; 2 = MOVING_1; 3 = MOVING_2 
    BufferedImage[] ARCHER_NORTH = new BufferedImage[4]; 
    BufferedImage[] ARCHER_SOUTH = new BufferedImage[4]; 
    BufferedImage[] ARCHER_EAST = new BufferedImage[4]; 
    BufferedImage[] ARCHER_WEST = new BufferedImage[4]; 

    Image[] TILE = new Image[12]; 

    //Animation Variables 
    int currentFrame = 0, framePeriod = 150; 
    long frameTicker = 0l; 
    Boolean still = true; 
    Boolean MOVING_NORTH = false, MOVING_SOUTH = false, MOVING_EAST = false, MOVING_WEST = false; 

    BufferedImage player; 

    //World Tile Variables 
    //20 X 15 = 300 tiles 
    Rectangle[][] blocks = new Rectangle[listWidth][listHeight]; 

    int tileX = 250, tileY = 250; 

    Rectangle playerRect = new Rectangle(playerX + 4,playerY+20,32,20); 

    //Map Navigation 
    static final byte PAN_UP = 0, PAN_DOWN = 1, PAN_LEFT = 2, PAN_RIGHT = 3; 
    final int speed = 8; 



    public Main(){ 

     this.setTitle("JAVA4K"); 
     this.setSize(640,505); 
     this.setResizable(false); 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     this.setVisible(true); 

     addKeyListener(new AL()); 

     for(int y = 0; y < listHeight; y++){ 
      for(int x = 0; x < listWidth; x++){ 
       blocks[x][y] = new Rectangle(x*32-8000, y*32-8000, 32, 32); 
      } 
     } 

    } 

    //Key Listener 

    public class AL extends KeyAdapter{ 

     public void keyPressed(KeyEvent e){ 

      int keyInput = e.getKeyCode(); 
      still = false; 
      if(keyInput == e.VK_LEFT){ 

       navigateMap(PAN_RIGHT); 

      }if(keyInput == e.VK_RIGHT){ 

       navigateMap(PAN_LEFT); 

      }if(keyInput == e.VK_UP){ 

       navigateMap(PAN_DOWN); 

      }if(keyInput == e.VK_DOWN){ 

       navigateMap(PAN_UP); 
      } 
     } 

     public void keyReleased(KeyEvent e){ 

      int keyInput = e.getKeyCode(); 
      setYDirection(0); 
      setXDirection(0); 

      if(keyInput == e.VK_LEFT){ 


      }if(keyInput == e.VK_RIGHT){ 


      }if(keyInput == e.VK_UP){ 


      }if(keyInput == e.VK_DOWN){ 

      } 

     } 
    } 


    public void moveMap(){ 

     for(int a = 0; a < 500; a++){ 
       for(int b = 0; b < 500; b++){ 
        if(blocks[a][b] != null){ 
         blocks[a][b].x += xDirection; 
         blocks[a][b].y += yDirection; 

        } 
       } 
      } 
    } 


    public void navigateMap(byte pan){ 
     switch(pan){ 
      default: 
       System.out.println("Unrecognized pan!"); 
       break; 
      case PAN_UP: 
       setYDirection(-1 * speed); 
       break; 
      case PAN_DOWN: 
       setYDirection(+1 * speed); 
       break; 
      case PAN_LEFT: 
       setXDirection(-1 * speed); 
       break; 
      case PAN_RIGHT: 
       setXDirection(+1 * speed); 
       break; 
     } 
    } 


    public void setXDirection(int xdir){ 
     xDirection = xdir; 
     if(blocks[0][0] != null) tileX = ((playerRect.x - blocks[0][0].x)/32)-1; 
    } 


    public void setYDirection(int ydir){ 
     yDirection = ydir; 
     if(blocks[0][0] != null) tileY = ((playerRect.y - blocks[0][0].y)/32)-1; 
    } 



    public void paint(Graphics g){ 

     dbImage = createImage(getWidth(), getHeight()); 
     dbGraphics = dbImage.getGraphics(); 
     paintComponent(dbGraphics); 
     g.drawImage(dbImage, 0, 25, this); 

    } 

    public void paintComponent(Graphics g){ 

     requestFocus(); 

     //Draws tiles and rectangular boundaries for debugging 
     for(int a = tileX - 18; a < tileX + 20; a++){ 
      for(int b = tileY - 15; b < tileY + 17; b++){ 
        g.setColor(Color.RED); 
        g.fillRect(blocks[a][b].x, blocks[a][b].y, 32, 32); 
        g.setColor(Color.BLACK); 
        g.drawRect(blocks[a][b].x, blocks[a][b].y, 32, 32); 
      } 
     } 

     //Draw player 
     g.drawRect(playerX, playerY, 40, 40); 

     repaint(); 
    } 

    public void run(){ 
     try{ 
      System.out.println("Running"); 
      while(true){ 
       moveMap(); 

       Thread.sleep(13); 
      } 
     }catch(Exception e){ 
      e.printStackTrace(); 
     }  
    } 


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

     //Threads 
     Thread thread1 = new Thread(main); 
     thread1.start(); 
    } 
} 
+1

1- не называйте запрос фокусом или перерисовкой в ​​рамках любого метода краски. В основном это настройка бесконечного цикла запроса краски, который будет потреблять ваш процессор с течением времени. 2- Я был бы осторожен в том, чтобы обновлять любую часть модели, на которую подкрадываются краски, от отдельного потока, это может привести к грязной живописи. 3- Компоненты Swing по умолчанию буферизованы по умолчанию, поэтому вам лучше отказаться от чего-то вроде JPanel для рендеринга. – MadProgrammer

+1

Использование магических чисел также вызывает беспокойство. Я бы создал отдельный компонент, отвечающий за простое отображение карты, чтобы вы могли сосредоточиться только на этой части игры ... позволить другим компонентам брать на себя ответственность за другие части игры – MadProgrammer

ответ

1

У вас нет синхронизации между нитью, обновляющей карту и чертеж. Таким образом, карта может находиться в противоречивом состоянии во время рисования.

Быстрое исправление будет оборачивать обновление карты и рисование в синхронизированный блок:

synchronized(blocks) { 
    // drawing or modification here 
} 

(или просто сделать целые методы synchronized) Кроме того, другие поля (например, модифицированные в ключе слушатель) также подвержены несогласованному состоянию.

Есть другие проблемы:

  • Не перегружайте paint() кадра. Вместо этого переопределите paintComponent() из JPanel. Нет необходимости создавать изображение при каждом перерисовке, механизм рисования качания по умолчанию является двойной буферизацией. См custom painting in swing.
  • Использование KeyBindings вместо того, KeyListener
  • компонентов Swing, должны быть доступны (и созданных) только в event dispatch thread.
Смежные вопросы