【问题标题】:Image rendering outside of the frame?画框外的图像渲染?
【发布时间】:2012-03-07 22:55:41
【问题描述】:

我正在使用 Java 开发一款游戏,但在渲染时遇到了问题(我相信它与内容窗格有关)。我有一个将背景和所有精灵绘制到图像的屏幕类。然后框架使用 doubleBuffer 显示图像。由于某些奇怪的原因,图像正在渲染框架的边缘。您可以在下面的链接中看到,图像向左渲染 3 个像素,在它应该在的位置上方渲染 28 个像素。有谁知道是什么原因造成的? ![在此处输入图片说明][1]

http://imageshack.us/photo/my-images/41/weirdg.png/

public class Game extends JFrame implements Runnable{
private static final long serialVersionUID = 1L;

//graphics
public BufferStrategy buffy;
BufferedImage image;
Screen screen;

public Boolean running = false;
public Boolean playerTurn = false;

public InputManager input;
public Level level;
//JButton b;

public static final int HEIGHT = 452;
public static final int WIDTH = 768;

public Game() {
    super("GridWars");
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    JPanel drawPanel = new JPanel();
    drawPanel.setPreferredSize(new Dimension(WIDTH, HEIGHT));
    drawPanel.setLayout(null);
    drawPanel.setOpaque(false);
    //drawPanel.setLocation(50,50);

    setContentPane(drawPanel);
    setResizable(false);
    pack();
    setLocationRelativeTo(null);
    setVisible(true);
    requestFocus();
    createBufferStrategy(2);

    //b = new JButton("this sucks");

    //getContentPane().add(b);
    //b.setBounds(300, 300, 100, 50);


    buffy = getBufferStrategy();
    image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    screen = new Screen(WIDTH, HEIGHT);
    input = new InputManager(this);
    level = new Level(WIDTH, HEIGHT, input, this);
}

public void start() {
    running = true;
    new Thread(this).start();
}
public void setup(){

}
public void run() {
    final double TICKS = 30.0;
    final double UPDATE_INTERVAL_NS = 1000000000 / TICKS;
    double pastUpdateNS = System.nanoTime();

    int updateCount = 0;
    int frameCount = 0;

    final double FRAPS = 60.0; 
    final double RENDER_INTERVAL_NS = 1000000000 / FRAPS;
    double pastRenderNS = System.nanoTime();

    int pastSecondNS = (int) (pastUpdateNS/1000000000);

    while(running) {
        double nowNS = System.nanoTime();

        if(nowNS - pastUpdateNS >= UPDATE_INTERVAL_NS) {
            update();
            pastUpdateNS += UPDATE_INTERVAL_NS;
            updateCount++;
        }

        float interp = Math.min(1.0f, (float) ((nowNS - pastUpdateNS) / UPDATE_INTERVAL_NS) );
        render(interp);
        pastRenderNS += RENDER_INTERVAL_NS;
        frameCount++;

        int thisSecondNS = (int) (pastUpdateNS/1000000000);
        if (thisSecondNS > pastSecondNS) {
            //System.out.println("TICKS: "+updateCount+" | FRAPS: "+frameCount);
            updateCount = 0;
            frameCount = 0;
            pastSecondNS = thisSecondNS;
        }

        while( nowNS - pastRenderNS < RENDER_INTERVAL_NS && nowNS - pastUpdateNS < UPDATE_INTERVAL_NS) {
            try { Thread.sleep(1); } catch(Exception e) {};
            nowNS = System.nanoTime();
        }
    }
}

public void update() {
    input.update();
    level.update();
}

public void render(float interp) {
    level.render(screen, interp);

    image = screen.getImage();
    Graphics g = buffy.getDrawGraphics();
    g.drawImage(image, 0, 0, null, null);
    //b.repaint();
    g.dispose();
    buffy.show();
}

public static void main(String[] args) {
    Game game = new Game();
    game.start();
}
}

【问题讨论】:

  • 打印声明在哪里? (对不起,如果我错过了)

标签: java image swing concurrency jframe


【解决方案1】:

您从buffy.getDrawGraphics(); 获得的Graphics 对象的0,0 坐标正好在JFrame 的左上角,它忽略了框架装饰。

  1. UPD 我忘记了一个明显的选项。 JFrame.getInsets() 提供有关装饰的信息。你可以简单地改变你的渲染。

  2. 您可以不装饰框架 (setUndecorated(true)) 并自己渲染/管理窗口控件。

  3. 或者,我认为这是更简单的方法,您会忘记在JFrame 上直接渲染,将Canvas 放在上面,然后改用它。 Canvas 还包含 createBufferStrategy 方法,因此您只需进行一些简单的更改。

    JPanel drawPanel = new JPanel();
    drawPanel.setLayout(new BorderLayout());
    Canvas canvas = new Canvas();
    canvas.setPreferredSize(new Dimension(WIDTH, HEIGHT));
    drawPanel.add(canvas, BorderLayout.CENTER);
    
    // some code skipped
    
    canvas.setIgnoreRepaint(true); //important
    canvas.createBufferStrategy(2);
    
    buffy = canvas.getBufferStrategy();
    

几天前我创建了具有类似渲染的简单demo 以获得另一个答案。也许会有所帮助。

【讨论】:

  • 非常感谢您的快速回复。我以前使用的是画布,但在使用画布时无法使用 JButtons。我在论坛上查看了有关该问题的信息,并被告知它不起作用,所以我切换到了这个。它修复了按钮问题,但随后开始出现当前问题。我在使用 setUndecorated “框架是可显示的”时遇到问题。
  • setUndecorated 必须在 setVisible(true) 之前调用。将轻量级组件(如JButtons)与重量级Canvas 混合时会出现很多问题。它总是在按钮上呈现。也许值得使用java.awt.Button。甚至实现自己的简单渲染按钮。使用标准组件需要额外的工作,因为它们旨在从 EDT 进行被动渲染,并且我们已使用 setIgnoreRepaint(true) 禁用重绘事件。
  • 嗯...我真的不知道该怎么办。我的游戏使用鼠标,它基于帧内单击的点的动作,所以如果我使用插图移动渲染,那么我的输入就会关闭。
  • 是的,我一直在考虑回到画布并渲染我自己的按钮
  • 再次感谢您提供的所有信息。我是 Java 新手,你真的很有帮助。我会以某种方式让它工作,知道你所说的一切会更容易
猜你喜欢
  • 1970-01-01
  • 2021-06-30
  • 1970-01-01
  • 1970-01-01
  • 2015-11-09
  • 2020-08-19
  • 1970-01-01
  • 1970-01-01
  • 2018-05-05
相关资源
最近更新 更多