1

首先感谢您花时间阅读我的问题!我正在开发一个 2D java 游戏,带有基于图块的地图。当我的角色四处移动时,一切都很好,尽管当他向左移动时,屏幕上会出现垂直的白线,也称为伪影/撕裂。当他向上移动时也会发生同样的事情,尽管线条是水平的并且宽度要小得多。奇怪的是,当我向右或向下移动时,这不会发生。我在互联网上四处搜索以找到解决方案,尽管我没有遇到任何适合我的问题的东西。

这是代码,尽管为了测试我已经大大缩小并简化了它。因此,它可以在没有任何图像的情况下运行。感谢您提供的任何答案!

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();
    }
}
4

1 回答 1

1

您在更新地图的线程和绘图之间没有同步。所以在绘制过程中地图可能会处于不一致的状态。

一个快速的解决方法是将地图更新和绘制包装在一个同步块中:

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

(或只是制作整个方法synchronized此外,其他字段(如在键侦听器中修改的字段)也容易处于不一致状态。

还有其他问题:

  • 不要覆盖paint()框架。而是覆盖paintComponent()一个JPanel. 无需在每次重绘时创建图像,摇摆绘画机制默认为双缓冲。见秋千定制绘画。
  • 使用KeyBindings而不是KeyListener
  • Swing 组件只能在事件调度线程中访问(和创建) 。
于 2013-09-15T21:40:42.777 回答