目标: 我正在尝试从游戏客户端在NPC周围绘制边界框。我需要将屏幕截图保存到文件夹,并将框坐标保存到文本文件。
问题: 当我旋转相机时,画布上绘制的框不再与NPC对齐。看起来NPC坐标落后于正在绘制的屏幕截图。一些屏幕截图似乎还位于前一帧的一半和新帧的一半。我认为这可能与在第一个图像完成之前发送要保存的多个图像有关。要注意的另一件事是,在下一帧出现在画布上之前,框还没有完成绘制。
如何强制屏幕截图与框坐标同步?有什么方法可以同时获取游戏数据和屏幕截图,然后强制客户端停止绘制直到任务完成?
这是我第一次使用Java(此脚本收集的数据旨在与我正在处理的Python项目一起使用),因此请尽可能简化答案。
更新: 在弄乱事物之后,似乎屏幕破裂可能是主要问题。延迟似乎是由屏幕撕裂引起的。框被绘制在屏幕上保存之前未更新的部分上的正确位置。
https://media.giphy.com/media/39yEawmLBT4zKpPoz3/giphy.gif
表现最差:
撕裂:
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;
}