Java getCanvasImage和paintComponent绘制不同步

时间:2018-07-04 17:55:36

标签: java canvas synchronization paintcomponent

目标: 我正在尝试从游戏客户端在NPC周围绘制边界框。我需要将屏幕截图保存到文件夹,并将框坐标保存到文本文件。

问题: 当我旋转相机时,画布上绘制的框不再与NPC对齐。看起来NPC坐标落后于正在绘制的屏幕截图。一些屏幕截图似乎还位于前一帧的一半和新帧的一半。我认为这可能与在第一个图像完成之前发送要保存的多个图像有关。要注意的另一件事是,在下一帧出现在画布上之前,框还没有完成绘制。

如何强制屏幕截图与框坐标同步?有什么方法可以同时获取游戏数据和屏幕截图,然后强制客户端停止绘制直到任务完成?

这是我第一次使用Java(此脚本收集的数据旨在与我正在处理的Python项目一起使用),因此请尽可能简化答案。

更新: 在弄乱事物之后,似乎屏幕破裂可能是主要问题。延迟似乎是由屏幕撕裂引起的。框被绘制在屏幕上保存之前未更新的部分上的正确位置。

https://media.giphy.com/media/39yEawmLBT4zKpPoz3/giphy.gif

Misaligned

Misaligned

Misaligned

表现最差:

Misaligned

撕裂:

Tearing

public class Pair {
   public String key;
   public Rectangle value;

   public Pair(String key, Rectangle value) {
      this.key = key;
      this.value = value;
   }
}

public class MyPaint extends JPanel{
    private static final long serialVersionUID = 9091790544960515120L;
    private BufferedImage paintImage = getClient().getCanvasImage();

    @Override
    protected void paintComponent(Graphics g){

        super.paintComponent(g);
        g.drawImage(paintImage, 0, 0, null);

    }

    public void updatePaint(){
        synchronized (this) {
            Graphics g = paintImage.createGraphics();

            List<NPC> rsNpcs = new NPCs(getClient()).all()
                    .stream()
                    .filter(i -> i.getName().equals(npcName)
                             &&  i.isOnScreen() == true
                             &&  inTile(i.getTile()) == false)
                    .collect(Collectors.toList());

            //Classifying the NPC in the box for the text file.
            for (NPC rsNpc : rsNpcs) {
                Rectangle bbox = rsNpc.getBoundingBox(); 
                g.drawRect(bbox.x, bbox.y, bbox.width, bbox.height);

                if (rsNpc.isInCombat() == true) {
                    Pair rsNpcPair = new Pair("CombatChicken", bbox);
                    onScreenRsNpcs.add(rsNpcPair);
                } else {
                    Pair rsNpcPair = new Pair("RegularChicken", bbox);
                    onScreenRsNpcs.add(rsNpcPair);
                }
            }

            //This bit is to save the boxes to a text file:
            for (Pair rsNpc : onScreenRsNpcs) {
                String data = (String.valueOf(rsNpc.value) + "Class Name: " + rsNpc.key + " Image Name: " + String.valueOf(count));
                globalData.add(data);
            }

            g.dispose();
            repaint();
        }
    }

    public void save() throws IOException{
            ImageIO.write(paintImage, "PNG", new File(String.format("%s/%s.jpg", getManifest().name(), count)));
            count = count + 1;
    }

    public void load() throws IOException {
        paintImage = ImageIO.read(new File(String.format("%s/%s.jpg", getManifest().name(), count)));
        repaint();
    }
}


//...


private MyPaint paint;


public void onStart() {
    paint = new MyPaint();
}


//...


@Override
public int onLoop() {   
    try {
        paint.updatePaint();
        paint.save();
        paint.load();
    } catch (Exception e) {
        e.printStackTrace();
    }

    return 1;
}

0 个答案:

没有答案